Category : OS/2 Files
Archive   : ME22.ZIP
Filename : CHANGES.DOC

Output of file : CHANGES.DOC contained in archive : ME22.ZIP


Virtual/EMS memory support!!!
The really big news for this release is that ME now supports virtual
memory and expanded memory (if you have an expanded memory driver in
your system). This means that you can edit files as large as the free
space on your disk!!!

ME still relies on the memory management routines found in the
Microsoft C run-time library (ie - malloc()) to allocate blocks to
hold the lines in. When malloc() returns a NULL to ME, signifying that
DOS no longert has any free memory to give away, ME will try to
allocate pages from expanded memory. When expanded memory runs out, ME
will start swapping to disk. ME creates a temporary swap file with the
name VMxxxxxx. ME will delete this file when you exit back to DOS.

The METEMP environment variable controls where the swap file will
be stored. By default, ME puts the swap file in your current
directory. If you want the swap file to be placed in another
directory, or on a RAM disk (for faster access), then you can set the
METEMP environment variable to the full DOS path name that you want to
use. For instance, if you have a RAM disk on drive E:, then you can
have the following line in your autoexec.bat file :

set METEMP=e:\

Real Tabs now supported!
Thanks to user John Palmer, ME now supports real variable-length
tabs. The cursor will now jump over the virtual space represented by a
tab character. Using real tabs will probably save you some space on
your disk, especially if you tend to use a lot of blanks for padding.

You can control whether ME will use real tabs or not by altering the
'rt' parameter in the CONFIG.ME file.

Customizable word delimiters
Three commands need to know what constitutes a word; these commands
are , , and . By default, ME considers a
word to be a series of alpha-numeric characters. Through the macro
language, you can tell ME what it thinks a word should consist of. See
the section below on the macro language additions for more in-

New option for Block Indent
The amount of space a block moves when you indent/undent is now con-
trolled by the 'sh' parameter in the options menu (and CONFIG.ME file).

Support for enhanced keyboard.
ME now supports the extended keyboard. Previously, ME did not
recognize the keys on the separate cursor keypads. Now, those keys
invoke the same functions as their counterparts on the numeric keypad.

New arguments for the DOS command line
You can now give wildcards on command line. ME will find all
matching files and will attempt to load in as many files as it can
before it runs out of window space. (Unfortunately, ME will not load
the remaining files into "invisible" buffers. Let us know if you want
this capability.)

If ME is started with a command line argument of -g where is
a number, then upon loading the first file on the command line, ME
will jump to line in that file. This is useful for programs which
analyze the error messages generated by a compiler, and wish to invoke
the editor and bring it immediately to the error line. As an example,
the command line "me -g25 ed.c" will load file ed.c and immediately
jump to line 25.

Two new command line arguments, -c and -r, tell ME how
many rows and columns are supported on the video display. Some video
adapters are able to display more than 80 columns and more than 25
rows in normal operation. If ME is invoked with these options, then it
will start up assuming that your display is already set at the
specified number of rows and/or columns.

For instance, the Everex enhanced EGA board is capable of
displaying 132 columns of text on one row. If your display is already
set up in this mode, then you must put the argument "-c132" on the ME
command line. It is probably easiest to do this within a BAT file.

Support for Video Boards
In the paragraph above, we mentioned that the -c and -r options will
work only if you are in the alternate video mode when you enter ME. Many
people would also like to use alternate video modes in conjunction with the
command (CTRL-E).

In version 2.0 and below, the command would simply toggle
between the normal 25 line mode and the 43 line mode produced by the EGA
when you load in the EGA's 8X8 font. Now, we offer video drivers which ME
can load in when it starts up. The video driver contains information about
the alternate video mode, such as the number of rows and columns it
supports, the code to turn the alternate mode on, and the code to turn it

A video driver is loaded into ME by specifying the "-v"
option on the ME command line. ME will perform its normal searching
algorithm to find the driver (first search the current directory, then the
paths specified by the ME environment variable, then search through the DOS

If you have a need for a video driver, or information on ow to write
your own, please contact us.

Command-line history using up and down keys
We have enhanced the prompting mechanism by allowing you to recall
previously entered responses. Responses are saved in a circular queue
in a last-in-first-out fashion. When ME prompts you for a response
(such as when you invoke the command), you can use the up and
down arrow keys to scroll backwards and forwards through the previous
responses. You can press to accept that response, or you can
use the editing keys to modify the response before accepting it.

The maximum number of responses which are saved is 16. When the
response queue gets full, the oldest response is discarded to make
room for the new response.

Current pick buffer displayed
The number of the current pick buffer is now displayed on the status
line, right next to the "modified" indicator.

Desqview compatibility.
ME now detects if DESQVIEW is loaded, and if it is, uses
DESQVIEW's alternate screen buffer when video accesses are done. This
enables you to use ME in a DESQVIEW window along side other processes.
In addition, if DESQVIEW is loaded, ME will not continuously poll the
keyboard for the shift status. This will let other processes run
smoothly under DESQVIEW.
(DESQVIEW is a trademark of Quarterdeck Office Systems.)

Keyboard push/pop fixed
The keyboard_push() and keyboard_pop() functions now work correctly.
Thanks to Kirk Wyatt for pointing out some glitches.



You must recompile all of your existing macros with the new 2.1 macro
compiler!!! They will not work otherwise!!!

In addition, we now recognize the difference between a carriage return
('\n', ascii 10) and a line feed ('\r', ascii 13). An ASCII 13 ('\r') is
generated when the user presses the ENTER key. An ASCII 10 ('\n') is
generated when the user presses the CTRL ENTER key combination. If any of
your macros test the keyboard for an ENTER key, you will need to change the
test from a '\n' to a '\r'.

We have added several new datatypes to the ME macro language which
should help with calling external C functions. The new data types are
unsigned values range from 0 to +65,335
long values range from -2,147,483,647 to +2,147,483,647
unsigned long values range from 0 to +4,294,967,295

You can now take get address of a variable and assign it to
another variable or pass it as an argument to an external C function.
Just like with the C language, an ampersand ('&') before a variable
will give you the address of the variable.

We added a new event (event number 9) which can be "hooked" into.
This new event occurs just after a command is processed. Event number
8 still occurs just before a command is processed. The new event will
let you perform any post-command processing that you need to do.

We added new functions to let you access the delimiter table.
These functions are :

void reset_word_delimiter()
Resets the word-delimiter table to its default state.

void set_word_delimiter(string delimiters, int value)
For each character is the string 'delimiters', sets the
corresponding entry in the word-delimiters table to 'value' (usually 0
or 1). If entry 'i' has a value of 0, then it is *not* a word

void clr_word_delimiter(int value)
Sets the entire word-delimiter table to the specified value
(usually 0 or 1). If entry 'i' has a value of 0, then it is *not* a
word delimiter.

New C functions added
The following C functions can be accessed through the macro lan-
guage :

void vidsetcursor(int start, int end)
Sets the starting and ending scan lines for the cursor to 'start'
and 'end' respectively. This is useful for macros where you would like
to hide the cursor (start=32,end=0) or change it from the default scan
lines for insert and overstrike modes.

int get_window_color()
Gets the color of the current window. The color returned has the
value of (background * 16 + foreground).

Mouse Support (DOS only)

ME now supports the use of any mouse which has a Microsoft mouse
compatible driver.

In the macro language, we have set up some new events which let
you trap mouse button presses. Event 11 is generated when you press
the left mouse button, event 12 is generated when you press the right
button, and event 13 is for the middle button. If the editor finds
that there is a hook defined on any one of these event, it will call
the hook macro. Otherwise, the default actions that it takes are :

Left button click - mark the current line
Right button click - set the cursor position to the clicked
Middle button click - no action

If the mouse is moved while the left button is held down, then the
marking of the lines which the mouse passes over will be toggled.



The biggest change to ME's windowing is the addition of vertical
windows. When you press 2 to open another window, ME will read the
specified file and then ask you if you want to split the file horizontally
or vertically. The default is a horizontal split; if you press 'v', the
window will be split vertically.

In previous versions of ME, each window was approximately the same
size. So, if you had three windows open, then each window would take up 7
lines. Starting with version 2.0, when you open a window, the current
window will be divided in half.

The addition of vertical windows also meant some difficulties for EGA
mode. Starting with version 2.0, you can only toggle in and out of 43-line
mode if there is one window open. It gets extremely difficult to determine
how a user wants windows resized when the characteristics of the screen
changes, so we took the easy way out.

Windows now have window identifiers associated with them. A window
identifier is just an integer. This id can be used in the new window
oriented macro functions which are detailed below.

New Keyboard Handling

The entire method of handling the keyboard was changed. As much as we
have tried to avoid the EMACS model of editing, there are just some things
that Richard Stallman did that we can't ignore. The concept of "keymaps"
fits the concept of "extensibility" perfectly. Therefore, ME now supports

A keystroke can be bound to an editor function, a user-defined macro, a
keyboard macro, or another keymap. A keymap is just an array of 256
keystrokes, and can be referred to by an integer identifier (much the same
way that buffers and windows have ids). There is also a "current keymap"
which is active at any time. When a keystroke is pressed, the command
associated with the bindings of the current keymap will be executed.

There are several new primitives in the macro language which allow you
to manipulate keymaps. You can push and pop keymaps from a stack. You can
create new keymaps and assign them default value. These new primitive are
outlined in the section below.

By using keymaps, we have been able to remedy some deficiencies that
were present with the macro language, as well as making the command
structure and keyboard handling more consistent.

Some of the things we were able to fix/enhance are :

- The repetition factor now works for all commands
- A macro function can now be bound to more than one keystroke sequence
(For instance, both F1 and ALT F1 can now invoke the same macro).
- Assign_key() can now bind a macro or editor function to a keystroke
sequence consisting of multiple keystrokes. For instance,

#define CTRL_Q 17
#define CTRL_G 7
assign_key("goline", CTRL_Q, CTRL_G);

will assign to function to the two-keystroke sequence Q,
G. This will make it much easier to emulate other editors' keystroke

In previous versions of ME, you could capture a sequence of keystrokes
using the F4 key and replay them using the F3 key. This meant that you
could only have one keyboard macro defined at one time. Starting with this
version, you can assign a keyboard macro to any key using the SHIFT-F4 key.

Macro Language

Several enhancements to the syntax of the macro language were made.
Switch/case statements can now take strings. This means that you can have
the following switch statement :

string s;
switch (s)
case "HELLO" : ......
case "BYE" : ......
default : ......

We have added labels and gotos to the macro language. These are exactly
the same as the corresponding ones in C. The format of a label is


The format of a goto is

goto label-name;

Of course, the label name must exist in the same function as the goto. An
example of a goto statement is the following :

a: ......
goto b;
goto a;
b: ......

A goto may backward or forward reference a label.

Hexidecimal constants are now allowed in the macro language. These
constants have the same format as hex constants in C. The format is

0x followed by a series of hex digits

For example, 0x10 is hexidecimal 16, and 0xFFF is hexidecimal 4095.

Keyboard Speedup

If you have an AT-class machine, then you can take advantage of the
machines programmable typeamatic rate. There are two new parameters in the
options menu (and in the CONFIG.ME file as well). These parameters are :

kr - keyboard typeamatic rate when a key is held down
kd - delay until typeamatic takes effect

In a normal computing environment, the rate is 12 and the delay is 1.
To get maximum keyboard speedup, set both of these values to 0.

New Macro Primitives

We have added a bunch of new primitives to the macro language.

id = create_window(r1,c1,r2,c2[,color])
int id;
int r1, c1, r2, c2; /* coordinates of the window */
int color;

Creates a "popup" window at the coordinates . You may optionally
specify a color as the last parameter. The color value should be :

(background color * 8) + foreground color

A window created with this function is considered to be a temporary
popup window for doing things like menus, messages, etc. One distinction
between this kind of window and a regular window is that a popup window
will not be replaced with another window when the popup window is killed.

When the window is created, there is no buffer attached to it, so
nothing will be displayed. You must use attach_buffer() and show_buffer()
to display the buffer in the window.

The value returned is the identifier of the created window. The
identifier can be used in various other window-related macro functions to
address that particular window.

window_id = attach_window(window_id, buffer_id)
int window_id, buffer_id;

Attaches the buffer whose id is 'buffer_id' to the window whose id is
'window_id'. If this function is successful, then the window_id is
returned, or else -1 is returned.

This function is typically used to connect a buffer to a popup window
before displaying the buffer.

Here is an example of its usage :

int win_id, new_buf;

new_buf = setcurrbuf(create_buffer("HELP.MNU"));
win_id = create_window(MenuRow1+1,MenuCol1+1,MenuRow2-1,MenuCol2-1,MenuColor);
attach_window(win_id, new_buf);

Keymap macros ----

id = keyboard_push()
int id;

Keyboard_push() will push the current keymap on the keymap stack. A
copy of the current keymap is created and is made the current keymap. The
id returned from this function is the identifier of the new keymap.

id = keyboard_pop(destroy_old)
int id;
int destroy_old;

Keyboard_pop() will pop the top keymap on the keymap stack and will
make it the current keymap. The id returned is the id of the new keymap. In
addition, the current keymap will be destroyed if the parameter 'destroy_old'
is non-zero. If the current keymap is not destroyed, it can be recalled at
any time by the function keyboard_set().

id = keyboard_id()
int id;

Keyboard_id() returns the id of the current keymap.

id = keyboard_set(id)
int id;

Keyboard_set() sets the current keymap to the keymap whose identifier
is id. If this is successful, then the id will be echoed as a return value.
If not successful (ie - the keymap with the specified id does not exist),
then -1 is returned.


Keyboard_defaults() will bind all of the keys of the current keymap to
the default values. The default values are the keystroke bindings that
comes preset when you obtain ME.

change_option(option, value)
string option; /* the two-letter option name to alter */
int value; /* the new value */

Change_option() allows you to alter the value of any of the editor
parameters which you find in the options menu and in the CONFIG.ME file.
The first parameter is the two-letter code for the option and the second
parameter in the new value.

Here are two examples :

change_option("in", 'Y'); /* turns insert-mode on */
change_option("sv", 200); /* sets autosave to every 200 keystrokes */

pos = search_string(str, pattern)
int pos; /* 0-based position that the pattern occured in */
string str, /* the string to search through */
pattern; /* the pattern to look for */

Search_string searches through the string specified by the first argu-
ment for the regular expression specified by the second argument.

if ((pos = search_string(currline(), "[0-9]")) >= 0)
message("The current line contains a digit");
message("No digit present in the current line");

Miscellaneous changes

The "-4" option on the command line will start ME in 43 line mode if
you have an EGA. For example, the command line :

me -4 ed.c

will edit the file ed.c starting in 43 line mode.

- Macro functions can now have names consisting of upper and lower case
- A bad EXM format on initial load will not cause a lockup.
- Entab won't compress blanks embedded in double-quoted strings. This
should make blank compression a little more reliable.

17) added tonum(str) in macro lang

Ability to link in external C functions

If you have the source and/or object code for ME, you have the ability
to link in external large model C functions, or functions written in any
language which obey the conventions of the C large model calling sequence.

There are only two kinds of parameters which you can pass to these
linked functions - integers and strings. You can only receive an integer
back as a return value (or any data item which fits in 16 bits).

To link an external C function in, you must make an entry in the table
in file CFUNCTBL.C. Each entry in This table has two elements - the name of
the function and a pointer to the function. You will use this name in the
macro language to refer to your function.

After your entry has been inserted in the table, you must recompile
CFUNCTBL.C, and relink the editor modules.

So far, the following C functions are available for use in the macro
language :

display(row, col, maxcol, color, str)
int row, col, maxcol;
int color;
string str;
Displays a string on the screen in the specified color. Row and Col are
0-based coordinates to display string at. Maxcol specifies the last
column that a character from the string can be displayed. An example is:

display(10, 20, 60, 0x2E, greeting);

erases the entire screen.

move_cursor(row, col)
int row, col;
moves the cursor to position on the screen. Both row and col
are 0 based, so the top left corner is at <0,0>.


Argument processing for do_macro()
Do_macro() can now take arguments. This allows you to build a macro
command line dynamically and invoke the macro with the passed arguments.
Also, a macro name entered by ALT P can take args. An arg beginning with a
digit is considered to be an integer, otherwise it's considered to be a
string. Look at the macro called 'menu' to see how a command line for
do_macro() is built at run-time.

Each argument can be separated by spaces or a comma.

As an example :

string macname, arg1, arg2;
int tab_amt, maxcol;

macname = "shift_line";
arg1 = tab_amt;
arg2 = maxcol;
do_macro(sprintf("%s %d %d", macname, arg1, arg2));

Enhanced formatting for message() and get_tty_str()
Message() and get_tty_str() can now take sprintf()-type formats and a
variable number of arguments. This will make the debugging of macros a lit-
tle easier. For example :

message("Hello %s", username);
foo = get_tty_str("Variable i is [%d]", i);

A "hook" is a user-defined macro which is executed when certain events
occur in the editor. The purpose of a hook is to allow the user to modify
or "filter" the processing which the editor does when these events happen.
The following events are supported :

Event Number Event Type
------------ ----------
0 The user inserted a character into the text
1 The editor is terminating
2 An illegal command was pressed
3 The CTRL BREAK key was pressed

We will add other event numbers as the need comes up - send us your

There are two primitives which manipulate hooks - one for adding a hook
and the other for removing a hook.

add_hook(eventnum, macro)
int eventnum;
string macro;


Add_hook() will cause the user-defined 'macro' to be called whenever
the event 'eventnum' occurs. The macro should NOT expect any arguments to
be passed.


'Eventnum' is a number from 0 through 3. The event numbers are defined
as follows :

Event Number Event Type
------------ ----------
0 The user inserted a character into the text.
The hook will be called before the cursor is
advanced to the next column.
1 The editor is terminating
2 An illegal command was pressed
3 The CTRL BREAK key was pressed

'Macro' is the name of a macro which should be called when the event




add_hook(0, "charhook"); /* called whenever a char is inserted */

/* Map all lower case letters to upper case */
if ((c = currchar()) >= 'a' && c <= 'z') /* lower case letter */
c = 'A' + c - 'a'; /* xlate to upper-case */
delchar(); /* remove the bad char */
insert(chr(c)); /* & insert the good one */

int eventnum;


Delete_hook() will remove the hook associated with event 'eventnum'.


'Eventnum' is an integer defined in the table above.





File Searching
rc = set_filespec(file_spec)
string file_spec;


If at least one file is found which matches the filespec, the number
1 is returned or else 0 is returned.

fname = next_filespec()
string fname;


If another file matching the filespec is found, the name of the file
is returned, or else the 0-length string is returned.

/* Prompt for a file specification, and insert each file name matching */
/* the filespec into the file */

if (set_filespec(get_tty_str("Input the filespec : ")))
while ((fname = next_filespec()) != "")

timestr = time()
string timestr;

The time() function returns a string which has the system time in the
form hh:mm:ss.

datestr = date()
string datestr;

The date() function returns a string which has the system date of the form

The TAGS function is now implemented as a macro. To use this
facility, you must load the TAGS macro into the editor. If you do this
from the DOS command line, you would use the command :


When you invoke the TAGS macro, you will be asked for the name of the function
to look up. If you press , you will be presented with a menu of
functions in a full-screen window. You can use the UP and DOWN arrow keys to
move through the menu. Position the highlight over the desired function and
press to select that function.

ALT 4 now splits the window vertically

Pressing at a marked line will now unmark it.
i = get_option(param)
c = get_lastkey()
Hook number 8