home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / kit / mail / pmail.exe / forms / tphone / tphone.c next >
Encoding:
C/C++ Source or Header  |  1995-01-15  |  11.6 KB  |  345 lines

  1. //
  2. //  TPHONE.C
  3. //  Pegasus Mail for Windows form, providing a telephone message
  4. //  interface.
  5. //
  6. //  Copyright (c) 1994, David Harris, All Rights Reserved.
  7. //
  8. //  The author grants explicit permission for this source code to be
  9. //  used or modified as required, subject only to the conditions that
  10. //  the copyright notices above are preserved and that by using this
  11. //  code you agree that the code is provided without warranty of any
  12. //  kind, either explicit or implied, and you use it at your own
  13. //  risk.
  14. //
  15.  
  16. #define STRICT
  17. #include <windows.h>
  18. #include <bwcc.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include "..\wpmforms.h"
  22. #include "tphone.h"        //  Dialog control item IDs
  23.  
  24. //  Form dialogs and callbacks: a form DLL can export a function
  25. //  which WinPMail's form manager will call with Windows messages
  26. //  destined for the form's dialog or window (such as menu selections
  27. //  and so forth). The function takes the following form:
  28.  
  29. typedef long pascal far (*FORM_CALLBACK) (HWND hWnd, WORD wMsg,
  30.    WPARAM wParam, LPARAM lParam);
  31.  
  32. //  The return from a form callback is passed back through the
  33. //  Windows call chain if non-zero, otherwise the default window
  34. //  proc is called. The reasons we call this function instead of
  35. //  simply sending messages to the dialog itself are:
  36. //
  37. //   1: Dialogs can only return Boolean values, whereas the callback
  38. //      can provide the long value Windows expects to pass back
  39. //      through the calling chain.
  40. //
  41. //   2: Having a separate callback means that it is potentially
  42. //      possible to have a form which does not create a dialog.
  43. //
  44. //
  45. //  Minimum interface: the minimum interface a form DLL must provide
  46. //  is a routine called "forminit" which is exported by name. "forminit"
  47. //  has the following prototype:
  48. //
  49. //  WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND hParent,
  50. //      char *data, HWND *hDialog, char *callback_name);
  51. //
  52. //  "version" is passed in with the version of the WinPMail forms
  53. //     manager which is running.
  54. //  "variant" indicates what type of form is required - the following
  55. //     values are currently defined:
  56. //       0: Create a form for composing a message
  57. //       1: Create a form for reading a message
  58. //  "hParent" contains the handle of the WinPMail MDI child window
  59. //     which is to contain the form.
  60. //  "data" contains any string defined as being required for the
  61. //     form in the menu interface.
  62. //  "hDialog" should be filled in with the window handle of the
  63. //     modeless dialog created within the MDI child window.
  64. //  "callback_name" (optional) should be filled in with the name of the
  65. //     function in the DLL of the exported function to which messages
  66. //     should be sent or NULL if there is none. If NULL, messages are
  67. //     sent to the dialog returned in "hDialog". You will use an
  68. //     indirect callback of this kind when your extension does not
  69. //     create a dialog within the enclosing parent window.
  70. //
  71. //  When forminit is called, the DLL should register any window
  72. //  classes it needs then create the dialog within the MDI parent
  73. //  window and size it to the correct size. On return WinPMail will
  74. //  resize the parent window to enclose the dialog correctly. The
  75. //  DLL should NOT make the dialog visible - WinPMail will do that
  76. //  as required.
  77.  
  78. #define WM_MARGIN (WM_USER + 1099)
  79. #define WM_SETDIR (WM_USER + 400)
  80. #define WM_ADDFILE (WM_USER + 401)
  81. #define WM_STARTUP (WM_USER + 403)
  82. #define WM_GET_ALIST (WM_USER + 404)
  83.  
  84. #define IDC_QUICKHELP_TO   970
  85. #define IDC_QUICKHELP_CC   971
  86.  
  87.  
  88. int register_form_classes (void);
  89.  
  90.  
  91. HINSTANCE  hLibInstance;            // set in LibMain, used throughout the DLL
  92. char szFormDlgName [] = "TM";    // Name of dialog resource template.
  93. char szFormDlgClassName [] =
  94.    "bordlg_tm";                  // Class name for the form dialog.
  95.  
  96. char *months [] =
  97.    {
  98.    "Jan", "Feb", "Mar",
  99.    "Apr", "May", "Jun",
  100.    "Jul", "Aug", "Sep", 
  101.    "Oct", "Nov", "Dec"
  102.    };
  103.  
  104. #pragma warn -par
  105.  
  106.  
  107. WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND hParent,
  108.    char *data, HWND *hDialog, char *callback_name)
  109.    {
  110.    //  First, check to see if the version of the form manager is
  111.    //  one we can work with.
  112.  
  113.    RECT r;
  114.    char szBuf [80];
  115.    int i;
  116.    HWND hControl;
  117.    BYTE tm [7];
  118.  
  119.    if ((version & 0xFF00) > 0x100) return 0;
  120.  
  121.    //  Now check the variant number; for a telephone form, we only
  122.    //  provide a composition format.
  123.  
  124.    if (variant != 0) return 0;
  125.  
  126.    (*hDialog) = CreateDialog (hLibInstance, (LPCSTR) szFormDlgName, hParent, NULL);
  127.    if ((*hDialog) == NULL) return 0;
  128.    GetClientRect (*hDialog, &r);
  129.    MoveWindow (*hDialog, 0, 0, r.right, r.bottom, FALSE);
  130.    hControl = GetDlgItem (*hDialog, IDC_F_PHONETYPE);
  131.    for (i = 1; i < 5; i ++)
  132.       {
  133.       LoadString (hLibInstance, i, szBuf, sizeof (szBuf));
  134.       SendMessage (hControl, CB_ADDSTRING, 0, (LPARAM) szBuf);
  135.       }
  136.    SendMessage (hControl, CB_SETCURSEL, 0, 0);
  137.    CheckDlgButton (*hDialog, IDC_F_PHONED, 1);
  138.    CheckDlgButton (*hDialog, IDC_F_PLEASECALL, 1);
  139.  
  140.    SendMessage (hParent, WM_F_GETDATETIME, 0, (LPARAM) tm);
  141.    sprintf (szBuf, "%d %s %d, %02d:%02d", tm [2], months [tm [1] - 1],
  142.       tm [0], tm [3], tm [4]);
  143.    SetDlgItemText (*hDialog, IDC_F_DATETIME, szBuf);
  144.  
  145.    //  Some default values can be passed in the "data" parameter
  146.    if ((data != NULL) && (*data))
  147.      SetDlgItemText (*hDialog, IDC_F_AREACODE, data);
  148.  
  149.    SetFocus (GetDlgItem (*hDialog, IDC_F_TO));
  150.    return 1;
  151.    }
  152.  
  153.  
  154. static void strip_ampersands (char *source)
  155.    {
  156.    //  Strip out any ampersands (&) which might appear in a 
  157.    //  string (typically the title of a control). The string
  158.    //  is converted in place.
  159.  
  160.    char *dest;
  161.  
  162.    for (dest = source; *source; source ++)
  163.       if (*source != '&') *dest ++ = *source;
  164.    *dest = '\0';
  165.    }
  166.  
  167.  
  168. int send_the_message (HWND hWnd)
  169.    {
  170.    //  Called when the user clicks the "send" button. This routine
  171.    //  gets a temporary filename from WinPMail, writes the message
  172.    //  text into it then asks WinPMail to send it.
  173.    //  Returns: 1 if the message is sent OK
  174.    //           0 if the delivery failed
  175.  
  176.    char szBuf [256], fname [80], subject [80], *gender, *s, *s2;
  177.    HWND hParent;
  178.    FILE *fil;
  179.    int result, id;
  180.  
  181.    hParent = GetParent (hWnd);
  182.    SendMessage (hParent, WM_F_NEWMESSAGE, 0, 0);
  183.    SendMessage (hParent, WM_F_TEMPFILE, sizeof (fname), (LPARAM) fname);
  184.    if ((fil = fopen (fname, "w+t")) == NULL)
  185.       return 0;
  186.  
  187.    GetDlgItemText (hWnd, IDC_F_TO, szBuf, sizeof (szBuf));
  188.    SendMessage (hParent, WM_F_TO, 0, (LPARAM) szBuf);
  189.  
  190.    GetDlgItemText (hWnd, IDC_F_NAME, szBuf, sizeof (szBuf));
  191.    wsprintf (subject, "Phone call: %.45s", szBuf);
  192.  
  193.    //  Now, we take a sort of semi-intelligent stab at working out
  194.    //  the gender of the caller...
  195.  
  196.    gender = "He/She";
  197.    if (strnicmp (szBuf, "Mr ", 3) == 0) gender = "He";
  198.    if ((strnicmp (szBuf, "Mrs", 3) == 0) ||
  199.       (strnicmp (szBuf, "Ms", 2) == 0) ||
  200.       (strnicmp (szBuf, "Miss", 4) == 0))
  201.       gender = "She";
  202.  
  203.    SendMessage (hParent, WM_F_SUBJECT, 0, (LPARAM) subject);
  204.  
  205.    GetDlgItemText (hWnd, IDC_F_DATETIME, subject, sizeof (subject));
  206.    fprintf (fil, "*   At %s,\n", subject);
  207.    GetDlgItemText (hWnd, IDC_F_OF, subject, sizeof (subject));
  208.    fprintf (fil, "*   %s, of %s", szBuf, subject);
  209.  
  210.    id = IDC_F_PHONED;
  211.    if (IsDlgButtonChecked (hWnd, IDC_F_CALLED)) id = IDC_F_CALLED;
  212.    if (IsDlgButtonChecked (hWnd, IDC_F_CALLEDBACK)) id = IDC_F_CALLEDBACK;
  213.    GetDlgItemText (hWnd, id, szBuf, sizeof (szBuf));
  214.    strip_ampersands (szBuf);
  215.    fprintf (fil, " %s.\n", szBuf);
  216.  
  217.    id = IDC_F_PLEASECALL;
  218.    if (IsDlgButtonChecked (hWnd, IDC_F_WILLCALL)) id = IDC_F_WILLCALL;
  219.    if (IsDlgButtonChecked (hWnd, IDC_F_NOACTION)) id = IDC_F_NOACTION;
  220.    fprintf (fil, "*   ");
  221.    switch (id)
  222.       {
  223.       case IDC_F_PLEASECALL :
  224.          fprintf (fil, "%s would like you to call back", gender);
  225.          break;
  226.  
  227.       case IDC_F_WILLCALL :
  228.          fprintf (fil, "%s will call again later", gender);
  229.          break;
  230.  
  231.       default :
  232.          fprintf (fil, "No further action is required on your part");
  233.          break;
  234.       }
  235.    fprintf (fil, ".\n");
  236.  
  237.    s = (char *) SendMessage (hParent, WM_F_GETTEXT, IDC_F_MESSAGE, 0);
  238.    if (s != NULL)
  239.       {
  240.       fprintf (fil, "\n%s also left the following message:\n\n", gender);
  241.       for (s2 = s; *s2; s2 ++) fputc (*s2, fil);
  242.       SendMessage (hParent, WM_F_FREE, 0, (LPARAM) s);
  243.       }
  244.  
  245.    fclose (fil);
  246.    SendMessage (hParent, WM_F_MESSAGEFILE, 0, (LPARAM) fname);
  247.  
  248.    result = (int) SendMessage (hParent, WM_F_SENDMESSAGE, 0, 0);
  249.    remove (fname);
  250.    return result;
  251.    }
  252.  
  253.  
  254. LONG FAR PASCAL _export FormProc (HWND hWnd, WORD wMsg, 
  255.    WORD wParam, LONG lParam)
  256.    {
  257.    //  Service routine for the form's enclosed dialog. This is a
  258.    //  standard windows WndProc.
  259.  
  260.    DWORD dwResult = 0;
  261.    BOOL fCallDefProc = TRUE;
  262.  
  263.    switch (wMsg)
  264.       {
  265.       case WM_COMMAND :
  266.          fCallDefProc = FALSE;
  267.          switch (wParam)
  268.             {
  269.             case IDC_F_CANCEL :
  270.                PostMessage (GetParent (hWnd), WM_CLOSE, 0, 0);
  271.                break;
  272.  
  273.             case IDC_F_RECADDR :
  274.                SendMessage (GetParent (hWnd), WM_F_QUICKADDRESS, 
  275.                   (WPARAM) (GetDlgItem (hWnd, IDC_F_TO)), 0);
  276.                break;
  277.  
  278.             case IDC_F_SEND :
  279.                if (send_the_message (hWnd))
  280.                   PostMessage (GetParent (hWnd), WM_CLOSE, 0, 0);
  281.                break;
  282.             }
  283.          break;
  284.       }
  285.  
  286.    if (fCallDefProc)
  287.       dwResult = BWCCDefDlgProc (hWnd, wMsg, wParam, lParam);
  288.  
  289.    return dwResult;
  290.    }
  291.  
  292.  
  293. #pragma warn -sus
  294.  
  295. void unregister_form_classes (void)
  296.    {
  297.    //  Remove any classes associated with the form; we have the
  298.    //  same problem here as we do with registering the classes
  299.    //  for the DLL - we only want to deregister the classes on
  300.    //  the last time we're unloaded.
  301.  
  302.    if (GetModuleUsage (hLibInstance) > 1) return;      //  Not a problem
  303.    UnregisterClass (szFormDlgClassName, hLibInstance);
  304.    }
  305.  
  306.  
  307. BOOL FAR PASCAL LibMain (HINSTANCE hInst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  308.    {
  309.    WNDCLASS wc;
  310.  
  311.    if (! hLibInstance)
  312.       {
  313.       hLibInstance = hInst;
  314.       BWCCGetVersion ();      //  Forces BWCC to be dynamically loaded.
  315.  
  316.       //  Register any window classes used by the form. Forms will usually
  317.       //  register either one or occasionally two classes which define
  318.       //  the composition and reader dialogs created by the DLL.
  319.       //
  320.       //  There's a gotcha here, of course (aren't there always, in
  321.       //  Windows?)... You can't register a window class more than once,
  322.       //  so if the DLL has already been loaded and the user asks to
  323.       //  create a second instance of the form, we have to be careful
  324.       //  not to re-register the class. We do this by checking the
  325.       //  instance usage counter of the DLL - if it's greater than 1,
  326.       //  then we DON'T register the classes.
  327.  
  328.       wc.style          = WS_CHILD;
  329.       wc.lpfnWndProc    = FormProc;
  330.       wc.cbClsExtra     = 0;
  331.       wc.cbWndExtra     = DLGWINDOWEXTRA;
  332.        wc.hInstance      = hLibInstance;
  333.        wc.hIcon          = NULL;
  334.       wc.hCursor        = LoadCursor (NULL, IDC_ARROW);
  335.       wc.hbrBackground  = (HBRUSH) (COLOR_WINDOW + 1);
  336.       wc.lpszMenuName   = NULL;
  337.       wc.lpszClassName  = szFormDlgClassName;
  338.       if (! RegisterClass (&wc))
  339.          MessageBeep (0);
  340.       }
  341.  
  342.    return (TRUE);             // Initialization went OK
  343.    }
  344.  
  345.