home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / kit / mail / pmail.exe / forms / finger / finger.c next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  11.2 KB  |  310 lines

  1. //
  2. //  FINGER.C
  3. //  Pegasus Mail for Windows extension providing a FINGER
  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 "finger.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. HFONT hFingerFont;
  92. HINSTANCE  hLibInstance;            // set in LibMain, used throughout the DLL
  93. char szFormDlgName [] = "FINGER";   // Name of dialog resource template.
  94. char szFormDlgClassName [] =
  95.    "bordlg_fn";                  // Class name for the form dialog.
  96. HWND last_focus;
  97. char no_tcp [] =
  98.    "This extension can only run on systems where WinPMail "
  99.    "has access to Winsock TCP/IP services.";
  100.  
  101. #pragma warn -par
  102.  
  103.  
  104. WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND hParent,
  105.    char *data, HWND *hDialog, FORM_CALLBACK *callback)
  106.    {
  107.    RECT r;
  108.    char szBuf [80];
  109.    int i;
  110.    HWND hControl;
  111.    BYTE tm [7];
  112.  
  113.    //  First, check to see if the version of the form manager is
  114.    //  one we can work with. This check is pretty arbitrary - you
  115.    //  should probably assume that you may not work with any version
  116.    //  where the major version number is higher than the original
  117.    //  version you targeted.
  118.  
  119.    if ((version & 0xFF00) > 0x100) return 0;
  120.  
  121.    //  Now check the variant number; for the Finger Client we only
  122.    //  provide a COMPOSER 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.  
  131.    hFingerFont = CreateFont (14, 0, 0, 0, 400, FALSE,
  132.       FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
  133.       CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  134.       DEFAULT_PITCH | FF_DONTCARE, "Arial");
  135.    SendMessage (GetDlgItem (*hDialog, 103), WM_SETFONT,
  136.       (WPARAM) hFingerFont, (LPARAM) TRUE);
  137.  
  138.    //  Some default values can be passed in the "data" parameter
  139.    if ((data != NULL) && (*data))
  140.      SetDlgItemText (*hDialog, 101, data);      // Default host
  141.    return 1;
  142.    }
  143.  
  144.  
  145. void finger (HWND hParent, HWND hControl, char *host, char *search)
  146.    {
  147.    //  Despatch a query to a finger server based on the hostname
  148.    //  and search string supplied by the user. The finger protocol
  149.    //  is one of the older protocols on the Internet and is pretty
  150.    //  basic - you just open port 79 and shove a CRLF delimited
  151.    //  string down its throat... It will then do whatever matching
  152.    //  it thinks is appropriate and return an arbitrary amount of
  153.    //  arbitrarily-formatted data to you. The data returned is
  154.    //  almost universally unparseable so we simply offer it to the
  155.    //  user as-is where-is.
  156.  
  157.    char buffer [256];
  158.  
  159.    if (SendMessage (hParent, WM_F_TCPOPEN, 79, (LPARAM) host) < 1)
  160.       return;
  161.  
  162.    SendMessage (hControl, EM_SETSEL, 0, 0x7FFF0000);
  163.    sprintf (buffer, "%s\r\n", search);
  164.    if (SendMessage (hParent, WM_F_TCPPUTS, 0, (LPARAM) buffer) > 0)
  165.       {
  166.       for (;;)
  167.          {
  168.          buffer [0] = '\0';
  169.          if (SendMessage (hParent, WM_F_TCPGETS, sizeof (buffer), (LPARAM) buffer) < 1)
  170.             break;
  171.          if (buffer [0] == '\0') break;
  172.          SendMessage (hControl, EM_REPLACESEL, 0, (LPARAM) buffer);
  173.          }
  174.       }
  175.    SendMessage (hParent, WM_F_TCPCLOSE, 0, 0);
  176.    }
  177.  
  178.  
  179. LONG FAR PASCAL _export FormProc (HWND hWnd, WORD wMsg, 
  180.    WORD wParam, LONG lParam)
  181.    {
  182.    //  Service routine for the form's enclosed dialog. This is a
  183.    //  standard windows modeless WndProc.
  184.  
  185.    DWORD dwResult = 0;
  186.    BOOL fCallDefProc = TRUE;
  187.    char host [80], search [80];
  188.  
  189.    switch (wMsg)
  190.       {
  191.       case WM_FM_INIT :
  192.          //  Check to see that TCP/IP services are actually
  193.          //  available on this system. If they aren't, we simply
  194.          //  post a close message to the parent.
  195.  
  196.          if (SendMessage (GetParent (hWnd), WM_F_TCPPRESENT, 0, 0) == 0)
  197.             {
  198.             MessageBox (hWnd, no_tcp, " Finger Client", MB_OK | MB_ICONSTOP);
  199.             PostMessage (GetParent (hWnd), WM_CLOSE, 0, 0);
  200.             }
  201.          break;
  202.  
  203.       case WM_FM_INITFOCUS :
  204.          SetFocus (GetDlgItem (hWnd, 101));
  205.          break;
  206.  
  207.       case WM_FM_RESTOREFOCUS :
  208.          //  There's a glitch in the way the Windows MDI manager
  209.          //  seems to manage focus which means that we can have
  210.          //  focus taken away and not returned when the user does
  211.          //  anything outside our window. WinPMail has some quite
  212.          //  complex logic to deal with this case and will send
  213.          //  this message whenever focus should be restored in
  214.          //  our window. We set focus to the last active control
  215.          //  (which we know from trapping EN_SETFOCUS messages).
  216.  
  217.          if (last_focus) SetFocus (last_focus);
  218.          break;
  219.  
  220.       case WM_DESTROY :
  221.          if (hFingerFont) DeleteObject (hFingerFont);
  222.          break;
  223.  
  224.       case WM_COMMAND :
  225.          fCallDefProc = FALSE;
  226.          if (HIWORD (lParam) == EN_SETFOCUS)
  227.             {
  228.             //  We have to trap EN_SETFOCUS messages so we know which
  229.             //  control was active last. When a menu selection is made
  230.             //  our current control will lose focus and because of a
  231.             //  curiosity in Windows' MDI management, we won't get it
  232.             //  back. Instead, WinPMail generates a WM_FM_RESTOREFOCUS
  233.             //  message which signals to us that we should set focus to
  234.             //  whatever the last active control was.
  235.  
  236.             last_focus = (HWND) LOWORD (lParam);
  237.             break;
  238.             }
  239.  
  240.          switch (wParam)
  241.             {
  242.             case 139 :
  243.                GetDlgItemText (hWnd, 101, host, sizeof (host));
  244.                GetDlgItemText (hWnd, 102, search, sizeof (search));
  245.                finger (GetParent (hWnd), GetDlgItem (hWnd, 103), host, search);
  246.                break;
  247.             }
  248.          break;
  249.       }
  250.  
  251.    if (fCallDefProc)
  252.       dwResult = BWCCDefDlgProc (hWnd, wMsg, wParam, lParam);
  253.  
  254.    return dwResult;
  255.    }
  256.  
  257.  
  258. #pragma warn -sus
  259.  
  260. void unregister_form_classes (void)
  261.    {
  262.    //  Remove any classes associated with the form; we have the
  263.    //  same problem here as we do with registering the classes
  264.    //  for the DLL - we only want to deregister the classes on
  265.    //  the last time we're unloaded.
  266.  
  267.    if (GetModuleUsage (hLibInstance) > 1) return;      //  Not a problem
  268.    UnregisterClass (szFormDlgClassName, hLibInstance);
  269.    }
  270.  
  271.  
  272. BOOL FAR PASCAL LibMain (HINSTANCE hInst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  273.    {
  274.    WNDCLASS wc;
  275.  
  276.    if (! hLibInstance)
  277.       {
  278.       hLibInstance = hInst;
  279.       BWCCGetVersion ();      //  Forces BWCC to be dynamically loaded.
  280.  
  281.       //  Register any window classes used by the form. Forms will usually
  282.       //  register either one or occasionally two classes which define
  283.       //  the composition and reader dialogs created by the DLL.
  284.       //
  285.       //  There's a gotcha here, of course (aren't there always, in
  286.       //  Windows?)... You can't register a window class more than once,
  287.       //  so if the DLL has already been loaded and the user asks to
  288.       //  create a second instance of the form, we have to be careful
  289.       //  not to re-register the class. We do this by checking the
  290.       //  instance usage counter of the DLL - if it's greater than 1,
  291.       //  then we DON'T register the classes.
  292.  
  293.       wc.style          = WS_CHILD;
  294.       wc.lpfnWndProc    = FormProc;
  295.       wc.cbClsExtra     = 0;
  296.       wc.cbWndExtra     = DLGWINDOWEXTRA;
  297.        wc.hInstance      = hLibInstance;
  298.        wc.hIcon          = NULL;
  299.       wc.hCursor        = LoadCursor (NULL, IDC_ARROW);
  300.       wc.hbrBackground  = (HBRUSH) (COLOR_WINDOW + 1);
  301.       wc.lpszMenuName   = NULL;
  302.       wc.lpszClassName  = szFormDlgClassName;
  303.       if (! RegisterClass (&wc))
  304.          MessageBeep (0);
  305.       }
  306.  
  307.    return (TRUE);             // Initialization went OK
  308.    }
  309.  
  310.