
                          Pegasus Mail System,
       Copyright (c) 1990-95, David Harris, All Rights Reserved.

             Extensions Support in Pegasus Mail for Windows


1: Introduction

In Pegasus Mail for DOS v3.0, I introduced a resource-based forms system
which allowed people to create new ways of sending pre-formatted mail
using Pegasus Mail's internal services. While the DOS version's Forms
Manager added a useful and quite powerful level of functionality to the
program, it suffered from some drawbacks - it required users to learn a
new and quite complex language, was somewhat difficult to use, and
provided (on the whole) insufficient means of hooking into the internals
of Pegasus Mail.

When I reached the stage of feeling ready to incorporate forms support
into the Windows version of Pegasus Mail, I was faced with a quandary -
how to provide something which offered an adequate compromise between
infinite flexibility and maximum ease of use. I sat and thought for a
long time about exactly what uses forms would have in an e-mail system
and eventually reached the conclusion that you get what you pay for...
As the old saying goes, "Provide a system easy enough for any idiot to
use and only idiots will use it"... In order to provide a forms system
which is capable of handling any imaginable task which might be asked of
it, the price is necessarily a fairly high level of complexity and
richness. Balancing this implementational cost came a realization that
forms could be either a gimmick, or a mission-critical component in a
system: clearly, in a situation where adding a form is a mission-
critical requirement, resources and effort become justifiable; as for
that class of user who simply wants a new toy, well, I'm afraid they
will be disappointed.

Once I began writing the forms interface, it became apparent almost
immediately that it would be possible to do far more than simple forms 
programming with it, so accordingly, I renamed it an "Extensions" 
interface.

The process of developing an extension for Pegasus Mail for Windows
involves direct, Windows-level programming and no small amount of
familiarity with the intricacies of writing for the Windows environment:
on the positive side, because an extension consists of executable code
which takes advantage of the internal services Pegasus Mail offers, there
is practically no limit at all to what one can do. Because many of the
mechanical tasks associated with mail processing are performed on a
server/client basis for the extension by WinPMail, the extension in its
most basic shape is simply a glue interface which can be potentially
quite easily produced simply by examining and modifying the source code
for any of the sample extensions provided with this kit.

Furthermore, WinPMail deals with the vast bulk of the complex issues 
associated with window management and user interaction, so an extension 
can concentrate in a more focussed way on the actual task it has to 
perform.


2: Requirements

In order to write a WinPMail extension, you will need access to the 
following tools or resources:

   * Borland C++ version 3.1 or later (recommended) or any other
     development environment capable of producing a standard Windows
     DLL module.

   * A good understanding of Windows messages and programming. If you
     don't have this already, you're probably in trouble, but if you're
     masochistic enough to want to continue anyway, then Charles Petzold's 
     excellent introduction to Windows programming will probably be a
     mandatory place for you to start.

   * Considerable patience; the process of developing an extension is much 
     easier than writing your own mail application, but you can still
     expect to spend some time debugging, cursing, swearing and all the
     other usual fun pastimes associated with normal Windows programming.


3: Overview

To WinPMail, an extension is simply a special piece of user-supplied code
which it agrees to host in one of its MDI (Multiple Document Interface)
windows. WinPMail offers an extensive "API" of over 70 functions to
extensions and co-operates with them to ensure correct presentation of
the extension's window, but otherwise places very few restrictions on
what it may do.

extensions come in two flavours - "Reader" extensions, and "Composer"
extensions. "Reader extensions" are special extensions which Pegasus Mail
can ask to display or handle mail messages which match particular
criteria, instead of using its own built-in message reader routines.
Reader extensions are opened automatically by WinPMail when the user asks
to read a message matching certain criteria (supplied by the extension
developer), but can never actually be directly triggered by the user -
they are always triggered by WinPMail in response to a condition becoming
true. Once a Reader extension has been triggered, it can take any action
it wishes and has access to the full API, including a number of specific
functions allowing it to access the data from the triggering message.
Reader extensions are intended to provide custom presentation windows for
particular types of message (usually messages generated using a matching
Composer extension) and can be used to provide extended automatic
processing of messages (much like WinPMail's own mail filtering rules).

Unlike Reader extensions, Composer extensions can ONLY be activated by
the user - they are never invoked automatically (other than the possible
option of being activated at startup). Composer extensions are primarily
intended to provide alternative ways of entering message data then
formatting it for transmission, and hence have considerable control over
the mail messages they generate. WinPMail provides full management for
Composer extensions, including a floating selection window from which
the user can load new extensions at any time.

It is important to note that although the extensions support is
primarily intended to offer mail-oriented extensions to Pegasus Mail,
extensions can in fact do almost anything they want - a good example is
either of the directory service clients supplied with Pegasus Mail (PH
and Finger) - they interact with the user and perform reasonably complex
user lookups using the TCP/IP protocol, but never so much as send or
examine a single mail message. Extensions could conceivably be used for
almost any purpose, including mail gateways, system monitoring
extensions, graphics editors, spreadsheet modules, OLE or OpenDoc
integration, DDE support - just about anything you could write code for.

There is a basic assumption that if an extension needs to interact with
the user in any way, then it will create a standard Windows dialog to do
so. WinPMail's Extensions Manager provides a mechanism which allows a
standard dialog to be fitted into a regular WinPMail MDI client window,
and if this paradigm is followed, your extension code will be nothing
more than a simple Windows modeless dialog handler - WinPMail will
occasionally send specific messages to an extension advising of certain
events, but you need not necessarily respond to any of these messages.

Extensions do not have to provide a dialog - for instance, an extension
which simply logs events to a file might need no user interface at all;
in cases like this, the extension can export a single function to which
WinPMail will send notifications, and the enclosing MDI window will be
hidden. It is important to note, however, that every instance of an
extension will always have a WinPMail MDI "parent" window associated with
it, whether or not it is visible or interacts with the user. Extensions
gain access to WinPMail internal services by sending standard Windows- 
style messages to this MDI window.


4: Writing an extension

To WinPMail, an extension consists of two parts - a "Form Fact File" 
(described below) and a DLL which it should load and with which it should 
interact. To write an extension, you need to use any language tool which 
can create a standard Windows DLL; while Pegasus Mail is written using 
Borland C++, there is no requirement that you use this language to create 
an extension, provided the language you use supports the standard Windows 
interface. The examples in this section presume that you are using 
Borland C.

A good starting point for writing an extension is to use the source code 
from one of the sample extensions provided with Pegasus Mail as a model. 
Using the Borland IDE, create a new project (or load a model) and set the 
code generation and output file format to "Windows DLL". You can use 
whatever memory model is most appropriate for your purposes, but be 
aware that many of the Windows messages you have to send to the Extension
Manager presume that you are using pointers to FAR data. I personally 
find that the Large memory model is the easiest and least complicated to 
use for projects like this.

Next, create or open the main file for the extension. This will be a
standard Windows program file; you should include <windows.h> as usual,
along with whatever other header files you need. You must also include
the file "wpmforms.h" supplied with this kit. Wpmforms.h contains all
the definitions necessary to interface with the Extensions Manager, and
is heavily commented; you should refer to this file for information and
syntax on all the API calls available to extensions. Also in the main
file you should create the standard Windows LibMain() function, which
almost always consists of the following code:

    int FAR PASCAL LibMain (HANDLE hInstance, WORD wDataSeg, 
       WORD wHeapSize, LPSTR lpszCmdLine)
       {
       if (wHeapSize > 0) UnlockData (0);
       return 1;
       }

If your extension is going to use a dialog, you should also register the 
class for your dialog window here. Note that dialog windows in extensions 
are by definition modeless, so they must have a registered class with a
standard window handler. Examine the PH.C sample file for an example of
how to register a window class in LibMain.    

The next step is to create the initialization function WinPMail calls 
when it loads the extension. This function >>must<< be called FORMINIT, 
and should have the following declaration:

   WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND 
      hParent, char *data, HWND *hDialog, char *callback_name);

WinPMail calls this function immediately on loading the extension, using 
the following parameters:

  "version" is passed in with the version of the WinPMail Extension
     Manager which is running. The major version of the Extension Manager
     is in the high byte and the minor version number is in the low byte.
  "variant" indicates what type of extension is required - the following
     values are currently defined:
       0: Load an extension for composing a message ("Composer")
       1: Load an extension for reading a message ("Reader")
     Having a "variant" field allows a single DLL to support multiple
     extension types, although you do not have to work this way.
  "hParent" contains the handle of the WinPMail MDI child window
     which is to contain the extension. If your extension does not create
     a dialog, you will need to store this value somewhere globally
     accessible, since you need it to communicate with the Extension
     Manager. If you create a dialog in your extension, you should create 
     the dialog without any borders using the WS_CHILD window style and
     set its parent to be this window.
  "data" contains any string specified to be passed to the form by its
     Form Fact File. Think of this as a commandline for the extension -
     as an example, the PH extension expects to find its default host
     in this parameter.
  "hDialog" should be filled in with the window handle of the modeless 
     dialog you create within the MDI child window, if any. If you set
     this value to NULL, then WinPMail will hide the MDI window associated
     with the extension and will route notification messages to the
     callback function (see the next entry).
  "callback_name" (optional) should be filled in with the name of the
     function in the DLL of the exported function to which messages
     should be sent or NULL if there is none. You will usually fill this
     entry in if you do not create a dialog so you can receive 
     notifications from the Extension Manager. If a dialog is defined,
     the Extension Manager will always route messages to it, even if you
     enter a value in this field. The function whose name you return 
     in this parameter (if you use it) should have the following 
     prototype:

        DWORD PASCAL FAR _export form_fn (HWND hWnd, WORD wMsg,
           WPARAM wParam, LPARAM lParam);

     Notice that the prototype simply mirrors the definition for a
     standard Windows Window handler (WndProc) function.

You've now done everything the Extension Manager requires to be able to 
use your extension - from here, only the good stuff is left for you to
do - the actual working end of the extension, which is up to you.


5: Form Fact Files

WinPMail learns about available extensions by looking for Form Fact
Files, which are text files with the extension .FFF, describing the
characteristics of the extension. WinPMail looks for FFF files first in
the user's home mailbox, and then in the same directory as WINPMAIL.EXE,
and finally (if present) in the directory pointed to by an FFF DOS
environment variable. Scanning this way allows the use of both global
and private extensions.

Form Fact Files use a simple text format and are line based. Blank 
lines, and any line in a FFF which starts with #, ; or *, are all ignored 
as comments. Command lines in an FFF consist of a keyword sequence 
followed by optional whitespace, followed by the character '=', followed 
by more optional whitespace and a parameter. The following keyword 
sequences are recognized:

   Form name
     - The name the WinPMail Extensions Manager should display in the
       "Extensions" window.
   Form DLL
     - A required parameter which indicates the full path to the DLL
       WinPMail should load to access the extension. Standard command
       substitutions (as in user-defined gateways) can be used in this
       field - so for example, ~a/forms/foo.dll would be interpreted as
       "start in the directory where WINPMAIL.EXE resides, then change
       to the FORMS subdirectory and load FOO.DLL". For a complete list
       of command substitutions available, please see the file UDG.TXT
       supplied with Pegasus Mail.
   Form type
     - Should be either of the strings READER or COMPOSER depending on
       the type of extension being defined. A single definition can only
       have a single form type, although an FFF can contain multiple
       definitions. If absent, the default for this keyword is COMPOSER.
   Form flags
     - Contains settings which affect the operation of the extension. The
       value is an unsigned long (32 bits) which is treated as a bitmap.
       The following bit values are currently defined:

       Mnemonic     Value   Meaning
       ----------------------------------------------------------------
       WPM_STARTUP    1     Load the extension when WinPMail starts up
       WPM_NOLIST     2     Do not show in the "Extensions" window list
       WPM_HIDDEN     4     Hide the parent MDI window on loading
       WPM_LOGGING    8     Extension wants to receive logging events
       WPM_ONEONLY   16     Only allow one running instance at any time

       Various flags can be combined by adding (or ORing) the values
       together - so to have a hidden extension which loads at startup,
       is interested in logging events, and does not appear in the
       "Extensions" window, you would use 1 + 2 + 4 + 8 = 15
   Form tagname
     - This is the extension's unique identifier (see below for 
       information on registering a tagname). WinPMail writes the tag
       name into any mail generated by the extension as an X- header -
       so, if your tagname was "FUBAR", WinPMail would write a header
       into the message which read "X-FUBAR: 1". Tagnames can be used
       as unique triggers for Reader extensions. Tagnames starting with
       the letters PM are reserved by the author.
   Form data
     - A "command line" for the extension. This text string is passed
       unmodified to the extension at load-time. The most normal use is
       to pass site-specific default information to the extension (for
       example, the Phone Message extension expects to see the default
       telephone area code in the "data" field).
   Form triggers
     - This keyword is only meaningful for READER extensions and is
       ignored if "Form Type = READER" has not already been seen. The
       parameter is an arbitrary regular expression which WinPMail should
       apply to the headers of a message to determine if the reader
       should be invoked for this message. The regular expression can
       contain '*' and '?' characters to match patterns within a header,
       and is presumed to start at the beginning of a line. So, for 
       example, if you wanted to load a reader every time you saw a
       header called "X-File-type" which contained the letters "JPG",
       you might enter the trigger "X-FILE-TYPE*JPG*". Only a single
       trigger may be defined in any "Form Triggers" statement, but you
       may have as many "Form Triggers" lines in a definition as you
       wish.
   Override
     - An optional keyword with a single integer parameter; can only
       be used with COMPOSER extensions. This keyword indicates that the
       extension wishes to replace a built-in WinPMail function or menu
       selection. WinPMail checks for overriding extensions every time
       it processes a menu selection and if it finds one, it invokes
       the extension instead of the built-in function. An entry in an
       FFF can have only one "Override" line, but you can have multiple
       entries each defining a different override. In normal use, you
       will set the "Form Flags" line for an overriding extension to 18,
       so that only one instance can be open and it doesn't appear in the
       Extension Manager's list. For a list of menu IDs, see Appendix A
       at the end of this document.
   End
     - Indicates that the definition is complete; the entry is added
       to the internal extension list maintained by WinPMail. You MUST
       have an END statement for each definition - reaching end of file
       without an End statement will result in the definition being
       discarded.

You may have as many definitions as you wish or need in a single FFF - 
and in fact, for system-wide FFFs there is a slight performance gain in
gathering all your definitions into a single file. Remember to use an END 
statement to close every definition though.


6: Using the Extensions Manager API

WinPMail's Extensions Manager makes a set of over 70 functions available 
to extensions, providing every imaginable kind of service from sending 
mail messages through to TCP/IP communications.

An extension accesses the Extensions Manager API by using the Windows
SendMessage function to send a message to its parent window. The
parameters to SendMessage depend on the service required, and are fully
described in WPMFORMS.H - you should consult that file as a definitive
reference. With one or two specific exceptions (most notably the
WM_F_GETMESSAGEFIELD message), the Extension Manager API messages can be
sent at any time while the extension is loaded, including times when
WinPMail is in the background.


7: Hints and tips

Configuration files: if your extension needs to create a configuration 
file, the following approach may be helpful:

  a) Obtain the user's home mailbox location using WM_F_GETHOMEBOX
  b) Construct a filename using your extension's registered Tagname
     and the extension .PM.
  c) Write whatever information you need to keep into the file.

You can use the same steps to locate a configuration file. Using your 
registered Tagname guarantees uniqueness for the filename, while using
the extension .PM lets Pegasus Mail maintain the location of the file
correctly for you even if the user shifts his/her home mailbox location.

Disabling WinPMail features: Many sites with student populations have
expressed the desire to be able to disable or regulate some of WinPMail's
built-in features. You can do this with extensions either by creating a
logging extension which looks for events concerning the features you want
to disable (the most likely is WLOG_LOADMENU, which will allow you to
disable the items in their menus), or else by creating extensions which
override the menu choice for the target functions and put up an explana-
tory dialog instead.


8: Accessing the Extension Manager from outside WinPMail

On occasions you may want to access WinPMail's Extension Manager services
from outside WinPMail itself; an example of such a situation might be the
implementation of a MAPI interface which is loaded by other programs - in
fact, WinPMail's own MAPI interface, which is in development at the time
of writing, uses exactly this approach.

To access the Extensions Manager in this way, locate the WinPMail frame
window (which has the class FRAME and the title "Pegasus Mail") and send
it a WM_INTERFACE message (#define WM_INTERFACE (WM_USER + 17480)). If you
have a window which you want to receive WinPMail's WM_FM_* Extensions
Manager notification messages, pass it in wParam. WinPMail will return the
HWND of a new, hidden Extension Manager window to which your code can send
messages requesting service just as if it were a standard extension. When
you have finished with the service, send the window a WM_CLOSE message.

** NOTE: Issues of memory handling are up to your module; there may be
** instances where you will have to allocate global memory before passing
** it to WinPMail, usually if you have to take memory allocated by another
** program and make it available to WinPMail.

The following code sample shows how to open an external connection to the
Extensions Manager in the manner described above:

   #define WM_INTERFACE   (WM_USER + 17480)
   
   HWND access_extension_service (HWND message_handler)
      {
      HWND hFrame;
   
      if ((hFrame = FindWindow ("FRAME", "Pegasus Mail")) == NULL)
         return NULL;
   
      return (HWND) SendMessage (hFrame, WM_INTERFACE, 
        (HWND) message_handler, 0);
      }


XX: Distributing extensions and reserving tagnames

Because extensions are distributed as working, executable machine code,
many sites may be reluctant to use an extension when they are unaware of
its pedigree. If you have an extension you think would be useful and
would like to see it widely distributed to the Pegasus Mail user
community in a verified, secure manner, then you can follow these steps:

   * Debug and test your extension thoroughly until you are sure it works. 
     This step is very important! The author does not provide a debugging
     service for your extensions and will reject out-of-hand anything 
     which does not compile correctly or which crashes when run.
   * Contact the author of Pegasus Mail, David Harris, at the Internet
     e-mail address David.Harris@pmail.gen.nz. He will arrange for you
     to upload a private copy of your extension to his system and will 
     examine it for certification.
   * You MUST upload source code to your extension. The author will only
     certify extensions which he has personally compiled, and when 
     distributing them will only distribute binary versions which he 
     has built. You are not required to distribute the source code 
     with the extension itself, but it must be made available to him.
   * If your extension checks out OK and builds correctly, it will be
     made available on the principal Pegasus Mail distribution sites and
     endorsed as "safe and authenticated" by the author.
   * For technical reasons, the author can only certify extensions which 
     are written for Borland C++ version 3.1 or later. Please make 
     sure you include the appropriate make, PRJ or IDE file, as well 
     as all associated RC, H and C or CPP files.

Reserving extension tag names: because extensions can define tags for
themselves which can be used to invoke a reader extension on receipt, it
is obviously desirable to ensure that tagnames remain unique. In order to
encourage this, the author offers a free tagname registration service.
Send a mail message to "tagnames@pmail.gen.nz" indicating the tagname(s)
you would like to reserve and optionally a brief description of your
extension (for the author's interest). Tagnames will be registered on a
first-come/ first-served basis, and if a tagname you have requested is
already taken, you will be advised as soon as possible. The author
reserves the right to refuse to register tagnames for any reasons he
deems fit - for example, tagnames containing obscene words will not be
accepted, nor will any tagname starting with the letters "PM", because
all such tagnames are reserved by the author. The list of currently-
registered extension tagnames can be retrieved by e-mail at any time by
sending a message to maiser@pmail.gen.nz consisting of the two lines:

    SEND TAGNAMES.TXT
    EXIT

Please note that tagnames can be a maximum of 12 characters long, may 
not contain characters with ASCII values lower than 33 or higher than 126 
and are case-insensitive. All form names starting with the letters "PM" 
are reserved by the author.


Appendix A: Menu IDs for overriding extensions

The following integer values can be used as the parameter to an
"Override" keyword line in a Form Fact File by extensions wishing to
override particular built-in menu choices within WinPMail.

------------------------------------------------------------------------
WinPMail Mnemonic       ID    Menu function (Which Menu)
------------------------------------------------------------------------
IDM_HELP                10    "Context-sensitive help" (HELP)
IDM_USING_HELP          11    "Using Help" (HELP)
IDM_HELPINDEX           12    "Help index" (HELP)
IDM_RMACRO              75    "Open glossary manager" (EDIT/GLOSSARY)
IDM_PMACRO              76    "Expand glossary entry" (EDIT/GLOSSARY)
IDM_NEWMESSAGE         101    "Start new message" (FILE)
IDM_READNEW            102    "Open new mail folder" (FILE)
IDM_OPENFOLDER         103    "Folders..." (FILE)
IDM_IMPORT             104    "Import into message" (MESSAGE)
IDM_SAVESESSION        105    "Save message as draft" (MESSAGE)
IDM_RESTORESESSION     106    "Open saved message" (FILE)
IDM_PRINT              107    "Print" (FILE)
IDM_PRINTSETUP         109    "Printer setup" (FILE)
IDM_FILTERS            110    "New mail filtering rules" (FILE)
IDM_EXIT               111    "Exit" (FILE)
IDM_PREF_GENERAL       121    "General settings" (FILE/PREFS)
IDM_PREF_SMF           122    "NetWare MHS settings" (FILE/PREFS)
IDM_PREF_SIGS          123    "Signatures..." (FILE/PREFS)
IDM_PREF_HOMEBOX       124    "Home mailbox location" (FILE/PREFS)
IDM_PREF_EXT           125    "Extended features" (FILE/PREFS)
IDM_UNDO               131    "Undo" (EDIT)
IDM_CUT                132    "Cut" (EDIT)
IDM_COPY               133    "Copy" (EDIT)
IDM_PASTE              134    "Paste" (EDIT)
IDM_CLEAR              135    "Clear" (EDIT)
IDM_SELECTALL          136    "Select all" (EDIT)
IDM_SPELLING           137    "Check spelling" (EDIT)
IDM_SERVER             138    "File servers..." (FILE)
IDM_LOCALUSERS         141    "Lookup local users" (ADDRESSES)
IDM_ADDRESSBOOKS       142    "Address books" (ADDRESSES)
IDM_MAILINGLISTS       143    "Distribution lists..." (ADDRESSES)
IDM_SORTBYKEY          144    "Sort by key" (ADDRESSBOOK)
IDM_SORTBYNAME         145    "Sort by name" (ADDRESSBOOK)
IDM_FIND               146    "Find text", (MESSAGE/FOLDER/READER/ADDRBK)
IDM_FINDAGAIN          147    "Find again", (MESSAGE/FOLDER/READER/ADDRBK)
IDM_PASTENAMES         148    "Paste names" (ADDRESSBOOK)
IDM_PASTEADDRESSES     149    "Paste addresses" (ADDRESSBOOK)
IDM_SAVESIZE           150    "Save window size" (Various)
IDM_OTHEROPTIONS       151    "Special message view" (MESSAGE)
IDM_SHOWHEADERS        153    "Show all headers" (READER)
IDM_EXTRACT            154    "Save messages to disk" (FOLDER/READER)
IDM_ATTACH             155    "Switch to attachments view" (MESSAGE)
IDM_MARKUNREAD         156    "Mark message as unread" (FOLDER and NB)
IDM_ALIASING           157    "Resolve aliases" (ADDRESSBOOK)
IDM_BPPREF             158    "Button panel preferences" (FILE/PREFS)
IDM_UUDECODE           160    "UUdecode message" (FOLDER/READER /SPECIAL)
IDM_UNBINHEX           161    "Un-BinHex message" (FOLDER/READER /SPECIAL)
IDM_LOCALSIG           162    "Signature for local mail" (FILE/PREFS)
IDM_INETSIG            163    "Signature for Internet mail" (FILE/PREFS)
IDM_MHSSIG             164    "Signature for MHS mail" (FILE/PREFS)
IDM_DELEXPIRED         165    "Delete expired messages" (FOLDER/SPECIAL)
IDM_EDMAIL             167    "Switch to message editor view" (MESSAGE)
IDM_QUICKLOOKUP        168    "Quick lookup" (ADDRESSES)
IDM_WORDWRAP           169    "Wrap long lines" (READER)
IDM_DELLINE            170    "Delete line" (MESSAGE)
IDM_REFORMAT           171    "Reformat paragraph" (MESSAGE)
IDM_INDENT             172    "Indent text" (MESSAGE)
IDM_REPLACE            173    "Search and replace" (MESSAGE)
IDM_DELWORD            174    "Delete word right" (MESSAGE)
IDM_APREFS             175    "Advanced settings" (FILE/PREFS)
IDM_ENLARGE            176    "Enlarge window" (WINDOW)
IDM_ABK_EXPORT         177    "Export addressbook" (ADDRESSBOOK)
IDM_ABK_IMPORT         178    "Import addressbook" (ADDRESSBOOK)
IDM_NOTICEBOARDS       179    "Noticeboards" (FILE)
IDM_ANN_EDIT           180    "Add/edit annotation" (FOLDER)
IDM_SRT_DATE           181    "Sort by date" (FOLDER)
IDM_SRT_REVDATE        182    "Sort by reverse date" (FOLDER)
IDM_SRT_SUBJECT        183    "Sort by subject" (FOLDER)
IDM_SRT_FROM           184    "Sort by sender's name" (FOLDER)
IDM_FORMS              185    "Open Forms Manager" (FILE)
IDM_ANN_DELETE         186    "Delete annotation" (FOLDER)
IDM_REVIEWMAIL         187    "Review Queued Mail" (FILE)
IDM_TODISK             230    "Save to disk" (Various)
IDM_FROMDISK           231    "Read from disk" (Various)
IDM_EXTRACTFILE        240    "MHS directory service" (ADDRESSES)
IDM_LOGGED_IN          241    "Logged-in users" (ADDRESSES)
IDM_ADD_USER           242    "Add sender to list" (READER/SPECIAL)
IDM_REMOVE_USER        243    "Remove sender from list" (READER/SPECIAL)
IDM_FONT               299    "Font" (Various)
IDM_TILE               500    "Tile" (WINDOW)
IDM_CASCADE            501    "Cascade" (WINDOW)
IDM_ARRANGEICONS       502    "Arrange Icons" (WINDOW)
IDM_BUTTONPANEL        503    "Button panel" (WINDOW)

