home *** CD-ROM | disk | FTP | other *** search
-
- 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)
-
-