home *** CD-ROM | disk | FTP | other *** search
/ Using the Internet / 21003.iso / email / PEGASUS / WINPM222.ZIP / WINPMAIL.ZIP / FORMS / WPMFORMS.TXT < prev    next >
Text File  |  1995-11-01  |  36KB  |  655 lines

  1.  
  2.                           Pegasus Mail System,
  3.        Copyright (c) 1990-95, David Harris, All Rights Reserved.
  4.  
  5.              Extensions Support in Pegasus Mail for Windows
  6.  
  7.  
  8. Contents:
  9.  
  10.    1: Introduction
  11.    2: Requirements
  12.    3: Overview
  13.    4: Writing an extension
  14.    5: Form Fact Files
  15.    6: Using the Extensions Manager API
  16.    7: Hints and tips
  17.    8: Accessing the Extension Manager from outside WinPMail
  18.    9: License to use Pegasus Mail Bitmaps
  19.   10: Distributing extensions and reserving tagnames
  20.   Appendix A: Menu IDs for overriding extensions
  21.  
  22.  
  23. 1: Introduction
  24.  
  25. In Pegasus Mail for DOS v3.0, I introduced a resource-based forms system
  26. that allowed people to create new ways of sending pre-formatted mail
  27. using Pegasus Mail's internal services. While the DOS version's Forms
  28. Manager added a useful and quite powerful level of functionality to the
  29. program, it suffered from some drawbacks - it required users to learn a
  30. new and quite complex language, was somewhat difficult to use, and
  31. provided (on the whole) insufficient means of hooking into the internals
  32. of Pegasus Mail.
  33.  
  34. When I reached the stage of feeling ready to incorporate forms support
  35. into the Windows version of Pegasus Mail, I was faced with a quandary -
  36. how to provide something that offered an adequate compromise between
  37. infinite flexibility and maximum ease of use. I sat and thought for a
  38. long time about exactly what uses forms would have in an e-mail system
  39. and eventually reached the conclusion that you get what you pay for...
  40. As the old saying goes, "Provide a system easy enough for any idiot to
  41. use and only idiots will use it"... In order to provide a forms system
  42. that is capable of handling any imaginable task that might be asked of
  43. it, the price is necessarily a fairly high level of complexity and
  44. richness. Balancing this implementational cost came a realization that
  45. forms could be either a gimmick, or a mission-critical component in a
  46. system: clearly, in a situation where adding a form is a mission-
  47. critical requirement, resources and effort become justifiable; as for
  48. that class of user who simply wants a new toy, well, I'm afraid they
  49. will be disappointed.
  50.  
  51. Once I began writing the forms interface, it became apparent almost
  52. immediately that it would be possible to do far more than simple forms 
  53. programming with it, so accordingly, I renamed it an "Extensions" 
  54. interface.
  55.  
  56. The process of developing an extension for Pegasus Mail for Windows
  57. involves direct, Windows-level programming and no small amount of
  58. familiarity with the intricacies of writing for the Windows environment:
  59. on the positive side, because an extension consists of executable code
  60. that takes advantage of the internal services Pegasus Mail offers, there
  61. is practically no limit at all to what one can do. Because many of the
  62. mechanical tasks associated with mail processing are performed on a
  63. server/client basis for the extension by WinPMail, the extension in its
  64. most basic shape is simply a glue interface that can be potentially
  65. quite easily produced simply by examining and modifying the source code
  66. for any of the sample extensions provided with this kit.
  67.  
  68. Furthermore, WinPMail deals with the vast bulk of the complex issues 
  69. associated with window management and user interaction, so an extension 
  70. can concentrate in a more focussed way on the actual task it has to 
  71. perform.
  72.  
  73.  
  74. 2: Requirements
  75.  
  76. In order to write a WinPMail extension, you will need access to the 
  77. following tools or resources:
  78.  
  79.    * Borland C++ version 3.1 or later (recommended) or any other
  80.      development environment capable of producing a standard Windows
  81.      DLL module.
  82.  
  83.    * A good understanding of Windows messages and programming. If you
  84.      don't have this already, you're probably in trouble, but if you're
  85.      masochistic enough to want to continue anyway, then Charles Petzold's 
  86.      excellent introduction to Windows programming will probably be a
  87.      mandatory place for you to start.
  88.  
  89.    * Considerable patience; the process of developing an extension is much 
  90.      easier than writing your own mail application, but you can still
  91.      expect to spend some time debugging, cursing, swearing and all the
  92.      other usual fun pastimes associated with normal Windows programming.
  93.  
  94.  
  95. 3: Overview
  96.  
  97. To WinPMail, an extension is simply a special piece of user-supplied code
  98. that it agrees to host in one of its MDI (Multiple Document Interface)
  99. windows. WinPMail offers an extensive "API" of over 70 functions to
  100. extensions and co-operates with them to ensure correct presentation of
  101. the extension's window, but otherwise places very few restrictions on
  102. what it may do.
  103.  
  104. extensions come in two flavours - "Reader" extensions, and "Composer"
  105. extensions. "Reader extensions" are special extensions that Pegasus Mail
  106. can ask to display or handle mail messages that match particular
  107. criteria, instead of using its own built-in message reader routines.
  108. Reader extensions are opened automatically by WinPMail when the user asks
  109. to read a message matching certain criteria (supplied by the extension
  110. developer), but can never actually be directly triggered by the user -
  111. they are always triggered by WinPMail in response to a condition becoming
  112. true. Once a Reader extension has been triggered, it can take any action
  113. it wishes and has access to the full API, including a number of specific
  114. functions allowing it to access the data from the triggering message.
  115. Reader extensions are intended to provide custom presentation windows for
  116. particular types of message (usually messages generated using a matching
  117. Composer extension) and can be used to provide extended automatic
  118. processing of messages (much like WinPMail's own mail filtering rules).
  119.  
  120. Unlike Reader extensions, Composer extensions can ONLY be activated by
  121. the user - they are never invoked automatically (other than the possible
  122. option of being activated at startup). Composer extensions are primarily
  123. intended to provide alternative ways of entering message data then
  124. formatting it for transmission, and hence have considerable control over
  125. the mail messages they generate. WinPMail provides full management for
  126. Composer extensions, including a floating selection window from which
  127. the user can load new extensions at any time.
  128.  
  129. It is important to note that although the extensions support is
  130. primarily intended to offer mail-oriented extensions to Pegasus Mail,
  131. extensions can in fact do almost anything they want - a good example is
  132. either of the directory service clients supplied with Pegasus Mail (PH
  133. and Finger) - they interact with the user and perform reasonably complex
  134. user lookups using the TCP/IP protocol, but never so much as send or
  135. examine a single mail message. Extensions could conceivably be used for
  136. almost any purpose, including mail gateways, system monitoring
  137. extensions, graphics editors, spreadsheet modules, OLE or OpenDoc
  138. integration, DDE support - just about anything you could write code for.
  139.  
  140. There is a basic assumption that if an extension needs to interact with
  141. the user in any way, then it will create a standard Windows dialog to do
  142. so. WinPMail's Extensions Manager provides a mechanism that allows a
  143. standard dialog to be fitted into a regular WinPMail MDI client window,
  144. and if this paradigm is followed, your extension code will be nothing
  145. more than a simple Windows modeless dialog handler - WinPMail will
  146. occasionally send specific messages to an extension advising of certain
  147. events, but you need not necessarily respond to any of these messages.
  148.  
  149. Extensions do not have to provide a dialog - for instance, an extension
  150. that simply logs events to a file might need no user interface at all;
  151. in cases like this, the extension can export a single function to which
  152. WinPMail will send notifications, and the enclosing MDI window will be
  153. hidden. It is important to note, however, that every instance of an
  154. extension will always have a WinPMail MDI "parent" window associated with
  155. it, whether or not it is visible or interacts with the user. Extensions
  156. gain access to WinPMail internal services by sending standard Windows- 
  157. style messages to this MDI window.
  158.  
  159.  
  160. 4: Writing an extension
  161.  
  162. To WinPMail, an extension consists of two parts - a "Form Fact File" 
  163. (described below) and a DLL that it should load and with which it should 
  164. interact. To write an extension, you need to use any language tool that 
  165. can create a standard Windows DLL; while Pegasus Mail is written using 
  166. Borland C++, there is no requirement that you use this language to create 
  167. an extension, provided the language you use supports the standard Windows 
  168. interface. The examples in this section presume that you are using 
  169. Borland C.
  170.  
  171. A good starting point for writing an extension is to use the source code 
  172. from one of the sample extensions provided with Pegasus Mail as a model. 
  173. Using the Borland IDE, create a new project (or load a model) and set the 
  174. code generation and output file format to "Windows DLL". You can use 
  175. whatever memory model is most appropriate for your purposes, but be 
  176. aware that many of the Windows messages you have to send to the Extension
  177. Manager presume that you are using pointers to FAR data. I personally 
  178. find that the Large memory model is the easiest and least complicated to 
  179. use for projects like this.
  180.  
  181. Next, create or open the main file for the extension. This will be a
  182. standard Windows program file; you should include <windows.h> as usual,
  183. along with whatever other header files you need. You must also include
  184. the file "wpmforms.h" supplied with this kit. Wpmforms.h contains all
  185. the definitions necessary to interface with the Extensions Manager, and
  186. is heavily commented; you should refer to this file for information and
  187. syntax on all the API calls available to extensions. Also in the main
  188. file you should create the standard Windows LibMain() function, which
  189. almost always consists of the following code:
  190.  
  191.     int FAR PASCAL LibMain (HANDLE hInstance, WORD wDataSeg, 
  192.        WORD wHeapSize, LPSTR lpszCmdLine)
  193.        {
  194.        if (wHeapSize > 0) UnlockData (0);
  195.        return 1;
  196.        }
  197.  
  198. If your extension is going to use a dialog, you should also register the 
  199. class for your dialog window here. Note that dialog windows in extensions 
  200. are by definition modeless, so they must have a registered class with a
  201. standard window handler. Examine the PH.C sample file for an example of
  202. how to register a window class in LibMain.    
  203.  
  204. The next step is to create the initialization function WinPMail calls 
  205. when it loads the extension. This function >>must<< be called FORMINIT, 
  206. and should have the following declaration:
  207.  
  208.    WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND 
  209.       hParent, char *data, HWND *hDialog, char *callback_name);
  210.  
  211. WinPMail calls this function immediately on loading the extension, using 
  212. the following parameters:
  213.  
  214.   "version" is passed in with the version of the WinPMail Extension
  215.      Manager that is running. The major version of the Extension Manager
  216.      is in the high byte and the minor version number is in the low byte.
  217.      Note that the Extension Manager version is not necessarily the same
  218.      as the version number of WinPMail itself: the Extension Manager
  219.      version number may be the same for several different versions of
  220.      WinPMail itself. If you need to know the version number of the copy
  221.      of WinPMail that is running, use the WM_F_GETVERSION API message.
  222.   "variant" indicates what type of extension is required - the following
  223.      values are currently defined:
  224.        0: Load an extension for composing a message ("Composer")
  225.        1: Load an extension for reading a message ("Reader")
  226.      Having a "variant" field allows a single DLL to support multiple
  227.      extension types, although you do not have to work this way.
  228.   "hParent" contains the handle of the WinPMail MDI child window
  229.      that is to contain the extension. If your extension does not create
  230.      a dialog, you will need to store this value somewhere globally
  231.      accessible, since you need it to communicate with the Extension
  232.      Manager. If you create a dialog in your extension, you should create 
  233.      the dialog without any borders using the WS_CHILD window style and
  234.      set its parent to be this window.
  235.   "data" contains any string specified to be passed to the form by its
  236.      Form Fact File. Think of this as a commandline for the extension -
  237.      as an example, the PH extension expects to find its default host
  238.      in this parameter.
  239.   "hDialog" should be filled in with the window handle of the modeless 
  240.      dialog you create within the MDI child window, if any. If you set
  241.      this value to NULL, then WinPMail will hide the MDI window associated
  242.      with the extension and will route notification messages to the
  243.      callback function (see the next entry).
  244.   "callback_name" (optional) should be filled in with the name of the
  245.      function in the DLL of the exported function to which messages
  246.      should be sent or NULL if there is none. You will usually fill this
  247.      entry in if you do not create a dialog so you can receive 
  248.      notifications from the Extension Manager. If a dialog is defined,
  249.      the Extension Manager will always route messages to it, even if you
  250.      enter a value in this field. The function whose name you return 
  251.      in this parameter (if you use it) should have the following 
  252.      prototype:
  253.  
  254.         DWORD PASCAL FAR _export form_fn (HWND hWnd, WORD wMsg,
  255.            WPARAM wParam, LPARAM lParam);
  256.  
  257.      Notice that the prototype simply mirrors the definition for a
  258.      standard Windows Window handler (WndProc) function.
  259.  
  260. You've now done everything the Extension Manager requires to be able to 
  261. use your extension - from here, only the good stuff is left for you to
  262. do - the actual working end of the extension, which is up to you.
  263.  
  264.  
  265. 5: Form Fact Files
  266.  
  267. WinPMail learns about available extensions by looking for Form Fact
  268. Files, which are text files with the extension .FFF, describing the
  269. characteristics of the extension. WinPMail looks for FFF files first in
  270. the user's home mailbox, and then in the same directory as WINPMAIL.EXE,
  271. and finally (if present) in the directory pointed to by an FFF DOS
  272. environment variable. Scanning this way allows the use of both global
  273. and private extensions.
  274.  
  275. Form Fact Files use a simple text format and are line-based. Blank 
  276. lines, and any line in a FFF that starts with #, ; or * are all ignored 
  277. as comments. Command lines in an FFF consist of a keyword sequence 
  278. followed by optional whitespace, followed by the character '=', followed 
  279. by more optional whitespace and a parameter. The following keyword 
  280. sequences are recognized:
  281.  
  282.    Form name
  283.      - The name the WinPMail Extensions Manager should display in the
  284.        "Extensions" window.
  285.    Form DLL
  286.      - A required parameter that indicates the full path to the DLL
  287.        WinPMail should load to access the extension. Standard command
  288.        substitutions (as in user-defined gateways) can be used in this
  289.        field - so for example, ~a/forms/foo.dll would be interpreted as
  290.        "start in the directory where WINPMAIL.EXE resides, then change
  291.        to the FORMS subdirectory and load FOO.DLL". For a complete list
  292.        of command substitutions available, please see the file UDG.TXT
  293.        supplied with Pegasus Mail.
  294.    Form type
  295.      - Should be either of the strings READER or COMPOSER depending on
  296.        the type of extension being defined. A single definition can only
  297.        have a single form type, although an FFF can contain multiple
  298.        definitions. If absent, the default for this keyword is COMPOSER.
  299.    Form flags
  300.      - Contains settings that affect the operation of the extension. The
  301.        value is an unsigned long (32 bits), which is treated as a bitmap.
  302.        The following bit values are currently defined:
  303.  
  304.        Mnemonic     Value   Meaning
  305.        ----------------------------------------------------------------
  306.        WPM_STARTUP    1     Load the extension when WinPMail starts up
  307.        WPM_NOLIST     2     Do not show in the "Extensions" window list
  308.        WPM_HIDDEN     4     Hide the parent MDI window on loading
  309.        WPM_LOGGING    8     Extension wants to receive logging events
  310.        WPM_ONEONLY   16     Only allow one running instance at any time
  311.  
  312.        Various flags can be combined by adding (or ORing) the values
  313.        together - so to have a hidden extension that loads at startup,
  314.        is interested in logging events, and does not appear in the
  315.        "Extensions" window, you would use 1 + 2 + 4 + 8 = 15
  316.    Form tagname
  317.      - This is the extension's unique identifier (see below for 
  318.        information on registering a tagname). WinPMail writes the tag
  319.        name into any mail generated by the extension as an "X-Tagname:"
  320.        header - so, if your tagname was "FUBAR", WinPMail would write a
  321.        header into the message that read "X-Tagname: FUBAR". Tagnames
  322.        can be used as unique triggers for Reader extensions. Tagnames
  323.        starting with the letters "PM" are reserved by the author.
  324.    Form data
  325.      - A "command line" for the extension. This text string is passed
  326.        unmodified to the extension at load-time. The most normal use is
  327.        to pass site-specific default information to the extension (for
  328.        example, the Phone Message extension expects to see the default
  329.        telephone area code in the "data" field).
  330.    Form triggers
  331.      - This keyword is only meaningful for READER extensions and is
  332.        ignored if "Form Type = READER" has not already been seen. The
  333.        parameter is an arbitrary regular expression that WinPMail should
  334.        apply to the headers of a message to determine if the reader
  335.        should be invoked for this message. The regular expression can
  336.        contain '*' and '?' characters to match patterns within a header,
  337.        and is presumed to start at the beginning of a line. So, for 
  338.        example, if you wanted to load a reader every time you saw a
  339.        header called "X-File-type" that contained the letters "JPG",
  340.        you might enter the trigger "X-FILE-TYPE*JPG*". Only a single
  341.        trigger may be defined in any "Form Triggers" statement, but you
  342.        may have as many "Form Triggers" lines in a definition as you
  343.        wish.
  344.    Bitmap File    (Requires WinPMail v2.11 or later)
  345.      - This optional keyword allows you to add a button to the Pegasus
  346.        Mail button panel: when depressed, the button will launch your
  347.        extension. The parameter takes two parts, separated by a comma:
  348.        the first part is a filename pointing to a Windows .BMP file
  349.        containing the bitmap, which must be exactly 22(h) x 20(v)
  350.        pixels in size. The filename can contain standard command sub-
  351.        stitutions just like the "Form DLL" keyword. The second part of
  352.        the parameter is the "fly-by" help that will appear on the status
  353.        line when the button is right-clicked. This string may contain
  354.        any characters and should be 45 characters in length or shorter.
  355.        Example:
  356.           Bitmap file=~a/forms/tphone2/tphone2.bmp,Start a phone message
  357.    Overrides
  358.      - An optional keyword with a single integer parameter; can only
  359.        be used with COMPOSER extensions. This keyword indicates that the
  360.        extension wishes to replace a built-in WinPMail function or menu
  361.        selection. WinPMail checks for overriding extensions every time
  362.        it processes a menu selection and if it finds one, it invokes
  363.        the extension instead of the built-in function. An entry in an
  364.        FFF can have only one "Overrides" line, but you can have multiple
  365.        entries each defining a different override. In normal use, you
  366.        will set the "Form Flags" line for an overriding extension to 18,
  367.        so that only one instance can be open and it doesn't appear in the
  368.        Extension Manager's list. For a list of menu IDs, see Appendix A
  369.        at the end of this document.
  370.    End
  371.      - Indicates that the definition is complete; the entry is added
  372.        to the internal extension list maintained by WinPMail. You MUST
  373.        have an END statement for each definition - reaching end of file
  374.        without an End statement will result in the definition being
  375.        discarded.
  376.  
  377. You may have as many definitions as you wish or need in a single FFF - 
  378. and in fact, for system-wide FFFs there is a slight performance gain in
  379. gathering all your definitions into a single file. Remember to use an END 
  380. statement to close every definition though.
  381.  
  382.  
  383. 6: Using the Extensions Manager API
  384.  
  385. WinPMail's Extensions Manager makes a set of over 70 functions available 
  386. to extensions, providing every imaginable kind of service from sending 
  387. mail messages through to TCP/IP communications.
  388.  
  389. An extension accesses the Extensions Manager API by using the Windows
  390. SendMessage function to send a message to its parent window. The
  391. parameters to SendMessage depend on the service required, and are fully
  392. described in WPMFORMS.H - you should consult that file as a definitive
  393. reference. With one or two specific exceptions (most notably the
  394. WM_F_GETMESSAGEFIELD message), the Extension Manager API messages can be
  395. sent at any time while the extension is loaded, including times when
  396. WinPMail is in the background.
  397.  
  398.  
  399. 7: Hints and tips
  400.  
  401. Configuration files: if your extension needs to create a configuration 
  402. file, the following approach may be helpful:
  403.  
  404.   a) Obtain the user's home mailbox location using WM_F_GETHOMEBOX
  405.   b) Construct a filename using your extension's registered Tagname
  406.      and the extension .PM.
  407.   c) Write whatever information you need to keep into the file.
  408.  
  409. You can use the same steps to locate a configuration file. Using your 
  410. registered Tagname guarantees uniqueness for the filename, while using
  411. the extension .PM lets Pegasus Mail maintain the location of the file
  412. correctly for you even if the user shifts his/her home mailbox location.
  413.  
  414. Disabling WinPMail features: Many sites with student populations have
  415. expressed the desire to be able to disable or regulate some of WinPMail's
  416. built-in features. You can do this with extensions either by creating a
  417. logging extension that looks for events concerning the features you want
  418. to disable (the most likely is WLOG_LOADMENU, which will allow you to
  419. disable the items in their menus), or else by creating extensions that
  420. override the menu choice for the target functions and put up an explana-
  421. tory dialog instead.
  422.  
  423.  
  424. 8: Accessing the Extension Manager from outside WinPMail
  425.  
  426. On occasions you may want to access WinPMail's Extension Manager services
  427. from outside WinPMail itself; an example of such a situation might be the
  428. implementation of a MAPI interface that is loaded by other programs - in
  429. fact, WinPMail's own MAPI interface, which is in development at the time
  430. of writing, uses exactly this approach.
  431.  
  432. To access the Extensions Manager in this way, locate the WinPMail frame
  433. window (which has the class FRAME and the title "Pegasus Mail") and send
  434. it a WM_INTERFACE message (#define WM_INTERFACE (WM_USER + 17480)). If you
  435. have a window that you want to receive WinPMail's WM_FM_* Extensions
  436. Manager notification messages, pass it in wParam. WinPMail will return the
  437. HWND of a new, hidden Extension Manager window to which your code can send
  438. messages requesting service just as if it were a standard extension. When
  439. you have finished with the service, send the window a WM_CLOSE message.
  440.  
  441. ** NOTE: Issues of memory handling are up to your module; there may be
  442. ** instances where you will have to allocate global memory before passing
  443. ** it to WinPMail, usually if you have to take memory allocated by another
  444. ** program and make it available to WinPMail.
  445.  
  446. The following code sample shows how to open an external connection to the
  447. Extensions Manager in the manner described above:
  448.  
  449.    #define WM_INTERFACE   (WM_USER + 17480)
  450.    
  451.    HWND access_extension_service (HWND message_handler)
  452.       {
  453.       HWND hFrame;
  454.    
  455.       if ((hFrame = FindWindow ("FRAME", "Pegasus Mail")) == NULL)
  456.          return NULL;
  457.    
  458.       return (HWND) SendMessage (hFrame, WM_INTERFACE, 
  459.         (HWND) message_handler, 0);
  460.       }
  461.  
  462.  
  463. 9: License to use Pegasus Mail Bitmaps
  464.  
  465. Pegasus Mail's author grants a non-exclusive license to any and all
  466. developers of WinPMail Extensions granting them the right to use any
  467. bitmap from Pegasus Mail itself or from any of its supplied components
  468. in the construction of a bona-fide Pegasus Mail Extension. You may use
  469. any suitable resource editor to extract bitmaps from the WINPMAIL.EXE
  470. binary file and may subsequently alter or use them in any way necessary,
  471. for the SOLE PURPOSE of enhancing your WinPMail Extension.
  472.  
  473. This license does NOT permit you to use any Pegasus Mail bitmap in any
  474. other application or in any development not directly related to the
  475. production of a Pegasus Mail Extension.
  476.  
  477. The author's hope in granting this license is that developers will
  478. produce Extensions faithful to the look and feel of WinPMail itself.
  479.  
  480.  
  481. 10: Distributing extensions and reserving tagnames
  482.  
  483. Because extensions are distributed as working, executable machine code,
  484. many sites may be reluctant to use an extension when they are unaware of
  485. its pedigree. If you have an extension you think would be useful and
  486. would like to see it widely distributed to the Pegasus Mail user
  487. community in a verified, secure manner, then you can follow these steps:
  488.  
  489.    * Debug and test your extension thoroughly until you are sure it works. 
  490.      This step is very important! The author does not provide a debugging
  491.      service for your extensions and will reject out-of-hand anything 
  492.      that does not compile correctly or that crashes when run.
  493.    * Contact the author of Pegasus Mail, David Harris, at the Internet
  494.      e-mail address David.Harris@pmail.gen.nz. He will arrange for you
  495.      to upload a private copy of your extension to his system and will 
  496.      examine it for certification.
  497.    * You MUST upload source code to your extension. The author will only
  498.      certify extensions that he has personally compiled, and when 
  499.      distributing them will only distribute binary versions that he 
  500.      has built. You are not required to distribute the source code 
  501.      with the extension itself, but it must be made available to him.
  502.    * If your extension checks out OK and builds correctly, it will be
  503.      made available on the principal Pegasus Mail distribution sites and
  504.      endorsed as "safe and authenticated" by the author.
  505.    * For technical reasons, the author can only certify extensions that 
  506.      are written for Borland C++ version 3.1 or later. Please make 
  507.      sure you include the appropriate make, PRJ or IDE file, as well 
  508.      as all associated RC, H and C or CPP files.
  509.  
  510. Reserving extension tag names: because extensions can define tags for
  511. themselves that can be used to invoke a reader extension on receipt, it
  512. is obviously desirable to ensure that tagnames remain unique. In order to
  513. encourage this, the author offers a free tagname registration service.
  514. Send a mail message to "tagnames@pmail.gen.nz" indicating the tagname(s)
  515. you would like to reserve and optionally a brief description of your
  516. extension (for the author's interest). Tagnames will be registered on a
  517. first-come/ first-served basis, and if a tagname you have requested is
  518. already taken, you will be advised as soon as possible. The author
  519. reserves the right to refuse to register tagnames for any reasons he
  520. deems fit - for example, tagnames containing obscene words will not be
  521. accepted, nor will any tagname starting with the letters "PM", because
  522. all such tagnames are reserved by the author. The list of currently-
  523. registered extension tagnames can be retrieved by e-mail at any time by
  524. sending a message to maiser@pmail.gen.nz consisting of the two lines:
  525.  
  526.     SEND TAGNAMES.TXT
  527.     EXIT
  528.  
  529. Please note that tagnames can be a maximum of 12 characters long, may 
  530. not contain characters with ASCII values lower than 33 or higher than 126 
  531. and are case-insensitive. All tagnames starting with the letters "PM" 
  532. are reserved by the author.
  533.  
  534.  
  535. Appendix A: Menu IDs for overriding extensions
  536.  
  537. The following integer values can be used as the parameter to an
  538. "Overrides" keyword line in a Form Fact File by extensions wishing to
  539. override particular built-in menu choices within WinPMail.
  540.  
  541. ------------------------------------------------------------------------
  542. WinPMail Mnemonic       ID    Menu function (Which Menu)
  543. ------------------------------------------------------------------------
  544. IDM_HELP                10    "Context-sensitive help" (HELP)
  545. IDM_USING_HELP          11    "Using Help" (HELP)
  546. IDM_HELPINDEX           12    "Help index" (HELP)
  547. IDM_RMACRO              75    "Open glossary manager" (EDIT/GLOSSARY)
  548. IDM_PMACRO              76    "Expand glossary entry" (EDIT/GLOSSARY)
  549. IDM_NEWMESSAGE         101    "Start new message" (FILE)
  550. IDM_READNEW            102    "Open new mail folder" (FILE)
  551. IDM_OPENFOLDER         103    "Folders..." (FILE)
  552. IDM_IMPORT             104    "Import into message" (MESSAGE)
  553. IDM_SAVESESSION        105    "Save message as draft" (MESSAGE)
  554. IDM_RESTORESESSION     106    "Open saved message" (FILE)
  555. IDM_PRINT              107    "Print" (FILE)
  556. IDM_PRINTSETUP         109    "Printer setup" (FILE)
  557. IDM_FILTERS            110    "New mail filtering rules" (FILE)
  558. IDM_EXIT               111    "Exit" (FILE)
  559. IDM_PREF_GENERAL       121    "General settings" (FILE/PREFS)
  560. IDM_PREF_SMF           122    "NetWare MHS settings" (FILE/PREFS)
  561. IDM_PREF_SIGS          123    "Signatures..." (FILE/PREFS)
  562. IDM_PREF_HOMEBOX       124    "Home mailbox location" (FILE/PREFS)
  563. IDM_PREF_EXT           125    "Extended features" (FILE/PREFS)
  564. IDM_UNDO               131    "Undo" (EDIT)
  565. IDM_CUT                132    "Cut" (EDIT)
  566. IDM_COPY               133    "Copy" (EDIT)
  567. IDM_PASTE              134    "Paste" (EDIT)
  568. IDM_CLEAR              135    "Clear" (EDIT)
  569. IDM_SELECTALL          136    "Select all" (EDIT)
  570. IDM_SPELLING           137    "Check spelling" (EDIT)
  571. IDM_SERVER             138    "File servers..." (FILE)
  572. IDM_LOCALUSERS         141    "Lookup local users" (ADDRESSES)
  573. IDM_ADDRESSBOOKS       142    "Address books" (ADDRESSES)
  574. IDM_MAILINGLISTS       143    "Distribution lists..." (ADDRESSES)
  575. IDM_SORTBYKEY          144    "Sort by key" (ADDRESSBOOK)
  576. IDM_SORTBYNAME         145    "Sort by name" (ADDRESSBOOK)
  577. IDM_FIND               146    "Find text", (MESSAGE/FOLDER/READER/ADDRBK)
  578. IDM_FINDAGAIN          147    "Find again", (MESSAGE/FOLDER/READER/ADDRBK)
  579. IDM_PASTENAMES         148    "Paste names" (ADDRESSBOOK)
  580. IDM_PASTEADDRESSES     149    "Paste addresses" (ADDRESSBOOK)
  581. IDM_SAVESIZE           150    "Save window size" (Various)
  582. IDM_OTHEROPTIONS       151    "Special message view" (MESSAGE)
  583. IDM_SHOWHEADERS        153    "Show all headers" (READER)
  584. IDM_EXTRACT            154    "Save messages to disk" (FOLDER/READER)
  585. IDM_ATTACH             155    "Switch to attachments view" (MESSAGE)
  586. IDM_MARKUNREAD         156    "Mark message as unread" (FOLDER and NB)
  587. IDM_ALIASING           157    "Resolve aliases" (ADDRESSBOOK)
  588. IDM_BPPREF             158    "Button panel preferences" (FILE/PREFS)
  589. IDM_UUDECODE           160    "UUdecode message" (FOLDER/READER /SPECIAL)
  590. IDM_UNBINHEX           161    "Un-BinHex message" (FOLDER/READER /SPECIAL)
  591. IDM_LOCALSIG           162    "Signature for local mail" (FILE/PREFS)
  592. IDM_INETSIG            163    "Signature for Internet mail" (FILE/PREFS)
  593. IDM_MHSSIG             164    "Signature for MHS mail" (FILE/PREFS)
  594. IDM_DELEXPIRED         165    "Delete expired messages" (FOLDER/SPECIAL)
  595. IDM_EDMAIL             167    "Switch to message editor view" (MESSAGE)
  596. IDM_QUICKLOOKUP        168    "Quick lookup" (ADDRESSES)
  597. IDM_WORDWRAP           169    "Wrap long lines" (READER)
  598. IDM_DELLINE            170    "Delete line" (MESSAGE)
  599. IDM_REFORMAT           171    "Reformat paragraph" (MESSAGE)
  600. IDM_INDENT             172    "Indent text" (MESSAGE)
  601. IDM_REPLACE            173    "Search and replace" (MESSAGE)
  602. IDM_DELWORD            174    "Delete word right" (MESSAGE)
  603. IDM_APREFS             175    "Advanced settings" (FILE/PREFS)
  604. IDM_ENLARGE            176    "Enlarge window" (WINDOW)
  605. IDM_ABK_EXPORT         177    "Export addressbook" (ADDRESSBOOK)
  606. IDM_ABK_IMPORT         178    "Import addressbook" (ADDRESSBOOK)
  607. IDM_NOTICEBOARDS       179    "Noticeboards" (FILE)
  608. IDM_ANN_EDIT           180    "Add/edit annotation" (FOLDER)
  609. IDM_SRT_DATE           270    "Sort by date" (FOLDER)
  610. IDM_SRT_REVDATE        271    "Sort by reverse date" (FOLDER)
  611. IDM_SRT_SUBJECT        272    "Sort by subject" (FOLDER)
  612. IDM_SRT_FROM           273    "Sort by sender's name" (FOLDER)
  613. IDM_SRT_SUBJECT2       274    "Sort by subject/reverse date" (FOLDER)
  614. IDM_SRT_COLOUR         275    "Sort by colour" (FOLDER)
  615. IDM_FORMS              185    "Open Forms Manager" (FILE)
  616. IDM_ANN_DELETE         186    "Delete annotation" (FOLDER)
  617. IDM_REVIEWMAIL         187    "Review Queued Mail" (FILE)
  618. IDM_TODISK             230    "Save to disk" (Various)
  619. IDM_FROMDISK           231    "Read from disk" (Various)
  620. IDM_EXTRACTFILE        240    "MHS directory service" (ADDRESSES)
  621. IDM_LOGGED_IN          241    "Logged-in users" (ADDRESSES)
  622. IDM_ADD_USER           242    "Add sender to list" (READER/SPECIAL)
  623. IDM_REMOVE_USER        243    "Remove sender from list" (READER/SPECIAL)
  624. IDM_FONT               299    "Font" (Various)
  625. IDM_TILE               500    "Tile" (WINDOW)
  626. IDM_CASCADE            501    "Cascade" (WINDOW)
  627. IDM_ARRANGEICONS       502    "Arrange Icons" (WINDOW)
  628. IDM_BUTTONPANEL        503    "Button panel" (WINDOW)
  629. IDM_NETCONFIG          210    "Network Configuration" (FILE)
  630. IDM_GETMAIL            211    "Check host for new mail" (FILE)
  631. IDM_SENDMAIL           212    "Send all queued mail" (FILE)
  632. IDM_GETANDSEND         189    "Check and send mail" (FILE)
  633.  
  634. IDM_MSGCOLOUR          260    "Set colour" (FOLDER)
  635. IDM_UADMIN             322    "Manage users..." (ADDRESSES)
  636. IDM_ONLINE             321    "Leave offline mode" (FILE)
  637. IDM_OFFLINE            320    "Enter offline mode" (FILE)
  638. IDM_QF_6               316    "Quick folder 6" (FILE/FOLDERS)
  639. IDM_QF_5               315    "Quick folder 5" (FILE/FOLDERS)
  640. IDM_QF_4               314    "Quick folder 4" (FILE/FOLDERS)
  641. IDM_QF_3               313    "Quick folder 3" (FILE/FOLDERS)
  642. IDM_QF_2               312    "Quick folder 2" (FILE/FOLDERS)
  643. IDM_QF_1               311    "Quick folder 1" (FILE/FOLDERS)
  644. IDM_QF_DEFINE          197    "Define quick folders" (FILE/FOLDERS)
  645. IDM_EDIT_FLAGS         199    "Edit message flags" (FOLDER)
  646. IDM_SRT_NEWTOTOP       198    "Sort unread before read" (FOLDER)
  647. IDM_DLM_EXPORT         196    "Export to text file" (LISTS)
  648. IDM_DLM_DUPLICATE      194    "Duplicate list" (LISTS)
  649. IDM_DLM_EDIT           193    "Edit list" (LISTS)
  650. IDM_DLM_DELETE         192    "Delete list" (LISTS)
  651. IDM_DLM_ADD            191    "Add new list" (LISTS)
  652. IDM_PREF_VIEW          190    "Attachment viewers" (FILE)
  653. IDM_FULLSCREEN         188    "Enlarge message editor" (MESSAGE)
  654.  
  655.