home *** CD-ROM | disk | FTP | other *** search
- //
- // FINGER.C
- // Pegasus Mail for Windows extension providing a FINGER
- // interface.
- //
- // Copyright (c) 1994, David Harris, All Rights Reserved.
- //
- // The author grants explicit permission for this source code to be
- // used or modified as required, subject only to the conditions that
- // the copyright notices above are preserved and that by using this
- // code you agree that the code is provided without warranty of any
- // kind, either explicit or implied, and you use it at your own
- // risk.
- //
-
- #define STRICT
- #include <windows.h>
- #include <bwcc.h>
- #include <stdio.h>
- #include <string.h>
- #include "..\wpmforms.h"
- #include "finger.h" // Dialog control item IDs
-
- // Form dialogs and callbacks: a form DLL can export a function
- // which WinPMail's form manager will call with Windows messages
- // destined for the form's dialog or window (such as menu selections
- // and so forth). The function takes the following form:
-
- typedef long pascal far (*FORM_CALLBACK) (HWND hWnd, WORD wMsg,
- WPARAM wParam, LPARAM lParam);
-
- // The return from a form callback is passed back through the
- // Windows call chain if non-zero, otherwise the default window
- // proc is called. The reasons we call this function instead of
- // simply sending messages to the dialog itself are:
- //
- // 1: Dialogs can only return Boolean values, whereas the callback
- // can provide the long value Windows expects to pass back
- // through the calling chain.
- //
- // 2: Having a separate callback means that it is potentially
- // possible to have a form which does not create a dialog.
- //
- //
- // Minimum interface: the minimum interface a form DLL must provide
- // is a routine called "forminit" which is exported by name. "forminit"
- // has the following prototype:
- //
- // WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND hParent,
- // char *data, HWND *hDialog, char *callback_name);
- //
- // "version" is passed in with the version of the WinPMail forms
- // manager which is running.
- // "variant" indicates what type of form is required - the following
- // values are currently defined:
- // 0: Create a form for composing a message
- // 1: Create a form for reading a message
- // "hParent" contains the handle of the WinPMail MDI child window
- // which is to contain the form.
- // "data" contains any string defined as being required for the
- // form in the menu interface.
- // "hDialog" should be filled in with the window handle of the
- // modeless dialog created within the MDI child window.
- // "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. If NULL, messages are
- // sent to the dialog returned in "hDialog". You will use an
- // indirect callback of this kind when your extension does not
- // create a dialog within the enclosing parent window.
- //
- // When forminit is called, the DLL should register any window
- // classes it needs then create the dialog within the MDI parent
- // window and size it to the correct size. On return WinPMail will
- // resize the parent window to enclose the dialog correctly. The
- // DLL should NOT make the dialog visible - WinPMail will do that
- // as required.
-
- #define WM_MARGIN (WM_USER + 1099)
- #define WM_SETDIR (WM_USER + 400)
- #define WM_ADDFILE (WM_USER + 401)
- #define WM_STARTUP (WM_USER + 403)
- #define WM_GET_ALIST (WM_USER + 404)
-
- #define IDC_QUICKHELP_TO 970
- #define IDC_QUICKHELP_CC 971
-
-
- int register_form_classes (void);
-
-
- HFONT hFingerFont;
- HINSTANCE hLibInstance; // set in LibMain, used throughout the DLL
- char szFormDlgName [] = "FINGER"; // Name of dialog resource template.
- char szFormDlgClassName [] =
- "bordlg_fn"; // Class name for the form dialog.
- HWND last_focus;
- char no_tcp [] =
- "This extension can only run on systems where WinPMail "
- "has access to Winsock TCP/IP services.";
-
- #pragma warn -par
-
-
- WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND hParent,
- char *data, HWND *hDialog, FORM_CALLBACK *callback)
- {
- RECT r;
- char szBuf [80];
- int i;
- HWND hControl;
- BYTE tm [7];
-
- // First, check to see if the version of the form manager is
- // one we can work with. This check is pretty arbitrary - you
- // should probably assume that you may not work with any version
- // where the major version number is higher than the original
- // version you targeted.
-
- if ((version & 0xFF00) > 0x100) return 0;
-
- // Now check the variant number; for the Finger Client we only
- // provide a COMPOSER format.
-
- if (variant != 0) return 0;
-
- (*hDialog) = CreateDialog (hLibInstance, (LPCSTR) szFormDlgName, hParent, NULL);
- if ((*hDialog) == NULL) return 0;
- GetClientRect (*hDialog, &r);
- MoveWindow (*hDialog, 0, 0, r.right, r.bottom, FALSE);
-
- hFingerFont = CreateFont (14, 0, 0, 0, 400, FALSE,
- FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
- DEFAULT_PITCH | FF_DONTCARE, "Arial");
- SendMessage (GetDlgItem (*hDialog, 103), WM_SETFONT,
- (WPARAM) hFingerFont, (LPARAM) TRUE);
-
- // Some default values can be passed in the "data" parameter
- if ((data != NULL) && (*data))
- SetDlgItemText (*hDialog, 101, data); // Default host
- return 1;
- }
-
-
- void finger (HWND hParent, HWND hControl, char *host, char *search)
- {
- // Despatch a query to a finger server based on the hostname
- // and search string supplied by the user. The finger protocol
- // is one of the older protocols on the Internet and is pretty
- // basic - you just open port 79 and shove a CRLF delimited
- // string down its throat... It will then do whatever matching
- // it thinks is appropriate and return an arbitrary amount of
- // arbitrarily-formatted data to you. The data returned is
- // almost universally unparseable so we simply offer it to the
- // user as-is where-is.
-
- char buffer [256];
-
- if (SendMessage (hParent, WM_F_TCPOPEN, 79, (LPARAM) host) < 1)
- return;
-
- SendMessage (hControl, EM_SETSEL, 0, 0x7FFF0000);
- sprintf (buffer, "%s\r\n", search);
- if (SendMessage (hParent, WM_F_TCPPUTS, 0, (LPARAM) buffer) > 0)
- {
- for (;;)
- {
- buffer [0] = '\0';
- if (SendMessage (hParent, WM_F_TCPGETS, sizeof (buffer), (LPARAM) buffer) < 1)
- break;
- if (buffer [0] == '\0') break;
- SendMessage (hControl, EM_REPLACESEL, 0, (LPARAM) buffer);
- }
- }
- SendMessage (hParent, WM_F_TCPCLOSE, 0, 0);
- }
-
-
- LONG FAR PASCAL _export FormProc (HWND hWnd, WORD wMsg,
- WORD wParam, LONG lParam)
- {
- // Service routine for the form's enclosed dialog. This is a
- // standard windows modeless WndProc.
-
- DWORD dwResult = 0;
- BOOL fCallDefProc = TRUE;
- char host [80], search [80];
-
- switch (wMsg)
- {
- case WM_FM_INIT :
- // Check to see that TCP/IP services are actually
- // available on this system. If they aren't, we simply
- // post a close message to the parent.
-
- if (SendMessage (GetParent (hWnd), WM_F_TCPPRESENT, 0, 0) == 0)
- {
- MessageBox (hWnd, no_tcp, " Finger Client", MB_OK | MB_ICONSTOP);
- PostMessage (GetParent (hWnd), WM_CLOSE, 0, 0);
- }
- break;
-
- case WM_FM_INITFOCUS :
- SetFocus (GetDlgItem (hWnd, 101));
- break;
-
- case WM_FM_RESTOREFOCUS :
- // There's a glitch in the way the Windows MDI manager
- // seems to manage focus which means that we can have
- // focus taken away and not returned when the user does
- // anything outside our window. WinPMail has some quite
- // complex logic to deal with this case and will send
- // this message whenever focus should be restored in
- // our window. We set focus to the last active control
- // (which we know from trapping EN_SETFOCUS messages).
-
- if (last_focus) SetFocus (last_focus);
- break;
-
- case WM_DESTROY :
- if (hFingerFont) DeleteObject (hFingerFont);
- break;
-
- case WM_COMMAND :
- fCallDefProc = FALSE;
- if (HIWORD (lParam) == EN_SETFOCUS)
- {
- // We have to trap EN_SETFOCUS messages so we know which
- // control was active last. When a menu selection is made
- // our current control will lose focus and because of a
- // curiosity in Windows' MDI management, we won't get it
- // back. Instead, WinPMail generates a WM_FM_RESTOREFOCUS
- // message which signals to us that we should set focus to
- // whatever the last active control was.
-
- last_focus = (HWND) LOWORD (lParam);
- break;
- }
-
- switch (wParam)
- {
- case 139 :
- GetDlgItemText (hWnd, 101, host, sizeof (host));
- GetDlgItemText (hWnd, 102, search, sizeof (search));
- finger (GetParent (hWnd), GetDlgItem (hWnd, 103), host, search);
- break;
- }
- break;
- }
-
- if (fCallDefProc)
- dwResult = BWCCDefDlgProc (hWnd, wMsg, wParam, lParam);
-
- return dwResult;
- }
-
-
- #pragma warn -sus
-
- void unregister_form_classes (void)
- {
- // Remove any classes associated with the form; we have the
- // same problem here as we do with registering the classes
- // for the DLL - we only want to deregister the classes on
- // the last time we're unloaded.
-
- if (GetModuleUsage (hLibInstance) > 1) return; // Not a problem
- UnregisterClass (szFormDlgClassName, hLibInstance);
- }
-
-
- BOOL FAR PASCAL LibMain (HINSTANCE hInst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
- {
- WNDCLASS wc;
-
- if (! hLibInstance)
- {
- hLibInstance = hInst;
- BWCCGetVersion (); // Forces BWCC to be dynamically loaded.
-
- // Register any window classes used by the form. Forms will usually
- // register either one or occasionally two classes which define
- // the composition and reader dialogs created by the DLL.
- //
- // There's a gotcha here, of course (aren't there always, in
- // Windows?)... You can't register a window class more than once,
- // so if the DLL has already been loaded and the user asks to
- // create a second instance of the form, we have to be careful
- // not to re-register the class. We do this by checking the
- // instance usage counter of the DLL - if it's greater than 1,
- // then we DON'T register the classes.
-
- wc.style = WS_CHILD;
- wc.lpfnWndProc = FormProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = DLGWINDOWEXTRA;
- wc.hInstance = hLibInstance;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor (NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szFormDlgClassName;
- if (! RegisterClass (&wc))
- MessageBeep (0);
- }
-
- return (TRUE); // Initialization went OK
- }
-
-