home *** CD-ROM | disk | FTP | other *** search
/ CD Actual: Unknown Issue / mycd.iso / APLICA / winpm223 / FORMS / TPHONE / TPHONE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-03  |  13.6 KB  |  404 lines

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