═══ 1. Introduction to the E Language ═══ In order to change existing features or add your own features to the E editor, you must understand the code in the *.E files which implements the editor. These files are written in a macro language (the E language) developed for the editor. To make changes to the editor, simply edit these files, remove the pertinent E code, and make the necessary changes, place in a My*.E file, and recompile using the etpm epm command as discussed in The EPM User's Guide. Special features of the E language include: o The E language provides high level list and display capabilities. o The E language combines file list primitives, display primitives, and keyboard primitives into a language with procedure definitions. Few other languages have attempted to provide useful display, file list and keyboard primitives. o The E language, like REXX, has untyped variables, making it easier to manipulate strings and numbers. (In essence all variables are strings.) o The E language allows definition of keys, commands and procedures in a similar manner. An E program consists solely of one or more definitions. Each definition can define: a procedure, which consists of tasks to be performed when that procedure is called by another definition; a command, which consists of tasks to be performed in order to execute a command that a user types in the command dialog box of the editor; a key, which consists of tasks to be performed when a user presses that key while in the E editor; initializations, which consist of variable assignments that must be performed immediately after the editor is invoked; constants, which consist of unchangeable values assigned to identifiers; configuration options, which allow the user to change the basic configuration (colors, cursor size, margins etc.) of the editor. Each definition is composed of statements which implement the procedure or key function being defined. A sample E program is presented below. The comments label and explain the key features, so that you can relate their form to the descriptions above. def a_f2 = /* beginning a definition: defining the A_F2 key */ 'temp' /* --> pressing this key causes the user- defined command temp to be performed */ defc temp /* beginning a definition: defining the temp command */ sayerror "Command TEMP in progress." /* a statement */ junk = machine() /* this statement includes a call to a built-in procedure (i.e. one that comes with the editor, and is not user-defined) */ call mydisplay(junk) /* a call to a user-defined procedure */ defproc mydisplay(machtype) /* beginning a procedure definition: defining a procedure = user-defined proc */ new_line = 'Machine type is: '||machtype /* string concatenation */ insertline new_line, 5 /* this built-in statement adds the contents of variable new_line to the fifth line of the current file */ We will devote a section of this manual to discussing each of the major components of the E language. These components (followed by an example) are: o Scoping (universal) o Variables and identifiers (newline (see above example)) o Arrays (do_array 1, arrayid, myarray) o Expressions and operators (x+1) o String expressions ('foo'||'bar') o Comments (/* like this */) o Line continuations (x=9+8; y=x-9) o Fileid structure (.filename) o Definition primitives (DEF, DEFC, DEFPROC) o Constants (const BLACK=0) o SET definitions (set cursors) o Built-in statements and procedures (insert; x=machine()) o Conditional and loop statements (IF-THEN-ELSE) o The PARSE statement (PARSE arg(1) WITH filename '.' filetype) o Compiler Directives (tryinclude) o Using EPM Command Statements ('E myfile.txt') o Predefined constants and variables (rc) In future sections, the following symbolic conventions will be used to convey points of the language more clearly: Symbol: Meaning: { } Zero or more repetitions of what is inside. [ ] Zero or one of what is inside. A | B Substitution of A or B. var The word var indicates that a variable is required and not an expression. ... More repetitions of the same syntactic pattern Note: For an example of a var variable being required instead of an expression, see the ACTIVATEFILE entry in section Built-in Statements and Procedures. After reading the following sections, users who wish to make extensive customizations to the E macros should rely heavily on the following: o Field Variables Listed; o Built-in Statements and Procedures; o E Language Syntax; o General Structure of E-Macro Files; o Descriptions of Procedures in Standard EPM. Note how these sections are divided. ═══ 1.1. Fileid Structures ═══ The Field Variables Listed section contains field variables that can take assignments or be be referenced. For example: if .messageline <> 14 then .messageline=14 endif The first reference to messageline checks the color of the message line (a referenced field variable). If it is not equal to color 14 (yellow) then it makes the message line color yellow (a field variable assignment). ═══ 1.2. Built-in Statements and Procedures ═══ There are built-in statements and procedures. These are internal in the E code, and therefore cannot be located in any of the .E files. These are listed in the Built-in Statements and Procedures section. For example: asciivalue = ASC('A') insert 'Written by the Yorktown E group',5 The first example is of the ASC() procedure. It will return the value 65 in the variable asciivalue. Only procedures can return values (but don't always have to). Procedures always take parentheses even if no arguments are passed. There cannot be any spaces between the procedure name (in my example ASC) and the left parenthesis, or E will think it is a statement. Statements, however, never take parentheses and don't return values. They can, but don't have to, take arguments. The second example is of the insert statement, shown here with arguments. It would insert on line five the text: Written by the Yorktown E group. ═══ 1.3. Standard Procedures ═══ There are also defproc procedures that have been written in E-code and therefore exist in one of the .E files. These are listed in Descriptions of Procedures in Standard EPM.. They always take parentheses and can return values, just like the built-in procedures. An example is: mymaxnum = MAX(4,5,98,6) This E code will set the variable mymaxnum to 98, the maximum number in the argument list. Again, the left parenthesis is flush with the procedure name. ═══ 1.4. EPM Commands ═══ Commands, defined with the defc and written in E-code can be invoked from the command line dialog box, and are listed in the The EPM User's Guide and the section Commands Omitted From the User's Guide in this manual. These can also be called from within the E language if surrounded by quotation marks. For example: 'bottom' will move the cursor position to the bottom of the file, as if the user had typed bottom from the command line dialog box. ═══ 1.5. Summary ═══ Understanding the differences between these commands, statements, and procedures is critical when programming in the E programming language. When looking for a specific result, remember to look in all these sections to help find a command, statement, or procedure that may accomplish your goal. The procedures defined with defproc and the commands defined with defc are good sources of reference when programming in E. Examining the E-code of procedures or commands can be helpful when trying to accomplish a goal close to an existing procedure or command. Note: E ignores case for procedure, statements, variable, and command names. Capitalizing ASC and MAX in the examples above was done purely by whim. Although the discussion above may be slightly fuzzy to a novice, it should get more clear as the manual progresses. It may help to refer back to these distinctions as the various elements of E are described in detail. ═══ 2. Basic Tools of the E Language ═══ Basic tools of the E language. ═══ 2.1. Comparision with to the REXX Language: Scoping ═══ Anyone familiar with the REXX language will notice that the E language has the same look and feel. The string handling looks the same, and the control structures are similar. You may well ask "Why not use REXX for the editor macro language?" The answer is that there are some important differences, which we will discuss. Unlike REXX, E makes all variables local by default. You can specify that a variable is to be global everywhere, i.e. available to any other procedure, not only to the current caller, by using the universal keyword in the declaration. A simple program will illustrate the scoping differences between REXX and E. REXX SAMPLE PROGRAM /* REXX scoping example */ call starthere starthere: procedure me='the old me' call p1 say me /* says 'the old me' */ exit 0 p1: procedure /* don't expose me here */ call p2 p2: procedure expose me me='the new me' /* try to modify me down here */ return '' E SAMPLE PROGRAM /* E scoping example */ defmain call starthere defproc starthere universal me me='the old me' call p1() say me /* says 'the new me' */ exit 0 defproc p1 call p2() defproc p2 universal me /* make it really global */ me='the new me' return '' For the REXX program to calculate the same results as the E program, procedure p1 would have to expose the me variable. The REXX expose statement requires that the symbol table be known at the time of the call. When a REXX procedure is called, the current symbol table entries are removed except for those entries that are exposed. This means that a symbol table must be maintained at run time. When a variable is referenced, a lookup is performed to see if it is already in the symbol table. If the variable is not in the symbol table a new symbol table entry is created. In the E language, like MODULA-2, C and PASCAL, no symbol table is required at run-time. The absence of variable lookup is one reason why E runs considerably faster than REXX. However, REXX programs are more easily debugged for the same reason. But the order of magnitude of improvement in performance was judged critical for the programming environment. ═══ 2.2. E Variables and Identifiers ═══ Variable declarations are not needed except for universal variables. All other variables are assumed to be local except for a few predefined, universal variables to be discussed in Predefined Constants and Variables. Identifiers have the following syntax: [a-z | A..Z]{a-z | A..Z | 0-9 | _} Identifiers are not case sensitive, and can consist of no more than 28 characters. ═══ 2.2.1. The Contents of Uninitialized Variables ═══ When a variable is referenced for the first time in a REXX program the variable holds the name of itself in upper case (e.g., abc='ABC'). In an E program the value of an uninitialized variable is undefined. This decision was made for the following reasons: 1. No symbol table information is required at run time. A complete symbol table is needed to know when the variable is first defined at run time. 2. Speed. Local variables do not have to be assigned anything except what the user assigns to the variable. Some people prefer the REXX convention because it allows you to type in some operating system commands without using quotes. For example, type profile exec But many operating system commands will still require quotation marks anyway. Requiring quotation marks in all cases reduces confusion. Since uninitialized variables are truly uninitialized (random) in E, strange behavior can occur if a programmer accidentally creates an unintended variable, for instance, by misspellling a statement ('sayeror'). The ET compiler will catch most uninitialized variables at compile time, and report "Variable not initialized". For example, the following will be caught: defc foo= insertline x /* x was never given a value */ This feature will also catch several other previously obscure errors. Omitting the commas between universal variable names: universal a b c /* wrong, should be universal a,b,c */ /* ET reports b as not initialized */ The omission of parentheses after a procedure call: call myproc /* ET will report myproc as not initialized */ And most misspellings that otherwise wouldn't be caught until the line was executed: sayeror 0 Limitation: This will not catch some cases where a variable is referenced twice, or where two variables are combined in an expression: call p(a+b) /* Won't catch uninitialized a. Will catch b. */ for i=i /* These are not caught. */ x=x+1 It should be noted that this feature is a benefit of E's compilation approach. The variable names are tokenized at compile time (unlike REXX), making it easy to tell when a new variable is being created. ═══ 2.3. Arrays in EPM ═══ Arrays are handled like files in a ring. When creating an array, an array id is returned as a "handle" for the array. This array id then can be used to get and put items into the array. Indices do not have to be numeric but instead can be any arbitrary string (like REXX stems). The following shows the format of the DO_ARRAY statement used to create, write to, and read from an array: do_array 1, array_id, myarray This creates an array called MYARRAY and returns its array id in the ARRAY_ID variable. If an array called MYARRAY already exists, then its array id will be returned. do_array 2, array_id, index, value This sets the entry INDEX in the array identified by the ARRAY_ID number to the value specified in VALUE. Both the index and value can contain arbitrary strings. do_array 3, array_id, index, result This will look up the INDEX entry in the array ARRAY_ID and assign the result to the variable RESULT. do_array 4, array_id, index This will delete an entry specified, by INDEX, from the array. do_array 6, array_id, array_name Returns the array_id associated with the array name specified by array_name Due to the common interface, the second and fourth arguments in the DO_ARRAY statement must be variables and not numeric or string constants or expressions. ═══ 2.4. Expressions and Operators ═══ Expressions and operators. ═══ 2.4.1. Operators ═══ + Add expressions - subtract expressions ==, /== exactly equal, not exactly equal forces exact string comparison, taking all spaces and digits as a string. =, <>, <=, >=, <, > These operators ignore leading and trailing spaces on expressions being compared. If both operands are numbers a number comparison is performed; otherwise a string comparison is performed. examples 'hi'='hi ' is true 'hi'=='hi ' is false not, -, + Boolean not, unary minus, unary plus and, &, or, | Boolean and, Boolean and, Boolean or, Boolean or || concatenates two strings *, /, % integer multiply, divide, integer divide // modulus (remainder) operator. 22 // 5 = 2. Note: The percent sign % is to be used for integer division, while the slash / is to be used for floating-point division. ═══ 2.4.2. Operator Precedence ═══ From lower to higher precedence: 1. AND, OR, NOT, &, | 2. >, <, =, ==, /==, <>, <=, >= 3. || 4. +, - 5. *, /, %, // ═══ 2.5. String Expressions ═══ The rules for delimiting strings are shown below: o Double or single quotes may be used. o Two single quotes inside single quotes represent the single quote character. o Two double quotes inside double quotes represent the double quote character. o Strings may not extend across line boundaries. o A backslash can be used to represent awkward characters, in the same style as the C language. \t (without quotes) represents the tab character. On a PC the ASCII value of the tab character is 9, so \9 represents the same thing. Other special characters are \r and \l, which denote carrage return and line feed, repectively. Examples: 'abc'== "abc" ''''=="'" """"=='"' '1'\50==12 /* 50 is ASCII value for the character '2' */ 3+ '1'\50==15 /* everything is a string! */ 3+ '1'||2==42 /* Concat'n has lower precedence than + */ asc(\t)==9 asc(\r)==13 \r\n==''\r\n'' /* Note that \r\n is a single string literal, */ /* generically the same as a single string of */ /* two characters "XY". No concatenation here. */ ═══ 2.5.1. Catenation (Concatenation) ═══ Strings can be joined by catenation using the (con)catenation operator (||). However, the operator can be omitted in most cases. When the operator is omitted, E will place a single blank between the catenated results IF there is at least one space between the operands. As the following examples illustrate, one can completely avoid using the catenation operator. Suppose: v1 = 'abc' v2 = 'xyz' r1 = v1 v2 r2 = v1 'def' r3 = v1'ghi' r4 = v1 'qrs' r5 = v1/* comment */v2 then: r1 == 'abc xyz' r2 == 'abc def' r3 == 'abcghi' r4 == 'abc qrs' r5 == 'abcxyz' ═══ 2.6. Comments ═══ E allows three ways to add comments: 1. placing a semicolon in column one; ; this is a comment 2. surrounding the comment with '/* */'; and /* this is a /* nested */ comment */ /* this is a leading comment */ followed by executable code /* this is a two line comment */ 3. a double-dash at the start of a line comment. this is executable code -- followed by a rest-of-line comment If a semicolon appears in the first column (that's column one, without preceding spaces) the rest of the line is ignored. This style is often handy for quick commenting-out of existing source code. A comment in a REXX-style /* */ enclosure does not cause the remainder of the line (if any) to be ignored. These comments can be nested. A double-dash ("--") causes the remainder of the line to be ignored. This is an easier way to type one-line comments, but does not allow multi-line comments or nesting. ═══ 2.7. Line Continuations ═══ This section was added to explain when statements can be continued across lines. In theory this information was already in the manual - the syntax listing in E Language Syntax shows that a semicolon (which the compiler considers to be the same as a new line) is often acceptable in mid-statement. But this will provide better illustrations. E does not require an explicit statement continuation character as REXX does. It automatically continues to the next line when it "knows" it needs more information, such as after an operator in the middle of an expression. This differs from the REXX treatment. REXX allows line continuations in more cases, but EPM does not require the explicit comma. In REXX you could do this: x = a , b /* REXX result is x = a b */ which concatenates the two strings a and b (implied concatenation). You can achieve a similar (but not identical) effect by supplying an explicit operator to make E aware that there must be more: x = a || /* explicit concatenation operator */ b /* gives x = a||b, no intervening space */ A new line is allowed in all the following cases: 1. After an operator in an expression: x = 1 + 2 2. After a comma in an expression list passed to a procedure: call myproc( 'foobar' , 'axolotl' ) 3. After a comma in declarations of procedure parameters, constants or universal variables: defproc myproc( a , b ) const x = 1, y = 2 universal a , b 4. After a comma in a DEF with a series of keynames: def a_a, a_b, a_c, a_d, a_e 5. Between if and then: if a=1 then b=a else c=a endif 6. And after commas between parameters of several statements - getcommand, setcommand, getfileid, getline, replaceline, insertline, deleteline, and getmark: replaceline 'this is a long new line' , linenumber , fileid As mentioned above, the semicolon can be used to separate statements on the same line. For example: x= 5+3; y= 9-7 will work and place the value of 8 in x and 5 in y Without a semicolon E expects only one statement per line. For example: x= 5+3 y= 9-7 will cause a compilation error of "Variable not initialized" on the y (it attempts to concatenate 3 and y). ═══ 2.8. Fileid Structure ═══ The E editor must store information on each file in its rings. Therefore each file is assigned a unique fileid, which acts as a handle for the file. The fileid is actually a structure composed of many fields, such as .FILENAME, .LINE, .DRAGCOLOR. Each field stores a value which identifies an attribute of the file. By manipulating the values of these fields, macros can get and set information about the files loaded, for example the modify status or the contents of the message line. Because macros need the fileid to set the fileid fields, E provides a GETFILEID statement to obtain the fileid. To access the structure of a file other than the active one, the GETFILEID statement is provided to get an ID or "handle" on a file. GETFILEID var fileid [,filename] If filename is given, a search is performed for it in the EPM rings. A match is considered to be found if the name portion (without drive and path) of a filespec in the ring matches filename. This could be ambiguous if two files of the same name (from different directories) are in the ring; if this is a concern, specify the full filespec, with path, to force an exact match. This feature can also be used to find a temporary file with a unique name, such as '.ALL' or '.DIR'. If a match is found, then the fileid will be a valid integer handle for that file, where fileid >= 0. Otherwise fileid='', a null string. If the filename is not given, then fileid will be a valid handle for the current file, where fileid>=0. Examples: GETFILEID fileid /* Set variable fileid to */ /* correspond to active file */ GETFILEID myid,'AUTOEXEC.BAT' /* Set variable myid to */ /* correspond to file AUTOEXEC.BAT. */ /* If AUTOEXEC.BAT is not already */ /* loaded then myid will be null. */ To assign values to the fileid fields: fileid.field = expression fileid must be an integer handle corresponding to a valid file. field must be one of the field names listed below. For example, to set the current line of the active file to one: getfileid fileid /* get the fileid of the active file */ fileid.line=1 /* set the current line to one */ The alternative syntax is: .field = expression Since no fileid is specified, the current file is assumed. .line=1 /* Make line 1 the current line of the */ /* current file. Note that there is */ /* no need to get a fileid to set a */ /* field of the current (active) file. */ You can blank out any of the EPM information lines off with the following code: .messageline = '' /* erases the message line */ .statusline = '' /* erases the status line */ A list of all the fileid fields and their meaning is presented here. In the following list, remember that x refers to the horizontal axis and y refers to the vertical axis. ═══ 2.8.1. Field Variables Listed ═══ The following is a list of the field (dot) variables and what information they contain: Field Variable Description AUTOSAVE number of changes (0 to 65535) between autosaves; this counts the true number of changes, not just number of lines entered. Changes within a single line are counted as one modification when you leave the line. COL current column position, 1 to 255. CURSORX cursor's x position relative to window origin. CURSORY cursor's y position relative to window origin. DRAGCOLOR is the color of the highlighted area within a drag area. DRAGSTYLE determines the type of mark done when a mouse drag is used to mark text. Valid values are: 0 = don't show drag 1 = show character mark 2 = show block mark 3 = show line mark DRAGTHRESHHOLDX determines how far (in pels) the mouse must be pulled in the x direction with a button down held before EPM recognizes the mouse activity as drag. The default value is zero, which uses the PM system value of SV_CXDBLCLK. -- Warning: DragThreshholdX is not a true file variable because any value assigned to it will apply to ALL files in the ring. -- DRAGTHRESHHOLDY determines how far (in pels) the mouse must be pulled in the y direction with a button down held before EPM recognizes the mouse activity as drag. The default value is zero, which uses the PM system value of SV_CYDBLCLK. -- Warning: DragThreshholdY is not a true file variable because any value assigned to it will apply to ALL files in the ring. -- EAAREA pointer to OS/2 1.2 extended attribute area. FILENAME name of current file. FONTHEIGHT contains the current font height in pixels. FONTWIDTH contains the current font height in pixels. KEYSET the name of the keyset bound to the file, a string like "EDIT_KEYS". LAST the total number of lines in the current file. LINE the line number of the cursor's position, ranging from 0 to LAST. LOCKHANDLE is a Boolean (0 or 1) variable determining whether the current file is locked against other user's access in a LAN situation. MARGINS the margin settings for the file, a string like "1 79 1". MARKCOLOR contains the color for marked text. MESSAGECOLOR contains the message display color. MESSAGELINE contains the contents of the message line. This variable can be assigned a string to force a message onto the message line or read to determine the contents of the current message line. MODIFY 0 or 1, showing whether the text has been modified. MOUSEX the column of the mouse location. This variable is only valid when processing a mouse message. MOUSEY the row of the mouse location. This variable is only valid when processing a mouse message. STATUSCOLOR contains the color of the status line. STATUSLINE contains the template for the status line. For more information about the contents of this variable see The EPM User's Guide. TABS the tab settings for the file, a string like "1 4 7 10" of up to 32 values. The tabs settings is not a single global setting, but is remembered for each file. TEXTCOLOR shows the current textcolor setting. TITLETEXT contains text to be displayed in the title bar when this file is the current file. By default, this field is empty, in which case the .filename field is used. USERSTRING this is a temporary storage string for the E programmer to use for file specific information. VISIBLE contains a one if the file is displayable (ie. not hidden) and a zero if the file is a hidden file. WINDOWHEIGHT contains the height of the current window. WINDOWWIDTH contains the width of the current window. WINDOWX gap between the right edge of the client windows presentation space and the right edge of the client window. WINDOWY gap between the bottom end of the client windows presentation space and the bottom end of the client window. Some fields with numeric values also follow certain constraints about their maximum and minimum values. Some fields are dependent upon other fields. The following chart shows these dependencies and some of the fields' ranges of values. Field name Max value Min value ---------- --------- --------- .AUTOSAVE 65535 0 .COL 255 1 .CURSORX .windowwidth 1 .CURSORY .windowheight 1 .FILENAME a string like 'C:\TESTFILE.DOC' .KEYSET a string like 'EDIT_KEYS' .LINE .last 0 .MARGINS a string like '1 254 1' .MARKCOLOR 255 0 .MESSAGECOLOR 255 0 .MODIFY 65535 0 .STATUSCOLOR 255 0 .TABS a string like '1 4 7 10' or '3' ═══ 2.9. Attribute Pairs ═══ EPM provides one with the ability to associate information with positions and regions of a file without modifying the content of the file. This capability is called attribute support and can be used to provide features like embedded objects, hidden text, bookmarks, hypertext links, and structured text editing. In most editors files/buffers are treated as streams of characters. EPM differs from most editors in that a file/buffer is treated (for display) as a stream of characters and attribute records. Attribute support simply provides an interface for managing files/buffers that contain attribute records. Attribute records themselves are essentially invisible, but because they can be used to pass information to the rendering, live parsing, and formatting components of the editor, a user of the editor can often ascertain the existence and location of some attribute records based on the effect these attribute records have on the rendering of the file/buffer. In order to manage attribute records, it is useful to have a notation system for referencing individual attribute records within a file/buffer. In EPM the notation system is positional-- that is, one points to location of the attribute record when one wants to reference it. In an ordinary text editor one can refer to any position in a file/buffer by specifying a line number and column number. This approach is not adequate for an editor like EPM that has the dual goal of supporting attributes record management and yet minimizing the impact of attribute support on applications/macros that are not attribute-aware. In order to best achieve both goals, EPM has replaced the common line/column coordinate system with a line/column/atoffset based coordinate system. In this system each character of a line occupies a unique column, but individual attribute records are denoted by their attribute offset relative to the next character in the buffer/file. The characters themselves always have an atoffset value of zero, so the atoffset value is often omitted when referring to characters. An attribute record located immediately to the left of a character is said to be located at the same column as that character but at an atoffset of -1. An attribute record immediately to the left of that is said to be at atoffset -2. The following diagram illustrates the notation for various characters and attributes on a line: abcd[A]efg[B][C][D]h[E] [F] │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └ col 11 atoffset -1 │ │ │ │ │ │ │ └ column 9 atoffset -1 │ │ │ │ │ │ └ column 8 (atoffset 0) │ │ │ │ │ └ column 8 atoffset -1 │ │ │ │ └ column 8 atoffset -3 │ │ │ └ column 5 (atoffset 0) │ │ └ column 5 atoffset -1 │ └ column 4 (atoffset 0) └ column 1 (atoffset 0) Note: The text in the example will simply appear as a sequence characters from "a" to "h" because attribute records are invisible. An exception to this might be if the attributes effect the formatting, parsing, or rendering of the text. As you can see in this first example, each of the characters resides at a unique column number and has an implicit atoffset of zero. You can also see all attribute records reside at negative atoffsets and that it is possible for more than one attribute record to reside between any two adjacent characters. In this example, three attribute records reside between the "g" in column 7 and the "h" in column 8. It should be noted that negative column numbers and positive at offset values are invalid. In previous versions of EPM it was possible to have positive atoffsets. This has been changed because it complicates the implementation without providing a satisfactory solution to any problem. It also be noted that overly negative atoffset values have undefined semantics that may vary depending on the operation requested. Most operations will flag an error when overly negative values are specified. ((Footnote: It is recognized by the developers of EPM that people tend to deal with positive numbers better than with negative. For this reason, we'd like to change the notation to be positive and to represent the position of attributes relative to the character to the left. Unfortunately, we are unlikely to find the time to make this change.)) When working with attributes records it is also important to have a notation for the spaces between characters and attribute records. The convention is that each interstitial is reference by the same coordinate as the character or attribute to its right. In the first example, the position on the left side of the "c" character is referred to column 3 atoffset 0. Similarly the interstitial between the C and D attribute records is referred to as column 8 atoffset -1. In addition to positional information, attribute records also contain class, value, and range information. Each attribute record has a class field that is used to categorize the attribute record based on its purpose. For example, one might be a member of a bookmark class or sgml tag class. Certain predetermined classes are supported by the editor: AC_FONT, AC_COLOR, AC_HSPACE. Internal support for additional classes will be added later, and applications can create and support additional classes. This is done by registering a class. The editor provides C and E macro API's for this. In addition to a class field, each attribute record has a four byte "value" field whose interpretation is based on the class field of the attribute record. For example, the value field of an SGML class attribute record might be a pointer to meta information about the SGML element enclosed by the attribute record. The interpretation of the value fields of the internally supported attribute classes are: AC_FONT The value fields of AC_FONT attribute records is interpreted as a font ID. (See pregister_font for further info about font ID's.) AC_HSPACE This attribute records are always interpreted has having point range and their value field is interpreted as the amount of horizontal white space that should be added at this point in the file when rendered. AC_COLOR The value fields of AC_COLOR attribute records is interpreted in the same fashion that the attribute byte of CGA monitors was interpreted. That is, the high nibble is the background color and the low nibble is the foreground color. In the future this class may be broken down into a foreground color class and a background color class so that support can be added for more than 16 colors. In the current implementation the class field is only one byte long. In addition, the classes below 64 are reserved for internal use. This leaves only 192 classes for application use. This is a relatively small domain, so it suggested that applications try to use as few classes as reasonable. For example, if one were to implement a SGML tag set where each tag type was a class, one could easily consume most of the available classes. In a situation like this it is suggested that the application just register a single SGML tag class and make the value field a pointer to a record that describes among other things, the type of SGML tag being represented by the attribute record. Each attribute record has a range field. The range field indicates over what domain the attribute record rules. That is, if the attribute record indicates that text should be colored red, the range value indicates what text should be colored red. There are currently four types of range values supported in EPM: point, set, push, and pop. The "point" range is simply used to remember a location. Attributes with this range might be used as book marks for example. Attribute records with such a range effect no text, they just mark a location. For example if one put a color attribute record with a point range into the document, no text would change color. The "set" range simply indicates that it's attribute record rules over all the text that follows until another set attribute record of the same class is encountered. Attribute records of this class can easily be used to simulate character oriented attribute support much like that seen in most word processors. The "push" range simply indicates that it's attribute record rules over the the text that follows until suspended with another push attribute record of the same class or until a matching "pop" attribute record is encountered. The "pop" range indicates that the text that follows should be ruled by the attribute record (of the same class) that was suspended by "push" attribute record that currently rules the text to the left of this pop attribute record. Together the push and the pop attribute records are ideally suited implement a structured text system or to do GML and SGML like text tagging. The above definitions of push, pop, and set attribute records are a bit ambiguous on what is done if a file contains both push/pop and set attribute records of the same class. In actuality the behavior is undefined. In the current implementation, push and set are actually the same value so the editor can not distinguish between them. In the future this may change in order to enable some optimizations. Therefore one should stick to the AR_PUSH, AR_POP, AR_SET, and AR_POINT constant definitions provided in ATTR.E and ATTRIB.H, and one should not mix push/pop attributes with set attributes of the same class. It is anticipated that when one uses several modules/utilties at the same time, each utility might choose to use a different set a ranges for a given attribute class. No solution to this problem has been adequately worked out at this point, but we don't expect this to be a major problem. Potential solutions might be to register each as being either push/pop or set and point. ═══ 3. Definition Primitives ═══ The E language has a rich collection of primitives. These primitives are the building blocks of E programs since all E statements must occur within a definition construct. Definition primitives define procedures, commands, keys and initializations. Some definition primitives may be considered procedures. When distinguishing between these DEF procedures, one must consider three factors: how many of each type of definition may coexist in one program, when they are executed and what parameters they can be passed. The definition primitives are : o DEFINIT These procedures may be multiply defined. All DEFINIT procedures are executed first upon initialization of the EPM editor, one after another in the order in which they were encountered during compilation. (That's what we mean by "may be multiply defined" - you can have several DEFINIT procedures and they will be executed in sequence as if they were concatenated.) They take no arguments and are typically used to initialize universal variables. o DEFEXIT The converse of DEFINIT. E executes all DEFEXIT procedures last, just before it returns to the operating system. DEFEXIT procedures are also called during unlinking. Like DEFINITs, these procedures may be multiply defined and take no arguments. o DEFMAIN This procedure may be defined only once. DEFMAIN is executed after the DEFINIT procedures are executed. This procedure is typically used to take control of the editor's command dialog box arguments and options before the editor. This can be particularly handy when you want the edit command to take your own arguments or funky file names like "h:profile exec a". The parameters that followed the epm command at the OS/2 prompt can be retrieved by ARG(1), ARG(2), ARG(3), etc. function calls for as many arguments as are passed. The number of arguments can be determined with the ARG() function. This type of retrieval will be discussed in the next section. o DEFPROC This kind of procedure is called by other procedures. It has a much more sophisticated parameter passing capability to make the programming of other procedures easier. Its capabilities include call by reference, call by value and the ability to receive a variable number of arguments. o DEFC This procedure allows the user to define new commands or redefine internal editor commands as well as external commands. The command dialog box arguments may be retrieved by an ARG(1) function call. o DEF This defines the operation of a key. It takes no arguments. o DEFKEYS This is not a procedure and will be talked about in the key definitions section of this document. This primitive allows KEY procedures to be grouped into a keyset. o SET This is not a procedure and will be talked about in the SET definitions section of this document. This primitive is used for setting some of the default configurations of the E editor. o CONST This is not a procedure and will be talked about in the CONST section of this document. This primitive is used for defining constants used by the E translator. Constants do not change during execution of the E procs. o DEFMODIFY DEFMODIFY, DEFLOAD and DEFSELECT are three "events". They are described more fully later in this section. DEFMODIFY is automatically triggered when the file's number of modifications crosses certain threshold values. o DEFLOAD DEFLOAD is invoked whenever a new file is created in the ring. o DEFSELECT This event is automatically triggered whenever you switch files. The procedure definition primitives DEFINIT, DEFMAIN, DEFPROC, DEF and DEFC have no explicit termination keyword. Each definition is ended by the beginning of another DEFxxx. The rest of this chapter will explain each definition primitive in more detail. ═══ 3.1. Parameter Retrieval using ARG(1) ═══ A DEFC or DEFMAIN receives only one argument/parameter: the command string. The command string consists of what was last typed at the command dialog box. The string may contain several words separated by spaces. In the case of DEFC, its sole argument will consist of all the characters typed at the E command dialog box after the name of the command. This argument is not declared as a parameter in the DEFC declaration. The DEFC construct does not allow for any parameter declarations. Instead, the argument can be retrieved via a function call, ARG(1). An example of this usage is: defc test sayerror "arg(1) is " arg(1) The user activates this command by typing test on the E command dialog box. This would result in the following being printed on the message area: arg(1) is . If the user added a parameter when calling test, for example test stuff, then the following string would be printed: arg(1) is stuff. In DEFMAIN, as with a DEFC, the only way to access the argument is to use an ARG(1) function call. DEFMAIN's argument/command string will consist of everything the user typed after the epm command at the OS/2 prompt. For example, assume that the following lines are added to the file MYMAIN.E: defmain sayerror "arg(1) is " arg(1) If the user invokes the editor with the command epm `list *.e', DEFMAIN will print arg(1) is 'list *.e' in the message area. A DEFPROC can receive multiple arguments separated by commas from the primitive that calls it. In a DEFPROC, ARG(1) is only the first parameter. An example of this usage is: defc test2 call test2('actual param 1', 'actual param 2') defproc test2(param1_decl, param2_decl) sayerror "arg(1) is " arg(1) If the user types test2 at the command dialog box, the procedure will print arg(1) is actual param 1. For the exact syntax of the ARG() procedure, please refer to section Built-in Statements and Procedures. ═══ 3.2. DEFINIT ═══ The DEFINIT keyword allows the initialization of variables for use by other E procedures. There is no limit to the number of DEFINIT definitions in an E source file. The order of execution of the DEFINIT definitions is the same as their compilation order. All DEFINIT definitions are executed before the DEFMAIN definition is executed. The general syntax is: DEFINIT {UNIVERSAL variable {,variable} } {statement} ═══ 3.3. DEFEXIT ═══ The DEFEXIT keyword allows for statements to be executed only when leaving the editor or unlinking a module. This is useful for any tasks the user wishes to perform once per session after any and all changes are made to a file. For example, this allows the user to keep files or communication channels open throughout the editing session for speed, and only close then when the user really exits from E. The syntax is the same as that of DEFINIT: DEFEXIT {UNIVERSAL variable {,variable} } {statement} ═══ 3.4. DEFMAIN ═══ The DEFMAIN construct allows the user to take control of the command line arguments, i.e. those arguments and options that the user specifies when invoking the editor at the OS/2 prompt. The command line arguments may be retrieved by an ARG(1) function call. The following example comes from the E editor's DEFMAIN in file MAIN.E: defmain os2cmdline = 'e 'arg(1) The DEFMAIN definition is not required, and if present, it is executed after all DEFINIT definitions. To avoid an undefined state of the editor, a blank file is inserted in the top ring of the editor before DEFMAIN is executed. The general syntax is: DEFMAIN {UNIVERSAL variable {,variable} } statement {statement} ═══ 3.5. Procedure Definitions (DEFPROC) ═══ The DEFPROC primitive is used to define new procedures (functions). The general syntax is: (See E language syntax for precise description). DEFPROC name [( [ [VAR] p1] {, [VAR] p2})] [=] {UNIVERSAL variable {,variable} } statement {statement} [RETURN [expression] ]. where name, p's and v's are valid E identifiers. Procedures can return a string of 255 characters or less. If no string is returned, or if a simple RETURN statement with no value is issued, a null string is automatically returned when the procedure definition ends. The maximum number of DEFPROC arguments is 8. If parameters are specified (like p1 and p2 above) then the function is assumed to require a minimum of that many arguments. For example, if you've defined defproc myproc(x,y,z) but call it elsewhere with call myproc(a,b), you'll get an error when the call occurs (at run-time) "Procedure needs more arguments". But you can pass MORE than the minimum number of arguments. That is, call myproc(a,b,c,d) will work. The number of arguments can be retrieved inside the procedure using arg(). You saw earlier how arg(1) retrieved the first parameter. Similarly, arg(2) retrieves the second parameter and arg(3) retrieves the third, etc. In the above example, the parameters c and d can be retrieved using the calls arg(3) and arg(4), respectively. For an illustration of this technique, see the file SORTE.E. If the keyword VAR prefaces a parameter name in the called procedure's parameter list, then the variable that the caller passes in the corresponding position may be changed (call by reference). If the caller passes a parameter in this position that is not a variable, the E interpreter will detect the error at run time and halt. In example 3, call by reference is demonstrated. If the user types test at the command dialog box, the defc test will call the defproc myproc() which will print: a and b are 1 2. After the procedure returns, defc test will print : a and b are 3 2. Variable b was permanently changed by the assignment in procedure myproc() because it had the var prefix. Variable a's value was unchanged once procedure myproc() returned. If defc test had made the following call: call myproc(a, 5*6), an invalid call by reference message would appear at run time. ═══ 3.5.1. Example 1: ═══ defproc myproc /* Define a new procedure */ return arg() /* Return number of arguments */ /* passed to procedure.*/ def a_l /* Define the key Alt-L */ call myproc() /* Throw away 0 returned by myproc */ Nofargs=myproc('a','b') /* Sets Nofargs to 2 */ ═══ 3.5.2. Example 2: ═══ defproc myproc /* Define a new procedure */ return arg(1) /* Return first argument */ /* passed to procedure.*/ def a_l /* Define the key Alt-L */ call myproc() /* Throw away '' returned by myproc */ Firstarg=myproc('a','b') /* Sets Firstarg to 'a' */ Firstarg=myproc() /* Sets Firstarg to '' */ ═══ 3.5.3. Example 3: ═══ definit universal always_around /* Define a global variable */ always_around=0 /* set global variable to 0*/ defc test a = 3 b = 5 call myproc(a, b) sayerror "a and b are " a b defproc myproc(a,var b) /* Define a new procedure */ universal always_around always_around=1 /* set global variable to 1*/ a=1 /* Change local parameter */ b=2 /* Change callers variable */ i=10 /* Set local variable */ sayerror "a and b are " a b ═══ 3.6. Command Definitions (DEFC) ═══ The DEFC construct is used to define new commands. When a command is issued, E will search for the first word of the command as follows: ═══ 3.6.1. Command search order: ═══ 1. Look for a DEFC command (i.e. one defined in a .E file) 2. Look for an internal editor command (e.g. MARGINS or EDIT) 3. Search the directories in the PATH environment variable for any executable file, as follows: a. a .EXE, .CMD, .EX file in current directory b. a .EXE, .CMD, .EX file in the PATH or EPMPATH directories c. a .EXE, .CMD, .EX file in the same directory as EPM.EXE. Because of the search order, user-defined commands with the same name as built-in commands can override internal editor commands. The XCOM command may be used to force execution of an internal editor command in the case of duplicates. ═══ 3.6.2. Example: ═══ defc edit= /* Redefine the edit command. */ 'xcom edit 'arg(1) /* Pass command through to the editor */ The general syntax is (See E language syntax for precise description): DEFC name {,name} [=] {UNIVERSAL variable {,variable} } statement {statement} [RETURN [expression] ]. where name is a valid E identifier. ═══ 3.7. Key Definitions (DEF and DEFKEYS) ═══ A keyset is a named collection of keys. Typically, this collection defines a particular mode of editing. For example, you might want the keyboard to behave one way in a drawing mode and another way in an editing mode. Therefore, each of these modes would warrant its own keyset. You can have many keysets defined, but only one can be used at any time. The DEFKEYS keyword names the keyset. The KEYS statement activates a keyset. The DEF keyword defines a key or pseudo-key that belongs to the current keyset. Note: Keys may be redefined. If you create a DEF and the same DEF already exists in an earlier place in the compilation, the compiler will not issue an error. It will forget the previous definition. The penalty is that the previous code is not removed (difficult to do in a fast one-pass compiler), so a little memory will be wasted in the E.EX file. For a list of definable keys, see E-Definable Keys. DEF key_name|ch [-ch] {, key_name|ch [-ch]}[=] Define key. ch represents any printable character. A line-break (newline) is allowed after the comma, which can help readability if you're defining many keynames at once. Example: /* Define 27 different keys to do same function, pagedown. */ def 'a'-'z', a_t = pagedown def '#' = 'add' /* define single key for add command */ DEFKEYS name [NEW | BASE | OVERLAY | CLEAR] Define keyset. If the OVERLAY or no option is specified, then the last set of key definitions is copied onto the named set of keys. The named keyset thus starts out with the same keys as the last one. The NEW (or equivalent BASE) option starts a keyset with only the alphabetic, numeric and control characters. The CLEAR option starts an empty keyset. Please refer to section Keysets for more information on the BASE, OVERLAY and CLEAR options. A sample keyset named test_keys is defined below. This example shows the redefinition of the Enter and Space keys: defkeys test_keys def ' '= universal expand_on if expand_on then if e_first_expansion()=0 then keyin ' ' endif else keyin ' ' endif def enter= universal expand_on if insertstate() then insert else call maybe_autosave() if expand_on then if e_second_expansion()=0 then call einsert_line() endif else call einsert_line() endif endif ═══ 3.8. SET Definitions ═══ The E editor has a set of configuration options which may be reconfigured by a SET definition. SET definitions are executed before the DEFINIT procedure definitions are executed. For examples of these configuration options, refer to The EPM User's Guide. It can be seen that there isn't much need for the SET definition primitive since most editor options can be set in DEFINIT and DEFMAIN. (We hope to do away with them in the future, in favor of straightforward commands like 'tabs' and 'margins'.) Most users will care to change only insert_state. ═══ 3.9. Constants ═══ The CONST keyword allows a user to define constants that the E translator remembers during the translation of the E procs. ET substitutes the value whenever it sees the constant name. Constants serve no purpose at run-time. Constants may be redefined to the same value without causing an error or loss of memory space. This is useful if you wish to develop a package for distribution, since you can define the constants you need without worrying about conflict with other files installed by the user. The syntax for defining constants is: CONST c1 = exp1 [,] c2 = exp2 [,] ... example CONST a=3 b=a * 2 ═══ 3.10. DEFMODIFY ═══ The DEFMODIFY event is executed when a file's number of modifications: o goes from zero to nonzero (the first modification - we might want to change the screen color); o goes from nonzero to zero (after a save - we might want to change the screen color back again); o goes from less than .autosave to greater than or equal to .autosave (so we can autosave). See the file MODIFY.E for more details. ═══ 3.11. DEFLOAD ═══ DEFLOAD is invoked whenever a new file is created in the ring, whether loaded from disk or created by 'edit /n' or 'edit /c'. It is invoked at the end of all processing, the last thing before returning control to the user, so as not to be fooled by the file moving around in the ring or being renamed. If a file is loaded from disk and renamed, DEFLOAD gets the right filename. After all new files are defload-processed, the expected current file is restored. Thus the command 'e one two' loads both files, invokes defload on 'one', then on 'two', and finally re-activates 'one'; the user is left looking at the same file as in the old days. This is done internally so the defload procs don't have to worry about restoring fileids. Understand this example: defc rcedit 'edit 'arg(1) if rc=sayerror('New file') then sayerror "It's a new file" endif defload -- this defload procedure need not be close to the defc. sayerror "DEFLOAD for ".filename When you type 'rcedit nosuch', the file nosuch (which doesn't exist on disk) is created in the ring. DEFLOAD is not triggered until after all other procs are done, so RCEDIT runs to completion with the proper RC value. You'll see 'It's a new file' and then 'DEFLOAD for nosuch'. For another example of a DEFLOAD definition statement see sample menu addition. It's not guaranteed that the files will be defload-processed in the same order as they're loaded. They're processed in fileid order. So 'two' might have been processed before 'one' if fileids are reused. The DEFLOAD event is also triggered whenever the name of the file changes. Typically a DEFLOAD will do things like set tabs and margins based on the filetype, so a name change is treated the same as a new load. ═══ 3.12. DEFSELECT ═══ This event is automatically triggered whenever you switch files. To be exact, it is invoked after all other command processing is done, if the then-current file is different from the current file before the command. Thus if a command switches to a temporary file but switches back to the original file before ending, this event will not be triggered. This replaces the clumsy previous method, a procedure select_edit_keys() which had to be explicitly called at the end of any action that might have switched files. But there's not much work to be done in this event because most of the things that used to be done in select_edit_keys() are now done only once at file-load time, in the DEFLOAD event. The keyset, tabs and margins stick with the file from then on. In the standard macros nothing is done in the DEFSELECT. Note: The order of events at start-up is: definit, defmain, defload, defmodify and defselect. The defmodify event would not normally occur at start-up, unless your defmain modified the newly-loaded file. These three events can be multiply defined. You can have multiple procedures under the same name scattered throughout your macro set, and they'll be run in succession. (As DEFINIT procedures have been scattered around the E files in the past.) This helps keep the macros modular - if you're writing an editor application that needs to get control whenever a new file is loaded (the old BOOKMARK application comes to mind), you can write a DEFLOAD within your module without having to alter the base E files. ═══ 4. Statements ═══ Procedures, commands and key definitions are composed of statements. Valid statements in the E language are: Construct: Example: assignment statements temp = 36 built-in statements insertline "Written by the Yorktown E group", 2 conditional statements to be discussed in section Conditional and Loop Statements parse statements to be discussed in section The Parse Statement compiler directive statements to be discussed in section Compiler Directive Statements procedure calls testproc(arg1, arg2) commands to be discussed in section Using EPM Commands in E Statements ═══ 4.1. Built-in Statements and Procedures ═══ In the following syntactic description the same symbolic conventions are used as in The EPM User's Guide section "E Commands". In addition, the word var followed by an argument means that the argument must be a variable, i.e. a number, string or expression is not acceptable. Most of the following statements can be optionally spelled with underscores between the words. Please refer to E Language Syntax for more information. Those commands followed by parentheses are procedures; those not followed by parentheses are statements. Each can be followed by arguments. Only procedures can return values. ═══ 4.1.1. ABBREV(information, info [, length] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.2. ACTIVATEACCELTABLE var fileid ═══ Choose: o Syntax o Definition o E Language Syntax See also: o Building Accelerator Tables from the Macro Language o BUILDACCELTABLE o DELETEACCEL o QUERYACCELSTRING ═══ 4.1.3. ACTIVATEFILE var fileid ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.4. ADJUSTBLOCK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.5. ADJUSTMARK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.6. ARG([numeric_expression]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.7. ASC(character) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.8. ATOI(numeric_expression) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.9. ATOL(numeric_expression) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.10. ATTRIBUTE_ACTION subop, var class, var offset, var column, var line [, var fileid] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.11. BACKTAB ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.12. BACKTABWORD ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.13. BACKWARD ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.14. BEEP([pitch [, duration] ]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.15. BEGINLINE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.16. BOTTOM, BOT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.17. BROWSE( 0 | 1 ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.18. BUFFER( subfunction_number, parameters... ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.19. BUILDACCELTABLE ═══ Choose: o Syntax o Definition o E Language Syntax See also: o Building Accelerator Tables from the Macro Language o ACTIVATEACCELTABLE o DELETEACCEL o QUERYACCELSTRING ═══ 4.1.20. BUILDMENUITEM ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.21. BUILDSUBMENU ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.22. CALL procedurename() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.23. CENTER(string, length [, pad] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.24. CENTRE(string, length [, pad] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.25. CHR(numeric_expression) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.26. CIRCLEIT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.27. COMPARE(string1, string2 [, pad] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.28. COPIES(string, n) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.29. COPYMARK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.30. CURSOR_DIMENSIONS ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.31. DELETE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.32. DELETEACCEL ═══ Choose: o Syntax o Definition o E Language Syntax See also: o Building Accelerator Tables from the Macro Language o ACTIVATEACCELTABLE o BUILDACCELTABLE o QUERYACCELSTRING ═══ 4.1.33. DELETECHAR ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.34. DELETELINE [line_number [,var fileid] ] ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.35. DELETEMARK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.36. DELETEMENU ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.37. DELSTR(string, n [, length] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.38. DELWORD(string, n [, length] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.39. DIRECTORY([path]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.40. DISPLAY '-4' | '-2' | '-1' | '1' | '2' | '4' ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.41. DO ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.42. DO_ARRAY ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.43. DO_OVERLAYWINDOWS ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.44. DOWN ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.45. DYNAFREE(library_name) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.46. DYNALINK(library_name, function_name, parameter_stack, [number_of_return_words]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.47. DYNALINKC(library_name, function_name, parameter_stack, [number_of_return_words]) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.48. ECHO( 'on'|'off' ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.49. ENDLINE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.50. ERASEENDLINE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.51. EXECUTE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.52. EXECUTEKEY key ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.53. EXIT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.54. FILESINRING( [number] ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.55. FILESIZE() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.56. FILLMARK [character] ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.57. FINDFILE destfilename, filename [,environment_path_variable, ('P'|'D') ] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.58. FOR ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.59. GETFILEID ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.60. GETKEYSTATE( virtual_key_code ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.61. GETLINE var line [, line_number [, var fileid] ] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.62. GETMARK var first_line_num,var last_line_num [,var first_col [,var last_col [, var fileid] ] ] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.63. GETMARKG var first_line_num,var last_line_num [,var first_col [,var last_col [, var fileid] ] ] ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.64. GETPMINFO (function ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.65. GETSEARCH var search_cmd ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.66. HEX( character ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.67. IF - THEN - ELSE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.68. INCLUDE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.69. INSERT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.70. INSERT_ATTRIBUTE class, value, isPush, offset [, col [, line [, fileid]]] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.71. INSERTLINE new_line [ ,line_number [,var fileid] ] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.72. INSERTSTATE() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.73. INSERTSTR(new, target [, n [, length [, pad ]]]) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.74. INSERTTOGGLE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.75. ISADIRTYLINE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.76. ITERATE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.77. ITOA(variable, radix) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.78. JOIN ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.79. KEYIN expression ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.80. KEYS name ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.81. LASTERROR() ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.82. LASTKEY([key_number]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.83. LASTPOS (needle, haystack [,startpos]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.84. LEAVE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.85. LEFT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.86. LEFTSTR(string, length [, pad] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.87. LENGTH(expression) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.88. LEXAM( functionname ) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.89. LINK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.90. LINKED ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.91. LONGESTLINE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.92. LOOP ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.93. LOWCASE(expression) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.94. LTOA(variable, radix) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.95. MACHINE() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.96. MAP_POINT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.97. MARKBLOCK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.98. MARKBLOCKG ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.99. MARKCHAR ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.100. MARKCHARG ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.101. MARKLINE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.102. MARKLINEG ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.103. MARKTYPE() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.104. MEMCPYX(destination, source, length) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.105. MOUSE_SETPOINTER type ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.106. MOVEMARK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.107. NEXTFILE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.108. OFFSET(variable) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.109. OFS(variable) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.110. OVERLAY(new, target[, n [, k [,pad] ] ]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.111. OVERLAYBLOCK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.112. PAGEDOWN ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.113. PAGEUP ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.114. PARSE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.115. PEEK(segment, offset, count) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.116. PEEKZ(segment, offset) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.117. POKE segment, offset, string ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.118. POS needle,haystack[,start] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.119. PREVFILE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.120. QPRINT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.121. QUERYACCELSTRING ═══ Choose: o Syntax o Definition o Example o E Language Syntax See also: o Building Accelerator Tables from the Macro Language o QUERYACCELSTRING o BUILDACCELTABLE o DELETEACCEL ═══ 4.1.122. QUERY_ATTRIBUTE var class, var value, var ispush, offset, column, line [, fileid] ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.123. QUERYFONT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.124. QUERYMENUSTRING(menuname, id) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.125. QUERYPROFILE(application, key_name) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.126. QUIETSHELL string_expression ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.127. REFLOW ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.128. REFRESH ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.129. REGISTERFONT ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.130. RELINK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.131. REPEATFIND ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.132. REPLACELINE new_line [ ,line_number [,var fileid] ] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.133. RETURN [expression] ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.134. REVERSE(string) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.135. RIGHT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.136. RIGHTSTR(string, length [, pad] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.137. RUBOUT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.138. SAYAT string, row, column, attribute [,length][,window] ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.139. SAYERROR expression ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.140. SAYERROR(error_string) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.141. SAYERRORTEXT(rc) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.142. SCREENHEIGHT() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.143. SCREENWIDTH() ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.144. SEG(variable) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.145. SELECTOR(variable) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.146. SETMARK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.147. SETPROFILE(application, key_name, data) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.148. SETSEARCH var search_cmd ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.149. SHIFTLEFT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.150. SHIFTRIGHT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.151. SHOWMENU ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.152. SPLIT ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.153. STOP ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.154. STOPONRC ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.155. STRIP(string [,option] [,char]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.156. SUBSTR(string,n [,k [,pad] ]) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.157. SUBWORD(string, n [, length] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.158. TAB ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.159. TABWORD ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.160. TEXTLINE(line_num) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.161. TOP ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.162. TRANSLATE(string [, tableo [, tablei [ pad ]]] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.163. TRYINCLUDE filename ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.164. UNDO ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.165. UNDOACTION ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.166. UNLINK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.167. UNMARK ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.168. UP ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.169. UPCASE(expression) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.170. VER([option]) ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.171. VERIFY(string, reference [,options [,start] ] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.172. WHILE ═══ Choose: o Syntax o Definition o E Language Syntax ═══ 4.1.173. WINDOWMESSAGE ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.174. WINMESSAGEBOX ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.175. WORD(string, n) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.176. WORDINDEX(string, n) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.177. WORDLENGTH(string, n) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.178. WORDPOS(needle, haystack [, start] ) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.1.179. WORDS(string) ═══ Choose: o Syntax o Definition o Example o E Language Syntax ═══ 4.2. Conditional and Loop Statements ═══ The IF statement is used to change the flow of statements depending upon some condition. As you can see, the syntax varies from that of REXX: IF Conditional execution IF expression THEN statements {ELSEIF expression THEN statements} [ELSE statements] ENDIF Note: Any nonzero, non-null value for expression is regarded as TRUE. The value zero is FALSE, and (as of version 3.07) a null value is FALSE. The null-value treatment is important because that's the default value returned by a DEFPROC. If a DEFPROC simply "runs off the end" and does not have an explicit RETURN statement, ET automatically assigns a null return value. For example: defproc tinyproc= x = 1 /* no return statement */ defc test= myswitch = tinyproc() if myswitch then sayerror 'null is true' else sayerror 'null is false' endif Previous versions of E would have printed null is true because the value of myswitch was not precisely zero ('0'). It makes more sense for no-value to be false. But it's still better practice to specify the return value explicitly in your procs. Several ways are provided to structure a repetitive loop: WHILE - DO Conditional loop WHILE expression DO statements ENDWHILE DO - WHILE Same effect as WHILE - DO DO WHILE expression statements END or ENDDO DO FOREVER Continuous loop (See LEAVE, below) DO FOREVER /* clearer meaning than WHILE 1 */ statements /* Exit with a RETURN or LEAVE */ END or ENDDO LOOP Same effect as DO FOREVER LOOP /* equivalent to the previous one */ statements ENDLOOP FOR Stepwise Iteration FOR i=expression TO expression [BY expression] statements ENDFOR DO (FOR) Same effect as FOR DO i=expression TO expression [BY expression] statements END or ENDDO LEAVE Exits LOOP, WHILE or DO. Execution resumes after ENDLOOP, ENDWHILE or END. ITERATE Iterates LOOP, WHILE or DO. Execution resumes at LOOP, WHILE or DO. Note: It is possible to modify the loop index within the FOR loop. For example, the following is correct: for i= 1 to 10 if i=7 then i= i - 1 -- i = 6 endif endfor ═══ 4.3. The Parse Statement ═══ Use the PARSE statement to extract information from a string. The syntax is: PARSE ARG template PARSE VALUE expression WITH template where expression is the input, i.e. the string to parse, and template is a list of symbols separated by blanks, which dictates how to parse the input. The syntax of template is { '.' | string | +number | -number |number | variable | '(' variable ')' } The only difference between the two forms of the parse statement is that the PARSE ARG statement is a special case of the PARSE - VALUE - WITH statement. The PARSE ARG statement automatically assumes ARG(1) to be its input. Therefore, the following two statements are logically equivalent: PARSE ARG A B C D PARSE VALUE arg(1) WITH A B C D The template in the above example is A B C D. A template in general specifies the names of variables that are to be given new values, together with optional triggers (either strings or special characters) to control the parsing. In the example, A, B, C and D are all variables to which new values will be assigned; there are no triggers. Normally each variable in the template is assigned one word from the input string. The last variable, however, is assigned the remainder of the string (if any). If there are fewer words in the string than variables in the template, all excess variables are set to null. A null, therefore, indicates the end of data. For example, if the string 'The Red Baron' is parsed with the template A B C D, then the first three variables would each be assigned one word from the string, in sequence, and the variable D would be set to ' '. If the template were changed to A B and the input string remained the same, then the variable A would be set to 'The' and the variable B would be set to 'Red Baron'. The parsing algorithm also allows some pattern matching, in which you may trigger on strings. If the template contains a string (such as a '/' or 'TO' ), then synchronization will occur at the next point where the trigger matches the data. This is best explained with the aid of examples: Input data: EDIT AUTOEXEC.BAT /D Template: X Fn '/'Opt Variables set: X = 'EDIT' Fn = 'AUTOEXEC.BAT' Opt = 'D' The value of a variable may be used as a trigger, by enclosing the name of the variable in parentheses. It then acts in exactly the same way as a literal string trigger. For example: delim=',' parse value 'abc, def' with x (delim) y /* splits the string */ This feature allows you to parse when you don't know what the trigger string (delim in the example) is in advance. Without the parentheses, the variable delim would receive the value 'def'. You may also use numbers as triggers to pick out positional substrings, or to extract a string of a certain length. These may be absolute column numbers, or numbers relative to the last trigger (or column) specified. Input string: This is the time for all good men Template: 8 X +4 16 Y +5 Variables set: X = ' the' /* four starting at column 8 */ Y = 'e for' /* five starting at column 16 */ In this case, a +n following the variable indicates that the string to be picked out should begin at the last column specified and should continue n characters to the right. The '-' unary operator cannot be used in this manner. However, both unary plus and minus can also be used in the template to advance the current column position. For example, Input string: This is the time for all good men Template: 10 't' X +4 +5 Y -4 Z Variables set: X = 'time' Y = 'all good men' Z = 'for all good men' Notice that in this example, the current position is moved to the 10th column, and then to the next instance of 't' (which is the 't' in 'time'). X is assigned a string of length 4 beginning from this point. The current position is then moved 5 positions to the right. The Y variable is assigned a string beginning at this point and continuing to the end of the string. The cursor position is then moved back (to the left) 4 positions and the Z variable gets a string from that position to the end of the string. Further examples: Input string: MSG WINPA(FRED) Hello Fred Template: X node'('userid')' msg Variables set: X = 'MSG' NODE = 'WINPA' USERID = 'FRED' MSG = ' Hello Fred' Input string: /foo/bar zot/ Template: delim 2 word1 (delim) word2 (delim) Variables set: delim = '/' word1 = 'foo' word2 = 'bar zot' Note that each substring (between triggers) is parsed in the same manner as a complete string would be if there were no triggers present. You can also use a period (.) as a place holder to skip over a word that would otherwise be placed in a variable. For example: Input string: 'The Red Baron' Template: word1 . word2 Variables set: word1 = 'The' word2 = 'Baron' ═══ 4.4. Compiler Directive Statements ═══ The following statements are different from other E statements because they serve no function when the program is being run, rather they provide instructions to the ET compiler. ═══ 4.5. compiler directives ═══ The compiler directive statements are: Includes INCLUDE 'filespec' TRYINCLUDE 'filespec' Conditional compilation COMPILE IF constant_expression statements { COMPILE ELSEIF constant_expression statements } [ COMPILE ELSE statements ] COMPILE ENDIF ═══ 4.5.1. Include Statements ═══ The usage and usefulness of INCLUDE statements is shown in The EPM User's Guide. In this section, we will discuss how these statements work. Let's say that there is an INCLUDE statement (INCLUDE 'filespec') in a file test.e. The statement directs the compiler (ET) to replace the INCLUDE statement with the E code found in the file named in filespec. The contents of file filespec are inserted into file test.e. If file filespec does not exist, compilation is aborted. The TRYINCLUDE statement has the same syntax as an INCLUDE file, i.e. filespec must be enclosed with quotes. It also behaves the same way as an INCLUDE statement: the specified file is included into the file where the INCLUDE statement appears. However, when a TRYINCLUDE statement is used, the compiler tries to include the file. If it is unsuccessful, compilation does not halt. For example, consider the following excerpt from a file: tryinclude 'test1.e' tryinclude 'test2.e' include 'test3.e' If the file test1.e does not exist, the compiler will simply go on to the next statement without notifying the user. Next it will try to include file test2.e. However, if file test3.e does not exist, the compiler will issue an error message and stop compilation. ═══ 4.5.2. Conditional Compilation ═══ In the past few releases of E we've tried to simplify configuration and updates. We've rearranged the standard E files to bring together all the usual configuration options (in STDCNF.E and COLORS.E) and all the INCLUDEs (into E.E). Ideally the user should be able to customize E with simple one-line changes. The available configuration techniques have been: o setting a universal variable, for example matchtab_on=0. This is fine for simple options but can be expensive for large features. The macros must contain the code for all possible values of the variable since the value can change at run-time. Even though you might never use the matchtab feature, memory space is used for the possibility. o setting a constant, like TEMP_PATH='C:\'. Constants have been good only for minor configuration options which don't change after installation, such as drive letters and directories. They're also useful for mnemonic names like GREEN=2 to make macros more readable. o using INCLUDE and TRYINCLUDE statements, such as tryinclude 'math.e', to ease the installation of large optional features if the features are cleanly separable into independent files. After the compilation is done, the INCLUDE statements have no effect and occupy no memory. Another tool, conditional compilation includes features which aren't cleanly separable into files. Programmers experienced with the C language will be familiar with this concept (as #if). Other users might be uncomfortable with the distinction between compile-time and run-time processing. Let's take a small feature as an illustration - imagine that whenever you press F4 (File) you don't want the file saved if it hasn't been modified. If you were a power user who wanted this feature, you had to modify STDCMDS.E as follows: defc f,file= if .modify=0 then /* my mod: don't file if not modified */ 'quit' endif /* rest of code as before */ The trouble with modifying the standard commands like this is that you had to repeat the modification on every new release of E. To ease your updates you might have tried to convince us developers to include the feature in the standard distribution version. But we've been reluctant to do this because every user would be forced to use the same feature, or at least to sacrifice memory space to it (if we turn it on/off with a variable assignment). But now it's possible to write: const FILE_ONLY_IF_MODIFIED = 1 defc f,file= compile if FILE_ONLY_IF_MODIFIED if .modify=0 then 'quit' endif compile endif /* rest of code as before */ When the compiler sees the compile if it will check the value of the constant FILE_ONLY_IF_MODIFIED, and, seeing that it's true, will compile the new code just as it did when you hand-modified it. But now the feature is easier to distribute to all users. A user who doesn't like it can set FILE_ONLY_IF_MODIFIED = 0, which will cause ET to ignore the code enclosed between compile if and compile endif. This happens at compile time, in much the same manner as a TRYINCLUDE, so the other user is not penalized memory space for the choice. We encourage developers of add-on packages to use this feature. In time we hope to make the most popular add-ons installable without the user having to touch the macro source code. The new keywords all start with the word compile: o COMPILE IF const_expression o COMPILE ELSE o COMPILE ELSEIF const_expression o COMPILE ENDIF const_expression must be a simple expression combining only constants known at compile time. Understand that ET cannot know the values that will be assigned to variables at run-time (like matchtab_on). If we assume that all uppercase identifiers represent pre-defined constants, the following are valid const_expressions: COMPILE IF 0 /* Means 'never compile'. */ COMPILE IF FOO + BAR >= 2 COMPILE IF EVERSION = '3.07' COMPILE IF STATUSCOLOR = NORMAL COMPILE IF not (OS2 or DOS) Note: simple arithmetic and logical expressions are possible, but not string functions such as substr(). Any strings in the constant expression associated with a COMPILE IF statement are converted to upper case. This means that many of the values for configuration options in the STDCNF.E file may now be entered in any combination of lower and upper case letters. For example, the following statement is now valid: HOST_SUPPORT = 'pdq' even though STDCNF.E contains the following statement: COMPILE IF HOST_SUPPORT = 'PDQ' HAVE_DOS = 0 COMPILE ENDIF Since the string constant `pdq' will be converted to `PDQ' at compile-time, the compile-if condition will be found to be true. There must be one COMPILE ENDIF to each COMPILE IF, zero or one COMPILE ELSE's, and zero or more COMPILE ELSEIF's. The ELSE must come after all ELSEIF's, as in normal E if-else-endif structures. These conditional blocks can be nested (in the same manner as if-else-endif structures) up to a maximum depth of 20 levels. Here's an example of how we might include different methods of host-file support: compile if HOST_SUPPORT = 'STD' include 'saveload.e' -- with host support compile elseif HOST_SUPPORT = 'EMUL' include 'e3emul.e' -- Brian Tucker's add-on package compile else include 'slnohost.e' -- without host support compile endif The COMPILE keyword can be inserted anywhere a newline is allowed, including cases where a newline serves as a line continuation in the middle of a statement. delay = 2000 / compile if OS2 10 /* delay = 200 here */ compile else 1 /* delay = 2000 here */ compile endif See the section Line Continuations for other examples. ═══ 4.5.3. Compiler Directives as Definition Primitives ═══ The compiler directives discussed in this section are valid E statements, i.e. they can be contained within a DEFPROC, DEFC, or other definition. However, compiler directives can also be considered definition primitives depending upon what they contain. Consider the following example: file junk.e contains: sayerror "print junk" x = x + 5 file main_junk.e contains: DEFPROC junk() universal x x = 8 include 'junk.e' temp = 250 After execution of the procedure junk(), the value of x is 13. In this case, the included file (junk.e) contains only statements, and therefore the INCLUDE statement acts as a statement. However, consider the next example: file junk.e contains: DEFPROC junk() sayerror "printing junk" file main_junk.e contains: SET insert_state 0 DEFC com1 = call junk() CONST a = 25 include 'junk.e' If the included file (junk.e) contained only statements, as in the last example, the ET compiler would issue the following error: "Expecting DEFinition primitive". Because the INCLUDE statement is no longer contained within a definition primitive, the included file must contain a definition primitive, as it does in this example. In this case, the INCLUDE statement is not really acting as a statement; it is acting as a definition primitive. The same can be said of the conditional compile statement: it can occur within a definition primitive and enclose only statements or it can occur outside a primitive and enclose one or more definition primitives. The following examples show various correct usages: CONST flag1 = 1 DEFPROC fred() universal perm perm = 8 compile if flag1 = 1 perm = perm + 5 compile endif sayerror "perm is " perm /************** Second example ****************/ CONST USERS_CHOICE = 0 compile if USERS_CHOICE DEFC optional_command = sayerror "just printing junk for testing" compile endif DEFPROC test() sayerror "stuff" In the first example, if flag1 is set to 1, then the value of perm becomes 13. If flag1 is set to 0, then the value of perm is 8. In either case, the value is printed out with the sayerror statement. In the second example, if USERS_CHOICE is set to 1, the optional_command is included in the code; otherwise it is not, and at run-time (when you are running the editor), the command optional_command does not exist, and will not be recognized. ═══ 4.6. Using EPM Commands in E Statements ═══ The E commands that were discussed in The EPM User's Guide can be used not only on the command dialog box, but also in E programs. When the name of a command and its options and parameters are enclosed in quotes (single or double), the command can be used in place of a statement. The syntax of these commands is the same as that which was presented in the User's Guide. An example of this usage follows: defproc zap_file() k = entrybox("Confirm",'/Yes/No/','Really quit?',18,0) if k then sayerror("Data has been cruelly obliterated ...") 'quit' /* <-- Note the quit command in quotes */ else sayerror("File has been mercifully spared ...") endif When the zap_file() procedure is activated, it will prompt the user. If the user picks 'Yes', it will quit the file; if he picks 'No' the user can continue editing. Another common usage is when redefining key strokes. For example: def c_2 'togglecontrol 9 ' 'togglecontrol 10' This will define the key ctrl-2 to toggle the scroll bars on or off. Other examples can be seen in section Sample E Procs. Any command can be used as a statement. The command need not be a built-in command; it can be a command defined by a user using a DEFC. For example: defc temp call temp() defproc temp() 'testA stuff' defc testA sayerror "argument is " arg(1) Issuing the command temp will print argument is stuff. ═══ 4.6.1. Commands Omitted From the User's Guide ═══ Most of the standard commands (defc constructions) are listed in The EPM User's Guide. However, a few were omitted because they produce no useful results by themselves, but are only really useful in a programming context or because they may not be understood by a novice. These advanced commands are: Command Description ACTIVATEFILEID fileid activates the file specified by the file handle fileid. AMU_ADDENDA_ADDITION word adds the word specified by word to the addenda file specified the variable ADDENDA_FILENAME. AMU_ADDENDA_PICKUP adds the addenda dictionary specified by the variable ADDENDA_FILENAME to the standard dictionary. CLEARSHARBUFF clears the shared PM buffer. COMMANDLINE [ text ] brings up the command line dialog box. This is the equivalent of the standard ESC key definition. This command optionally takes an argument of text or a string variable. If the argument is included, it will be placed on the command line. COPY2DMBUFF copies the marked area to the "Delete Mark" buffer. COPY2SHARBUFF copies a marked area to the shared buffer. CURSOROFF turns the cursor off. This command is equivalent to a: `TOGGLECONTROL 14 0' To turn the cursor back on again, issue a TOGGLECONTROL command with a 1 instead of a zero as the second argument. DUPMARK typemark takes an argument (typemark) of: M = move marked text C = copy marked text O = overlay marked text U = unmark marked text D = delete marked text and executes that action on the marked text. EPM will look first in the local buffer and then in the shared buffer for marked text. GETDMBUFF gets text from the Delete Mark buffer. GETSHARBUFF gets text from EPM shared buffer. LOADDEFAULTMENU loads the default menu setup. MH_BEGIN_MARK mouse handler's begin mark. This is executed when the standard mouse setup begins a drag. See MOUSE.E and Configuring the Mouse. for more information. MH_CANCEL_MARK mouse handler's cancel mark. This is executed when the standard mouse setup double clicks on button one. See MOUSE.E and Configuring the Mouse for more information. MH_END_MARK mouse handler's end mark. This is executed when the standard mouse setup ends a drag. See MOUSE.E and Configuring the Mouse for more information. MH_GOTOPOSITION moves the cursor to the current mouse pointer location. This is like the standard mouse of a single button one click. See MOUSE.E and Configuring the Mouse for more information. ═══ 4.7. Predefined Constants and Variables ═══ There are several predefined UNIVERSAL variables which may be accessed in any definition without an explicit UNIVERSAL declaration: o RC, o join_after_wrap, o center_search, o exit_after_last_file, and o two_spaces. RC holds the error code from the last-executed command. All commands, for example 'edit', 'quit', and 'file', set the value of RC. If no error occurs, RC will be reset to zero by a command. Upon entering a DEFC, the value of RC depends upon the source of the command invocation. If another definition (internal to the E program) activates the command, RC is set to zero. If a user issues the command from the command dialog box, RC is set to the position of the cursor in the command dialog box. However, statements and procedures, such as 'nextfile', 'copymark', or 'top', do NOT normally set RC. If no error occurs, whatever value RC had before the statement is still there. This approach was followed for considerations of speed, space, and to allow an earlier command's RC to "filter down" to the end of the proc. Commands are the ones most likely to encounter meaningful errors. Thus if you want a sure error-check on a statement, zero RC first: rc = 0 copymark if rc then /* complain */ endif One special case: REPEATFIND is a statement but it sets RC to zero if the find is successful. An assignment to one of the function key text variables changes the value of the function key text displayed at the bottom of the screen. There is also one predefined constant called ARGSEP. Since the argument option separator can change from machine to machine, this constant is used to keep the E procs portable. On a PC, ARGSEP is the slash '/'. On a RT, it's the hyphen '-'. JOIN_AFTER_WRAP, CENTER_SEARCH and other configurable constants are discussed in The EPM User's Guide. ═══ 5. Sample E Procs ═══ Using the E language, the user can configure the editor and define complex macros for increased editing power. The E language is translated by the 'etpm' compiler to increase the speed of execution. The syntax of the ETPM compiler is: ETPM filespec[.E] [destfile[.EX]] The default extension of the source code is .E. If no destination file is specified, ETPM will use the same source file name and just attach an .EX extention. Typically, only the filespec is given. These source modules are referred to as E Procs. Two examples of an E Procs are shown below. ═══ 5.1. Example One ═══ The first E Proc is a simple procedure to define a command to display the different mouse pointers available. Edit a file (say TESTFILE.E). Then type in the following code: defc firsttime -- Define a initialization procedure universal pointertype -- Make available to both procedures pointertype = 1 /* Initialize pointertype (same as pointertype = '1') */ mouse_setpointer pointertype -- Set the mouse pointer type sayerror "Completed first time." -- Message so you know it worked defc more -- Define a subsequent procedure universal pointertype -- Make E know pointertype is global pointertype = pointertype + 1 -- Increment pointer type mouse_setpointer pointertype -- Set the mouse pointer type sayerror "Completed subsequent time. Cusor number: "||pointertype -- Message so you know it worked Then enter RELINK from the commandline dialog box. This will save, compile, and link this code (provided, of course, that there were no typos and the code compiled successfully). The commands FIRSTTIME and MORE are now defined. From the command line dialog box, type FIRSTTIME. Mouse pointer 1 is an arrow so you won't notice a change in the pointer but will see the message Completed first time. Now enter the MORE command. This should change the mouse pointer type. You can continue changing the mouse pointer (upto 15 times) by entering the MORE command. Entering FIRSTTIME again will start you at mouse pointer one again. Note how the variable pointertype is declared universal so it can carry a value between procedures. Since strings and numbers are interchangeable, we could have initialized pointertype with a string instead of a numeric constant. ═══ 5.2. Example Two ═══ The second E Proc shows how key set definitions can be programmed. This E Proc will configure a few keys of the editor to mimic the EMACS editor. /**********************************************************************/ /* This E Proc will configure a few keys in the E editor to perform */ /* the same operations as the EMACS editor. */ /**********************************************************************/ defkeys mykeys def F3 = 'quit' /* define a key for fast exit. */ def C_A = beginline def C_B = left def C_D = deletechar def C_E = endline def C_F = right def C_N = down def C_P = up def C_X = choice = listbox("/Quit/Save/") if (choice='Quit') then 'quit' endif if (choice='Save') then 'save' endif If we have a file called EMACS.E which contains the above E Procs, this file would then be translated by the E translator with the following command from the command dialog: etpm emacs To load this file (assuming it compiled correctly) we could type from the command line dialog box: link emacs This will load EMACS into the currently running version of EPM. To have this file automatically included we could add the line: include "emacs.e" in the file MYKEYS.E. When we recompile EPM (see The EPM User's Guide for information on recompiling your editor from the OS/2 prompt) the EMACS key definition will always be available by issuing the following from the command dialog: keys mykeys ═══ 6. Advanced Configuration ═══ The fact that you are reading this means that you probably want to configure EPM beyond that which can be done merely by setting constants. In this section are listed a few advanced configuration options that involve some programming. ═══ 6.1. Building Accelerator Tables from the Macro Language ═══ A Named Accelerator Table is the way true PM accelerators are created from the E macro language. This is achieved using the BuildAccelTable, and the ActivateAccelTable statements. First, the BuildAccelTable statement is used to create, and add keys to, a named accelerator table. (The first time BuildAccelTable is called the table is automatically created.) During this process a data base is created linking accelerator keys to command ids, and command ids to user strings. When a named accelerator table is activated, it becomes a true PM accelerator table. This is done via the ActivateAccelTable statement. Now, when a pre-registered key is pressed, the corresponding command id is issued as part of the message parameter of a PM - WM_COMMAND message. In the E macro world, the defc PROCESSMENU is executed whenever a WM_COMMAND message is received. ARG(1) of PROCESSMENU contains the command-id corresponding to the event that just took place. If an accelerator key was the cause of the PROCESSMENU command, ARG(1) will be the command-id registered during the corresponding BuildAccelTable statement. During the PROCESSMENU command, it is sometimes useful to take the command-id (passed as arg(1)) and look up the corresponding user string. This is done using the QueryAccelString function. Accelerator tables created with the BuildAccelTable statement can be deleted with the DeleteAccel statement. BY DEFAULT, named accelerator tables are deleted when the corresponding edit window is closed. ═══ 6.1.1. BUILDACCELTABLE ═══ The buildacceltable statement adds a key to a named accelerator table. If it is the first key added, the named table is automatically created. Once a table is built, the ActivateAccelTable statement can be issued to make the named accelerator table into an true, active PM Accelerator table. The syntax for the buildacceltable statement is: buildacceltable table-name, user-string, key-style, key, command-id table-name where 'table-name' is a text string containing the name of your particular accelerator table. (MAX. = 80 characters) user-string where 'user-string' is an information string that can be retrieved using the QueryAccelString function. key-style where 'key-style' describes the style of the accelerator key. The value must be one of the PM defined AF_xxx flags defined in PMWIN.H. (i.e. AF_VIRTUALKEY) key where 'key' is a key constant, (i.e. VK_F1) command-id where 'command-id' is a unique number within this particular accelerator table to define the key in question. (1-MAXINT) ═══ 6.1.2. ACTIVATEACCELTABLE ═══ The activateacceltable statement activates a named Accelerator table created with BuildAccelTable. When a named accelerator table is activated, it becomes a true PM accelerator table. The syntax for the activateacceltable statement is: activateacceltable table-name table-name where 'table-name' is a text string containing the name of your particular accelerator table. (MAX. = 80 characters) ═══ 6.1.3. QUERYACCELSTRING ═══ The queryaccelstring statement allows the retrival of the user-string which was registered with the BuildAccelTable statement. The syntax for the queryaccelstring statement is: queryaccelstring table-name, command-id table-name where 'table-name' is a text string containing the name of your particular accelerator table. (MAX. = 80 characters) command-id where 'command-id' is a unique number within this particular accelerator table to define the key in question. (1-MAXINT) ═══ 6.1.4. DELETEACCEL ═══ The deleteaccel statement deletes a named Accelerator table created with BuildAccelTable. BY DEFAULT, named accelerator tables are deleted when the corresponding edit window is closed. The syntax for the deleteaccel statement is: deleteaccel table-name table-name where 'table-name' is a text string containing the name of your particular accelerator table. (MAX. = 80 characters) ═══ 6.1.5. An example that uses the Named Accelerator statements ═══ -- constants needed for Accelerator example. -- key constants const VK_F2 = 33 -- Taken from PMWIN.H VK_F3 = 34 VK_F4 = 35 VK_F5 = 36 -- key style constants AF_CHAR = 1 -- Taken from PMWIN.H AF_VIRTUALKEY = 2 AF_SCANCODE = 4 AF_SHIFT = 8 AF_CONTROL = 16 AF_ALT = 32 AF_LONEKEY = 64 AF_SYSCOMMAND = 256 AF_HELP = 512 -- Creates Two named accel tables, and activates the "default" table defc loadaccel universal activeaccel activeaccel='default' otheraccel ='other' -- Register F2 and F3 as accelerator keys buildacceltable activeaccel, 'john', AF_VIRTUALKEY, VK_F2, 1000 buildacceltable activeaccel, 'thomas',AF_VIRTUALKEY, VK_F3, 1001 -- Register F4 and F5 as accelerator keys buildacceltable otheraccel, 'jason', AF_VIRTUALKEY, VK_F4, 1002 buildacceltable otheraccel, 'larry', AF_VIRTUALKEY, VK_F5, 1003 -- Make the "default" named accel table active. Now F2 and F3 -- are real accel keys, when they are selected they will cause -- "processmenu" to be executed with id's of 1000 or 1001 activateacceltable activeaccel -- In the E macro world, the defc PROCESSMENU is executed whenever -- a WM_COMMAND message is received. ARG(1) of PROCESSMENU contains -- the command-id corresponding to the event that just took place. -- If an accelerator key was the cause of the PROCESSMENU command, -- ARG(1) will be the command-id registered during the corresponding -- BuildAccelTable statement. -- If a pull-down menu was selected then ARG(1) will be the command-id -- registered during the corresponding BUILDMENUITEM statement. defc processmenu universal activemenu, activeaccel -- arg(1) contains the command id specified as registered with -- either the BUILDMENUITEM, or BUILDACCELTABLE statements. cmdid = arg(1) -- First check if a usersting exists for this command-id in the -- active accel table. accelstr=queryaccelstring(activeaccel, cmdid) sayerror "querystring=<"accelstr"> cmdid=<"cmdid">" -- "flip-flop" active accel tables just for fun! if accelstr="thomas" then activeaccel="other" activateacceltable activeaccel endif if accelstr="jason" then activeaccel='default' activateacceltable activeaccel endif -- if an accel string was not found, try the menu manager. if accelstr="" then strip(querymenustring(activemenu,cmdid),"T",\0) -- execute user string after stripping off null terminating char endif ═══ 6.2. Building Menus from the Macro Language ═══ EPM allows user configurable pull down menus. The menus are created from the macro language using a set of macro procedures: BuildSubMenu Adds an entry to the action bar. BuildMenuItem Adds an entry to an action bar submenu. ShowMenu Activates an action bar . DeleteMenu Deletes an action bar, submenu, or menu item. QueryMenuString Returns the command associated with a menu item. ═══ 6.2.1. Buildsubmenu ═══ The buildsubmenu command creates an option on the action bar. If the option name already exists, then the command is appended to the existing option menu as a sub menu option. Although the menu is built internally, it is not seen until a 'showmenu' is issued. The syntax for a buildsubmenu command is: buildsubmenu menu_name, subid, text, cmd, mis_style, mia_attr menuname where 'menuname' is a text string containing the name of your particular menu. (MAX. = 80 characters) subid where 'subid' is a unique number within this particular menu to define that sub-menu in question. (1-MAXINT) text where 'text' is a string of text which is to appear in as the title of that particular sub-menu. cmd where 'cmd' is the editor defc that is to be executed when the submenu is selected. If the submenu has associated items then the defc is not executed. mis_style where 'mis_style' is a PM menu style. (See PM tech ref vol. 3 pages 59-60) mis_attr where 'mis_attr' is a PM menu attribute. (See PM tech ref vol. 3 pages 59-60) ═══ 6.2.2. Buildmenuitem ═══ The buildmenuitem command appends a menu item under an existing option on the action bar (which can be created with buildsubmenu). The syntax for buildmenuitem is: buildmenuitem menu_name, subid, item_id, text, cmd, mis_style, mia_attr menu_name where 'menuname' is a string containing the name of your particular menu. (MAX. = 80 characters) subid where 'subid' is a unique number within this particular menu to define that sub-menu in question. (1-MAXINT) item_id where 'item id' is a unique number within this particular menu to define that menu-item in question. (1-MAXINT) text where 'text' is a string of text which is to appear in as the title of that particular sub-menu. cmd where 'cmd' is the editor defc that is to be executed when the submenu is selected. mis_style where 'mis_style' is a PM menu style. (See PM tech ref vol. 3 pages 59-60) mis_attr where 'mis_attr' is a PM menu attribute. (See PM tech ref vol. 3 pages 59-60) ═══ 6.2.3. Showmenu ═══ Displays a prebuilt menu, built using 'buildsubmenu' and 'buildmenuitem'. The syntax for the showmenu command is: showmenu menuname menuname where 'menuname' is a string containing the name of your particular menu. (MAX. = 80 characters) Note: When a menu item is selected, the PROCESSMENU command (defined in STDCTRL.E) is called, with an argument of the itemid. PROCESSMENU retrieves the command associated with this itemid in the menu whose name is stored in the universal variable ACTIVEMENU, and then executes the retrieved command. Therefore, whenever a SHOWMENU is done, ACTIVEMENU should be set to the name of the menu that was shown. ═══ 6.2.4. Deletemenu ═══ Deletes a named menu or a particular part of a named menu from the internal menu manager. The syntax of the deletemenu command is: deletemenu menuname, subid, itemid, itemonly menuname where 'menuname' is a string containing the name of your particular menu. (MAX. = 80 characters) subid where 'subid' is the sub-menu that is to be deleted. To delete all submenus set this parameter to 0. itemid where 'item id' is the item to start deleting off a particular sub menu. To delete all menu items under a sub menu, set this parameter to 0. itemonly where 'itemonly' is true if it is desired to delete only the items under a sub-menu but not the sub-menu itself. ═══ 6.2.5. querymenustring ═══ Returns the command associated with a menu option. The syntax of the querymenustring command is: cmd = querymenustring(menuname, subid) cmd where 'cmd' will contain the command associated with the menu option requested. menuname where 'menuname' is a string containing the name of the menu to be queried. subid where 'subid' is the sub-menu id number of the menu to be queried. ═══ 6.2.6. sample menu addition ═══ This example shows a menu being added to the default action bar menu. It is defined as a DEFINIT in my MYSTUFF.E file. This means that each time a new edit window is initialized, the action bar option Compile will be added to the default action bar choices. Remember to recompile your editor to have this addition take effect. defload universal defaultmenu buildsubmenu defaultmenu, 19, 'Compile', '', 0, 0 buildmenuitem defaultmenu, 19, 911, 'Save', 'save', 0, 0 buildmenuitem defaultmenu, 19, 912, 'Relink', 'relink test', 0, 0 showmenu defaultmenu Note that the numbers 19, 911, and 912 where chosen to insure that they are unique. ═══ 6.3. Configuring the Mouse ═══ Power users may want to configure the mouse to meet their needs. There are three base mouse sets that can be configured. See The EPM User's Guide for information on setting the constant my_Mousestyle to the desired value (1,2 or 3). This will change the basic mouse configuration styles. You can also configure the mouse actions yourself. To execute these use the built-in procedure REGISTER_MOUSEHANDLER. The REGISTER_MOUSHANDLER(IsGlobal, event, mcommand) command allows the binding of mouse actions to commands. Mouse actions can be global or local. Mouse actions will be processed as follows: 1. local mouse action definition (if defined) 2. else global mouse action definition (if defined) 3. else mouse action ignored. The variable IsGlobal determines whether the mouse action described is local or gloabl. The variable event determines the mouse action to be bound with the command listed in the variable mcommand. Event should be in the following format: 'key action state' The key refers to the mouse key (either 1 or 2). The action must be one of the following: BEGINDRAG activates at the beginning of the drag CLICK activates if a button (specified by key) is single clicked SECONDCLK activates if a button (specified by key) is double clicked These actions must be capitalized and have exactly one space between the key and the state numbers. The state should be the sum of the following: 0 = no states active 1 = shift key active 2 = control key active 4 = alternate key active An Event should can also be of the following format: 'action' where action must be one of the following: ENDDRAG activates at the end of a drag CANCELDRAG activates if a drag is cancelled These actions must be capitalized and unpadded by spaces. An example of a mouse action is: call register_mousehandler(0,'2 SECONDCLK 3','quit') This would set the second click of button two on the mouse with the shift and control states activated to do a QUIT command. This key action would be bound locally to a particular file. Similarly, call register_mousehandler(1,'CANCELDRAG','SynthesizeVoice whoops') would cause the 'SynthesizeVoice whoops' command to be invoked every time a drag was canceled in any file that did not have a local CANCELDRAG event handler defined. By combining several of these register_mousehandler statements together in a DEFLOAD statement, one can customize the mouse actions. Note that the following defc commands are useful for helping define common mouse actions: o MH_BEGIN_MARK o MH_CANCEL_MARK o MH_END_MARK o HH_GOTOPOSITION See the section Commands Omitted From the User's Guide. for descriptions on these commands. An example use of these commands is: defc mymouse register_mousehandler(0,'1 CLICK 2','MH_GOTOPOSITION') sayerror "New mouse command is in effect." Compiling and linking this command into EPM will allow the new mouse action to be added when the command MYMOUSE is entered in the commandline dialog box. Then, whenever you hit a ctrl+left mouse button one click, the cursor will move to the mouse's position. If you want a series of events to happen, define a new command using defc. The following is an example: defc mycmd getline txtline -- get the current line 'mh_gotoposition' -- go to the mouse position insertline txtline -- copy the line up -- move up to the new line defc mymouse register_mousehandler(0,'1 CLICK 2','mycmd') -- set the mouse key sayerror "New mouse command is in effect." -- show it worked In this example, when compiled and linked, executing the command MYMOUSE will setup the ctrl+single button one click combination to copy the line the cursor is on, to the line the mouse is pointing to. See the file MOUSE.E for more examples of defining mouse actions. As you can see, the REGISTER_MOUSEHANDLER is a very powerful command that should be exploited to make the most of EPM and the mouse. ═══ 6.4. Programming Hints ═══ Programming Hints ═══ 6.4.1. Using REFRESH ═══ Advanced users may find themselves writing applications that rely heavily on the E programming language. In such applications the need may arise to have messages and actions update the screen while the macro continues in progress. Take the following example: defproc delay(time)= -- procedure to slow things down totaltime=time * 100 -- this procedure represents the time consumed for i = 1 to totaltime -- ... by calculations and E commands or j = i+5/3 -- ... external programs endfor defc mycmd= 'togglecontrol 8 1' -- make sure the message bar is showing .messageline = "Stage one executing..." -- this should trace call delay(4) -- ... the macro's execution .messageline = "Stage two executing..." call delay(4) .messageline = "Stage three executing..." In this example, all the message appear very quickly as the message buffer empties at the end of the procedure and not throughout the procedure as was intended. This occurs because the compiler doesn't refresh the screen during the execution of the macro. Constantly refreshing the screen is very costly and would slow down the execution of EPM too much. To accomplish the goal (ie. have the messageline trace the execution) replace mycmd with: defc mycmd= 'togglecontrol 8 1' .messageline = "Stage one executing..." refresh call delay(4) .messageline = "Stage two executing..." refresh call delay(4) .messageline = "Stage three executing..." refresh The new MYCMD will show the lines as they execute. All that was added was the internal statement REFRESHto cause a screen refresh. (By the way the command 'TOGGLECONTROL 8 0' will turn the messageline off). ═══ 6.4.2. Using ECHO ═══ Debugging programs can sometimes be a rather tricky task. E is no exception. There is an internal procedure ECHO that can be inserted into programs to allow a command trace. Whenever a command is executed, it will first appear in a message dialog box. By keeping track of the commands the programmer can help trace down errors. There is also a defc front end for this internal command, allowing ECHO to be issued from the command line dialog box. Another useful debug tool is the messageNwait standard procedure. By placing messageNwaits one can view variables and create check points to verify the macro's execution. ═══ 7. Linkable External Modules ═══ Linkable external modules. ═══ 7.1. Introduction ═══ You can compile a group of .E files into an .EX file that is separate from the E.EX file, and yet still incorporate both into the editor. In other words, multiple .EX files can be loaded into the editor. Each .EX file can use up to 64K of p-code space. This means that there's effectively no limit on the total size of a user's compiled macros, as long as they can be broken into logical chunks ("modules") of less than 64K each. I'll use the DRAW feature as an example of the new reorganization of E via these linkable modules. We used to include the draw code into the base E.E so that it was always available, and always occupied 3410 bytes of p-code space. But in version 4.02, E.E omits the feature: compile if EVERSION < '4.02' include 'slimdraw.e' compile endif Instead, DRAW.E is compiled separately into its own .EX file. Now when you type draw in the command dialog box, EPM searches for DRAW.EX on disk, loads it into its own block of memory, and begins execution. The relocation of the draw code is transparent to the user, except for the slight delay of the disk search. Once the draw command is completed, the module is released again, to free up memory. ═══ 7.2. Implicit Loading of External Modules ═══ External modules can be invoked implicitly, by simply issuing the name of the module as a command. As in our previous example, the user (or a macro) can simply issue the DRAW command (F6). When E sees that the command is not in its base set, it will search the disk for an .EX file of the same name. The search follows the same rules as for shelling an external .EXE program: o It does not occur if AUTOSHELL is off. o The search path is: - the current directory, - the directories in PATH, - the directories in EPMPATH, and - E's directory. o An .EX file will be found before a .EXE or .CMD file, but after an internal system command. (That is, you can't name a module EDIT.EX because EDIT will always be recognized first as an internal system command.) Upon activation of the module, its code contents will be executed in the following order: o DEFINIT will be executed first if it exists. This will consist of minor initialization tasks like predefining variables. o DEFMAIN will be executed. This is the body of the command. If you convert an old macro to an external module, you'll usually rename its DEFC to DEFMAIN. For instance, when SLIMDRAW.E was converted to the module DRAW.E, defc draw was changed to defmain. o DEFEXIT, if it exists, will be executed after DEFMAIN finishes. When a module is invoked implicitly, it is executed once and discarded. All three sections -- DEFINIT, DEFMAIN, DEFEXIT -- are run in sequence, so the division makes little difference; you'd get the same results by lumping them all into DEFMAIN. ═══ 7.3. Explicit Linking of External Modules ═══ For better control, you can explicitly load a module with the LINK and UNLINK statements. The DRAW module can be linked by the statement: link 'draw' E will search the disk for the explicit filename DRAW.EX, without bothering to check for internal system commands or .EXE files. This gives you some minor advantages since an explicit search can be faster, and the module can have the same name as a system command (DIR.EX) or a DEFC compiled into your base set. But the primary advantage is a better control of the order of execution. DEFMAIN is not executed at all. DEFINIT is executed at link time, and DEFEXIT at unlink time. In the interim all the module's commands, procs, universal variables and keysets are available globally. This will be important if procedures or variables are shared by several modules. Explicit linking to the draw module does NOT execute the DRAW command. In fact the DEFMAIN of such a module is never executed if it is explicitly linked. In order to execute the DRAW command under these conditions, you must define a defc draw. The following example shows how the new external draw module allows users to link to it implicitly and explicitly: definit /* initializations, global vars, etc. */ defmain 'draw' arg(1) defc draw /* code which implements DRAW command */ /* remains the same as when it was */ /* included in E.E */ If you repeat a link of an already-linked module, no harm is done. The disk is not searched again, but the module's DEFINIT is re-executed as if the module were reloaded from scratch. Note: if your module has a DEFEXIT, don't use a STOP statement to end execution of DEFMAIN. A STOP will permanently end the module's execution before getting to the DEFEXIT. Note: The RC, universal return code variable, is set to the module number of the .ex file linked. ═══ 7.4. Useful Commands ═══ Since LINK and UNLINK are statements, we had to redefine them as commands in order to give you access to explicit linking from the command dialog box. We also added a RELINK command. All of these commands are defined in the file LINKCMDS.E as follows: defc link link arg(1) defc unlink unlink arg(1) A combination of the two gives us the nifty RELINK command: defc relink if arg() > 0 then modulename=arg(1) -- if argument is given, then uses that else modulename=.filename -- if no argument, then assume current file 'save '||.filename -- ... and save current file endif 'etpm' modulename -- Recompile it, unlink modulename -- unlink the old version, link modulename -- relink the new one. This is very useful for fast development of macros, since you don't have to exit from the editor to compile revised macros and re-run the newly compiled version. You can relink a macro in a few seconds. (RELINK DRAW, for example, takes 3 seconds on my AT. Understand that the slow step is the compilation; LINK and UNLINK are almost instantaneous.) When using LINK, UNLINK and RELINK as commands, you need not enclose the module name in quotes. For example, the statement link 'draw' is acceptable, but the command link 'draw' would be incorrect. The interpreter would assume that the name of the module was six characters and included the quotes. The correct syntax for the command (i.e. issued from the command line dialog box) is: link draw ═══ 7.5. Keysets ═══ Individual keys cannot be linked; you cannot define a single key (like def f1) in an external module. You can however link a keyset, which is almost as easy, by following these steps: 1. Begin the key definitions with a DEFKEYS declaration: In MYMODULE.E: defkeys mymodule_keys def f5= sayerror 'F5 pressed' 2. Compile the module: et mymodule. 3. Link it: link mymodule. 4. Execute a KEYS statement: keys mymodule_keys. The best place to put the KEYS statement is in the module's DEFINIT so that it automatically gets executed immediately after linking: definit -- Also in MYMODULE.E keys mymodule_keys It doesn't make much sense to define keys in a module that will be implicitly loaded. An implicitly-loaded module will be run once and discarded; its keyset will not be retained long enough to be used. Instead you should explicitly link an external module with keyset definitions, so that its resources will stick around until released. Keysets are stored economically (as a linked list) so that a two-key keyset occupies only 8 bytes. The expansion and overlaying onto a base keyset occur at run time, within the KEYS statement. Partial keysets can be defined usefully in external modules. edit_keys can be defined in the base module E.E, and mymodule_keys can be defined elsewhere. The overlaying occurs soon after the link (assuming you put a KEYS statement in MYMODULE's DEFINIT as recommended). We refer to the partial external keyset as an overlay keyset and edit_keys as the base. E will accept BASE as a synonym for NEW, and OVERLAY means the same thing as the absence of NEW. The following are equivalent: defkeys edit_keys new = defkeys edit_keys base defkeys c_keys = defkeys c_keys overlay You can return to the base edit_keys either by executing keys edit_keys or by unlink 'mymodule'. When a module is unlinked, its keyset is automatically removed. Note: That's true only for OVERLAY keysets. E will complain if you try to unlink a module containing the current base keyset, since that would leave no keys at all. You'd see the message Cannot unlink base keyset module. Note: A base keyset (as defined by DEFKEYS BASE or NEW) is automatically given a starting set of the standard 128 ASCII keys, including 'A'-'Z', '0'-'9', and control keys. Even if you don't give the keyset any DEF's, it will include the ASCII keys. But some applications might not want those keys included, so another keyset attribute CLEAR has been added. For example: defkeys zero_keys base clear defines a REALLY empty keyset. ═══ 7.6. Multiple Definitions ═══ If a command (DEFC) of the same name is defined in more than one module, the highest (latest-linked) module wins. The last-linked module can be regarded as the "current application", whose commands take precedence in case of name conflicts. If the highest module is unlinked, commands in lower modules become available again. Keysets are similar. If multiple modules define the same keyset name, the latest-linked module's keyset wins. If a procedure (DEFPROC) is defined in multiple modules, the definition in the caller's module (if any) wins, whether or not that module is the latest-linked. This is consistent with the concept of a current application. If module 3 calls myproc() and module 3 itself contains a defproc myproc(), that's certainly the one that the application writer intended to be called. If a procedure is multiply defined but none of the definitions are in the caller's module, an error Call: duplicated proc is issued. If a procedure is defined only once, that definition wins even if it isn't in the caller's module. To determine a module number, issue a QLINK command followed by the name of an E module already linked. For example: QLINK EPM would return module number zero (the lowest level) because it is always linked, and always the first module loaded. Universal variables can be declared in many different modules, all of which share the same data. A universal variable is not discarded as long as any active module references it. Thus a module can initialize a variable and be unlinked, without the value being lost, as long as any other module needs it. ═══ 7.7. E Applications ═══ Large applications are feasible in the E language. Dynamic linking, i.e. the ability to link a compiled module at run-time, makes it possible to distribute an application as a compiled .EX file. Distributing object-code-only applications is possible. This is not recommended, as many programmers wish to be able to examine and adjust the source code of applications according to their own needs. However, this type of distribution would have its advantages. For example, this would make such an application much easier for the end-user to use. The user would simply have to: 1. copy it onto the hard disk, somewhere along the PATH, and 2. type its name as a command. Note: that's strictly true only for implicit loading. Complex applications will usually require explicit LINK and UNLINK commands, but even those can be given single-word front ends if desired; see MATH.E for examples. In addition, invoking it is fast: the time for a link equals a fraction of a second plus the path-search time. (Path-search times can be minimized by explicit LINK commands with explicit file specs for the modules, like "link c:\epm\mymodule".) Another recent change to support compiled applications is that: EPM.EXE can run earlier-version .EX files. If a developer releases an application as an object-code black box (compiled, say, with ET 4.03) it will still be runnable if and when the user upgrades EPM.EXE. The versions of E and ETPM will not have to match, as long as E is more recent than the .EX file. (Assuming we don't make any more major structural revisions as we did in release 4.02.) If your application really must know the exact versions of E and ET it's working with, it can check two things: o EVERSION is a constant supplied automatically by ET. It's a constant attribute of the .EX file. The name EVERSION appears to be an unfortunate choice in hindsight, since it's really ETVERSION. o A new function VER() provides EPM.EXE's version. This will be the same version number now shown by the VER command, but in function form so it's queryable by a macro. Your application could do something like: if ver() <> EVERSION then sayerror "Sorry, I can only run with EPM.EXE version "EVERSION"." stop endif Note: Advice to writers of add-on applications: If you're writing a stand-alone E application, one that you'd like to compile separately and link in as an external module (which we recommend), feel free to include STDCONST.E because unused constants do not waste space now. You should also try to include MYCNF.E to allow the user to pre-override your constants. A catch-all header is: include 'colors.e' include 'stdconst.e' tryinclude 'mycnf.e' Your applications can check whether the user overrode your constants with compile if defined(). For example: compile if not defined(AUTOSAVE_PATH) const AUTOSAVE_PATH='' compile endif A similar technique allows your application to check whether it's being compiled as part of the base (by an INCLUDE) or as an external module (by a LINK). Query the existence of any constant that's defined in the base, like SMALL. compile if not defined(SMALL) -- are we separately compiled? include 'colors.e' -- if so, must include color names compile endif The file USERAPP.SMP, which is included in EMACROS.FLS, is a good example of a routine that tests to see if it's base or external; if external, sets configuration constants the same way they would be set if it were included in the base; and defines the routines it needs without duplicating anything that's included in the base macros. ═══ 7.8. Dynamic Linking ═══ Dynamic linking is the delayed binding of application program external references to subroutines. There are two forms of dynamic linking -- load time and run time. In load time dynamic linking, a program calls a dynamically linked routine just as it would any external routine. When the program is assembled or compiled, a standard external reference is generated. At link time, the programmer specifies one or more libraries which contain routines to satisfy external references. External routines to be dynamically linked contain special definition records in the library. A definition record tells the linker that the routine in question is to be dynamically linked and provides the linker with a dynamic link module name and entry name. The module name is the name of a special executable file with the filename extension of .DLL which contains dynamic link entry points. The linker stores module name/entry name pairs describing the dynamic link routines in the executable file created for the program. When the calling program is run, OS/2 loads the dynamic link routines from the modules specified and links the calling program to the called routines. For more information on Dynamic Linking see the OS/2 Technical Reference Manual. For an example of dynamic linking in E using the DYNALINK command see the DYNATEST.E file. ═══ 7.9. Run-Time Error Messages for Linking and Keysets ═══ Call: duplicated proc A macro called a procedure that is not defined in the caller's module, but which is defined in more than one other module. The caller can't decide which DEFPROC is the right one. Call: unknown proc A macro tried to call a procedure that is not defined in any module. Note that ET will now allow you to compile an .E file with unresolved procedure calls; it assumes some other module will supply the DEFPROC by the time the call occurs. If that doesn't happen, this message is given at run-time. Cannot find keyset A macro tried to execute a KEYS statement with an unknown keyset name. Perhaps the module containing the keyset (the DEFKEYS) has not been linked. Cannot unlink base keyset module You tried to unlink the module that selected the current base keyset. What keys would be left after the unlink? Cannot unlink module in use A macro tried to unlink the same module it was contained in. Or it tried to unlink a calling module (one that must be kept around for returning to). Only modules which are not involved in the current chain of execution can be unlinked. You can produce this message by the command 'UNLINK E' which tries to unlink E.EX. Invalid EX file or incorrect version You tried to link to a file that does not have the proper .EX format expected, or you tried to link to an .EX file that was compiled with a past version of the ET translator. Link: file not found You probably misspelled the module's filename in a LINK statement. The filename.EX could not be found in the current directory or along the PATH. Link: invalid filename The module name is poorly formed in a link statement, for example with multiple periods or colons. This is an unusual error; normally you'll get "Link: file not found". Unlink: bad module filename You tried to unlink a module that does not exist on disk. Unlink: unknown module You tried to unlink a module that is not currently linked, although it does exist on the disk. ═══ 8. E Language Syntax ═══ In this appendix the syntax of the E language is presented in a modified EBNF notation. For those who are unfamiliar with this form, a brief summary of its symbolic conventions are presented here: Keywords of the E language are printed here entirely in capital letters. All program components (non-terminals) whose definition is included in this section are highlighted in a bold font. All other literals (i.e. those strings that should be included in an E phrase exactly as they appear here in the syntax) are enclosed with single or double quotes. Any other character in the syntax is used as a symbol to convey the following meanings: A B represents the concatenation of A AND B. (A | B) represents either expression A OR expression B. [ A ] represents an optional occurrence of expression A: zero or one occurrence. { A } represents zero or more occurrences of expression A. 'a'..'z' represents: 'a' OR 'b' OR 'c' ... OR 'z' ═══ 8.1. Syntax Notes ═══ 1. A semicolon is treated the same as a new line. Wherever you see ';' in the following listing, a line-break (a 'newline', CR-LF) is acceptable. Several examples of line breaks were given in the earlier section Line Continuations. 2. Quoted strings in syntax descriptions below indicate that the enclosed string is not a keyword in the language. Quoted strings (ex. 'filename') below are not case specific. 3. For speed reasons the lexer does not return a space token for space and tab characters. Syntax descriptions have been written without space tokens for convenience. 4. Strings may not cross file or line boundaries. 5. Comments may not cross file boundaries. There are three styles of comments. /* */ may be nested and may cross line boundaries. ; in column 1 makes the rest of line a comment. -- in any column makes the rest of line a comment. 6. Include files may be nested. 7. Implied concatenation expressions with comments between have undefined values. 'a' /* comment */'b' Undefined value 8. Identifiers are not case sensitive. 9. Compiler directives (COMPILE IF and INCLUDEs) are included in the following listing, but cannot be sufficiently explained with this limited syntactical depiction. Be aware that they can occur anywhere a semicolon or newline can. For a more in depth discussion, see section Compiler Directive Statements. ═══ 8.2. The Syntax ═══ Syntax of the E language. ═══ 8.2.1. e_program ═══ e_program ::= definition_group ═══ 8.2.2. definition_group ═══ definition_group ::= definition {definition} ═══ 8.2.3. definition ═══ definition ::= DEF keyname {','{';'} keyname} ['='] global_decl_group statement_group [RETURN] | DEFC identifier {',' identifier} ['='] global_decl_group statement_group [RETURN [expression] ] | DEFEXIT {';'} global_decl_group statement_group | DEFINIT {';'} global_decl_group statement_group | DEFKEYS identifier [NEW | BASE | OVERLAY | CLEAR] | DEFMAIN {';'} global_decl_group statement_group | DEFPROC identifier ['('{';'} formal_decl_group')'] global_decl_group statement_group [RETURN [expression] ] | SET 'cursors' ['='] number | SET 'insert_state' ['='] 0 | 1 | CONST {';'} const_decl_group | compiler_directive | ';' ═══ 8.2.4. compiler_directive ═══ compiler_directive INCLUDE string ';' | TRYINCLUDE string ';' | COMPILE IF constant_expression { ';' } ( statement_group | definition_group ) {COMPILE ELSEIF constant_expression { ';' } ( statement_group | definition_group ) } [COMPILE ELSE { ';' } ( statement_group | definition_group ) ] COMPILE ENDIF ═══ 8.2.5. formal_decl_group ═══ formal_decl_group ::= formal_declaration { {';'} [','] {';'} formal_declaration } ═══ 8.2.6. formal_declaration ═══ formal_declaration ::= [VAR] identifier ═══ 8.2.7. const_decl_group ═══ const_decl_group ::= { constant_declaration {';'} (';' | ',') {';'} } ═══ 8.2.8. constant_declaration ═══ constant_declaration ::= identifier '=' expression ═══ 8.2.9. global_decl_group ═══ global_decl_group ::= {global_declaration {';'} } ═══ 8.2.10. global_declaration ═══ global_declaration ::= UNIVERSAL {';'} identifier ['*'] {';'} {',' {';'} identifier } ═══ 8.2.11. keyname ═══ keyname ::= " ' " printable_char " ' " | " ' " printable_char " ' " '-' " ' "printable_char " ' " Although ETPM will accept all key definitions, some may seem not to take effect because PM intercepts these keys before EPM sees them. For a list of these keys see PM Keys. | 'backspace' | 'keydown' | 'keyend' | 'keyenter' | 'keyleft' | 'keyright' | 'keytab' | 'keyup' | 'space' | 'del' | 'end' | 'tab' | 'up' | 'enter' | 'entry' | 'esc' | 'f1'..'f12' | 'down' | 'home' | 'ins' | 'left' | 'pgdn' | 'pagedown' | 'pgup' | 'pageup' | 'right' | 'padenter' | 'pad_enter' | 's_f1'..'s_f12' | 's_tab' | 's_backspace' | 's_enter' | 's_esc' | 's_pgup' | 's_pageup' | 's_pgdn' | 's_pagedown' | 's_end' | 's_home' | 's_left' | 's_up' | 's_right' | 's_down' | 's_ins' | 's_del' | 's_padenter' | 's_space | 'a_0'..'a_9' | 'a_a'..'a_z' | 'a_f1'..'a_f12' | 'a_enter' | 'a_padenter' | 'a_backspace' | 'a_space' | 'a_minus' | 'a_equal' | 'a_leftbracket' | 'a_rightbracket' | 'a_tab' | 'a_quote' | 'a_comma' | 'a_period' | 'a_slash' | 'a_semicolon' | 'a_backslash' | 'c_0'..'c_9' | 'c_a'..'c_z' | 'c_f1'..'c_f12' | 'c_backslash' | 'c_backspace' | 'c_keyenter' | 'c_pagdown' | 'c_pgdn' | 'c_pageup' | 'c_pgup' | 'c_space' | 'c_quote' | 'c_comma' | 'c_period' | 'c_slash' | 'c_semicolon' | 'c_equal' | 'c_del' | 'c_down' | 'c_end' | 'c_enter' | 'c_home' | 'c_ins' | 'c_left' | 'c_leftbracket' | 'c_minus' | 'c_prtsc' | 'c_right' | 'c_rightbracket' | 'c_tab' | 'c_up' | 'c_padenter' | 'c_pad_enter' | 'otherkeys' | 'other_keys' ═══ 8.2.12. statement_group ═══ statement_group ::= { {';'} statement ';' {';'} } ═══ 8.2.13. statement ═══ statement ::= assignment_statement | built-in_statement | conditional_statement | parse_statement | compiler_directive | procedure_call | " ' "command" ' " All commands used in an E program must be quoted, e.g. if new=0 then 'edit' ═══ 8.2.14. assignment_statement ═══ assignment_statement ::= designator '=' expression ═══ 8.2.15. designator ═══ designator ::= identifier | identifier '.' field | '.' field | built-in_universal_variable ═══ 8.2.16. field ═══ field ::= 'autosave' | 'col' | 'cursorx' | 'cursory' | 'dragcolor' | 'dragstyle' | 'dragthreshholdx' | 'dragthreshholdy' | 'filename' | 'fontheight' | 'fontwidth' | 'keyset' | 'last' | 'line' | 'lockhandle' | 'margins' | 'markcolor' | 'messagecolor' | 'messageline' | 'modify' | 'mousex' | 'mousey' | 'statuscolor' | 'statusline' | 'tabs' | 'textcolor' | 'userstring' | 'visible' | 'windowheight' | 'windowwidth' | 'windowx' | 'windowy' ═══ 8.2.17. built-in_universal_variable ═══ built-in_universal_variable ::= CENTER_SEARCH | FUNCTIONKEYTEXT | JOIN_AFTER_WRAP | RC | EXIT_AFTER_LAST_FILE | TWO_SPACES ═══ 8.2.18. built-in_statement ═══ built-in_statement ::= See individual statement. ═══ 8.2.19. conditional_statement ═══ conditional_statement ::= DO i=expression TO expression [BY expression] statement_group [LEAVE] [ITERATE] statement_group (END | ENDDO) | DO FOREVER statement_group [LEAVE] [ITERATE] statement_group (END | ENDDO) | DO WHILE expression statement_group [LEAVE] [ITERATE] statement_group (END | ENDDO) | FOR i=expression TO expression [BY expression] statement_group [LEAVE] [ITERATE] statement_group ENDFOR | IF expression { ';' } THEN statement_group {ELSEIF expression { ';' } THEN statement_group} [ELSE statement_group] { ';' } ENDIF | LOOP statement_group [LEAVE] [ITERATE] statement_group ENDLOOP | WHILE expression { ';' } DO statement_group [LEAVE] [ITERATE] statement_group ENDWHILE ═══ 8.2.20. parse_statement ═══ parse_statement ::= PARSE ARG {string | +number | -number |number | identifier } | PARSE VALUE expression WITH {string | +number | -number |number | identifier } ═══ 8.2.21. expression ═══ expression ::= simple_expression [relation simple_expression] ═══ 8.2.22. simple_expression ═══ simple_expression ::= term {operator term} ═══ 8.2.23. term ═══ term ::= numeric_term | string | unary_operator term | '(' expression ')' ═══ 8.2.24. arithmetic_expression ═══ arithmetic_expression ::= arithmetic_term {arithmetic_operator arithmetic_term} ═══ 8.2.25. arithmetic_term ═══ arithmetic_term ::= '('arithmetic_expression')' | number | hex_number | octal_number | [numeric_unary_operator] arithmetic_term ═══ 8.2.26. numeric_expression ═══ numeric_expression ::= numeric_term {numeric_operator numeric_term} ═══ 8.2.27. numeric_term ═══ numeric_term ::= number | designator | '('numeric_expression')' | procedure_call | numeric_unary_operator numeric_term ═══ 8.2.28. string_expression ═══ string_expression ::= string | designator | procedure_call ═══ 8.2.29. constant_expression ═══ constant_expression ::= simple_constant_expression [ relation simple_constant_expression ] ═══ 8.2.30. simple_constant_expression ═══ simple_constant_expression ::= constant_term { operator constant_term } ═══ 8.2.31. constant_term ═══ constant_term ::= number | designator | '('simple_constant_expression')' | unary_operator constant_term | string ═══ 8.2.32. relation ═══ relation ::= '==' | '/==' | '=' | '<>' | '<=' | '>=' | '<' | '>' ═══ 8.2.33. operator ═══ operator ::= numeric_operator | AND | '&' | OR | '|' | '||' | spaces ═══ 8.2.34. spaces ═══ spaces ::= (' '|'\t') spaces ═══ 8.2.35. numeric_operator ═══ numeric_operator ::= arithmetic_operator | '//' | '%' ═══ 8.2.36. arithmetic_operator ═══ arithmetic_operator ::= '+' | '-' | '*' | '/' ═══ 8.2.37. unary_operator ═══ unary_operator ::= NOT | numeric_unary_operator ═══ 8.2.38. numeric_unary_operator ═══ numeric_unary_operator ::= '+' | '-' ═══ 8.2.39. procedure_call ═══ procedure_call ::= user_defined_proc_call | built-in_proc_call ═══ 8.2.40. user_defined_proc_call ═══ user_defined_proc_call ::= identifier '(' [expression_list] ')' ═══ 8.2.41. built-in_proc_call ═══ built-in_proc_call ::= See individual procedure. ═══ 8.2.42. command ═══ command ::= macro-defined_command | internal_command | dos_command ═══ 8.2.43. internal_command ═══ internal_command ::= NUMBER | '+' [number] | '-' [number] | 'C/' unquoted_string '/' unquoted_string '/' ['-'] ['+'] ['*'] ['m'] ['a'] ['c'] ['e'] ['r'] ['f'] ['g'] | ( 'E' | 'ED' | 'EDIT' ) {['/d'] ['/e'] ['/n'] ['='] unquoted_string} [quoted_string] | ( 'F' | 'FILE' ) ['/t'] [unquoted_string] | ( 'L/' | '/' ) unquoted_string '/' unquoted_string'/' ['-'] ['+'] ['m'] ['a'] ['c'] ['e'] ['r'] ['f'] ['g'] | ( 'MA' | 'MARGINS' ) [number_list3] | ( 'N' | 'NAME' ) [unquoted_string] | ( 'O' | 'OPEN' ) {[ options ] filespec } | 'OS2' string_expression | ( 'Q' | 'QUIT' ) | ( 'S' | 'SAVE' ) ['/t'] [unquoted_string] | 'TABS' number_list3 | 'VER' | 'XCOM' internal_command ═══ 8.2.44. macro-defined_command ═══ macro-defined_command ::= 'ADD' | 'ALL' '/' searchstring ['/'][c] | ( 'APPEND' | 'APP' ) [unquoted_string] | 'ASC' ( character ) | 'AUTOSAVE' [ ( number | 'on' | 'off') ] | 'AUTOSAVEDLG' | 'AUTOSHELL' ( ['0' | '1' ] ) | ( 'BOTTOM' | 'BOT' ) | 'BOX' ('1' | '2' | '3' | '4' | '5' | '6' | 'C' | 'P' | 'A' | 'E' | 'R' | '/'character) | 'BROWSE' ( ['ON' | 'OFF' | '?'] ) | 'CD' [unquoted_string] | ( 'CHANGE' | 'C' ) '/' find_text '/' replace_text ['/' [-] [+] [*] [M] [A] [C] [E] [R] [F] [G] ] | 'CHANGEDLG' | 'CENTER' | 'CHR' number | 'CLOSE' | 'COMMANDLINE [ string_expression ] | 'CUT' | 'DIR' [ path ] | 'DOLINES' | 'DPATH' | 'DRAW' ('1' | '2' | '3' | '4' | '5' | '6' | 'B' | '/'character) | 'ECHO' ('on' | 'off') | ( 'ETPM' | 'ET' ) ['/e' unquoted_string] ['/u'] [unquoted_string [unquoted_string] ] | 'EXPAND' ['on' | 'off'] | 'FILL' character | 'FINDDLG' | ( 'FINDFILE' | 'FILEFIND' ) unquoted_string | 'GET' unquoted_string | 'HELP' | 'KEY' ( number ' ' character ) | 'LINK' ( filespec ) | 'LIST' [unquoted_string] | 'LOCK' ( [ filespec ] ) | 'LOOPKEY' ( number | 'all' ) | 'LOWERCASE' | 'MARGINSDLG' | 'MARKWORD' | 'MATCHTAB' ['on' | 'off'] | 'MATH' arithmetic_expression | 'MATHO' arithmetic_expression | 'MATHX' arithmetic_expression | 'MESSAGEBOX' | 'MULT' | 'OPENDLG' | 'PASTE' | 'PATH' | 'PRINT' [ printer_name ] | 'PROCESSBREAK' | 'PROOF' | 'PROOFWORD' | 'PUT' [unquoted_string] | 'QCONTROL' idnum | ( 'QDATE' | 'QD' ) | ( 'QL' | 'QLINK' | 'QLINKED' ) | ( 'QUIETSHELL' | 'QS' ) | ( 'QTIME' | 'QT' ) | 'RC' command | 'RELINK' [ filename ] | 'SET' | 'SETSCROLLS' | ( 'SORT' | 'SORTDLL' ) [ 'R' ] [ 'C' ] | 'STAY' ( 'ON' | 'OFF' ) | 'STDFILE_READ' | 'STDFILE_WRITE' | 'TABS' { numeric_expression } | 'TOGGLECONTROL' numeric_expression [, '0' | '1' ] | 'TOGGLEFONT' | 'TOP' | 'UNLINK' [ filespec ] | 'UNLOCK' filespec | 'UPPERCASE' | 'VOL' ═══ 8.2.45. dos_command ═══ dos_command ::= Any command recognized and interpreted by the current operating system, whether that is DOS or OS/2. ═══ 8.2.46. expression_list ═══ expression_list ::= expression { {';'} [','] {';'} expression } ═══ 8.2.47. identifier ═══ identifier ::= letter {letter | digit | '_' } ═══ 8.2.48. identifier_list ═══ identifier_list ::= identifier [spaces identifier [spaces identifier [spaces identifier . . . ] ] ] ═══ 8.2.49. unquoted_string ═══ unquoted_string ::= {character} ═══ 8.2.50. string ═══ string ::= " ' " {character} " ' " | ' " ' {character} ' " ' | esc_code ═══ 8.2.51. letter ═══ letter ::= 'a' .. 'z' | 'A' .. 'Z' ═══ 8.2.52. character ═══ character ::= any character whose ASCII value is between 0 and 255 ═══ 8.2.53. printable_char ═══ printable_char ::= any character whose ASCII value is between 0 and 255 ═══ 8.2.54. esc_code ═══ esc_code ::= '\' ('n' | 't' | 'b' | 'r' | 'f') | '\' digit [digit [digit] ] | '\'x hex_digit [hex_digit] ═══ 8.2.55. hex_number ═══ hex_number ::= 'x'hex_digit {hex_digit} ═══ 8.2.56. octal_number ═══ octal_number ::= 'o'octal_digit {octal_digit} ═══ 8.2.57. octal_digit ═══ octal_digit ::= '0'..'7' ═══ 8.2.58. hex_digit ═══ hexdigit ::= (number | 'a' .. 'f' | 'A' .. 'F' ) ═══ 8.2.59. number ═══ number ::= digit{digit} ═══ 8.2.60. digit ═══ digit ::= '0' .. '9' ═══ 8.2.61. number_list2 ═══ number_list2 ::= number [spaces number] ═══ 8.2.62. number_list3 ═══ number_list3 ::= number [spaces number [ spaces number] ] ═══ 8.2.63. number_list4 ═══ number_list4 ::= number [spaces number [ spaces number [spaces number] ] ] ═══ 9. Summary of Keywords, Procedures, Variables, and Keys ═══ Summary of keywords, procedures, variables and keys. ═══ 9.1. Built-in Statement and Procedure Summary ═══ In this section all of E's internal procedure and statements are listed followed by a brief description. See Built-in Statements and Procedures for more complete descriptions and parameters. Procedures are followed by parentheses and can return values. Statements have no parentheses, return nothing, and generally perform some operation on the screen. Both statements and procedures can be followed by arguments. Procedure arguments must within the parentheses. ABBREV() returns 1 if one string is an abbreviation of another ACTIVATEFILE makes a file the current file ADJUSTBLOCK moves a marked area by overlaying ADJUST_BLOCK same as ADJUSTBLOCK ADJUSTMARK same as ADJUSTBLOCK for any marked type ADJUST_MARK same as ADJUSTMARK ARG() returns an argument ASC() determins an ASCII value ATOI() converts a string to integer ATOL() converts a string to a long integer ATTRIBUTE_ACTION does an attribute action BACKTAB moves cursor to previous tab BACKTABWORD moves cursor to beginning of last word BACKTAB_WORD same as BACKTABWORD BEEP() emits a noise BEGINLINE moves cursor to beginning of line BEGIN_LINE same as BEGINLINE BOT goes to the bottom of the file BOTTOM same as BOT BEGINLINE moves cursor to beginning of the line BEGIN_LINE same as BEGIN_LINE BROWSE() turns browse mode on/off BUFFER() allows shared buffers BUILDMENUITEM builds an action bar menu item BUILDSUBMENU builds an action bar sub menu item CALL executes a procedure CENTER centers a string in a given length field CENTRE centers a string in a given length field CHR() finds the character from an ASCII value COMPARE compares two strings; returns the character position of the first difference COPIES returns n copies of the given string COPYMARK copies marked to text to the cursor pos. COPY_MARK same as COPYMARK DELETE deletes the line the cursor is on DELETECHAR deletes the character under the cursor DELETE_CHAR same as DELETECHAR DELETELINE deletes a line of text DELETEMARK removes marked text DELETE_MARK same as DELETEMARK DELETEMENU removes an action bar menu item or subitem DELSTR deletes a substring of a string DELWORD deletes a phrase from a string DIRECTORY( [path]) returns current directory; if path is given, changes current directory first DISPLAY allows screen updating etc. to be toggled DO start of an iteration routine DO_ARRAY handles arrays in E DO_OVERLAYWINDOWS is undisclosed DOWN moves the cursor down a line DYNAFREE() releases a dynalink library DYNALINK() allows PM calls thru C code DYNALINKC() same as DYNALINK but in C format ECHO() performs a command execution trace ENDLINE moves the cursor to the end of line END_LINE same as ENDLINE ERASEENDLINE erases text to the end of line ERASE_END_LINE same as ERASEENDLINE EXECUTE executes the command dialog box EXECUTEKEY executes the key specified EXIT exits from the current macro FILESINRING returns the number of files in the ring FILESIZE returns the sum of the lengths of all lines in the file FILLMARK fills the marked area FILL_MARK same as FILLMARK FINDFILE finds a file path FOR begining of an iterative loop GETFILEID gets a file id number GETKEYSTATE() gets the shift state of keys GET_KEY_STATE same as GETKEYSTATE GETLINE returns the current text line GETMARK gets the type of mark GETPMINFO() returns PM information GETSEARCH saves the last search string GET_SEARCH same as SETSEARCH HEX() returns the hex value of a char. IF - THEN - ELSE the beginning of a conditional stmt. INCLUDE includes another E file INSERT inserts a blank line INSERT_ATTRIBUTE inserts an attribute INSERTLINE inserts a line at a specified location INSERTSTATE() returns insert/replace mode INSERT_STATE() same as INSERTSTATE() INSERTSTR inserts a string into another string INSERTTOGGLE toggles the insert/replace modes INSERT_TOGGLE same as INSERTTOGGLE ITERATE part of a repeat loop ITOA() converts a integer to string JOIN joins two lines KEY executes the key specified KEYIN enters text into the file KEYS actives a keyset name LASTERROR() returns the last error code LAST_ERROR() same as LASTERROR LASTKEY() returns the last key hit LASTPOS() finds text in the file LEAVE leaves a repetitive loop LEFT moves the cursor one column left LEFTSTR() returns the leftmost n characters of a string LENGTH() retuns the length of a string LEXAM() access the dictionary functions LINK links an .EX module into EPM LINKED() returns if a module is linked LONGESTLINE() returns the length of the longest line in the file LOOP a iterative looping command LOWCASE() lowers the case on a string LTOA() converts a string to a long integer MACHINE() returns the type of Operating System MARKBLOCK issues a block-type mark MARK_BLOCK same as a MARKBLOCK MARKCHAR issues a character-type mark MARK_CHAR same as a MARKCHAR MARKLINE issues a line-type mark MARK_LINE same as a MARKLINE MARKTYPE() returns the marktype set MEMCPYX() copies information from one memory location to another MOUSE_SETPOINTER sets the mouse pointer MOVEMARK moves marked text to the cursor pos. MOVE_MARK same as MOVEMARK NEXTFILE actives the next file in the ring NEXT_FILE same as NEXTFILE OFFSET() returns the offset in binary OFS() returns the offset in a string format OVERLAY allows the overlay of strings OVERLAYBLOCK copies marked text without inserting OVERLAY_BLOCK same as OVERLAY_BLOCK PAGEDOWN moves the cursor one page down PAGE_DOWN same as PAGEDOWN PAGEUP moves the cursor one page up PAGE_UP same as PAGEUP PARSE parses a string PEEK() looks up a memory location value PEEKZ() returns an ASCIIZ string from memory POKE() inserts a value into a memory location PREVFILE moves to the previous file QUERY_ATTRIBUTE determines the attribute type set QUERYMENUSTRING get the command associated with an menu option QUERYPROFILE() gets a string from OS2.INI QUIETSHELL allows an OS/2 command to be executed REFLOW reformats text REFRESH updates the screen RELINK compiles and links .E modules REPEATFIND finds the next occurrence of a search REPEAT_FIND same as REPEATFIND REPLACELINE replaces a line with new text RETURN returns an expression to the caller REVERSE() returns the reverse of a string RIGHT moves the cursor one column right RIGHTSTR() returns the rightmost n characters of a string RUBOUT deletes the character to the left SAYAT writes text at a location on the screen SAY_AT same as SAYAT SAYERROR displays an error code or a message SAYERROR() displays a message SAYERRORTEXT() returns the error message associated with a given error code SCREENHEIGHT() returns the screen height SCREENWIDTH() returns the screen width SEG() returns the segment address as a string SELECTOR() returns the segment address in binary SETPROFILE() sets a string in OS2.INI SETSEARCH sets the search command string SET_SEARCH same as SETSEARCH SHIFTLEFT shifts marked text one position left SHIFT_LEFT same as SHIFTLEFT SHIFTRIGHT shifts marked text one position right SHIFT_RIGHT same as SHIFTRIGHT SHOWMENU displays a newly built action bar menu SPLIT splits a line of text into two lines STOP stops execution of a macro STOPONRC stops only if RC is non-zero STOP_ON_RC same as STOPONRC STRIP() strips away extra spaces SUBSTR() returns a sub-string from within a string SUBWORD returns a phrase from a string TAB moves to the next tab stop TABWORD moves to the beginning of the next word TAB_WORD same as TABWORD TEXTLINE() gets the contents of the indicated line TOP moves to the top of the file TRANSLATE() translates a string according to a given translate table TRYINCLUDE attempts to include a .E file UNDO undoes changes on a line UNLINK removes a .EX module from EPM UNMARK unmarks text UP moves the cursor up one key UPCASE() converts a string to upper case VER() returns the version number VERIFY() makes sure a string is valid in a set WINMESSAGEBOX() does a Dynalink call to the PM WinMessageBox function WORD() returns the nthe word of a string WORDINDEX() returns the character position of a word in a string WORDLENGTH() returns the length of a word in a string WORDPOS() returns the position of a phrase in a string WORDS() returns the number of words in a string WHILE a conditional repetitive statement ═══ 9.2. Command Summary ═══ These commands can be issued from within the command line dialog box or from within a program. When used within the E language they must be surrounded by quotation marks. For example: `CD' or `CD C:\EPM\FILES' or `CD` mypath In the first example the macro command CD will be executed as if the user typed it in on the command line dialog. In the second example CD was issued with an argument. And in the third example, the argument was a variable name. For more information on the commands and their syntax see The EPM User's Guide and Commands Omitted From the User's Guide in this manual. #### goes to line number #### + [####] moves cursor forward #### lines. - [####] moves cursor backward #### lines. /find_string/[options] same as 'L' command ACTIVATEFILEID activates the file specified ADD adds a marked block of numbers ALL if included, it finds all occurrences of a given string in the current file APP appends marked text to a file APPEND same as APP ASC determines the ASCII value of a char. AUTOSAVE sets the AUTOSAVE field value AUTOSAVEDLG brings up the AUTOSAVE dialog box AUTOSHELL turns AUTOSHELLing on or off BOT goes to the bottom of the file BOTTOM same as BOT BOX draws a box of specified style around block mark. (See BOX.E) BROWSE make the file read-only or read-write C changes text strings CD changes the default drive/path CENTER centers marked text CHANGE same as C CHANGEDLG brings up the change dialog box CHR displays the character associated CLEARSHARBUFF clears the shared buffer CLOSE closes files in the ring COMMANDLINE brings up the command line dialog box COPY2DMBUFF copies marked area to "Delete Mark" buffer COPY2SHARBUFF copies marked area to shared buffer CURSOROFF turns the cursor off CUT moves marked text to the shared buffer DIR lists the directory in a temp. file DOLINES executes the current line or marked lines DPATH shows the DPATH setting DRAW enters draw mode DUPMARK executes a mark action specified ECHO turns command trace on E edit a file ED same as E EDIT same as E and ED ET invoke the compiler ETPM same as ET EXPAND turns syntax expansion on/off F saves and quit the current file FILE same as F FILEFIND attempts to find a file FILL fills the marked block with a character FINDDLG invokes the find dialog box FINDFILE same as FILEFIND GET gets the file into the current file GETDMBUFF gets text from the delete mark buffer GETSHARBUFF gets text from the shared buffer HELP brings up EPM help KEY allows the repeat of a key or macro L searches for text LINK links an .EX module into EPM LIST same as FILEFIND and FINDFILE LOADDEFAULTMENU loads the default action bar menu LOCK prevents other users from updating a file LOOPKEY repeats a key in a vertical direction LOWERCASE converts marked text into lowercase MA sets/displays the margin settings MARGINS same as MA MARGINSDLG brings up the margins dialog box MARKWORD marks the word under the mouse pointer MATCHTAB sets tab stops to the words in the line above MATH computes an expression in base 10 MATHO computes an expression in base 8 MATHX computes an expression in base 16 MESSAGEBOX brings up the message review dialog box MH_BEGIN_MARK mouse handler begin mark MH_CANCEL_MARK mouse hander cancel mark MH_END_MARK mouse handler end mark MH_GOTOPOSITION mouse handler go to position MULT multiplies the numbers in a marked area N renames the current file NAME same as N O loads a file into a new window OPEN same as O OPENDLG brings up the OPEN dialog box OS2 executes an OS/2 command PASTE copies text from the shared buffer PATH displays the path settings PRINT prints a marked area or whole file PROCESSBREAK stops a macro in progress PROOF initiates spell checking PROOFWORD spell checks the current word PUT writes the marked text to a file QCONTROL determines the status of windows QD returns the current date QDATE same as QD QL determines if a module is linked QLINK same as QL QLINKED same as QL and QLINK QS executes an OS/2 command w/ no results QUIETSHELL same as QS QT displays the time QTIME same as QT Q quits the current file QUIT same as Q RC returns the error code of a command RELINK compiles and links and E module S saves a file to disk SAVE same as S SET displays all SET parameters in a temp. file SETSCROLLS turns the scroll bars on/off SORT sorts marked text or the whole file SORTDLL same as SORT STAY sets whether to move on a find & replace STDFILE_READ reads in from standard input stream STDFILE_WRITE writes out the the standard output stream TABS sets the tabs stops TOGGLECONTROL toggles the window on/off TOGGLEFONT toggles between large/small fonts TOP goes to the top of the current file UNLINK removes an .EX module from EPM UNLOCK allows other users to update a file UPPERCASE makes text in a marked area uppercased VER displays the EPM version VOL displays the current drive's volume info XCOM executes a built in command ═══ 9.3. E Language Keywords ═══ AND Boolean AND function. That is, a logical AND like REXX, not a bit operator. ARG is used in parse constructs BASE is used in defkeys construct BY is used in loop constructs CLEAR is used in defkeys construct COMPILE conditional compilation instruction, followed by IF/ELSE/ELSEIF/ENDIF CONST defines constants that the E translator uses during translation of the E procs DEF defines a key or pseudo-key that belongs to the current keyset DEFC defines new commands DEFINIT allows initialization of variables for use by other E procedures DEFKEYS names a keyset DEFLOAD is executed whenever a new file is loaded DEFMAIN allows the user to take control of the command dialog box arguments of the editor DEFMODIFY is executed when .modify passes certain threshold values DEFPROC is used to define new procedures (functions) DEFSELECT is executed whenever you switch to a different file DO is used in loop constructs ELSE indicates action to take place when an IF statement proves false ELSEIF executes a secondary IF when an IF statement proves false END or ENDDO is used in loop constructs, to terminate a DO block (DO WHILE, DO (FOR), or DO FOREVER) ENDFOR is used in loop constructs ENDIF marks the end of an IF block ENDLOOP is used in loop constructs ENDWHILE is used in loop constructs FOR is used in loop constructs FOREVER is used in loop constructs IF changes the flow of statements depending upon a condition INCLUDE includes another file into the current file for compilation. ITERATE iterates a loop, while, or do LEAVE exits loop, while, or do LOOP is used in loop constructs NEW is used in defkeys construct NOT Boolean NOT function OR Boolean OR function OVERLAY is used in defkeys construct PARSE is used to extract information from a string RETURN returns from a defined procedure or command, with an expression. SAY writes a line to terminal when shelled to OS/2 SAYS writes a line to terminal when shelled to OS/2, no CR-LF SET defines configuration options. Only a few options are still set in this way: cursors and insertstate. THEN indicates action to take place when an IF statement proves true TO is used in loop constructs TRYINCLUDE includes another file into the current file for compilation, similar to INCLUDE, but does not stop compilation if the file cannot be found. UNIVERSAL specifies that a variable is available to all procs, is not local to the current one. VALUE is used in Parse constructs VAR is used in DEFPROC definitions. Specifies that the following variable is passed by reference. If the procedure modifies the variable its value is also changed in the caller. Otherwise the caller's value for the variable is not modifiable by the called procedure. WHILE is used in loop constructs WITH is used in Parse constructs ═══ 9.4. Field Attributes ═══ Field attributes are variables that are unique to each file. They can be accessed by specifying the fileid and the attribute name separated by a period. If the fileid is omitted, the current file is assumed. Some are able to be assigned and all are able to be referenced. For example: .line = 1 sayerror "The current line is: "||.line tmpfileid.line = 1 The first is an assignment statement. The second is reference statement. In the third a fileid (in the form of the variable tmpfileid) is used. For a more complete description of field variables see Field Variables Listed. Valid field variables are: .AUTOSAVE number of changes before autosaving .COL the cursor column position .CURSORX the cursor x coordinate .CURSORY the cursor y coordinate .DRAGCOLOR the drag color .DRAGSTYLE the drag style .DRAGTHRESHHOLDX how far (in x dir.) mouse must move for a drag .DRAGTHRESHHOLDY how far (in y dir.) mouse must move for a drag .FILENAME the current file's filename .FONTHEIGHT the font height .FONTWIDTH the font width .KEYSET the current active keyset .LAST the maximum file line number .LINE the cursor's line number .LOCKHANDLE determines if the file is LOCKed .MARGINS contains the margin settings .MARKCOLOR contains the mark color .MESSAGECOLOR contains the message color .MESSAGELINE the contents of the messageline .MODIFY the number of modifications made .MOUSEX the mouse's x coordinate .MOUSEY the mouse's y coordinate .STATUSCOLOR the status bar color .STATUSLINE the contents of the status line .TABS the tab settings .TEXTCOLOR the text color .USERSTRING a user definable variable .VISIBLE determines if the file is visible .WINDOWHEIGHT contains the window height .WINDOWWIDTH contains the window width .WINDOWX the window x coordinate .WINDOWY the window y coordinate ═══ 9.5. E-Definable Keys ═══ The following keys may be defined using E. In all cases, the prefix A_ means that the Alt key must be depressed at the same time as the key to get the desired function. Similarly, the prefix C_ means the Ctrl key must be used, and S_ means the shift key must be used. For information on the format of defining these keys, refer to section Key Definitions (DEF and DEFKEYS) or E Language Syntax. A - Z A_A - A_Z A_EQUAL A_F1 - A_F12 A_LEFTBRACKET A_MINUS A_RIGHTBRACKET A_TAB A_0 - A_9 BACKSPACE C_A - C_Z C_BACKSLASH C_BACKSPACE C_DEL C_DOWN C_END C_ENTER C_F1 - C_F10 C_HOME C_INS C_LEFT C_LEFTBRACKET C_MINUS C_PGDN C_PGUP C_PRTSC C_RIGHT C_RIGHTBRACKET C_TAB C_UP C_2, C_6 DEL DOWN END ENTER ESC F1 - F10 HOME INS LEFT PGDN PGUP RIGHT S_F1 - S_F10 S_PAD5 S_TAB TAB UP any printable character whose ASCII value is 0 to 255. The following name may be defined in the same manner as keys, but is used as a pseudo-key: ENTRY The following keys are available only on enhanced keyboards, which come with the PS/2 and AT models: A_ENTER A_F11, A_F12 A_PADENTER C_F11, C_F12 C_PADENTER F11, F12 PADENTER S_F11, S_F12 ═══ 9.5.1. PM Keys ═══ The keys listed below are used be Presentation Manager to accomplish certain functions standard to all PM applications (set by CUA standards). To maintain consistency between PM applications, these keys cannot be redefined. Key PM Function F1 Help F10 Goto action bar. A_F7 Move a PM window. A_F8 Size a PM window. A_F9 Minimize a PM window. A_F10 Maximize a PM window. A_Esc Switch application. C_Esc Goto Task List. ═══ 10. General Structure of E-Macro Files ═══ ALL.E Procedure for including the ALL command and the ctrl-Q key setup for paging between ALL occurrences. This file is only included if the variable WANT_ALL is TRUE. BOX.E Procedure for the BOX command. This is compiled separately into a BOX.EX file. The file is loaded when the user issues a BOX command. When the command finished, BOX is unlinked from EPM, thereby saving memory space. BUFF.E Test procedures for the buffer() opcode. CHAROPS.E Procedures for block fill, copy, delete and mark, for character-marked text. CKEYS.E Syntax aids for C files. CKEYSEL.E A small file which selects the C keyset. This is a separate file to allow easy omission of the syntax-expansion feature by erasing CKEYS*.E. As of version 4.12, this file is no longer needed. The selection of the keyset is done in CKEYS.E where the keyset is defined. This is made possible by the new DEFLOAD feature. Similarly, EKEYSEL.E and PKEYSEL.E are unnecessary. CLIPBRD.E Contains procedures and commands that: o allow a user to pass lines of text between edit windows o allow text to be placed in the PM clipboard. COLORS.E Defines default colors. DOSUTIL.E Procedures interfacing to the operating system. Note: No longer used under OS/2. DRAW.E Includes the procedures for the DRAW command. This is compiled separately into a DRAW.EX file. The file is loaded when the user issues a DRAW command. The code is then unlinked when the DRAW command is finished. DRAWKEY.E Includes the key definition for F6 to trigger the draw command. DYNATEST.E An example program showing how to program in E using the DYNALINK command. E.E The main file containing all the include statements that create EPM. Do not compile this module, however. Compile the EPM.E file. E3EMUL.E Includes the procedures and commands to enable E3EMUL host support. See The EPM User's Guide for more information on the E3EMUL package support. EKEYS.E Key definitions for E syntax support. EKEYSEL.E A small file which selects the E keyset. This is a separate file to allow easy omission of the syntax-expansion feature by erasing EKEYS*.E. EPM.E The main file for compilation. See The EPM User's Guide for information on compiling this file. EPMLEX.E Includes spell checking and synonym support for the EPM editor. EXIT.E Asks the user if he really wants to leave EOS2. No longer used in EPM. GET.E Procedures for the GET command. This is an external package created to save memory space. When the user issues a GET command, EPM loads the GET.EX file. Once the GET command is completed, GET will unlink itself from memory to free up memory space. HELP.E Procedure for the HELP command. This is an external package created to save memory space. When the user issues a HELP command, EPM loads the HELP.EX file. Once the user has finished viewing the EPMHELP.HLP file, HELP automatically unlinks itself from memory to free up memory space. LINKCMDS.E Contains procedures and commands related to the linking of editor modules (ie. LINK, ETPM, RELINK and UNLINK). LOAD.E This file is executed immediately after a file is loaded. It will be invoked after loading an existing file from disk, or opening a new file, but not after an error such as "Not enough memory". In other words, a new file must be entered into the ring. This is the place to select a keyset (like c_keys for .C files) since keysets now stay bound to a file once assigned. This is also a good place to do other one-time processing like returning to a saved bookmark. MAIN.E Contains the DEFMAIN procedure, which is where E begins execution after all DEFINITs. Processes the OS/2 command dialog box. MARKFILT.E Defines procedures to extract and replace strings from marked text. MATH.E Definitions for ADD and MULT commands. Also refer to the file MATHLIB.E for more math command definitions. MATHLIB.E An extension of MATH.E created for EOS/2 to allow the components to compile only if needed. See MATH.E for more math command definitions. MODIFY.E This file contains the procedures and commands executed when a DEMODIFY event is triggered. The DEMODIFY event occurs when a file's number of modifications (.modify): o goes from zero to nonzero (first modification, so we can change the textcolor or title to indicate that the file needs to be saved; o goes from nonzero to zero (so we can return to the safe textcolor, usually after a save); o goes from less than .autosave to greater than or equal to .autosave. The DEMODIFY.E file is new as of EPM. MOUSE.E Contains the commands and procedures associated with the MOUSE movements and actions. This file is new as of EPM. PKEYS.E Syntax aids for Pascal files. PKEYSEL.E A small file which selects the Pascal keyset. This is a separate file to allow easy omission of the syntax-expansion feature by erasing PKEYS*.E. PUT.E Contains the procedures and statements for the PUT command. This was made an external module to save space. RETREIVE.E Used to retrieve commands from a hidden file in E3. This file is no longer used under EPM. SAVELOAD.E Things common to loading and saving files (host file support). SELECT.E Contains the procedure select_edit_keys() which selects options (like keysets) whenever you switch to a new file. SHELL.E Presents an E interface to the internal shell command. SLNOHOST.E Substitute for SAVELOAD.E, without host file support. SMALL.E A version of E.E with several features removed to save memory. SORTDLL.E Provides the link between the E's SORT command and the QISRTMEM sort DLL. SORTE.E Definitions for the sorting using the E language. STDCMDS.E Definitions of standard E commands. STDCNF.E Mode settings and default values for the standard E configuration. STDCONST.E Contains EPM's standard constants. STDCTRL.E Adds LISTBOX and MENU support. Routines to interface with EPM and PM controls are defined here. STDKEYS.E Standard E command-key definitions. STDMENU.E The default action bar is defined here. STDPROCS.E Standard procedural support for other files. WINDOW.E Definitions for tiled window support. No longer used in EPM. ═══ 11. Descriptions of Procedures in Standard EPM ═══ This section lists in alphabetical order all of the procedures in the *.E files and gives a brief description of how they function and what they are used for. For more detailed information, please study the comments in the .E code itself. ═══ 11.1. ALREADY_IN_RING(filename, var tryid) ═══ Attempts to find the filename in the current ring. If successful tryid returns the file id for the filename. This function returns a one if the filename is in the ring and a zero if not. ═══ 11.2. APPEND_PATH(filename) ═══ For use with DOS 3.30 or higher: searches the path listed in the APPEND path string for filename and returns the path (ended by a trailing backslash) where it was found; otherwise it returns null. Only included if requested with the USE_APPEND option variable. ═══ 11.3. ASKYESNO() ═══ Displays the message: 'Are you sure (Y/N)' and returns an uppercase keystroke to the caller. If called with a string parameter, the string is displayed before the message: 'Are you sure (Y/N)'. An optional second argument is a flag to prevent the 'Are you sure (Y/N)' message from appearing. For example: usersays = askyesno("About to erase") The user's response would be placed in the variable usersays. ═══ 11.4. BEEP(pitch,duration) ═══ Emits a tone of pitch (range 25Hz - 7FFFHz) and a duration of duration in milliseconds. ═══ 11.5. BREAKOUT_MVS(filename,lastqual) ═══ Breaks out a filetype from a MVS filename. PASCAL will return PAS and C will return C. Only included if requested with HOST_SUPPORT. ═══ 11.6. CHECK_FOR_HOST_FILE() ═══ Parses arg(1) in the host filename form: fname ftype fmode; gives an error message and returns zero if not in correct format; returns one if in correct format. Included only if HOST_SUPPORT is requested. ═══ 11.7. CHECK_FOR_PRINTER(name) ═══ Tests whether name is actually a printer device. Returns zero if not a valid printer device and the printer number if valid. ═══ 11.8. CHECK_MARK_ON_SCREEN() ═══ Tells if a mark is visible on the screen. Returns a one if the mark is on the visible screen and a zero if not. Use checkmark() to see if a mark exists anywhere in the file. ═══ 11.9. checkmark() ═══ Checks if a marked area exists in the current file. Returns a one if a mark is set; zero if no mark exists. ═══ 11.10. CURSOROFF() ═══ Turns the cursor off. ═══ 11.11. DEC2HEX() ═══ Converts a decimal number, arg(1), to a number of base arg(2) (default is hexadecimal). Example usage is: HexStringOut=Dec2Hex(DecimalIn) ═══ 11.12. DOS_COMMAND() ═══ Executes the DOS (OS/2) command specified in the arg(1) and redirects the output to the file specified in vTEMP_FILENAME. Used by commands like the DIR command. ═══ 11.13. DOS_VERSION() ═══ Returns DOS version number, multiplied by 100 so it can be treated as an integer string. For example DOS 3.2 is reported as "320". ═══ 11.14. EINSERT_LINE() ═══ Inserts a line after current line and positions the cursor on the same column number of the first nonblank character of preceding line. ═══ 11.15. ENTRY_BOX(title) ═══ Creates a System-Modal Dialog Box with an entry field and two push buttons. The format for entry_box is: userstext = entrybox(title,buttons,entrytext,cols, maxchars) with the following field definitions: userstext is the variable that will contain the user's text entered. title the text to be displayed in the title bar. buttons the labels on the buttons separated by delimiting characters. If this entry is null, the EPM defaults to Enter and Cancel. entrytext contains the text to be entered into the user's text entry area. This is useful for displaying defaults for change. cols is the width of the dialog box. maxchars is the maximum number of characters allowed for entry. An example of a procedure (called testit) that uses the entrybox command follows: defc testit k=entrybox('This is a test box.', '/one/two/', 'Hi!',30, 10) message("The character returned was = "||k) In the procedure, a dialog box with the title This is a test box will appear. The two buttons will be labeled one and two. Initially the word Hi! will be entered in the text input area. This is useful for displaying current values and allowing the user to change them. The dialog box will be thirty characters wide and allow the user to input up to ten characters. The input will be stored in the variable k and the command message will display the input. Also see the LISTBOX procedure in this section for an alternative means of getting user input. ═══ 11.16. ERASETEMP(filename) ═══ Erases a file quietly (no "File not found" message) on both DOS and OS/2; returns 0 if successful erase, and the error code (if on DOS) which is usually 2 for 'file not found'. ═══ 11.17. EXIST(filename) ═══ Determines whether filename exists. Returns a one if it does exist; a zero if it doesn't. ═══ 11.18. FILETYPE() -- in SLNOHOST.E ═══ Returns the extension (everything after '.') of the current filename or fileid specified in arg(1). ═══ 11.19. FILETYPE() -- in SAVELOAD.E ═══ Returns the 'ftype' portion of the host filename. ═══ 11.20. FIND_ROUTINE(utility) ═══ Used to both verify that the external utility program exists, and to get its path. ═══ 11.21. GET_CHAR() ═══ Returns the character at the current cursor position. ═══ 11.22. GET_ENV(varname) ═══ Returns whether the variable name (varname) is found in the environment. Returns the setting if found; zero if not found. For example: res=get_env('DPATH') In this case the contents of the DPATH environment variable would be returned into the variable res. ═══ 11.23. GETDATE() ═══ Returns the date in the form: Weekday Month Day, Year; MonthNum. ═══ 11.24. GETTIME() ═══ Returns the time in the form: hh:mm:ss xm;hour24:hund. ═══ 11.25. HEX2DEC() ═══ Converts the number in arg(1) to a decimal number; arg(1) is assumed to be a number of base arg(2) (hexadecimal by default). See the dec2hex() procedure for an example. ═══ 11.26. ISA_MVS_FILENAME(candidate, var hostfile, var tempfile, var thisLT, var bin, var error_msg) ═══ Returns a zero and the error message (in error_msg) if it is not a valid MVS filename; and returns a one and the rest of the information if the candidate is a valid MVS filename. ═══ 11.27. ISA_PC_FILENAME(candidate, var tempfile, var error_msg) ═══ Returns a zero and the error message (in error_msg) if it is not a valid PC filename; and returns a one and the rest of the information if the candidate ═══ 11.28. ISA_VM_FILENAME(candidate, var hostfile, var tempfile, var thisLT, var bin, var error_msg) ═══ Returns a zero and the error message (in error_msg) if it is not a valid VM filename; and returns a one and the rest of the information if the candidate ═══ 11.29. ISHOST(candidate, verb, var hostfile, var tempfile, var thisLT, var bin) ═══ Determines a filename's type and returns: 0 = PC filename 1 = VM filename 2 = MVS filenme ═══ 11.30. ISNUM() ═══ Returns true if parameter given is a number, ignores leading and trailing spaces. ═══ 11.31. ISOPTION(var cmdline, optionletter) ═══ Eliminates optionletter from cmdline; if optionletter occurred in the commandline, returns 1; returns 0 otherwise. ═══ 11.32. JOINLINES() ═══ Joins the line below the cursor line with the cursor line. ═══ 11.33. LISTBOX(params) ═══ Enables the dynamic creation of modal PM list boxes. A macro can pop up a list of items and have the user's selection returned to the macro. The entry chosen (with a mouse double click or enter from the keyboard) is returned. If ESC was hit then a null string is returned. Parameters are: param1 the list of items, separated by a common separator. The common separator is the first character in the string. example: /cat/dog/fish separator='/' list=cat, dog, fish example: $cat/ground$fish/water separator='$' list=cat/ground, fish/water These lists will be displayed like the past commands are displayed in the command line dialog box. If one of elements in the box is double-clicked on, it will be returned. For instance, if the second element of the first example list was chosen by the user, the string DOG would be returned. param2 (optional) button names. A maximum of four button names can be specified to allow multiple buttons. If button one is clicked on, the highlighted value from the list is returned and so should probably be entitled ENTER. If the second button is chosen, a null string will be returned as so should have a title something equivalent to Cancel. If included the third and fourth boxes return the numbers 3 and 4 respectively. The meanings of these buttons can be defined by the programmer. If no button names are given, buttons one and two will default to ENTER and CANCEL respectively. param3 (optional) row of text in which list box will go under. If this parameter is not specified or if a parameter of zero (0) is specified, the box will be placed under the cursor. param4 (optional) column of text in which list box will go under. If this parameter is not specified or if a parameter of zero (0) is specified, the box will be placed under the cursor. Note: If the row parameter is selected the column parameter must be selected as well. param5 (optional) height of the listbox in characters Note: Since the default PM font is proportional the character height and width are approximate values. param6 (optional) width of listbox in characters. An example of listbox usage is: retvalue = listbox("/one/two/three", "/Enter/Cancel/None") In this example there would be three entries in the list: one, two, and three. There would also be three buttons entitled: Enter, Cancel, and None. Since the last three parameters were omitted, the box would be located at the cursor position and would be wide enough to accommodate the longest element of the list and three buttons. Also see the ENTRYBOX procedure in this section for an alternative method of getting user input. ═══ 11.34. LOADFILE(files, options) -- in SLNOHOST.e ═══ Issues edit command on the specified files with the specified options. ═══ 11.35. LOADFILE(files,options) -- in SAVELOAD.e ═══ Issues edit command on the specified files with the specified options, after checking for host file specification ('H:'). ═══ 11.36. LOCK(filename) ═══ Locks a file from other users in a LAN situation. Returns a zero if successful; one if unsuccessful. This procedure is only available if requested with the WANT_LAN_SUPPORT option variable. ═══ 11.37. MakeTempName() ═══ Creates a temporary filename using the optional arguments filename and fileid. If no arguments are specified, the current filename and current fileid are used. For example, if filename = `origname' and its fileid is 2, then the temporary filename returned will be origname.$$2. ═══ 11.38. MATHCOMMON(input, suffix) ═══ Is responsible for math computations (dec, hex, or oct) done at commandline in E, where input is the expression to be calculated and suffix is either 'x', 'o' or '' depending upon the base of the number to be returned. ═══ 11.39. MAX(a,b) ═══ Returns the number which has the maximum value of those numbers in the arguments list. As many arguments as needed can be listed. ═══ 11.40. MESSAGE(mymsg) ═══ Prints the message specified by the string mymsg on the messageline. This procedure is a carry-over from earlier versions of E and effectively does the same thing as a SAYERROR statement, except this MESSAGE() procedure takes up more code. ═══ 11.41. MESSAGENWAIT() ═══ Prints the message passed to it in the editor messages dialog box and waits for Cancel or ESC. ═══ 11.42. MIN(a,b) ═══ Returns the number which has the minimum value of those numbers in the list of parameters. As many parameters as needed can be included for comparison. ═══ 11.43. MY_C_ENTER() ═══ Applies to c_enter key the appropriate action defined in C_ENTER_ACTION constant. ═══ 11.44. MY_ENTER() ═══ Applies to enter key the appropriate action defined in ENTER_ACTION constant. ═══ 11.45. NAMEFILE() -- in SLNOLOAD.e ═══ Issues name command using arg(1) as the new filename. ═══ 11.46. NAMEFILE() -- in SAVELOAD.e ═══ Issues name command using arg(1) as the new filename, after checking whether file is a host file. ═══ 11.47. NO_CHAR_MARK() ═══ Checks if WANT_CHAR_OPS option was set in STDCNF.e. ═══ 11.48. OPENSHELLWINDOW() ═══ Opens a edit window under a temporary filename for output. (i.e. like the DIR command does) ═══ 11.49. PARSE_FILE_N_OPTS(argstr) ═══ Parses argstr which contains a mix of options and DOS file specs. The DOS file specs can contain an '=' for the path or fileid, which will be replaced by the corresponding part of the previous file. ═══ 11.50. PARSE_FILENAME(var filename) ═══ Parses a DOS filename. Optional second argument gives source for '=' when used for path of fileid. Rc is 0 if successful, or rc is the position of '=' in first argument if no second argument given but was needed. ═══ 11.51. PARSE_LEADING_OPTIONS(var rest, var options) ═══ Parses options portion of the edit command. It does not assume that all options are specified before filenames. It is called by DEFC EDIT. ═══ 11.52. PBEGIN_MARK() ═══ Moves the cursor to the first character of the mark area. If the mark area is not in the active file, the marked file is activated. ═══ 11.53. PBEGIN_WORD() ═══ Moves the cursor to the beginning of the word if the cursor is on this word. If its not on a word, its moved to the beginning of the first word on the left. If there is no word on the left its moved to the beginning of the word on the right. If the line is empty the cursor doesn't move. ═══ 11.54. PBLOCK_REFLOW(option, var space, var tempofid) ═══ Reflows the text in the marked area; then the destination block area must be selected and a second call to this procedure to reflow the source block in the destination block. The source block is filled with spaces. Option=0 saves the marked block in temp file; option=1 reflows temp file text and copies it to marked area ═══ 11.55. PCENTER_MARK() ═══ Centers the strings inside a block mark. If a line mark exists, the text in the marked lines is centered within the current margins. If no mark exists, the text on the current line is centered within the current margins. ═══ 11.56. PCOMMON_ADJUST_OVERLAY(letter) ═══ Implements adjust and overlay commands for character and line marks (previously only block marks enjoyed these privileges); parameter letter specifies 'A' for adjust and 'O' for overlay. This procedure is only included if requested with the WANT_CHAR_OPS option variable. ═══ 11.57. PCOPY_MARK(var destfirstline, var destlastline, var destfirstcol, var destlastcol) ═══ Implements the copymark statement for character marks; parameters specify the marked area. ═══ 11.58. PDELETE_MARK(var destfirstline, var destlastline, var destfirstcol, var destlastcol) ═══ Implements the deletemark statement for character marks; parameters specify the marked area. ═══ 11.59. PDISPLAY_MARGINS() ═══ Puts the margin settings on the current line. ═══ 11.60. PDISPLAY_TABS() ═══ Puts the tab stops on the current line. ═══ 11.61. PEND_MARK() ═══ Moves the cursor to the end of the marked area. ═══ 11.62. PEND_WORD() ═══ Moves the cursor to the end of the word if the cursor is on this word. If it's not on a word, it's moved to the end of the first word on the right. If there is no word on the right it's moved to the end of the word on the left. If the line is empty the cursor doesn't move. ═══ 11.63. PFILE_EXISTS() ═══ Checks if file already exists in ring. ═══ 11.64. PFILL_MARK() ═══ Implements the fillmark statement for character marks; checks arg() to see if a character for fill was specified, otherwise prompts for a character. This procedure is available only if requested with the WANT_CHAR_OPS option variable. ═══ 11.65. PFIND_BLANK_LINE() ═══ Finds first blank line starting from current line. ═══ 11.66. PFIRST_NONBLANK() ═══ Finds first nonblank character in the current line. ═══ 11.67. PLOWERCASE() ═══ Changes all alphabetic characters in the marked area to lowercase. ═══ 11.68. PMARGINS() ═══ Returns the current margins setting. Uses pcommon_tab_margin(). ═══ 11.69. PMARK(mt) ═══ Marks at the cursor position; receives the mark type as an argument. ═══ 11.70. PMARK_WORD() ═══ Marks the word pointed at by the cursor. If the cursor is on a space the word at the right is marked. If there is no word on the right, the word on the left is marked. ═══ 11.71. PMOVE_MARK() ═══ Implements the movemark statement for character marks by calling pcopy_mark() and pcopy_delete(). ═══ 11.72. PPUT_STRING_BACK(string) ═══ Puts string back into marked area on current line. ═══ 11.73. PRESTORE_MARK(savemark) ═══ Marks the area specified in savemark, where savemark is a concatenated string composed of the components: first_line, last_line, first_col, last_col, fileid, marktype. ═══ 11.74. PRESTORE_POS(save_pos) ═══ Resets the cursor position according to save_pos, a string composed of the concatenation of the fields: .col, .line, .cursorx, and .cursory. ═══ 11.75. PRINTER_READY() ═══ In EPM this procedure will always return ready. It remains for compatibility with previous E macros. ═══ 11.76. PROOF1(word) ═══ Calls Lexam to spell check for the word specified by word. ═══ 11.77. PROOF2() ═══ Calls Lexam to begin spell-checking at the current word. ═══ 11.78. PSAVE_MARK(var savemark) ═══ Saves the specifications of the currently marked area in savemark, a string composed of the concatenation of: first_line, last_line, first_col, last_col, fileid, and marktype. ═══ 11.79. PSAVE_POS(var save_pos) ═══ Saves the cursor position according to save_pos, a string composed of the concatenation of the fields: .line, .col, .cursorx, and .cursory. ═══ 11.80. PSET_MARK(firstline, lastline, firstcol, lastcol, mt, fileid) ═══ Marks the area designated by the parameters. The firstline, lastline, firstcol and lastcol refer to position of the text in the file. The mt is the mark type (block, line, or character). The fileid is the id number of the file to be marked. ═══ 11.81. PTABS() ═══ Calls pcommon_tab_margin() to return tab settings. ═══ 11.82. PUPPERCASE() ═══ Converts all alphabetic characters in the marked area to uppercase letters. ═══ 11.83. QUITFILE() -- in SLNOHOST.e ═══ Issues quit command after checking windowing and modify status. ═══ 11.84. QUITFILE() -- in SAVELOAD.e ═══ Issues quit command after checking windowing and modify status. ═══ 11.85. REGISTER_MOUSEHANDLER(IsGlobal, event, mcommand) ═══ Allows the binding of mouse actions to commands. Mouse actions can be global or local. Mouse actions will be processed as follows: 1. local mouse action definition 2. global mouse action definition 3. mouse action ignored The variable IsGlobal determines whether the mouse action described is local or global. The variable event determines the mouse action to be bound with the command listed in the variable mcommand. Event should be in the following format: 'key action state' The key refers to the mouse key (either 1 or 2). The action must be one of the following: BEGINDRAG activates at the beginning of the drag ENDDRAG activates at the end of a drag CANCELDRAG activates if a drag is cancelled CLICK activates if a button (specified by key) is single clicked SECONDCLK activates if a button (specified by key) is double clicked These actions must be capitalized and have exactly one space between the key and the state numbers. The state should be the sum of the following: 0 = no states active 1 = shift key active 2 = control key active 4 = alternate key active An example of a mouse action definition is: register_mousehandler(0,'2 SECONDCLK 3','quit') This would set the second click of button two on the mouse with the shift and control states activated to do a QUIT command. This key action would be bound locally to a particular file. ═══ 11.86. REMOVE_TRAILING_SPACES() ═══ Calls strip() to remove all trailing blanks; no longer used by standard EPM, but left in for compatibility --> use strip() directly. ═══ 11.87. SAVEFILE(name) -- in SLNOHOST.e ═══ Issues save command with file specified in name parameter. ═══ 11.88. SAVEFILE(name) -- in SAVELOAD.e ═══ Issues save command with file specified, after checking whether the file is a host file. ═══ 11.89. SAYATBOX() ═══ Use the messageNwait command instead. ═══ 11.90. SCROLL_LOCK() ═══ Determines whether or not the Scroll Lock key has been set on; if so, returns 1; otherwise returns 0. ═══ 11.91. SEARCH_PATH(AppendPath, FileName) ═══ Searches a path specifed in AppendPath for the file specified in FileName. Returns the pathname, if successful; a null string if unsuccessful. ═══ 11.92. SELECT_EDIT_KEYS() ═══ Calls filetype() which returns the extension of the file whose fileid is specified in arg(1), then activates the default keyset edit_keys. In EPM this function is defunct. ═══ 11.93. SETLT(var LT_to_use) ═══ Sets the logical terminal to use. This procedure is only active if host editing is included. ═══ 11.94. SET_FTO(hostfile, bin var fto) ═══ Sets the file transfer options. This procedure is only active if host editing is included. ═══ 11.95. SetMouseSet (IsGlobal, NewMSName) ═══ Sets the current mouse action definition keys to the NewMSName. If IsGlobal is true then the effects will be global, if IsGlobal if false then the new settings will only affect the local file and not the rest of the files in the ring. ═══ 11.96. SetTitleText() ═══ Sets the text in the editor's active title bar. ═══ 11.97. SHOWWINDOW() ═══ Allows the edit window to be invisible or visible. ═══ 11.98. SKIP_SPACES() ═══ Performs upon universal variables input (a string) and i (a position in the string) set by next_sym(); increments i beyond any blank spaces. ═══ 11.99. SORT(firstline, lastline, firstcol, lastcol, fileid) ═══ Sorts the text in the area specified by the parameters. The first four arguements outlines the area of the text to be sorted and the fifth is the id number of the file to be sorted. ═══ 11.100. SPELLWORD() ═══ Checks the word at the cursor position, removing punctuation characters. It is assumed that the cursor is positioned at the beginning of the word. (Used by proof2 and proofword.) If it's a valid word then check the spelling of the word using the lexam opcode. If a valid result is returned place it in a PM list box using the 'listbox' procedure. Returns the length of the word found. The optional argument is a string containing a button name. E.g., '/Next' ═══ 11.101. SPLITLINES() ═══ Inserts a line; moves the text from the cursor position to the end of line onto the new line; and indents the new line to the column of the first non-blank character of the line preceding it. ═══ 11.102. SUBDIR() ═══ Uses SUBDIR if in DOS; uses FILEFIND if in OS/2 protect mode; then calls find_routine() to verify that the external utility program exists, and to get its path. ═══ 11.103. SYNONYM() ═══ Checks the next word on the line for its possible synonyms. If synonyms are found a PM list box is displayed showing the possible new words. ═══ 11.104. TRUNC(num) ═══ Truncates that part (if any) of num after a decimal point. ═══ 11.105. UNLOCK(file) ═══ Attempts to unlock a previously locked file in a LAN situation. Returns a zero if successful; a one if unsuccessful. This procedure is only available if requested with the WANT_LAN_SUPPORT option variable. ═══ 11.106. VMFILE(var name, var cmdline) ═══ Checks to make sure that a host filename (name) is of the correct form. ═══ 11.107. WINDOWSIZE1(row,col,x,y) ═══ Sizes a window row high and col wide based at the lower left hand corner coordinates of x and y. An optional fifth argument sets: 1 = size window 2 = move window 3 = both (default) ═══ 12. Return Codes ═══ RC Error strings ---- ----------------- -1 Unable to Initialize interpreter object -2 File not found -3 Path not found -4 Too many open files -5 Access denied -6 DOS ERROR: Message not available -7 Memory control blocks destroyed. Save files and reboot. -8 Insufficient memory -9 Error Building SubMenu -10 Error Building Menu Item -11 Error Showing Menu -12 Error Deleting Menu -13 Too Many AVIO window -14 DOS ERROR: Message not available -15 Invalid drive -16 DOS ERROR: Message not available -17 DIS ERROR: Message not available -18 No more files -19 Disk is write-protected -20 Unknown unit -21 Drive not ready -22 Unknown command -23 Data error (CRC) -24 Bad request structure length -25 Seek error -26 Unknown media type -27 Sector not found -28 Printer out of paper -29 Write fault -30 Read fault -31 General failure -32 ERROR: Message not available ... ERROR: Message not available -253 ERROR: Message not available -254 Numeric overflow or underflow -255 Invalid number of arguments -256 Recursion too deep -257 Invalid number of parameters -258 Out of string space -259 Expression stack overflow -260 Invalid fileid -261 Illegal opcode -262 -263 Invalid argument -264 For loops nested too deep -265 Divide by zero -266 Unable to shrink -267 Invalid call by reference -268 Procedure needs more arguments -269 User Break. Command halted -270 Not enough memory -271 Error in margin settings -272 Error in tab settings -273 String not found -274 Unknown command -275 Missing filename -276 Line too long to join -277 Too many files -278 Line(s) truncated -279 Text already marked -280 Text not marked -281 Source destination conflict -282 New file -283 Line mark required -284 Error opening file -285 Error writing file -286 Error reading file -287 Insufficient disk space -288 Block mark required -289 Too many rings -290 Invalid EX file or incorrect version. -291 No main entry point -292 Error closing file -293 has been modified -294 Quit without saving? -295 -296 -297 -298 -299 -300 Command dialog box too long to shell -301 Cannot unlink module in use -302 Cannot unlink base keyset module -303 Internal error: unlink invalid mod -304 Linking module error -305 DEFMAIN not found -306 DEFINIT not found -307 Link: file not found -308 Link: invalid filename -309 File already linked -310 Unlink: unknown module -311 Unlink: bad module filename -312 Call: duplicated proc -313 Call: unknown proc -314 Grep: memory error -315 Grep: missing ] -316 Grep: bad range in [a-z] -317 Grep: empty [] -318 Grep: regular expression too long -319 Dynalink: incorrect number of parameters -320 -321 Cannot find keyset -322 Dynalink: unrecognized library name -323 Line number invalid or too large for file -324 Keyboard status failed -325 Buffer creation size too large -326 Dynalink: unrecognized procedure name -327 Too many keysets -328 -328 Invalid first parameter -329 Invalid second parameter -330 Invalid third parameter -331 Invalid fourth parameter -332 Invalid fifth parameter -333 Invalid sixth parameter -334 Invalid seventh parameter -335 Invalid Subcommand -336 Invalid column number -337 Invalid array identifier -338 Array already exists: -339 ERROR: Message not available ... ERROR: Message not available etc. ═══ 13. ET Compilation Error Message Explanations ═══ If you have made changes to the configuration or have programmed your own macros in the E language, this section is important to you. Any syntactic or semantic errors in your programming, will be noted by the ET compiler. The following section describes each compilation error in simple terms. When you receive an error from ET, note the error message and look it up in the following list. The messages appear in alphabetic order. ═══ 13.1. Column specification out of range. ═══ The value specified for a column position exceeds the compiler's maximum line length of 255. ═══ 13.2. Comment not terminated. ═══ You have begun a comment with the '/*' string but never ended it with a matching '*/'. This means that all code after the comment has been ignored by the compiler. Reaching an end of file has alerted the compiler to the fact that the comment was not terminated. ═══ 13.3. DEFMAIN already defined. ═══ You have defined more than one main procedure using the DEFMAIN statement. Only one can be defined at a time. See User's Manual section Definition Primitives for more information. ═══ 13.4. EX code too big. ═══ The code that ET is producing after compiling your input file is taking up more space than allowable. The maximum amount of memory available for a .EX file is 65,500 bytes. ═══ 13.5. Expecting '('. ═══ The compiler was expecting a left parenthesis. Possible reasons for this are that you have called a procedure and omitted the parentheses after the procedure name. The syntax for procedure calls is either: proc_name([parameters]) OR call proc_name([parameters]) ═══ 13.6. Expecting ')'. ═══ The compiler was expecting a right parenthesis to match a left parenthesis which was read in earlier. Perhaps you have not matched each parenthesis in a procedure call or complex expression. For example, if the following expression was typed in YOUR_FILE.E: call proc_test( k=( (a*b)+ 8 ), you would have received such an error message because there are three left parentheses and only two right parentheses. ═══ 13.7. Expecting ';'. ═══ The compiler's newline symbol is the semi-colon (';'). Therefore, they are often interchangeable. A statement was encountered whose syntax requires either a semi-colon or a new line in a specific place, but no such semi-colon or new line was found. For example, each INCLUDE statement is required to end with either a semi-colon or a new line. All of the following examples are syntactically correct: include 'mystuff.e' ; include 'mykeys.e' AND include 'mystuff.e' include 'mykeys.e' AND include 'mystuff.e' ; x = 1 However, you could not have multiple INCLUDE statements on one line without a semi-colon as separator. ═══ 13.8. Expecting ','. ═══ A statement has been found whose syntax dictates that there should be a comma in a specific position, yet no comma was found there. The most likely cause of this error message is that you have called some built-in procedure, but have not given the correct number of parameters. The compiler is looking for a comma which would indicate that there are more parameters still to come. ═══ 13.9. Expecting '='. ═══ A statement was found whose syntax dictates that an assignment operator must occur at some specific place in the statement, but no such assignment symbol was found. One example of such a statement is the FOR statement. As shown in section Conditional and Loop Statements, there must be a '=' symbol immediately after the loop variable name. The other likely causes of this error are syntax errors in: (1) the FUNCTIONKEYTEXT statement (see Built-in Statements and Procedures for correct syntax) and (2) a CONST declaration (see Constants). ═══ 13.10. Expecting an identifier. ═══ A statement has been found whose syntax dictates that there should be an identifier in a specific position, yet no such identifier was found. One possible cause of this error message is that you have defined a keyset with the DEFKEYS keyword, but forgot to name the keyset. See section Key Definitions (DEF and DEFKEYS) for the syntax of the DEFKEYS statement. Another less obvious reason for this error is that you have used a keyword or procedure name in place of an identifier. For example, if you try to declare: UNIVERSAL function_key_text Since function_key_text is a predefined universal variable, it is a reserved word, and therefore is not considered an identifier. ═══ 13.11. Expecting constant expression. ═══ You have begun a constant definition statement by using the CONST keyword, but you have not assigned a constant expression (an expression involving only arithmetic operators, numbers and previously defined constants) to an identifier. Please use the following syntax: CONST max_id=7 max_len=max_id * 10 ═══ 13.12. Expecting DEFinition primitive. ═══ The compiler is expecting a definition primitive, i.e. one of the DEFxxxx statements, a SET statement, an INCLUDE statement or a CONST statement. Unfortunately, this error message can be triggered at inappropriate times when the compiler is confused by the syntax it has read. This error message often complains about a statement in the middle of a DEF construct. Do not necessarily assume that you need to add a DEF. Each of these cases must be evaluated individually. However, this error message does have value when it reports on a statement that has been issued outside a DEF construct. Remember that you cannot have statements outside a DEFxxxx block. All statements must be contained within a DEFxxxx primitive. Often a statement issued outside a DEF is not reported because since there is no keyword or statement to terminate the DEF, the compiler assumes that the statement belongs to the last DEF. However, there are cases when it will correctly report this error. For example, assume the following statements occur in some file TEST.E: CONST stuff = 1 sayerror "stuff is " stuff defproc test1() temp = 45 * 36 During compilation of TEST.E, the user would receive an "Expecting DEF" error message with an arrow pointing to the sayerror statement. Since a CONST statement is a DEF primitive, it ends all previous DEFS, and since sayerror is not accepted as part of a CONST construct, an error is reported. ═══ 13.13. Expecting DO ═══ A WHILE construct has been started, i.e. a WHILE keyword has been found, but the keyword DO is missing from the statement. Please check the section on Conditional and Loop Statements for the syntax of the WHILE DO statement. ═══ 13.14. Expecting DO WHILE or DO FOREVER ═══ One of the DO constructs has been started, i.e. a DO keyword was found, but the rest of the statement's syntax does not fit any of the DO constructs ( DO WHILE, DO FOREVER, and/or DO (FOR) ). See section Conditional and Loop Statements for the syntax of the DO construct. ═══ 13.15. Expecting END to DO loop. ═══ One of the DO constructs ( DO-WHILE, DO FOREVER or DO (FOR) ) has been started, but no 'END' or 'ENDDO' statement has been found to end the loop. Please refer to section Conditional and Loop Statements for the syntax of the DO constructs. ═══ 13.16. Expecting ENDFOR. ═══ A FOR construct has been started, i.e. a FOR keyword has been found, but no ENDFOR keyword has been found to end the loop. Please check the section on Conditional and Loop Statements for the syntax of the FOR statement. ═══ 13.17. Expecting ENDIF to terminate IF statement. ═══ An IF keyword has been read, but no ENDIF statement has been found to end the block of statements encased by the IF condition. See the section on Conditional and Loop Statements for the syntax of the IF statement. ═══ 13.18. Expecting ENDLOOP to terminate LOOP. ═══ A LOOP construct has been started, but no ENDLOOP statement has been found to end the loop. See section Conditional and Loop Statements for the syntax of the LOOP construct. ═══ 13.19. Expecting ENDWHILE to terminate WHILE. ═══ A WHILE construct has been started, but no ENDWHILE statement has been found to end the loop. Please refer to section Conditional and Loop Statements for the syntax of the WHILE construct. ═══ 13.20. Expecting procedure name. ═══ A procedure definition has been started, i.e. a DEFPROC keyword has been found, but no procedure name appeared after it to identify the procedure. Please see the section on Definition Primitives for the syntax of a DEFPROC statement. ═══ 13.21. Expecting quoted string. ═══ A statement was found whose syntax dictates that a quoted string must occur at some specific place in the statement, but no such quoted string was found. An example of such a statement is the SAY statement. As shown in section Built-in Statements and Procedures, there must be a quoted string immediately after the SAY keyword. ═══ 13.22. Expecting THEN. ═══ An IF construct has been started, i.e. an IF keyword was found, but no THEN keyword can been found. See section Conditional and Loop Statements for the syntax of the IF-THEN-ELSE statement. ═══ 13.23. Expecting TO. ═══ A FOR construct has been started, i.e. a FOR keyword has been found, but the keyword TO is missing from the statement. Please check the section Conditional and Loop Statements for the syntax of the FOR statement. ═══ 13.24. Expecting VALUE. ═══ A PARSE statement has been started, i.e. the keyword PARSE was found, but neither a VALUE nor an ARG keyword can been found. See the User's Manual section The Parse Statement for the syntax of the PARSE statement. ═══ 13.25. Expecting variable name. ═══ A statement was found whose syntax dictates that a variable name must occur at some specific place in the statement, but no such variable name was found. An example of such a statement is the FOR statement. As shown in the section on Conditional and Loop Statements, there must be a variable name (the loop variable to be incremented) immediately after the FOR keyword. ═══ 13.26. Expecting WITH. ═══ A PARSE-VALUE statement has been started, i.e. the keywords PARSE and VALUE were found, but a WITH keyword cannot be found. See the section on The Parse Statement for the syntax of the PARSE statement. ═══ 13.27. Expression not assignment compatible. ═══ The compiler has detected an assignment in which the expression on the right side of the assignment operator can not be assigned to the expression or identifier on the left side. The most common cause of this is that you have tried to assign a value to something other than a variable, i.e. a constant or procedure. ═══ 13.28. Expression too complex. ═══ An expression is any combination of identifiers (variables, constants, and/or procedures), numbers and operators that fit the syntax of a language. A complex expression is one that contains expressions within itself. For example, the following is an expression: test_var + 6. An example of a complex expression would be: ( (test_var + 6) * 8). Each of the innermost expressions must be evaluated before the entire expression can be assigned a value. The specified expression in your input file is too complicated, i.e. has too many expressions within itself, for the compiler to evaluate it. Please break the expression into several less complex expressions. For example, let us assume that the following expression was too complex: call proc_test( k=( (a*b)+ 8 ) ), You could simplify the call to proc_test by assigning some of the inner expressions to temporary variables. One solution would be: temp1 = a*b k = temp1 + 8 call proc_test(k) Note: The above expression is a simple example. It is not too complex for the compiler. ET allows for 40 expressions within an expression. ═══ 13.29. Extraneous parameters. ═══ You have specified too many parameters in the command dialog box. The syntax is: ET [options] inputfile[.e] [outputfile[.ex]] Remember that any options MUST PRECEDE the input and output filenames! ═══ 13.30. FUNCTION_KEY_TEXT exceed max number of characters. ═══ You have attempted to change the text displayed at the bottom of the screen which describes what function each function key performs. The text that you have chosen is longer than the maximum number of characters allowed, which is 80. ═══ 13.31. Identifier already defined as same or different type. ═══ You are trying to use an identifier to name a variable, constant or procedure uniquely, yet the identifier has already been used in the same scope for another purpose. Check over your program and rename the appropriate identifiers. ═══ 13.32. Identifier too long. ═══ The number of characters in the name of the specified variable, constant, procedure, etc. exceeds the maximum allowance of 255 characters. Please rename it with fewer letters and/or numbers. ═══ 13.33. Illegal character. ═══ This character does not make sense or is not allowed in the E language. One example of E code which would yield this error message is if a unary minus or plus operator is used preceding an alphabetic character rather than a digit. For example, temp = +c These unary operators make sense only with numeric operands. ═══ 13.34. Illegal operator. ═══ An operator is some function to be performed on its operands. Operands are identifiers or constant values that are acted upon by operators. Examples of operators are: '+' (addition), '=' (assignment), 'NOT' (logical negation), and '<=' (less than or equal). The operator you have specified does not exist in the E language. Please check the Operators section for a complete list of operators. ═══ 13.35. INCLUDES nested too deep. ═══ A nested INCLUDE statement means that a file, for example FILE1.E, contains a statement: include 'file2.e' and that file2.e also contains an INCLUDE statement, which includes a third file. ET only allows for 5 levels of nested include files. You have exceeded this limit. Please reorganize your files. ═══ 13.36. Internal error in POPS. ═══ This error is internal to the workings of the ET compiler. It has nothing to do with user input. Please send a note to the userid EOS2 at YORKTOWN with information regarding the error. ═══ 13.37. Invalid argument. ═══ The argument specified in the procedure call is incorrect. Specifically, the string argument in the SAYERROR() procedure call does not match any of the strings associated with error messages known to the compiler. Read the description of the usage of the SAYERROR() procedure in section Built-in Statements and Procedures for more information. ═══ 13.38. Invalid color. ═══ You are trying to redefine the colors of the E editor; however the syntax of your statement is incorrect. Possible explanations of this are that: (1) you have not used an identifier to name the constant, (2) you have not used a valid color value name, or (3) you have not separated each assignment with either a semi-colon or a new line. An example of the syntax is: /* color example */ TEXTCOLOR = BLUE For more information on usage, see section Changing the Default Configuration in The EPM User's Guide. For a list of valid color value names, see the top of the COLORS.E file which contains the values of the defaults. ═══ 13.39. Invalid cursor setting. ═══ You are trying to set the default cursor sizes, but the values you have given in the set cursors statement are not valid. Valid values are 1 through 15. ═══ 13.40. Invalid expression. ═══ This expression is not a valid expression in the E language. Please refer to E Language Syntax for a list of all valid expressions. ═══ 13.41. Invalid field name. ═══ You have attempted to manipulate a field in the fileid structure; however the field you have named does not exist. Check section Fileid Structure for a list of all field names. ═══ 13.42. Invalid key name. ═══ A KEY keyword has been found, but no valid keyname followed the keyword. There are a limited number of keys on the keyboard that can be redefined. For a complete list of those keys, see E Language Syntax. ═══ 13.43. Invalid margin setting. ═══ You are trying to reset the margins for the E editor, but the column values of your desired margin settings are invalid. Possible causes of this error are that you have tried: (1) to set a margin past E's maximum margin column (254), (2) to set a margin in a zero or negative column, or (3) to set the left margin in a column greater than the right margin. Please refer to The EPM User's Guide for examples of the correct syntax. ═══ 13.44. Invalid number of parameters. ═══ You have called a procedure with fewer parameters than it is defined to have. For example, in the section Built-in Statements and Procedures, look at the description of the procedure SUBSTR(). SUBSTR() is defined to have two, three or four parameters, but it requires AT LEAST two parameters to perform its function. If the user invokes the function with only one argument, for example SUBSTR('abc'), an error will occur. ═══ 13.45. Invalid numeric. ═══ You have attempted to perform some arithmetic function on variables that are not numeric; or you have mixed other characters in with some digits. For example, 35.x or 3temp_var are not valid expressions. The compiler expects identifiers to BEGIN WITH AN ALPHABETIC CHARACTER, and expects numbers to consist solely of digits and certain special characters (for example, the decimal point "."). ═══ 13.46. Invalid option. ═══ You have specified an option in the command dialog box which does not exist. Check The EPM User's Guide or section Command Summary for all possible command dialog box options. ═══ 13.47. Invalid set name. ═══ You are trying to set a configurable option for the E editor, but the option you have named in the SET statement does not exist. Please check The EPM User's Guide for a complete list of options. ═══ 13.48. Invalid tab setting. ═══ You are trying to reset the tabs for the E editor, but the column values of your desired tab settings are invalid. Possible causes of this error are that: (1) you have tried to set a tab past E's maximum column (255), (2) you have tried to set a tab in a negative column, or (3) you have not typed the tab settings in ascending order. Tab settings CANNOT be listed in a mixed order, for example: tabs 5 10 20 15 30 25 ... They must be written in ascending order. In the above example, the statement must be rewritten as follows: tabs 5 10 15 20 25 30 ... ═══ 13.49. ITERATE may only be executed inside a loop. ═══ An ITERATE statement has been issued outside one of the loop constructs (WHILE, LOOP, or DO). Since the ITERATE statement only makes sense in combination with a loop, this is an error. See section Conditional and Loop Statements for the rules governing and syntax of the ITERATE statement. ═══ 13.50. Keyset not defined. ═══ You have issued a KEYS statement to change the keyset to a predefined keyset; however the named keyset has not been defined in the current scope. In order to use a KEYS keyset_name statement, you must have issued a DEFKEYS keyset_name statement to define the named keyset and then issued a series of DEF statements to define the new function of the desired keys. A sample keyset definition can be found in section Key Definitions (DEF and DEFKEYS). ═══ 13.51. LEAVE may only be executed inside a loop. ═══ A LEAVE statement has been issued outside one of the loop constructs (WHILE, LOOP, or DO). Since the LEAVE statement only makes sense in combination with a loop, this is an error. See section on Conditional and Loop Statements for the rules governing and syntax of the LEAVE statement. ═══ 13.52. Line too long. ═══ The number of characters in this line exceeds the maximum. The maximum line length is 255 characters. Please break-up the line using the technique discussed in section Line Continuations. ═══ 13.53. More than max number of global variables. ═══ You have defined more global variables than the compiler allows. The maximum number of global variables is 8200. Note Any variable preceded by the UNIVERSAL keyword is considered global, i.e. any procedure can access it. ═══ 13.54. More than max number of local variables. ═══ Your procedure has been defined with more than the compiler's maximum number of allowable local variables, i.e. variables defined within the procedure. The maximum number of locals is 1038. ═══ 13.55. Not enough core. ═══ Your computer does not have enough core memory (primary memory not disk space) to compile the specified input file and write compiled code to an output file. Typically, 320K of memory is required; however if you have added a great amount of code to the e.e file, more memory may be necessary. ═══ 13.56. Number out of range or expecting number. ═══ This error could occur for a few different reasons. The first possible cause of the error is incorrect syntax or semantics in a parse statement. If a '+' or '-' was encountered in the template portion of a PARSE statement, a number is expected to follow it. Either a number did not follow one of these operators or the number that did follow exceeded 255. Remember that the numbers in the template represent column specifications and therefore cannot exceed the maximum column. Please see section The Parse Statement for the exact syntax of the parse statement. Another possible cause of this error is that an arithmetic operator symbol was found in an expression, and yet all of the operands were either not numeric or exceeded the compiler's maximum number of 32,767. ═══ 13.57. Number too large. ═══ This error occurs only when the compiler is translating ASCII codes preceded by the '\' operator. Values following such a '\' cannot exceed 255. See section String Expressions for a more detailed explanation of this use of the backslash character. ═══ 13.58. Numeric overflow. ═══ You have attempted to perform some arithmetic function where the result has an exponent greater than 999999999. ═══ 13.59. Out of symbol table space. ═══ The compiler allocates a certain amount of memory space for each variable. The space is needed to store necessary information relevant to that variable. There is not enough primary memory (not disk space) on your computer to allow any more variables to be used. ═══ 13.60. Procedure not defined. ═══ You have called or made reference to a procedure which was never defined. Please define the procedure or delete the call to it. Note: the compiler will not tell you where the call to the undefined procedure occurred or whether there are many such occurrences. ═══ 13.61. String not terminated. ═══ The specified string was not enclosed with quote marks. The final quote was omitted. ═══ 13.62. Too many arguments. ═══ You have defined a procedure or function with more than the compiler's maximum number of allowable arguments. The maximum number of arguments is 8. ═══ 13.63. Unable to open input file. ═══ The compiler could not open the file which you listed in the command dialog box as the input file. This is probably due to the fact that no such file exists. Check your spelling of the filename and make sure the file is in the current directory. ═══ 13.64. Unable to open output file. ═══ The compiler cannot create the file you named in the command dialog box as the output file. This probably occurred because you gave a nonexistent path to the file. Check the spelling and accuracy of the pathname. (The default pathname is the current directory.) ═══ 13.65. Unable to read input file. ═══ The compiler was unable to read from the input file you specified in the command dialog box. This maybe due to the fact that the file is locked or damaged. Please check the file. ═══ 13.66. Unable to write output file. ═══ The compiler cannot write to the file you named in the command line as the output file. This error could occur because the file is read-only or because no space is left on the disk. ═══ 13.67. Variable not initialized. ═══ You have used a variable which was never initialized. The variable has no value; therefore the expression containing it cannot be evaluated. Another common cause for this error is when a command has been issued within an E statement, but the command has not been quoted. Please read the section Using EPM Commands in E Statements for information on how to use commands in an E program. ═══ 14. Ordinal Values of Functions Accessed via DOSCALLS.DLL ═══ This list shows the mapping between the DOS system function names and their ordinal values. In order to access one of these system functions in OS/2, you must make a call to the function DYNALINK(), and include the function's ordinal value in the parameter list. For more information, see the DYNALINK() entry in section Built-in Statements and Procedures. Function Name Ordinal Value ------------- ------------- DBGETKVAR 109 DBGETOWNER 117 DBMEMFREE 116 DBMEMLOCK 112 DBMEMREALLOC 115 DBMEMUNLOCK 113 DBPHYSINFO 118 DBSEGALLOC 114 DOSALLOCHUGE 40 DOSALLOCSEG 34 DOSALLOCSHRSEG 35 DOSBEEP 50 DOSBUFRESET 56 DOSCALLBACK 157 DOSCHDIR 57 DOSCHGFILEPTR 58 DOSCLIACCESS 51 DOSCLOSE 59 DOSCLOSESEM 23 DOSCREATECSALIAS 43 DOSCREATESEM 24 DOSCWAIT 2 DOSDELETE 60 DOSDEVCONFIG 52 DOSDEVIOCTL 53 DOSDEVIOCTL2 99 DOSDUPHANDLE 61 DOSENTERCRITSEC 3 DOSENUMATTRIBUTE 204 DOSERROR 120 DOSEXIT 5 DOSEXITCRITSEC 6 DOSEXITLIST 7 DOSFILELOCKS 62 DOSFINDCLOSE 63 DOSFINDFIRST 64 DOSFINDNEXT 65 DOSFLAGPROCESS 15 DOSFREEMODULE 46 DOSFREESEG 39 DOSGETCP 130 DOSGETDATETIME 33 DOSGETENV 91 DOSGETHUGESHIFT 41 DOSGETINFOSEG 8 DOSGETMACHINEMODE 49 DOSGETMODHANDLE 47 DOSGETMODNAME 48 DOSGETPID 94 DOSGETPROCADDR 45 DOSGETPRTY 9 DOSGETSEG 121 DOSGETSHRSEG 36 DOSGETSTDA 119 DOSGETVERSION 92 DOSGIVESEG 37 DOSGLOBALSEG 132 DOSHOLDSIGNAL 13 DOSHUGEINCR 136 DOSHUGESHIFT 135 DOSICANONICALIZE 100 DOSICREATETHREAD 1 DOSIEXECPGM 4 DOSIRAMSEMWAKE 125 DOSIREAD 79 DOSISEMREQUEST 18 DOSISEMWAIT 21 DOSISETCP 131 DOSISYSSEMCLEAR 17 DOSISYSSEMSET 19 DOSIWRITE 87 DOSKILLPROCESS 10 DOSLIBINIT 96 DOSLOADMODULE 44 DOSLOCKSEG 122 DOSMAKEPIPE 16 DOSMEMAVAIL 127 DOSMKDIR 66 DOSMOVE 67 DOSMUXSEMWAIT 22 DOSNEWSIZE 68 DOSOPEN 70 DOSOPEN2 95 DOSOPENSEM 25 DOSPHYSICALDISK 129 DOSQPATHINFO 98 DOSSETPATHINFO 104 DOSPOKETESTDAEMON 104 DOSPORTACCESS 69 DOSPROFILE 133 DOSPTRACE 12 DOSQCURDIR 71 DOSQCURDISK 72 DOSQFHANDSTATE 73 DOSQFILEINFO 74 DOSQFILEMODE 75 DOSQFSINFO 76 DOSQHANDTYPE 77 DOSQPROCSTATUS 154 DOSQTRACEINFO 93 DOSQVERIFY 78 DOSREADPHYS 103 DOSREALLOCHUGE 42 DOSREALLOCSEG 38 DOSRESUMETHREAD 26 DOSRMDIR 80 DOSSELECTDISK 81 DOSSEMSETWAIT 20 DOSSENDSIGNAL 134 DOSSETCP 153 DOSSETDATETIME 28 DOSSETFGND 101 DOSSETFHANDSTATE 82 DOSSETFILEINFO 83 DOSSETFILEMODE 84 DOSSETFSINFO 97 DOSSETINFOSEG 128 DOSSETMAXFH 85 DOSSETPRTY 11 DOSSETSIGHANDLER 14 DOSSETVEC 89 DOSSETVERIFY 86 DOSSGSWITCH 54 DOSSGSWITCHME 55 DOSSGSWITCHPROC 124 DOSSICG 95 DOSSIZESEG 126 DOSSLEEP 32 DOSSUSPENDTHREAD 27 DOSSWAPTASKINIT 102 DOSSYSTEMSERVICE 88 DOSSYSTRACE 90 DOSTIMERASYNC 29 DOSTIMERSTART 30 DOSTIMERSTOP 31 DOSUNLOCKSEG 123 GETADDR 111 GETHEADERS 108 GETSELADDR 110 PANICWRITE 105 STRUCHECK 106 STRURESUPDATE 107 UNUSEDA 98 UNUSEDB 99 The following Operating System entry points are defined in the library DOSCALL1. In this case, the procedures must be called by name rather than ordinal value. For an example of this usage, see the explanation of the DYNALINK() function. DOSREAD DOSWRITE DOSERRCLASS DOSSEMREQUEST DOSSEMCLEAR DOSSEMWAIT DOSSEMSET DOSEXECPGM DOSCREATETHREAD DOSSUBSET DOSSUBALLOC DOSSUBFREE DOSREADASYNC DOSWRITEASYNC DOSSEARCHPATH DOSSCANENV ═══ 15. Advanced Compiler Features ═══ Advanced compiler features. ═══ 15.1. Compile time variables ═══ Compile time variables. ═══ 15.1.1. Definition ═══ E provides certain language extensions and configuration options by means of a single pass symbol table access facility. This means that the macro programmer can assign a compile time variable and later test the value of that variable. ═══ 15.1.2. Advantages ═══ The usage of compile time variables can aid in the portability of the macro language. This means that one set of macros can be used in DOS, OS/2, and the Presentation Manager environments. For examples of this see the current E-macros. By testing the version, the compiler can know which code to include. This means later versions can make use of the newest features while still maintain compatibility with older versions of the E family of editors. The usage of compile time variables saves disk space. The reason for this is that universal variables must be actually saved on the disk in the resultant .EX file. Compile-time variables are saved in far memory while the translation process executes and are freed when the translation process ends. ═══ 15.1.3. Compile-time variable assignment ═══ We allow a compile-time variable assignment by means of the define statement in the macro language. An example of such as assignment is the following: define compile_variable = 'this is a compile-time variable' ═══ 15.1.4. Compile-time variable and conditional compilation ═══ Compile-time variables can be used in concert with the translator's compile if statements to provide a powerful conditional compilation facility. An example of the usage of compile if is the following: compile if compile_variable = 'this is a compile-time variable' sayerror 'compile_variable exists' compile else sayerror 'compile_variable does not exists' compile endif ═══ 15.1.5. Compile `defined' test ═══ In addition to the straightforward test of a compile-time variable value, we can also test whether a variable is defined or not. This is useful in cases where the macro programmer does not wish to expressly assign a value to a compile-time variable, but simply would like to know if the variable has any value. For example: compile if defined compile_variable sayerror 'compile_variable is defined' compile else sayerror 'compile_variable is not defined' compile endif ═══ 15.1.6. Text replacement ═══ A powerful text replacement function is part of the translator language. This text replacement option allows one to literally change the text upon which the translator is operating during the translation process. The text replacement option is initiated when the translator encounters a '$' (dollar sign). When the text replacement character is encountered the translator places the value of the compile-time variable that follows the '$' into a text buffer and begins to use the that buffer as the input buffer to the translator. When the buffer is empty, we switch back to the previous translation buffer. For example: define sayinformation = 'sayerror' $sayinformation 'this is information' In the preceding example, we have defined our own language extension. The example is equivalent to the standard E code of: sayerror 'this is information' ═══ Syntax ═══ ABBREV(information, info [, length]) ═══ Definition ═══ ABBREV returns 1 if info is equal to the leading characters of information and the length of info is not less than length. ABBREV returns 0 if neither of these conditions is met. If specified, length must be a nonnegative whole number. The default for length is the number of characters in info. ═══ Example ═══ Here are some examples: ABBREV('Print','Pri') -> 1 ABBREV('PRINT','Pri') -> 0 ABBREV('PRINT','PRI',4) -> 0 ABBREV('PRINT','PRY') -> 0 ABBREV('PRINT','') -> 1 ABBREV('PRINT','',1) -> 0 Note: A null string will always match if a length of 0 (or the default) is used. This allows a default keyword to be selected automatically if desired. For example: say 'Enter option:'; pull option . select /* keyword1 is to be the default */ when abbrev('keyword1',option) then ... when abbrev('keyword2',option) then ... ... otherwise nop; end; ═══ Syntax ═══ ACTIVATEACCELTABLE table_name ═══ Definition ═══ Makes the named accelerator table the active one. ═══ Syntax ═══ ACTIVATEFILE fileid ═══ Definition ═══ Makes the file identified by the variable fileid the current file. Fileid must be a simple variable (as indicated by the word var) containing a valid file id number. If you give an expression, the compiler will stop and complain, "Expression not assignment compatible." ═══ Example ═══ Correct usage: ACTIVATEFILE myfileid The following expressions will not work: ACTIVATEFILE fileid' ' ACTIVATEFILE ARG(1) ═══ Syntax ═══ ADJUSTBLOCK | ADJUST_BLOCK ═══ Definition ═══ Overlays marked block at cursor, like the standard key definition Alt-A. The source block is filled with spaces. ═══ Syntax ═══ ADJUSTMARK ═══ Definition ═══ Moves marked text to the location of the cursor by overlaying. The old location is filled with blanks. ═══ Syntax ═══ ARG([numeric_expression]) ═══ Definition ═══ May be used only in a DEFMAIN, DEFC or DEFPROC. In the case of a DEFPROC, if numeric_expression is not given, the number of arguments passed to the macro is returned. Otherwise the expression is evaluated to a number and the corresponding argument is returned. If there are fewer arguments than specified by the expression, a null string is returned. ═══ Example ═══ For example: numofargs = arg() argfour = arg(4) In the first example, the number of arguments that were passed is returned in the variable numofargs. In the second example the four argument is returned in the variable argfour. ═══ Syntax ═══ ASC('character') ═══ Definition ═══ Returns the ASCII decimal value of the character expression. ═══ Example ═══ For example: ASC('A') = 65 ═══ Syntax ═══ ATOI('numeric_expression') ═══ Definition ═══ Converts the E language representation of a number (as a string) to the C language representation of an integer (data type int). Since many functions that are available through the function DYNALINK() require input to be in binary numbers as opposed to ASCII strings, we provide functions to convert ASCII strings into binary numbers. For an example of this usage see the DYNALINK() entry in this section. ═══ Example ═══ The following shows the high-level strings and the equivalent machine representation: string machine representation (hexadecimal digits) '40' 34 30 /* '4' is 0x34 & '0' is 0x30 */ atoi('40') 28 00 /* 28 00 is 40 decimal */ /* since byte swapping */ /* exists in the Intel */ /* architecture */ /* In reality the word */ /* would be 0x0028 */ ═══ Syntax ═══ ATOL('numeric_expression') ═══ Definition ═══ Converts the E language representation of a number (as a string) to the C language representation of a long integer (data type long). For use with C functions that require numeric parameters, for example function calls via DYNALINK(). ═══ Syntax ═══ ATTRIBUTE_ACTION subop, var class, var offset, var column, var line [, var fileid] ═══ Definition ═══ subop is one of the following: const FIND_NEXT_ATTR_SUBOP = 1 FIND_PREV_ATTR_SUBOP = 2 FIND_MATCH_ATTR_SUBOP = 3 DELETE_ATTR_SUBOP = 16 The use of the remaining parameters varies with the operation to be performed. FIND_NEXT_ATTR_SUBOP This action finds the next occurance (not including the specified location) of an attribute record of the specified class. class On input, this specifies the attribute class of the attribute records of interest. A value of ANY_CLASS (zero) indicates that the position of the next attribute record of any class should be returned. On output, the class of the found attribute. A class of zero indicates that no attribute record was found. offset On input, the location (non-inclusive) where the search is to begin. On output, the location of the found attribute record. If none was found, then the parameter will not be modified. column On input, the location where the search is to begin. On output, the location of the found attribute record. If none was found, then the parameter will not be modified. line On input, the location where the search is to begin. On output, the location of the found attribute record. If none was found, then the parameter will not be modified. fileid The fileid of the file where the search is to occur. The default is the current file. FIND_PREV_ATTR_SUBOP This action is just like the FIND_NEXT_ATTR_SUBOP except that it finds the previous occurance of an attribute record of the specified class rather than the next occurance. FIND_MATCH_ATTR_SUBOP This action finds the (push/pop model) attribute record that matches the specified attribute record. For example, if a push attribute record was specified, the location of the corresponding pop attribute record is returned. class Unused parameter offset On input, the location (non-inclusive) where the search for the match is to begin. An attribute record must exist at this location or an error code will be flagged. On output, the location of the found attribute record. If none was found, then the parameter will not be modified. column On input, the location where the search is to begin. On output, the location of the found attribute record. If none was found, then the parameter will not be modified. line On input, the location where the search is to begin. On output, the location of the found attribute record. If none was found, then the parameter will not be modified. fileid The fileid of the file where the search is to occur. The default is the current file. DELETE_ATTR_SUBOP Deletes the attribute record at the specified location. If attribute records exists at the specified character position having an offset of the same sign as the specified attribute record but of larger magnitude, then those attribute records will be shifted in (their offset will be incremented or decremented) to fill in the vacated location. class On input, this is unused On output, the class of the deleted attribute record. Zero if no attribute record exists at the specified location. offset The location of the attribute record to be deleted. column The location of the attribute record to be deleted. line The location of the attribute record to be deleted. fileid The fileid of the file where the specified attribute record is to be found. The default is the current file. See Attribute Pairs for additional information on attributes, or EPMTOOLS PACKAGE on the OS2TOOLS disk for the file ATTRIBUTE.DOC that more fully describes programming attributes. ═══ Example ═══ class = 1 -- 1 = COLOR_CLASS offst1 = -255 col = .col line = .line getfileid fileid attribute_action 1, class, offst1, col, line, fileid -- 1=FIND NEXT ATTR if class & col = .col & line = .line then -- Found one on this character. offst2 = offst1 attribute_action 3, class, offst2, col, line, fileid -- 3=FIND MATCH ATTR if class then -- Found a match; delete them both. attribute_action 16, class, offst1, .col, .line, fileid -- 16=DELETE ATTR attribute_action 16, class, offst2, col, line, fileid -- 16=DELETE ATTR endif endif This code checks for a color attribute on the current character. If found, it checks for the matching attribute. If both a Push and Pop exist, both are deleted. ═══ Syntax ═══ BACKTAB ═══ Definition ═══ Moves cursor to previous tab stop. Like the standard Shift-Tab. ═══ Syntax ═══ BACKTABWORD | BACKTAB_WORD ═══ Definition ═══ Positions cursor on first character of previous word, like the standard Ctrl-Left. If there are no more previous words the cursor is positioned at beginning of line. ═══ Syntax ═══ BEEP( [ pitch [, duration] ] ) ═══ Definition ═══ Sounds a beep defined by pitch (in Hertz) and duration (in milliseconds). The default pitch is 900 and the defualt duration is 500. ═══ Example ═══ BEEP(850,1000) This example will produce a beep with a frequency of 850 Hertz for a duration of 1 second. ═══ Syntax ═══ BACKWARD ═══ Definition ═══ Same as page_up. ═══ Syntax ═══ BEGINLINE | BEGIN_LINE ═══ Definition ═══ Moves cursor to beginning of current line, like the standard Home key. ═══ Syntax ═══ BOTTOM | BOT ═══ Definition ═══ Moves cursor to last line of file, like the standard Ctrl-End. ═══ Syntax ═══ BROWSE([0 | 1]) ═══ Definition ═══ Turns browse mode on for the current file. Browse mode is a read-only mode. 0 turns the browse mode off; 1 turns it on. If no argument is given BROWSE returns the current mode. ═══ Syntax ═══ BUFFER() ═══ Definition ═══ Is for developers of advanced applications who want to share text with external processes. It allows an E application to create a shared memory buffer of a specified name and copy text to it, so that other processes can open the buffer and read the text from E. (For those interested in OS/2 internals, the buffer creation calls DosAllocShrSeg().) The buffer function provides several subfunctions: create a new buffer; open an existing buffer; free a buffer; get and put text; query the allocated and used size of a buffer. You specify the subfunction you want with the first argument, one of: CREATEBUF, OPENBUF, FREEBUF, GETBUF, PUTBUF, MAXSIZEBUF, or USEDSIZEBUF. (These are only numeric constants from 0 to 6, as defined in STDCONST.E.) The meaning of the remaining arguments to buffer() depends on the subfunction, as shown in the seven cases below. The maximum buffer size is 65535 bytes. E uses the first 32 bytes of the buffer for status information: 2 bytes: bufsize available for text, without the header 2 bytes: amount of buffer filled, <= bufsize 2 bytes: format (explained below) 2 bytes: number of lines if known (E fills this in on a PUT) 26 bytes: reserved for anything the application might want. Thus the maximum space available for text is 65535-32 = 65503 bytes. bufhndl = buffer( CREATEBUF, name [,size [,private]]) CREATEBUF allocates a shared memory segment of name "\SHAREMEM\name". The prefix "\SHAREMEM\" is automatic and shouldn't be supplied. The size specification is optional. If it's zero or omitted, it defaults to the maximum size of 65503. A last optional argument, private, can be supplied with a nonzero value if you do not want want the buffer to be shared by other processes. You might wish to create a memory buffer for use by your application only, in which case you should specify private to avoid using one of the limited number of OS/2 shared buffers. (Technically, a private buffer is created with DosAllocSeg() rather than DosAllocShrSeg().) The return value from CREATEBUF is a handle or ID, to be used by the other subfunctions. (Actually the handle is the buffer segment selector, in string form like that returned by seg(), ready for use by peek and poke.) A return value of 0 means an error; RC will contain the error code given by OS/2. bufhndl = buffer( OPENBUF, name) OPENBUF shares a buffer created by another process. Again, bufhndl is returned; zero means a system error is returned in RC. It is expected that the other process has put the format and size into the first 2 words of the buffer, and starts the data at offset 32. success = buffer( FREEBUF, bufhndl) FREEBUF frees the buffer. It's not required if you're exiting from E, but recommended. The return value is zero if an error occurred, for consistency; zero means an error for all these subfunctions. noflines= buffer( GETBUF, bufhndl) GETBUF loads all of a buffer into the current file at the current location, in the same manner as a GET command. You have no control over the number of lines; normally you'll do the GETBUF into a new empty file. The return value is the number of lines transferred. A zero value along with a zero RC means the buffer was empty. (Note: RC is automatically zeroed at the start of any buffer() function.) noflines= buffer( PUTBUF, bufhndl, startline [,endline [,format]]) PUTBUF copies the current file's text from startline through endline. If endline is omitted, or specified as zero or a huge value, as many whole lines are copied as will fit, stopping at the end of file of course. The return value is the number of lines transferred. size = buffer( MAXSIZEBUF, bufhndl) MAXSIZEBUF returns the buffer capacity, in case some other process created it and you don't know its size. (This subfunction gives the same value as peek(bufhndl,0,2).) size = buffer( USEDSIZEBUF, bufhndl) USEDSIZEBUF returns the size of data in the buffer. (This gives the same value as peek(bufhndl,2,2).) The format word in the header determines how the lines are formatted. It's a bit string so you can mix and match options: APPENDCR 1 append ASCII 13 after each line APPENDLF 2 append ASCII 10 after the CR if any APPENDNULL 4 append ASCII 0 after the CR-LF if any TABCOMPRESS 8 tab-compress the line STRIPSPACES 16 remove trailing spaces as usual in a save FINALNULL 32 append a null at end of the buffer The default format if unspecified is 19, for CR-LF and remove trailing spaces. Note: The format is ignored on a GET. E handles whatever characters it finds, in the same manner as loading a disk file. CR-LF's are dropped, tabs are expanded. Note 2: if an external process fills a buffer, it should make sure that the last line is properly terminated with the appropriate end-of-line. E will double-check for this to protect against overrunning the end of the buffer. E will deposit an end-of-line if needed and restore whatever character was there, but this might not be what the other process expected. For sample usages, see the file BUFF.E. ═══ Syntax ═══ BUILDACCELTABLE table_name, command, accel_flags, key, index ═══ Definition ═══ Adds an entry to an accelerator table. 'tablename' is the name of the accelerator table being built (and is later passed as a parameter to the activateacceltable statement), 'command' is the command to be executed when the accelerator key is pressed, accel_flags is the sum of some AF_ constants from STDCONST.E, 'key' is as ASCII value for AF_CHAR, a VK_ constant for AF_VIRTUALKEY, etc., and 'index' is a unique index number for that table. You can reuse an index value to replace an entry in the accelerator table. Note: Index values must be unique in both the current accelerator table and the current action bar. Some of the VK_ constants are defined in STDCONST.E; the full set can be found in PMWIN.H in the OS/2 toolkit. ═══ Syntax ═══ BUILDMENUITEM ═══ Definition ═══ Is used to build entries on the action bar menu. See Building Menus from the Macro Language for more information on the BUILDMENUITEM statement. ═══ Syntax ═══ BUILDSUBMENU ═══ Definition ═══ Is used to build sub menu entries on the action bar menu. ═══ Syntax ═══ CALL procedurename ═══ Definition ═══ Throws away the result of the procedure call. You could substitute any expression for procedurename, e.g. call 2*2, but typically it will be a procedure call such as "call machine()". Throwing away the result of a procedure call is often necessary because otherwise the result is executed. If a procedure returns 0, the valid command '0' is executed which takes the cursor to the "Top of File" header (line 0). Generally is always advisable to use the call statement unless the returned value is used in some manner. ═══ Syntax ═══ CENTER( string, length [, pad] ) ═══ Definition ═══ Returns a string of length length with string centered in it, with pad characters added as necessary to make up length. The default pad character is a space. If the string is longer than length, it will be truncated at both ends to fit. If an odd number of characters are truncated or added, the right hand end loses or gains one more character than the left hand end. ═══ Example ═══ Here are some examples: CENTER(abc,7) -> ' ABC ' CENTER(abc,8,'-') -> '--ABC---' CENTRE('The blue sky',8) -> 'e blue s' CENTRE('The blue sky',7) -> 'e blue ' ═══ Syntax ═══ CENTRE( string, length [, pad] ) ═══ Definition ═══ (same as CENTER) ═══ Definition ═══ (same as CENTER) ═══ Syntax ═══ CHR( value ) ═══ Definition ═══ Is the inverse of ASC(), CHR() returns the character corresponding to the ASCII value. ═══ Example ═══ For example, CHR( ASC('A') ) = 'A' CHR(65)='A' ═══ Syntax ═══ CIRCLEIT style, line, col1, col2, attribute ═══ Definition ═══ Draws a circle on the screen for highlighting a section of text. The circle goes away when the screen is refreshed. 'line' is the line number of the file to be highlighted, and col1 and col2 are the first and last columns. There are two styles of circle. 1 = a perfect circle or oval; 2 = a rougher version with the ends crossing rather than meeting. The highlighting is added by XORing onto the screen, so the color displayed is a function of the screen background color and can not be directly controlled. ('Attribute' is currently unused.) The two styles use different XOR masks. ═══ Syntax ═══ COMPARE( string1, string2 [, pad] ) ═══ Definition ═══ Returns 0 if the strings, string1 and string2, are identical. If they are not, the returned number is non-zero and is the position of the first character that does not match. The shorter string is padded on the right with pad if necessary. The default pad character is a space. ═══ Example ═══ Here are some examples: COMPARE('abc','abc') -> 0 COMPARE('abc','ak') -> 2 COMPARE('ab ','ab') -> 0 COMPARE('ab ','ab',' ') -> 0 COMPARE('ab ','ab','x') -> 3 COMPARE('ab-- ','ab','-') -> 5 ═══ Syntax ═══ COPIES( string, n ) ═══ Definition ═══ Returns n concatenated copies of string. n must be positive or 0. ═══ Example ═══ Examples: COPIES('abc',3) -> 'abcabcabc' COPIES('abc',0) -> '' ═══ Syntax ═══ COPYMARK | COPY_MARK ═══ Definition ═══ Copies marked text to cursor position, like standard Alt-C. ═══ Syntax ═══ CURSOR_DIMENSIONS cursorw, cursorh ═══ Definition ═══ Queries or sets the cursor dimensions. 'cursorw' and 'cursorh' must be variables. If their values are question marks, they will be changed to reflect the current dimensions. If their values are numbers, this will set the size of the text cursor. A positive number represents that number of pixels; a negative number represents a proportional value of the size of the current character. The absolute value of that number is used as the number of 128ths of the height or width of the current character that the cursor should be drawn. ═══ Syntax ═══ DELETE ═══ Definition ═══ Deletes the line the cursor is located on. Note that the statement DELETELINE allows parameters, but DELETE does not. Note: Previously, DELETE_LINE was a synonym for DELETE. This was dropped because it was felt that it was too confusing to have two statements, DELETE_LINE and DELETELINE, with different behaviors. ═══ Syntax ═══ DELETEACCEL tablename ═══ Definition ═══ Deletes the named accelerator table. ═══ Syntax ═══ DELETECHAR | DELETE_CHAR ═══ Definition ═══ Deletes character under cursor, like standard Del. ═══ Syntax ═══ DELETELINE line_number [, {;} fileid] ═══ Definition ═══ Deletes a specified line from a specified file. Defaulted values for omitted parameters are line_number = current line, and fileid = current file. This is NOT the same as DELETE_LINE: see the clarification above, under DELETE. ═══ Syntax ═══ DELETEMARK | DELETE_MARK ═══ Definition ═══ Deletes marked text, like standard Alt-D. ═══ Syntax ═══ DELETEMENU (stmt) ═══ Definition ═══ Deletes a menu option or submenu option from the action bar. For more information on DELETEMENU see Building Menus from the Macro Language. ═══ Syntax ═══ DELSTR( string, n [, length] ) ═══ Definition ═══ Deletes the substring of string that begins at the nth character, and is of length length, and returns the result. If length is not specified, the rest of string is deleted. If n is greater than the length of string, the string is returned unchanged. n must be positive. ═══ Example ═══ Here are some examples: DELSTR('abcd',3) -> 'ab' DELSTR('abcde',3,2) -> 'abe' DELSTR('abcde',6) -> 'abcde' ═══ Syntax ═══ DELWORD( string, n [, length] ) ═══ Definition ═══ Deletes the substring of string that begins at the nth word, and is of length length blank-delimited words, and returns the result. If length is not specified, the rest of string is deleted. n must be positive. If n is greater than the number of words in string, the string is returned unchanged. The string deleted includes any blanks following the final word involved. ═══ Example ═══ Here are some examples: DELWORD('Now is the time',2,2) -> 'Now time' DELWORD('Now is the time ',3) -> 'Now is ' DELWORD('Now is the time',5) -> 'Now is the time' ═══ Syntax ═══ DIRECTORY( [string_expression] ) ═══ Definition ═══ Returns current directory. If path parameter is given, the current drive and path are changed accordingly. Note: The drive and path are changed before the current directory is returned. ═══ Example ═══ This provides a way of verifying that a user-supplied path is valid. current_dir = directory() -- Save current if upcase(directory(user_dir)) <> upcase(user_dir) then -- Try user's sayerror 'Directory 'user_dir' is invalid.' -- Warn endif call directory(current_dir) -- Restore ═══ Syntax ═══ DISPLAY -4|-2|-1|1|2|4 ═══ Definition ═══ Allows screen updates to be turned off (-1) or on (1); non-critical messages to be turned off (-2) or on (2); and errors to be forced to the message box (-4) or to the default messageline (4). These numbers can be combined. (DISPLAY -3 would turn off the screen updates and the error messages.) DISPLAY -1 prevents the screen from begin updated until a DISPLAY 1 statement is issued. This can eliminate files being flashed on the screen briefly while an application loads and manipulates files. When a DISPLAY 4 is in effect, all messages (unless explicitly sent to a dialog box) will be sent to: 1. first to the message line, unless toggled off; 2. next to the status line, unless toggled off; 3. or else overwrites the first line of text temporarily. ═══ Example ═══ An sample usage of DISPLAY is: display -3 -- turn off display updates getfileid startfid -- and error messages 'xcom e profile.xxx' -- load the profile getfileid profile_fid -- won't show on screen .visible = 0 -- make a hidden file 'xcom 1 /define' -- if not found, no error message activatefile startfid -- activate the file display 3 -- turn updates & messages on In this example the user would see no screen flashing or "Not found" error message. ═══ Syntax ═══ Is described in the section Conditional and Loop Statements. ═══ Definition ═══ Is described in the section Conditional and Loop Statements. ═══ Syntax ═══ DO_ARRAY ═══ Definition ═══ Handles arrays in E. The DO_ARRAY statement can create an array, add to the array, and lookup information from the array. The syntax for these functions is: do_array 1, array_id, arrayname creates an array of arrayname and returns the array_id in the variable array_id. do_array 2, array_id, index, value adds the value to the array under the index in the array denoted by array_id. do_array 3, array_id, index, result looks up the contents of the index entry of the array specified by array_id and places the value into result. do_array 4, array_id, index This will delete an entry specified, by INDEX, from the array. do_array 6, array_id, array_name Returns the array_id associated with the array name specified by array_name See Arrays in EPM for more information on arrays and the DO_ARRAY statement. ═══ Syntax ═══ DO_OVERLAYWINDOWS ═══ Definition ═══ Provides various functions for the manipulation of graphics within a document. Further information on graphics within EPM and the E Toolkit will be made available. ═══ Syntax ═══ DOWN ═══ Definition ═══ Moves the cursor down 1 line, like the standard Down key. ═══ Syntax ═══ DYNAFREE( number ) ═══ Definition ═══ Releases a dynalink library that has been previously called using the dynalink statment. Also see the DYNALINK and DYNALINKC statements for more information. ═══ Syntax ═══ DYNALINK( library_name, function_name, parameter_stack [, number_of_return_words ]) ═══ Definition ═══ Provides an interface between an E language program and external functions stored in a dynamic link library. The operating system functions are implemented via dynamic linking, and therefore DYNALINK() provides you with the full power of the operating system calls such as DosDelete, DosQFileMode, DosDevIOCtl, and video input/output calls such as VioWrtTty, VioWrtCharStrAtt, and much more. DYNALINK() allows you to call any dynamic link library that exists (files with a .DLL extension). Since application writers can develop general purpose dynamic link libraries, E programs can call functions written in other languages. For example, let us say that the "C" library functions are available via a dynamic link library, then we may call the library functions from an E program; or suppose that a spell checking dynamic link library exists, DYNALINK() allows you to use the spell checking. This procedure is the protect-mode equivalent of the INT86X() function of E3. For more information on the system functions or dynamic link libraries, please refer to The OS/2 Technical Reference. In order to make a system call, you must provide the following parameters to dynalink(): library_name the name of the dynalink library (e.g. file library_name.DLL) which contains the function you wish to call. function_name this is a string containing the function name in most cases. However if you are making calls to some DOS functions (DOS functions being those whose names begin with 'Dos') that are contained within the DOSCALLS.DLL library, the function name is actually the ordinal value of the DOS function, preceded by a '#'. These numbers can be found in Ordinal Values of Functions Accessed via DOSCALLS.DLL. parameter_stack a string consisting of all of the parameters expected by the function, concatenated together into one string. Those parameters that the function requires to be pushed on the parameter stack first should appear first when concatenating. Parameter information is dependent upon the function to be called, and can be found in The OS/2 Technical Reference. number_of_return_words an optional parameter that allows one to set the size of the return code variable that the system should expect to receive from the dynamic link function. This parameter is provided for those dynalink library functions whose return code is a long int rather than simply an int. If the user simply uses DYNALINK() for system calls to DOS and OS/2 functions, this parameter need never be specified. The default value is 1. ═══ Example ═══ The numeric parameters passed by the E program must be converted from string form to the proper C data type via E functions like ATOI(), ATOL(), SELECTOR(), and OFFSET(), as shown below: defc hello = string = 'hello' result = dynalink( 'VIOCALLS', /* library name */ 'VIOWRTTTY', /* function name */ selector(string) || /* address of */ offset(string) || /* string */ atoi(length(string)) ||/* length */ atoi(0) ) /* vio handle */ defc curdir2 = /* create empty strings for DosQCurDir() to fill */ string = atoi(80) || substr('',1,80) stringlen_b = substr('',1,2) result = dynalink( 'DOSCALLS', /* library name */ '#71', /* ordinal of DosQCurDir */ atoi(0) || /* drive number */ selector(string) || /* address of */ offset(string) || /* DirPath buffer */ selector(stringlen_b) || /* address of */ offset(stringlen_b) ) /* buf length */ stringlen = itoa(stringlen_b,10); sayerror 'The current directory is "' || substr(string,1,stringlen) || '".' defc beep = result = dynalink( 'DOSCALLS', /* library name */ '#50', /* ordinal of Dos Beep() */ atoi(3000) || /* frequency of beep */ atoi(1000) ) /* duration of beep */ defc clear_semaphore = result = dynalink( 'DOSCALL1', /* library name */ 'DOSSEMCLEAR', /* function name */ atol(handle) ) /* semaphore handle */ ═══ Syntax ═══ DYNALINKC( library_name, function_name, parameter_stack [, number_of_return_words ]) ═══ Definition ═══ Is used to load and pass information to a dynalink library. It is like the DYNALINK() procedure except that it passes its parameters using the C language parameter passing convention rather than the Pascal convention. See the file DYNATEST.E for examples of the use of DYNALINKC(). Also see DYNAFREE() for information about releasing a dynalink library and DYNALINK() for information about calling a dynalink library procedure using standard Pascal parameter passing conventions. ═══ Syntax ═══ ECHO( [ON | OFF] ) ═══ Definition ═══ Displays the command about to be executed. This is useful for debugging E code. ═══ Syntax ═══ ENDLINE | END_LINE ═══ Definition ═══ Positions the cursor at end of current line, like standard End. ═══ Syntax ═══ ERASEENDLINE | ERASE_END_LINE ═══ Definition ═══ Erases the rest of current line starting at cursor position, like standard Ctrl-E. ═══ Syntax ═══ EXECUTE ═══ Definition ═══ Executes the contents of the command dialog box. ═══ Syntax ═══ EXECUTEKEY keyname | identifier ═══ Definition ═══ Interprets key as if typed by user; key may be any valid expression. This is very similar to the KEY statement, except that KEY can take only a literal key name as in KEY A_L. EXECUTEKEY can take a variable, as in k=page_down; executekey k. In fact the KEY statement is superfluous, since EXECUTEKEY can be given a literal key name. ═══ Syntax ═══ EXIT [return_code] ═══ Definition ═══ Exits the current E macro and all calling macros. This is useful to halt a macro execution if a fatal error is generated. See the RETURN statement to exit only the current macro. A return code can be given as an argument. ═══ Syntax ═══ FILESINRING( [ number ] ) ═══ Definition ═══ Returns the number of files in the ring. If number is 0 or missing, the number of normal files in the ring is returned. If number is 1 the total number of files is returned, including hidden files and arrays. If number is 2 the maximum number of files currently allocated is returned. This corresponds to the size of an internal structure, and in the current release will always be a power of 2. An attempt to load more than this number of files will result in a new structure being allocated, with room for twice as many files. ═══ Syntax ═══ FILESIZE() ═══ Definition ═══ Returns sum of the lengths of each line in the file. ═══ Syntax ═══ FILLMARK [ 'character' ] | FILL_MARK [ 'character' ] ═══ Definition ═══ If a character is given, fills the marked area with character. If no character is specified, the user is asked to type a character for the fill. Like the standard Alt-F. ═══ Syntax ═══ FINDFILE filename , destfilename [, environment_path_variable, (P|D)] ═══ Definition ═══ Searches for filename in the current directory and returns its entire pathname in destfilename. Note: This statement depends upon the program FILEFIND.EXE, which is available on the PCTOOLS disk. You must download this into a directory which is in your PATH environment variable (or the same directory as the E files) before this statement will work properly. The 'P' option specifies program searching. It forces a search for a file with the extension .EXE or .CMD in each directory named in the environment_path_variable. If environment_path_variable is "PATH", the effect is the same as a normal OS/2 program search. Some variable other than path can be specified, for example "EPMPATH", and that string will be looked up in the environment. (The area where OS/2 keeps strings SET by the user.) The 'P' option also checks whether the filename is an internal OS/2 command. If so, destfilename is set up for invocation of the command processor, with "COMMAND.COM /C" at the start. If the 'D' option is used, the third parameter (environment_path_variable) is ignored (although at least a null string must be passed in anyway). The 'D' option will cause filename to be searched for in the following directories: 1. the current directory, and then 2. the directories listed in the EPMPATH environment variable (if it is defined), and then 3. the directories in the DPATH environment variable, and then 4. the same directory as the file EPM.EXE. An example of usage is: findfile complete_filespec, 'e3help.hlp', '', 'D' ═══ Example ═══ Examples: findfile cmdline,'dir','','P' If rc is zero (no error) then cmdline could be 'C:\COMMAND.COM /C dir' findfile cmdline,'subdir','PATH','P' If rc is zero then cmdline could be 'C:\UTIL\subdir.com' ═══ Syntax ═══ Is described in section Conditional and Loop Statements. ═══ Definition ═══ Is described in section Conditional and Loop Statements. ═══ Syntax ═══ GETFILEID identifier [ ',' {';'} string_expression] ═══ Definition ═══ Is described in the section Fileid Structure. ═══ Syntax ═══ GETKEYSTATE(number ) ═══ Definition ═══ Is used to test the shift state of the shift keys. This statement replaces E's previous statements of: GETSHIFTSTATE and SETSHIFTSTATE. The syntax for EPM's GETKEYSTATE is: keystate = getshiftstate( virtual_key_code) where the virtual_key_code is one of the VK codes from PMWIN.H. For convenience, the returned test states of VK codes (like PositiveOdd and NegativeEven) have been converted to single values as follows: KS_DOWN 1 (NegativeEven; key is down) KS_DOWNTOGGLE 2 (NEgativeOdd; key is down + toggled) KS_UP 3 (PositiveEven; key is up) KS_UPTOGGLE 4 (PostiveOdd; key is up + toggled) ═══ Syntax ═══ GETLINE line [, {;} line_number [ , {;} fileid] ] ═══ Definition ═══ Gets a specified line from a specified file into the variable line. Defaulted values for omitted parameters are line_number = current line, and fileid = current file. ═══ Example ═══ For example: GETLINE line /* line = current line of current file */ GETLINE line, 7 /* line = line 7 of current file */ GETLINE line, 3, ThatFile /* line = line 3 of file whose fileid is in variable ThatFile */ The statement: GETLINE line, 0 results in the variable line being set to null. ═══ Syntax ═══ GETMARK first_line [, {;} last_line [, {;} first_col [, {;} last_col [ , {;} mark_fileid ] ] ] ═══ Definition ═══ Returns the current mark coordinates and fileid. If no mark exists, the values returned are meaningless; use the function MARKTYPE() to precheck whether a mark exists. ═══ Example ═══ IF MARKTYPE()<>'' THEN /* text marked? */ /* Get active mark coordinates and fileid */ GETMARK first_line, last_line,first_col, last_col, mark_fileid ENDIF ═══ Syntax ═══ GETMARKG first_line [, {;} last_line [, {;} first_col [, {;} last_col [, {;} mark_fileid ] ] ] ═══ Definition ═══ Like GETMARK in that it returns the current mark coordinates and fileid, but unlike GETMARK, the last_col parameter of GEMARKG represents the right edge of the mark as opposed to the last column in the mark. ═══ Syntax ═══ GETPMINFO( parameter ) ═══ Definition ═══ The following are constants values that are to be used as parameters to the getpminfo internal function: HAB 0 EDITORMSGAREA 8 OWNERCLIENT 1 EDITORVSCROLL 9 OWNERFRAME 2 EDITORHSCROLL 10 PARENTCLIENT 3 EDITORINTERPRETER 11 PARENTFRAME 4 EDITVIOPS 12 EDITCLIENT 5 EDITTITLEBAR 13 EDITFRAME 6 EDITCURSOR 14 EDITSTATUSAREA 7 Depending on the parameter passed, certain PM information will be returned. See the OS/2 Reference Manual for more information on the meanings of these constants and the meaning of the information returned. Also the the file STDCTRL.E for sample usage of the GETPMINFO command. ═══ Syntax ═══ GETSEARCH identifier ═══ Definition ═══ Saves last search command in string variable search_cmd. See the SETSEARCH command for retrieving such a command, and examples of usage. ═══ Syntax ═══ HEX( 'character' ) ═══ Definition ═══ Returns the hexadecimal value associated with the ASCII representation of character. ═══ Example ═══ HEX('A') = 41 ═══ Syntax ═══ Is described in Conditional and Loop Statements. ═══ Definition ═══ Is described in Conditional and Loop Statements. ═══ Syntax ═══ Is described in section Compiler Directive Statements and in The EPM User's Guide. ═══ Definition ═══ Is described in section Compiler Directive Statements and in The EPM User's Guide. ═══ Syntax ═══ INSERT ═══ Definition ═══ Inserts a new line after the current line and position cursor in same column of new line as the first non-empty column of the previous line. Note: Previously, INSERT_LINE was a synonym for INSERT. This was dropped because it was felt that it was too confusing to have two statements, INSERT_LINE and INSERTLINE, with different behaviors. ═══ Syntax ═══ INSERT_ATTRIBUTE class, value, isPush, offset [, col [, line [, fileid]]] ═══ Definition ═══ This statement (non destructively) inserts an attribute record at the specified location. Class The class of the attribute record to be inserted. Value The value field of the attribute record to be inserted. IsPush The support field of the attribute to insert. Offset The offset of the position being queried. Offsets must be negative, and indicate a position before the specified character location. ...[ar-2][ar-1][char]... If a negative offset is specified that is less (more negative) than the smallest offset of an attribute record at the specified column, then the new attribute record is placed at an offset that is one less than the smallest offset. If an attribute record already exists at the specified offset, then the old attribute record (and any attribute records at an offset of larger magnitude) is shifted to an offset of greater magnitude to vacate the specified offset for the new attribute record. Column The column number where the new attribute record should be placed. If this parameter is omitted, the current column of the cursor is assumed. Line The line number where the new attribute record should be placed. If this parameter is omitted, the current line number of the cursor is assumed. Fileid The fileid of the file where the new attribute record should be placed. If this parameter is omitted, the active file is assumed. See Attribute Pairs for additional information on attributes, or EPMTOOLS PACKAGE on the OS2TOOLS disk for the file ATTRIBUTE.DOC that more fully describes programming attributes. ═══ Example ═══ class = 1 -- COLOR_CLASS val = Red + WhiteB -- Red on a white background insert_attribute class, val, 1, -1, 1 insert_attribute class, val, 0, -1, length(textline(.line))+1 if not (.levelofattributesupport // 2) then -- Turn on mixed color support .levelofattributesupport = .levelofattributesupport + 1 endif This will color the current line red. Note that the pop attribute is put at the end of the line + 1, since it attaches to the left side of a character, and we want the last character to be colored as well. ═══ Syntax ═══ INSERTLINE new_line [,{;} line_number [, {;} fileid] ] ═══ Definition ═══ Inserts contents of variable new_line just before the designated line of a specified file. Defaulted values for omitted parameters are line_number = current line, and fileid = current file. Without arguments INSERTLINE is identical to the INSERT statement. ═══ Example ═══ INSERTLINE line /* inserts line before current line of current file */ INSERTLINE line, 7 /* inserts line before line 7 of current file */ INSERTLINE line, 3, ThatFile /* inserts line before line 3 of file whose fileid is in variable ThatFile */ ═══ Syntax ═══ INSERTSTATE() ═══ Definition ═══ Returns the insert state of EPM. A 1 means insert mode is active; 0 means overwrite mode is active. ═══ Syntax ═══ INSERTSTR( new , target [, n [, length [, pad]]] ) ═══ Definition ═══ Inserts the string new, padded to length length, into the string target after the nth character. length and n must be non-negative. If n is greater than the length of the target string, padding is added there also. The default pad character is a blank. The default value for n is 0, which means insert before the beginning of the string. ═══ Example ═══ Here are some examples: INSERTSTR(' ','abcdef',3) -> 'abc def' INSERTSTR('123','abc',5,6) -> 'abc 123 ' INSERTSTR('123','abc',5,6,'+') -> 'abc++123+++' INSERTSTR('123','abc') -> '123abc' INSERTSTR('123','abc',,5,'-') -> '123--abc' ═══ Syntax ═══ INSERTTOGGLE | INSERT_TOGGLE ═══ Definition ═══ Toggles cursor from insert mode to replace mode and vice versa. Like pressing the standard Ins key. ═══ Syntax ═══ ISADIRTYLINE ═══ Definition ═══ Boolean function that tells whether or not the current line has been modified but not yet "checked in". This corresponds to whether or not the undo opcode will change the line; the function was added in order to enable the Undo menu item to be greyed if not applicable. ═══ Syntax ═══ Is described in section Conditional and Loop Statements. ═══ Definition ═══ Is described in section Conditional and Loop Statements. ═══ Syntax ═══ ITOA( variable, radix ) ═══ Definition ═══ Converts a two byte binary representation of an integer stored in variable to a string representation of the integer, so that the E language can understand it. radix specifies the base of the number (i.e. base 10 = decimal; base 16 = hexadecimal) to be converted to a string representation. This function is often used to convert integers returned by dynalink library functions from binary representation to ASCII string representation. See DYNALINK() for an example of the use of ITOA(). ═══ Syntax ═══ JOIN ═══ Definition ═══ Joins the next line with current line, with an intervening space. Like the standard a_J key combination. ═══ Syntax ═══ KEYIN expression ═══ Definition ═══ Types expression at current cursor position as if typed from the keyboard without translation or execution. expression is most often a quoted command, although it can also be a numeric expression. ═══ Example ═══ For example, one could file the current file: keyin 'file' key enter One could also type graphics characters in the text by placing the cursor at the desired location and issuing the statement: keyin \24 ═══ Syntax ═══ KEYS name ═══ Definition ═══ Changes to the keyset name. The keyset is created by the DEFKEYS statement Key Definitions (DEF and DEFKEYS). The KEYS statement can be used in conjunction with DEFLOAD DEFLOAD. ═══ Example ═══ The following example changes to a keyset that enhances keys such that the C programming language syntax could be recognized: defload ext=filetype(name) -- get file extention if ext='C' then -- test file is a c file keys c_keys -- change to new keyset endif ═══ Syntax ═══ LASTERROR() ═══ Definition ═══ Returns the last error code. The example illustrates its usage. ═══ Example ═══ 'tabs 0' 'ma 75 1' if lasterror() = -271 then sayerror "margin setting error" elseif lasterror() = -272 then sayerror "tabs setting error" else sayerror "no error" endif In the above example, an error would occur while trying to set both tabs and margins. LASTERROR() would return -271, and margin setting error would be printed. Assume the following two lines were substituted for the first two lines of the above example: 'tabs 0' 'margins 1 75' The result of LASTERROR() would be -272, and tabs setting error would be printed. In this way, you can retain the error code returned by a command even after a second command completes successfully. ═══ Syntax ═══ LASTKEY( [0 | 1] ) ═══ Definition ═══ Returns the user's last keystroke, whether typed manually or executed by a KEYIN or EXECUTEKEY statement. The only values that are valid for the parameter key_number are 0 and 1. The LASTKEY(0) call has the same effect as a LASTKEY() call, which has the same behavior as it always has. This procedure call is not useful for checking for prefix keys. ═══ Example ═══ You would expect that the following example would check for the two-key sequence Esc followed by F5: def f6= if lastkey()=esc then /* do the new code for Esc-F6 */ else /* do the normal F5 (in this case the draw command) */ 'draw' endif However, this is not the case. This definition is executed only if F5 is pressed, and once F5 has been pressed, it becomes the value of LASTKEY(). Therefore the if condition in the example never holds true. The procedure could be useful in the following case: def f5, a_f5, esc = if lastkey() = f5 then /* do something for F5 case */ elseif lastkey() = a_f5 then /* do something for A_F5 case */ else /* do something for Esc case */ endif /* do something for all of the keys */ In this case, one DEF is defined for multiple keys. By using the LASTKEY() procedure, you can determine which of these keys was pressed. As of version 3.10 we have added an extension to the LASTKEY() procedure to handle two key sequences. The procedure call, LASTKEY(1), returns the key before last, and will handle the problem discussed in the first example. By substituting LASTKEY(1) calls for the LASTKEY() calls in the first example, this piece of code will work as expected: trapping the Esc followed by F5 key sequence. ═══ Syntax ═══ LASTPOS( needle, haystack [, start] ) ═══ Definition ═══ searches for needle in haystack from startpos to beginning of string. If startpos is not present, the search begins from the end of string. If needle is not found, zero is returned. needle and haystack must be strings. ═══ Example ═══ LASTPOS(' ','abc def ghi') ==8 LASTPOS(' ','abcdefghi') ==0 LASTPOS(' ','abc def ghi',7) ==4 ═══ Syntax ═══ Is described in section Conditional and Loop Statements. ═══ Definition ═══ Is described in section Conditional and Loop Statements. ═══ Syntax ═══ LEFT ═══ Definition ═══ Moves cursor 1 character to the left, like the standard Left. ═══ Syntax ═══ LEFTSTR( string, length [, pad] ) ═══ Definition ═══ Returns a string of length length containing the left-most length characters of string. That is, padded with pad characters (or truncated) on the right as needed. The default pad character is a blank. length must be non-negative. Exactly equivalent to SUBSTR(string,1,length[,pad]). ═══ Example ═══ Here are some examples: LEFTSTR('abc d',8) -> 'abc d ' LEFTSTR('abc d',8,'.') -> 'abc d...' LEFTSTR('abc def',7) -> 'abc de' ═══ Syntax ═══ LENGTH( expression ) ═══ Definition ═══ Returns length of expression. ═══ Example ═══ Here are some examples: LENGTH('abcdefgh') -> 8 LENGTH('abc defg') -> 8 LENGTH('') -> 0 ═══ Syntax ═══ LEXAM( numeric_expression ) ═══ Definition ═══ Provides spell checking and synonym support for the EPM. The LEXAM opcode allows word verification and word/dictionary lookup. The LEXAM opcode can take on the following syntax: lexam('Initialize') lexam('Terminate') lexam('PIckup Dictionary',dictionary_name) lexam('DRop Dictionary',dictionary_name) lexam('SEt Addenda Language Type',addenda_type) lexam('Add to Transient Addenda',addenda_name) lexam('Read from Transient Addenda',addenda_name) lexam('Verification',word) lexam('SPelling Aid',word) lexam('Hyphenation',word) lexam('DEhyphenation',word) lexam('SYnonym',word) lexam('GRAMmar Aid',word) lexam('GRADe level',word) lexam('PArt-of-speech',word) ═══ Syntax ═══ LINK string_expression ═══ Definition ═══ Is described in section Linkable External Modules. ═══ Syntax ═══ LINKED( module ) ═══ Definition ═══ Queries whether a module is linked. The return value is: o module number (a small positive integer) if linked o -1 if found on disk but not currently linked o -307 if module can't be found on disk. This RC value -307 is the same as sayerror("Link: file not found"). o -308 if the expression is a bad module name that cannot be expanded into a proper filename. Same as sayerror("Link: invalid filename"). ═══ Example ═══ Sample usage: result = linked("draw"). Note: If you wish to make sure a module is linked, you can always just repeat the link command. E won't reload the file from disk if it's already linked, but it will rerun the module's DEFINIT which might not be desirable. ═══ Syntax ═══ LONGESTLINE() ═══ Definition ═══ Returns the length of the longest line in the current file. ═══ Syntax ═══ Is described in section Conditional and Loop Statements. ═══ Definition ═══ Is described in section Conditional and Loop Statements. ═══ Syntax ═══ LOWCASE( expression ) ═══ Definition ═══ Returns the lower-case conversion of the expression. (In versions earlier than 4.12, the input string was converted in place. Now the input is left alone and the converted string is returned as the result.) ═══ Syntax ═══ LTOA( variable, radix ) ═══ Definition ═══ Converts the C representation of a long integer (data type long) stored in variable to a string representation of the same number, so that the E language can understand the number. radix specifies the base of the number (i.e. base 10 = decimal; base 16 = hexadecimal) to be converted to a string representation. For use in converting numbers returned by C functions, for example function calls via DYNALINK(). ═══ Syntax ═══ MACHINE() ═══ Definition ═══ Returns operating system and machine information string. Return values are "PCDOS" or "OS2REAL" or "OS2PROTECT". ═══ Syntax ═══ MAP_POINT subop, op2, op3 [, op4 [, comment ] ] ═══ Definition ═══ Everything other than subop must be a variable. This opcode is used to map between a pixel-offset in the window, a pixel-offset in the document, and a line, column and offset within the file. subop op2_in op3_in op4_in op2_out op3_out op4_out 1 WindowToDoc x y - x y = 2 DocToLCO x y - Line Col Off 3 LCOToDoc Line Col Off x y = 4 Doc2Win x y - x y = 5 Win2LCO x y - Line Col Off 6 LCO2Win Line Col Off x y = The comment field is an extra field that eventually will be used to indicate if the special processing had to occur. For example, a requested point was beyond the EOF and the returned values are based on extrapolation. ═══ Syntax ═══ MARKBLOCK | MARK_BLOCK ═══ Definition ═══ Starts or changes coordinates of a block mark, like the standard Alt-B. ═══ Syntax ═══ MARKBLOCKG ═══ Definition ═══ Like MARKBLOCK, but right column must be specified one beyond the desired right column. ═══ Syntax ═══ MARKCHAR | MARK_CHAR ═══ Definition ═══ Starts or changes coordinates of a character mark, like the standard Alt-Z. ═══ Syntax ═══ MARKCHARG ═══ Definition ═══ Like MARKCHAR, but column numbers represent edges rather than characters, so that they can be between attributes (and right column will generally be one higher that it would be for MARKCHAR). ═══ Syntax ═══ MARKLINE | MARK_LINE ═══ Definition ═══ Starts or changes coordinates of a line mark, like the standard Alt-L. ═══ Syntax ═══ MARKLINEG ═══ Definition ═══ Same as MARKLINE. ═══ Syntax ═══ MARKTYPE() ═══ Definition ═══ Returns 'BLOCK', 'LINE', or 'CHAR'. ' ' is returned if no text is highlighted. ═══ Syntax ═══ MEMCPYX( hexadecimal_address , hexadecimal_address , length ) ═══ Definition ═══ Copies length bytes from source to destination. Both source and destination are binary far pointers; e.g. call memcpyx(atoi(ptr1) || atoi(seg1), atoi(ptr2) || atoi(seg2), len) ═══ Syntax ═══ MOUSE_SETPOINTER ═══ Definition ═══ Sets the mouse pointer to the figure specified by type. Mouse figures are: 1 = arrow pointer (can also user the constant SYSTEM_POINTER) 2 = a vertical bar (like those used to request text in a dialog box) 3 = an hour glass 4 = invisible 5 = four way arrows 6 = two way arrow (upper left/lower right) 7 = two way arrow (upper right/lower left) 8 = horizontal arrow 9 = vertical arrow 10 = an outlined box 11 = a stop octagon with a hand in a box 12 = the browse question mark in a box 13 = an explanation point in box 14 = an asterisk in a box 15 = cropping lines (as defined by the constant MARK_POINTER) For instance, when entering browse mode the mouse pointer can be changed to indicate that no text can be entered. ═══ Syntax ═══ MOVEMARK | MOVE_MARK ═══ Definition ═══ Moves marked text to cursor position, like the standard Alt-M. ═══ Syntax ═══ NEXTFILE | NEXT_FILE ═══ Definition ═══ Activates the next file in the active ring, like the standard F12 or Ctrl-N. ═══ Syntax ═══ OFFSET( variable ) ═══ Definition ═══ Returns the offset of the memory address of variable in the form of a binary word. To be used with C functions like those made via DYNALINK(). ═══ Syntax ═══ OFS( variable ) ═══ Definition ═══ Returns a string representation of the offset of the actual memory address of variable. See SEG() for an example of usage. ═══ Syntax ═══ OVERLAY(new, target [, n [, length [, pad] ] ]) ═══ Definition ═══ overlays the string new, padded to length k, onto the string target starting at the nth character. k must be zero or positive. If n is greater than the length of the target string, padding is added there also. The default pad character is the blank, and the default value for n is 1. n must be greater than 0. ═══ Example ═══ Examples are: OVERLAY(' ','abcdef',3) == 'ab def' OVERLAY('.','abcdef',3,2) == 'ab. ef' OVERLAY('qq','abcd') == 'qqcd' OVERLAY('qq','abcd',4) == 'abcqq' OVERLAY('123','abc',5,6,'+') == 'abc+123+++' Although E's OVERLAY procedure is similar to REXX's, they are not identical. E requires that each field be filled with a string, even if it is only a null string. REXX allows a field to be skipped. For example: OVERLAY('qq',,5,6,'+') This would be legal syntax in REXX, but would cause errors in E. The E equivalent would be: OVERLAY('qq','',5,6,'+') ═══ Syntax ═══ OVERLAYBLOCK | OVERLAY_BLOCK ═══ Definition ═══ Copies marked text to cursor position without inserting, like standard Alt-O. ═══ Syntax ═══ PAGEDOWN | PAGE_DOWN ═══ Definition ═══ Moves cursor to next page of current file, like standard PgDn. ═══ Syntax ═══ PAGEUP | PAGE_UP ═══ Definition ═══ Moves cursor to previous page of current file, like standard PgUp. ═══ Syntax ═══ See The Parse Statement. ═══ Definition ═══ See The Parse Statement. ═══ Syntax ═══ PEEK( segment , offset , count ) ═══ Definition ═══ Returns string of length count starting at the address segment:offset. The segment and offset values are used just as they are in assembler programs. See also POKE in the section Built-in Statement and Procedure Summary. A PEEK() call is often necessary to access the string pointed to by a pointer returned by a DYNALINK() function call. ═══ Example ═══ The following example of this type of usage is based on the procedure get_env() in DOSUTIL.E. seg_ptr = 1234 /* 4-byte place to put a far ptr */ cmd_ptr = 1234 call dynalink('DOSCALLS', /* dynamic link library name */ '#91', /* ordinal val for DOSGETENV */ selector(seg_ptr) || /* ptr to env. seg */ offset(seg_ptr) || selector(cmd_ptr) || /* ptr to ofs after */ offset(cmd_ptr) )/* COMSPEC: unneeded */ env_seg = itoa(seg_ptr,10) env_ofs = 0 start = env_ofs do while peek(env_seg,env_ofs,1) /== \0 env_ofs = env_ofs + 1 end setting = peek(env_seg,start,env_ofs-start) PEEK() allows us to determine where the end of the string is (marked by a null character: \0), and thereby determine the length of the string. WARNING: Attempts to PEEK to an area not owned by your process will cause a TRAP-D error. ═══ Syntax ═══ PEEKZ( hexadecimal_address ) | PEEKZ( numeric_expression , numeric_expression ) ═══ Definition ═══ Like PEEK, but for an ASCIIZ string. Returns the contents of storage starting with the address given and ending with the character before the next null character. ═══ Example ═══ This lets us simplify the PEEK example to: env_seg = itoa(seg_ptr,10) setting = peekz(env_seg,0) An alternate format supported is PEEKZ(address), where address is the 4-byte hex address of the storage. This is useful when calling an external routine that returns a far pointer to an ASCIIZ string. ═══ Syntax ═══ POKE( segment , offset , string ) ═══ Definition ═══ Writes string to the address segment:offset The segment and offset values are used just as they are in assembler programs. WARNING: Attempts to POKE to an area not owned by your process will cause a TRAP-D error and crash. ═══ Example ═══ -- put greeting at beginning of segment. SelOfSharedSeg = itoa(Selector1, 10); poke SelOfSharedSeg , 0 , "Bonjour"\0; ═══ Syntax ═══ POS( needle, haystack [, start] ) ═══ Definition ═══ Returns the position of one string, needle, in another, haystack. (See also the LASTPOS and INDEX functions.) If the string needle is not found, 0 is returned. By default the search starts at the first character of haystack (that is start is of the value 1). This may be overridden by specifying start (which must be a positive whole number), the point at which to start the search. ═══ Example ═══ Here are some examples: POS('day','Saturday') -> 6 POS('x','abc def ghi') -> 0 POS(' ','abc def ghi') -> 4 POS(' ','abc def ghi',5) -> 8 ═══ Syntax ═══ PREVFILE | PREV_FILE ═══ Definition ═══ Activates the previous file in the active ring, like the standard Alt-F11 or Ctrl-P key combinations. ═══ Syntax ═══ QPRINT printername ═══ Definition ═══ Performs a WYSIWYG print of the current file to the print queue associated with the named printer. ═══ Syntax ═══ QUERYACCELSTRING (table_name, id) ═══ Definition ═══ Returns the string associated with identifier 'id' in the accelerator table named 'table_name'. ═══ Example ═══ accelstr=queryaccelstring(activeaccel, menuid) if accelstr <> '' then sayerror 'menu id' menuid 'would execute command' accelstr endif ═══ Syntax ═══ QUERY_ATTRIBUTE class, value, ispush, offset, column, line [, fileid] ═══ Definition ═══ This statement allows a macro program to deterine what attribute record can be found at the specified location. Class returns the class of the found attribute record. A value of zero is returned if no attribute was found. A value between 1 and 63 is returned if an internally supported attribute record was found. A value from 64 to 255 is returned if an application supported attribute record was found. The meaning of an application supported attribute record is not predictable at compile time. Some administrative macros will be provided for determining the meaning of a macro during runtime. Value returns the value of the found attribute record. Its value is unchanged if no attribute record was found at the specified location. IsPush returns the value of the support field of the found attribute. This parameter's value is unchanged if no attribute record was found at the specified location. Offset The offset of the position being queried. Must be a negative value, indicating a position before the specified character location. Column The column number of the position being queried. Line The line number of the position being queried. FileID The fileid of the position being queried. If unspecified, the current file will be assumed. See Attribute Pairs for additional information on attributes, or EPMTOOLS PACKAGE on the OS2TOOLS disk for the file ATTRIBUTE.DOC that more fully describes programming attributes. ═══ Syntax ═══ QUERYFONT (font_id) ═══ Definition ═══ Returns the font description associated with font_id, in the form fontname.fontsize.fontsel - e.g. Courier.DD100WW9HH8BB.0 Times New Roman.DD240WW0HH0.0 In fontsize, the numbers following DD are the size of the font in decipoints for a proportional font, and the numbers following WW and HH are the width and height of the font in pixels for a monospaced font. The BB is present at the end if the font is a bitmapped font. 'fontsel' is any combination of 1 = Italic 2 = Underscore 8 = Outline 16 = Strikeout 32 = Bold ═══ Syntax ═══ QUERYMENUSTRING( menuname , id ) ═══ Definition ═══ Determines the command to be executed by the menu specified by the menuname and by id. See Building Menus from the Macro Language for more information on the QUERYMENUSTRING statement. ═══ Syntax ═══ QUERYPROFILE( file_handle, application , key_name ) ═══ Definition ═══ Returns the value for key key_name listed under the application application, found in the .INI file given by the file_handle or the null string if not found. Some valid arguments for file_handle are: HINI_PROFILE = 0 -- Searches both OS2.INI and OS2SYS.INI HINI_USERPROFILE = -1 -- Searches OS2.INI HINI_SYSTEMPROFILE = -2 -- Searches OS2SYS.INI ═══ Syntax ═══ QUIETSHELL | QUIET_SHELL string_expression ═══ Definition ═══ Executes string_expression. string_expression is to be an OS/2 command. If string_expression is an external program, the screen and cursor are not touched before or after the program is executed. ═══ Example ═══ Use this when you know the external program will not write to the screen, and you prefer not to see the screen clear and to be asked to press a key. Normally this is used to keep redirected utilities invisible, for example quietshell "subdir *.* >etemp". If the command DOES write to the screen, say after an unexpected error, its message will appear on top of E's text screen. The text will appear messy until the next time E refreshes the screen. You can manually force a screen refresh by pressing ESC a couple of times. Another example is quietshell "mc2", which runs Richard Redpath's MC2 calculator. This is an unusual example because MC2 does write to the screen, but it takes responsibility for restoring the screen contents it found. The effect is that of a pop-up calculator on top of the text screen. ═══ Syntax ═══ REFLOW ═══ Definition ═══ Reformats marked text using current margin settings, like the standard Alt-P. ═══ Syntax ═══ REFRESH ═══ Definition ═══ Activates the active file in the top level ring. Activates the top level ring and updates portions of screen which need to be updated. ═══ Syntax ═══ REGISTERFONT (fontname, fontsize,fontsel) ═══ Definition ═══ Loads the font specified and returns an identifier that can be set in the .font field or which can be used as the value of a font attribute. 'fontsel' is any combination of 1 = Italic 2 = Underscore 8 = Outline 16 = Strikeout 32 = Bold ═══ Example ═══ Examples: .font = registerfont('Times New Roman', 24, 0) -- Set a 24-point font. .font = registerfont('System Monospaced','WW8HH16',0) -- 8 x 16 font ═══ Syntax ═══ Is described in section Linkable External Modules. ═══ Definition ═══ Is described in section Linkable External Modules. ═══ Syntax ═══ REPEATFIND | REPEAT_FIND ═══ Definition ═══ Repeats find of last string searched, like the standard Ctrl-F. The previous search options are preserved. (Note: If the cursor is currently at the beginning of a target search string, it skips to the next occurrence.) ═══ Syntax ═══ REPLACELINE new_line [, {;} line_number [, {;} fileid] ] ═══ Definition ═══ Replaces a specified line in the specified file with the contents of variable new_line Defaulted values for omitted parameters are line_number = current line, and fileid = current file. See example under GETLINE. ═══ Example ═══ For example: REPLACELINE line /* Replaces current line of current file with line */ REPLACELINE line, 7 /* Replaces line 7 of current file with line */ REPLACELINE line, 3, ThatFile /* Replace line 3 of file whose fileid is in variable ThatFile with line */ ═══ Syntax ═══ RETURN [expression] ═══ Definition ═══ Returns expression to caller. If no expression is supplied, a null value is returned to the caller. From a procedure, the returned value is passed back to the caller as a function value (as in x=myproc()). From a command the returned value is assigned to RC. When returning from a key (DEF), an expression is not allowed. A return from a key DEF is unusual, since keys do not return values, but a return is sometimes used as an easy early exit from a key's program. A return is better than a STOP in case some other procedure was "calling" the key with an executekey; a STOP prevents the caller from regaining control. ═══ Syntax ═══ REVERSE( string_expression ) ═══ Definition ═══ Returns the reverse of the string string. ═══ Example ═══ Here are some examples: REVERSE('BACKWORDS') --> 'SDROWKCAB' REVERSE('seluR MPE') --> 'EPM Rules' ═══ Syntax ═══ RIGHT ═══ Definition ═══ Moves cursor one character to the right, like the standard key Right. ═══ Syntax ═══ RIGHTSTR( string, length [, pad] ) ═══ Definition ═══ Returns a string of length length containing the right-most length characters of string. That is, padded with pad characters (or truncated) on the left as needed. The default pad character is a blank. length must be non-negative. ═══ Example ═══ Here are some examples: RIGHTSTR('abc d',8) --> ' abc d' RIGHTSTR('abc def',5) --> 'c def' RIGHTSTR('12',5,'0') --> '00012' ═══ Syntax ═══ RUBOUT ═══ Definition ═══ Deletes character to left of cursor, like the standard key Backspace. ═══ Syntax ═══ SAYAT string, row, column, attribute [, length] ═══ Definition ═══ Writes string at the screen location specified by row (any number included in 1..screenheight()) and column (any number included in 1..screenwidth()). The parameter attribute allows you to specify any screen attribute (0..255 or any constant color value listed in COLORS.e) to highlight string. If length is omitted, E assumes length = LENGTH(string). If length < LENGTH(string), E writes the first length number of characters. If length > LENGTH(string), E changes the screen attribute to attribute for the last length - LENGTH(string) number of character positions without changing the text. The window option defines which text window area should be written to by the SAYAT statement. 0=Edit Window, 1=Extra window. The extra window is the window that makes up the status line and message line. The edit window is everything else. ═══ Example ═══ Examples: /* write red string in upper right corner */ sayat 'mymessage', 1, 70, RED /* change screen positions (10,20) to (10,24) to green color without changing text */ sayat '', 10, 20, GREEN, 5 To put a message to the message line, use the MESSAGE() defproc. Note: that something printed with the SAYAT statement only stays on the screen until a screen refresh is done. Since a SAYERROR call produces a screen refresh, combining these two statements: sayat 'My Procedure.', 12, 20, GREEN, 5 sayerror "File not found!" will result in the SAYAT message never being seen. To prevent this, you can use the DISPLAY statement to stop screen refreshing, for example: display -1 -- turn off display updating sayat 'My Procedure.', 12, 20 ,GREEN, 5 sayerror "File not found!" display +1 -- turn on display updating In this way, the screen will not be refreshed (and therefore the message will stay on the screen) until the next screen update. ═══ Syntax ═══ SAYERROR( expression ) ═══ Definition ═══ Should not be confused with the built-in procedure SAYERROR() described in this section. If expression is the number 0 or 1, any pending error messages are discarded and not displayed. 0 will refresh the screen; 1 will not. If expression is any number other than 0 or 1, `the interpreter displays the string corresponding to that numbered error message. Error messages and their corresponding return codes are listed in the section Return Codes. Each command in the E language returns a code which indicates any errors that were encountered while trying to perform the command. Each of these return codes has a corresponding string which explains the error. ═══ Example ═══ For example: sayerror -275 This will display the text "Missing filename" on the message line. If expression is a number which does not correspond to a return code, an "ERROR: Message not available" message is printed on the message line. If expression is anything other than a number, the text will be displayed on the message line. For example: err1 = "-275" -- remember everything is a string sayerror err1 -- equivalent to: err1 = -275 err2 = "David" sayerror err2 The first example will display the error message (not "-275") on the message line. The second example will display the text David on the message line. A combination of text and numbers will act as if it were all text. For example: sayerror "The error message was " err1 The intention to display all text would not work in this case. Instead the user would get: The error message was -275 The error code did not get translated. To help clarify this explanation, try entering and compiling the following defc: defc mytest sayerror arg(1) Then experiment by typing in the command line dialog box mytest followed by valid error numbers, invalid error numbers, text, and text with numbers to determine what will happen. ═══ Syntax ═══ SAYERROR expression ═══ Definition ═══ Returns the return code specified by error_string. Note that this is only true if the sayerror procedure acts as a function and returns a return code. If the SAYERROR() procedure is not assigned and not used in a comparison, then the procedure acts the same as the SAYERROR statement (also described in this section). ═══ Example ═══ For example: x = sayerror("new file") sayerror("new file") The first example will put the return code for new file (ie. -282) into the variable x. The second example will act in the same manner as a SAYERROR statement and would display the words "new file" on the message line. The case of error_string does not matter. The compiler will convert error_string to uppercase and then perform the lookup for error_string. The compiler reduces sayerror(error_string) to a constant for efficiency. Therefore, if the words new file were changed to gobbildy gook (not a valid error message), the compiler would not compile and return an "invalid parameter" error message. The most common usage of this is to test an return code to see if a certain error occurred. For example: 'e myfile' if rc=sayerror("new file") then All error messages and their corresponding RC code numbers can be found in Return Codes. ═══ Syntax ═══ SAYERRORTEXT'(' numeric_expression ')' ═══ Definition ═══ Returns the message that would be displayed for error code rc. ═══ Syntax ═══ SCREENHEIGHT() ═══ Definition ═══ Returns physical screenheight, usually 25. ═══ Syntax ═══ SCREENWIDTH() ═══ Definition ═══ Returns physical screenwidth, usually 80. ═══ Syntax ═══ SEG( variable ) ═══ Definition ═══ Returns a string representation of the segment of the actual memory address of variable. ═══ Example ═══ For example: v = 'testing' sayerror peek( seg(v), ofs(v), 7 ) The above example prints testing. See also OFS(). ═══ Syntax ═══ SELECTOR( variable ) ═══ Definition ═══ Returns the segment address of variable in the form of a binary word. To be used with C functions, like those made via DYNALINK(). This function it is to be used only during the protected mode execution. ═══ Syntax ═══ SETMARK firstline, lastline, firstcol, lastcol, marktype, fileid ═══ Definition ═══ Sets a mark in file 'fileid' from firstline firstcol to lastline lastcol. marktype must be one of: 0 = line mark 1 = char mark 2 = block mark 3 = charg mark 4 = blockg mark ═══ Syntax ═══ SETPROFILE( string_expression, string_expression, string_expression ) ═══ Definition ═══ Sets the value for key key_name listed under the application application to data in OS2.INI. ═══ Syntax ═══ SETSEARCH identifier ═══ Definition ═══ Retrieves the search command string saved in the variable search_cmd via a GETSEARCH statement. These two statements allow the user to save a search command, perform other searches and then retrieve the original command, so that Ctrl-F's and REPEATFIND statements refer to the original search pattern. ═══ Example ═══ For example: 'xcom L /foobar/c' GETSEARCH search_command 'L /word' SETSEARCH search_command The first statement in the above example issues a search command. The GETSEARCH statement effectively sets the variable search_command to 'xcom L/foobar/c'. Then another search command is issued, wiping out the first search command, but the SETSEARCH statement restores the first command, so that if a Ctrl-F (REPEAT_FIND) is now executed, the string foobar will be once again located. ═══ Syntax ═══ SHIFTLEFT | SHIFT_LEFT ═══ Definition ═══ Shifts marked text 1 position to left, like the standard Ctrl-F7. ═══ Syntax ═══ SHIFTRIGHT | SHIFT_RIGHT ═══ Definition ═══ Shifts marked text 1 position to right, like the standard Ctrl-F8. ═══ Syntax ═══ SHOWMENU ═══ Definition ═══ Displays a menu after it has been built. See the section Building Menus from the Macro Language for more information on the SHOWMENU statement. ═══ Syntax ═══ SPLIT ═══ Definition ═══ Splits current line at cursor position, like the standard Alt-S. ═══ Syntax ═══ STOP ═══ Definition ═══ Stops execution of interpreter. A RETURN statement returns control to any calling procedures, however the STOP statement ends the execution immediately. RETURN is the preferred means of exiting a procedure, however, STOP is useful for terminating execution on a critical error. ═══ Syntax ═══ STOPONRC | STOP_ON_RC ═══ Definition ═══ Stops execution of interpreter only if rc is non-zero. ═══ Syntax ═══ STRIP( string [, (L|T|B)] [, 'char' ] ) ═══ Definition ═══ Removes char from string in any of the following positions depending upon the option specified: Option: Position: 'L' Leading 'T' Trailing 'B' Both If option is omitted, the default is B. If char is omitted, the default is the space character. (Same as REXX.) ═══ Example ═══ strip(' ab c ') = 'ab c' strip(' ab c ','L') = 'ab c ' Note: Calling the STRIP() function does not actually change the value of the parameter string. In order to modify a variable you must assign to it, for example: field = strip( field ) ═══ Syntax ═══ SUBSTR( string, n [, length [, 'pad' ] ] ) ═══ Definition ═══ Returns the substring of string which begins at the nth character, and is of length, padded with blanks or the specified character (pad). If k is omitted, it defaults to be the rest of the string, and the default pad character is a blank. n must be positive. ═══ Example ═══ SUBSTR('abc',2) == 'bc' SUBSTR('abc',2,4) == 'bc ' SUBSTR('abc',2,6,'.') == 'bc....' Note: in some situations the positional (numeric) patterns of parsing templates are more convenient for selecting substring, especially if more than one substring is to be extracted from a string. ═══ Syntax ═══ SUBWORD( string , n [, length] ) ═══ Definition ═══ Returns the substring of string that begins at the nth word, and is of length length blank-delimited words. If length is not specified, the rest of the string is returned. n must be positive. The returned string will never have leading or trailing blanks, but will include all blanks between the selected words. ═══ Example ═══ Here are some examples: SUBWORD('Now is the time',2,2) -> 'is the' SUBWORD('Now is the time',3) -> 'the time' SUBWORD('Now is the time',5) -> '' ═══ Syntax ═══ TAB ═══ Definition ═══ Moves cursor to next tab stop, like standard key Tab. ═══ Syntax ═══ TABWORD | TAB_WORD ═══ Definition ═══ Positions cursor on first character of next word, like the standard key Ctrl-Right. If there are no more words, the cursor is positioned at the end of the last word. ═══ Syntax ═══ TEXTLINE( line_num ) ═══ Definition ═══ Returns the text of line number line_num. The following statements perform the same function: getline line, i and line = textline(i) The TEXTLINE() procedure is simply a more economical way to do comparison loops like: while textline(i) == '' deleteline i ═══ Syntax ═══ TOP ═══ Definition ═══ Moves cursor to top of file. ═══ Syntax ═══ TRANSLATE( string [, tableo [, tablei [, pad ] ] ] ) ═══ Definition ═══ Translates characters in string to be other characters, or may be used to reorder characters in a string. If neither translate table is given, string is simply translated to uppercase. tableo is the output table and tablei is the input translate table (the default is ASCII 0...255). The output table defaults to the null string, and is padded with pad or truncated as necessary. The default pad is a blank. The tables may be of any length: the first occurrence of a character in the input table is the one that is used if there are duplicates. ═══ Example ═══ Examples: TRANSLATE('abcdef') == 'ABCDEF' TRANSLATE('abbc','?','b') == 'a??c' TRANSLATE('abcdef','12','ec') == 'ab2d1f' TRANSLATE('abcdef','12','abcd','.') == '12..ef' TRANSLATE('4123','abcd','1234') == 'dabc' Note: The last example shows how the TRANSLATE function may be used to reorder the characters in a string. In the example, any 4-character string could be specified as the second argument and its last character would be moved to the beginning of the string. ═══ Syntax ═══ Is described in section Compiler Directive Statements. ═══ Definition ═══ Is described in section Compiler Directive Statements. ═══ Syntax ═══ UNDO ═══ Definition ═══ Restores the current line after modification (but before leaving it), like the standard F9 key. Pressing the key (or issuing the statement) twice causes the UNDO to undo itself, i.e. the line is re-modified. ═══ Syntax ═══ UNDOACTION action, statevar ═══ Definition ═══ Statevar must be a variable; it is used for input or output depending on the action. Actions are: Action Value Result 1=GET_STATE Returns a handle for the current state of the current file. If the file hasn't changed since the the last time the file was checked, then the same value is returned. If the file has changed, the current state is checkpointed and a new handle is returned. 2=GET_OLDEST_STATE The editor periodically forgets old states in order to save memory. This call allows one to determine the oldest reachable state. 3=GOTO_STATE If the current state is not yet named, it is checkpointed and then the content of the file is changed to reflect the specified state. 4=DISABLE_RECORDING The parameter specifies at which times state checkin should no longer automatically be done. A sideeffect of this command is to checkin the current state if it is not already checked in. Times 0 upon starting each keystroke 1 upon starting each command 2 when moving the cursor from a modified line. 5=ENABLE_RECORDING The parameter specifies at what additional times checkin should be done. Unlike the disabling code, this operation does not have checkin as a side effect. See DISABLE for time codes. 6=QUERY_NAMED_SEQ This returns a string consisting of two numbers seperated by an elipsis. This string represents the oldest and most recent states that can be reached. These are lowlevel handles, so they can only be use to call GOTO_STATE2. The left most number returned represents the oldest state the is currently remembered. It is possible that it is not reachable going to a state causes a checkpointing of the current state and check pointing may require a trimming of the undo tree. If the current state is checked in, the second value represents the current state. If the current state is not checked in, the second value represents the state of file when the next checkin is done. (Note a checkin will be done as a side effect of the first GOTO.) BTW, one can go to any state between the first and last. They do represent a temporal sequence. 7=GOTO_STATE2 This is like GOTO_STATE, except the parameter should be a low level handle like those returned from QUERY_NAMED_SEQ. ═══ Syntax ═══ UNLINK string_expression ═══ Definition ═══ Is described in section Linkable External Modules. ═══ Syntax ═══ UNMARK ═══ Definition ═══ Removes text marks, like the standard key Alt-U. ═══ Syntax ═══ UP ═══ Definition ═══ Moves cursor 1 character up, like standard Up key. ═══ Syntax ═══ UPCASE( expression ) ═══ Definition ═══ Returns the upper-case conversion of the expression. ═══ Syntax ═══ VER() ═══ Definition ═══ Returns the version of the editor being used. If option is 1 then VER returns the editors numeric version. If option is 2, VER returns the minimum allowed version number of a E macro file to be used within this version. If no option is specified, the version "string" is returned. ═══ Syntax ═══ VERIFY( string , reference [ ,(M|N) [, start] ]) ═══ Definition ═══ verifies that string is composed only of characters from reference, by returning the position of the first character in string that is not also in reference. If all the characters are present in reference, 0 is returned. The options are: 'Match' and 'Nomatch' If 'Match' is specified, i.e. the value of the third argument expression is a string beginning with 'M' or 'm', the position of the first character in string that is in reference is returned. 0 is returned if none of the characters are found. 'Nomatch' (or any string expression beginning with 'N' or 'n') can also be specified, although you would not normally do so because 'Nomatch' is the default. The default for start is 1, making the search start at the first character of string. This can be overridden by giving a different start value, which must be positive. If string is null, 0 is returned regardless of the value of the third argument. Similarly if start is greater than length(string), 0 is returned. ═══ Example ═══ Examples: VERIFY('123','1234567890') == 0 VERIFY('1Z3','1234567890') == 2 VERIFY('AB3','1234567890','M') == 3 The REXX documentation includes this example: VERIFY('1P3Q4','1234567890',,3) == 4 Notice that the third parameter is completely omitted between two adjacent commas. This causes REXX to use the default option of 'nomatch'. In general, the E compiler does not like parameters to be completely omitted in this way. It expects the parameter to be present even if it's an empty string. Thus the same intent can be achieved by either of these: VERIFY('1P3Q4','1234567890','',3) == 4 VERIFY('1P3Q4','1234567890','N',3) == 4 ═══ Syntax ═══ Is described in section Conditional and Loop Statements. ═══ Definition ═══ Is described in section Conditional and Loop Statements. ═══ Syntax ═══ WINDOWMESSAGE(send_flag, target, message, mp1, mp2) ═══ Definition ═══ Performs a WinPostMessage (if send_flag = 0) or WinSendMessage (if send_flag = 1) to the target window with the given message number and MP1 and MP2 values. ═══ Example ═══ /* Pop the command line and pre-fill it with 'Prompt' call windowmessage(0, getpminfo(EPMINFO_OWNERCLIENT), 5124, -- EPM_POPCMDLINE 0, put_in_buffer('Prompt') ) ═══ Syntax ═══ WINMESSAGEBOX(caption, text [, attributes]) ═══ Definition ═══ Puts up a PM message box containing caption as the title and text as the contents. attributes is any combination of the MB_ constants from PMWIN.H in the OS/2 Toolkit. These are duplicated in STDCONST.E. ═══ Example ═══ r = WinMessageBox('Reality check', 'Are you sure you want to delete your thesis?', MB_YESNOCANCEL + MB_WARNING + MB_DEFBUTTON3 + MB_MOVEABLE) if r = MBID_YES then sayerror 'Maybe you should sleep on it...' elseif r = MBID_NO then sayerror 'Good idea!' else sayerror '(Forget the whole thing.)' endif ═══ Syntax ═══ WORD( string , n ) ═══ Definition ═══ Returns the nth blank-delimited word in string. n must be positive. If there are less than n words in string, the null string is returned. Exactly equivalent to SUBWORD(string,n,1). ═══ Example ═══ Here are some examples: WORD('Now is the time',3) --> 'the' WORD('Now is the time',5) --> '' ═══ Syntax ═══ WORDINDEX( string , n ) ═══ Definition ═══ Returns the character position of the nth blank-delimited word in string. n must be positive. If there are less than n words in string, 0 is returned. ═══ Example ═══ Here are some examples: WORDINDEX('Now is the time',3) --> 8 WORDINDEX('Now is the time',6) --> 0 ═══ Syntax ═══ WORDLENGTH( string , n ) ═══ Definition ═══ Returns the length of the nth blank-delimited word in string. n must be positive. If there are less than n words in string, 0 is returned. ═══ Example ═══ Here are some examples: WORDLENGTH('Now is the time',2) --> 2 WORDLENGTH('Now comes the time',2) --> 5 WORDLENGTH('Now is the time',6) --> 0 ═══ Syntax ═══ WORDPOS( needle , haystack [, start] ) ═══ Definition ═══ Searches haystack for the first occurrence of the sequence of blank-delimited words needle and returns the word number of the first word of needle in haystack. Multiple blanks between words in either needle or haystack are treated as a single blank for the comparison, but otherwise the words must match exactly. Returns 0 if needle is not found. By default the search starts at the first word in haystack. This may be overridden by specifying start (which must be positive), the word at which to start the search. ═══ Example ═══ Here are some examples: WORDPOS('the','now is the time') -> 3 WORDPOS('The','now is the time') -> 0 WORDPOS('is the','now is the time') -> 2 WORDPOS('is the','now is the time') -> 2 WORDPOS('is time ','now is the time') -> 0 WORDPOS('be','To be or not to be') -> 2 WORDPOS('be','To be or not to be',3) -> 6 ═══ Syntax ═══ WORDS( string ) ═══ Definition ═══ Returns the number of blank-delimited words in string. ═══ Example ═══ Here are some examples: WORDS('Now is the time') --> 4 WORDS(' ') --> 0 ═══ ═══ An alternative approach might involve having a handle to an attribute record. In such an approach one can still refer to an attribute record by the same handle even if the attribute record changes location. On the other hand, implementation of this approach is often inefficient because it often includes generation of new handles when text containing attributes is copied so that a handle only refers to a single attribute record. ═══ ═══ Note in this diagram, the attribute records are delimited by brackets. Throughout this document I will only use brackets to delimit attribute records. To avoid confusion, I will refrain from using brackets as a textual character in my examples. The use of capital letters here between brackets is only used in this example as a means of referring to individual attribute records. In other examples in this document, I might actually put words or numbers between the brackets if I want to denote some characteristic of an attribute record. ═══ ═══ The last character of line in the example is the "h". There is an attribute record located immediately to the right of that character. Because it is at the end of the line there is no character to the right of it. This is acceptable because there is a virtual character to the right of it. (In the case of line mode, there is a virtual space, and in the case of stream mode there is a virtual CR/LF or questionably a soft linebreak.) The F attribute record in the example is a slightly different situation. It is similar in that its positional notation is derived from the assumed existence of virtual spaces beyond the end of line. It differs from the previous attribute record in that its location is invalid in stream mode and may not be effectively supported by some operations. ═══ ═══ The exception to this is the '/' (search) command. When this command is invoked, E searches for the 'L' command definition. ═══ ═══ DEFC's and DEFPROC's cannot be redefined. CONSTants can be redefined (to the same value) without penalty. ═══ ═══ The ET compiler does a simple substitution for every occurrence of a constant. If you define a long string constant and reference it ten times, its value is included ten times and takes up ten times its length in the resulting EX file. You might prefer to make a long string value a universal variable rather than a constant. ═══ ═══ By "event" we mean a procedure that is automatically invoked when a certain condition becomes true. Previous examples are DEFINIT (executed when you start the editor or a new module) and DEFEXIT (executed when you quit the editor or a module). In a sense keystrokes are also events, and in the past we sometimes called events "pseudo-keys". ═══ ═══ Understand that the word var is only a notational convenience. Do not include the word literally in your program. ═══ ═══ As described in the OS/2 Technical Reference Manual section 2.3.8.1 entitled Dynamic Linking. ═══ ═══ In the 'printable_char' cases, the keyname must be quoted in an E program. For example, the following example redefines the '~' key on the keyboard to toggle the cursor between the text and the command dialog box, and redefines some of the alphabetic keys to produce help information: def '~' = command_toggle def 'a' - 'z' = 'help' However, the rest of the keynames need not be quoted, e.g. KEY c_end ═══ ═══ In all constructs which require a numeric_term, a numeric value is expected. The following can be substituted for a number: o the name of a variable representing a numeric value, or o a procedure call which returns a numeric value ═══ ═══ In all constructs which require a string_expression, a string value is expected. The following can be substituted for a string: o the name of a variable representing a string, or o a procedure call which returns a string ═══ ═══ In a constant_expression, any identifiers or designators must be the names of constants; no variables are permitted. ═══ ═══ There may not be spaces between the identifier and the '('. ═══ ═══ A macro-defined command is any command defined using a DEFC construct in the E macro code, whether it is part of the distributed macros written by the E developers or added later by a user. For an example of such a DEFC construct, see section Using EPM Commands in E Statements. ═══ ═══ Note: Two double quotes inside a double-quoted string will output one double quote character. For example, the string: "She said, ""Oh, that's fascinating."" " will yield the following output: She said, "Oh, that's fascinating." There can be no spaces between the two double quotes. ═══ ═══ Note: Two single quotes inside a single-quoted string will output one single quote character. For example, the string: 'I went to Jim Kennedy''s house' will yield the following output: I went to Jim Kennedy's house. There can be no spaces between the two single quotes. ═══ ═══ Any number to be interpreted or manipulated by the editor cannot exceed 32,767. ═══ ═══ AF_ constants: AF_CHAR = 1 -- 'key' represents an ASCII value AF_VIRTUALKEY = 2 -- 'key' is a VK_ constant AF_SCANCODE = 4 -- 'key' represents a keyboard scan code AF_SHIFT = 8 -- The Shift key must be pressed along with 'key' AF_CONTROL = 16 -- The Control key must be pressed along with 'key' AF_ALT = 32 -- The Alt key must be pressed along with 'key' AF_LONEKEY = 64 -- 'key' is a shift key, but is used by itself AF_SYSCOMMAND = 256 -- 'index' should be sent in a WM_SYSCOMMAND message AF_HELP = 512 -- 'index' should be sent in a WM_HELP message