This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/odoors/ODFrame.c

1760 lines
61 KiB
C
Raw Normal View History

2016-12-03 05:08:50 +00:00
/* OpenDoors Online Software Programming Toolkit
* (C) Copyright 1991 - 1999 by Brian Pirie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* File: ODFrame.c
*
* Description: Implements the OpenDoors frame window which provides the
* menu, toolbar, and status bar. The frame window's client
* area contains the display window which shows the door's
* output as the remote user would see it. This file should
* not be built into non-Windows versions of OpenDoors.
*
* Revisions: Date Ver Who Change
* ---------------------------------------------------------------
* Aug 20, 1995 6.00 BP Created.
* Dec 20, 1995 6.00 BP Remember toolbar & statusbar settings.
* Dec 22, 1995 6.00 BP Added od_connect_speed.
* Jan 20, 1996 6.00 BP Made ODFrameCenter...() shared.
* Jan 21, 1996 6.00 BP Added ODScrnShowMessage() and related.
* Feb 17, 1996 6.00 BP Add ...Accelerator() return value.
* Feb 17, 1996 6.00 BP Pass WM_MENUSELECT to DefWindowProc().
* Feb 19, 1996 6.00 BP Changed version number to 6.00.
* Feb 21, 1996 6.00 BP Fixed user keyboard off command.
* Feb 22, 1996 6.00 BP Allow escape to close Help About box.
* Feb 23, 1996 6.00 BP Properly update when toolbar turned on
* Mar 03, 1996 6.10 BP Begin version 6.10.
* Mar 14, 1996 6.10 BP Added configuration menu option.
* Aug 10, 2003 6.23 SH *nix support
*/
#define BUILDING_OPENDOORS
#include <stdio.h>
#include "windows.h"
#include "commctrl.h"
#include "OpenDoor.h"
#include "ODRes.h"
#include "ODFrame.h"
#include "ODGen.h"
#include "ODScrn.h"
#include "ODKrnl.h"
#ifdef ODPLAT_WIN32
/* Frame window information structure. */
typedef struct
{
HINSTANCE hInstance;
BOOL bToolbarOn;
HWND hwndToolbar;
BOOL bStatusBarOn;
HWND hwndStatusBar;
HWND hwndTimeEdit;
HWND hwndTimeUpDown;
BOOL bWantsChatIndicator;
HACCEL hacclFrameCommands;
HWND hwndMessageWindow;
char *pszCurrentMessage;
int nCurrentMessageFlags;
} tODFrameWindowInfo;
/* Toolbar button information. */
TBBUTTON atbButtons[] =
{
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, ID_DOOR_CHATMODE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{1, ID_DOOR_USERKEYBOARDOFF, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{2, ID_DOOR_SYSOPNEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{3, ID_DOOR_HANGUP, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{4, ID_DOOR_LOCKOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{5, ID_DOOR_EXIT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
};
/* Other toolbar settings. */
#define NUM_TOOLBAR_BITMAPS 6
#define MIN_TIME 0
#define MAX_TIME 1440
/* Pointer to default edit box window procedure. */
WNDPROC pfnDefEditProc = NULL;
WNDPROC pfnDefToolbarProc = NULL;
/* Global frame window handle. */
static HWND hwndCurrentFrame;
/* Status bar settings. */
#define NUM_STATUS_PARTS 2
#define NODE_PART_WIDTH 65
/* Child window IDs. */
#define ID_TOOLBAR 1000
#define ID_TIME_EDIT 1001
#define ID_TIME_UPDOWN 1002
#define ID_STATUSBAR 1003
/* Private function prototypes. */
static HWND ODFrameCreateToolbar(HWND hwndParent, HANDLE hInstance,
tODFrameWindowInfo *pWindowInfo);
static void ODFrameDestroyToolbar(HWND hwndToolbar,
tODFrameWindowInfo *pWindowInfo);
static HWND ODFrameCreateStatusBar(HWND hwndParent, HANDLE hInstance);
static void ODFrameSetMainStatusText(HWND hwndStatusBar);
static void ODFrameDestroyStatusBar(HWND hwndStatusBar);
static void ODFrameSizeStatusBar(HWND hwndStatusBar);
LRESULT CALLBACK ODFrameWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
LRESULT CALLBACK ODFrameToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
static void ODFrameUpdateTimeLeft(tODFrameWindowInfo *pWindowInfo);
LRESULT CALLBACK ODFrameTimeEditProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
BOOL CALLBACK ODFrameAboutDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam);
static HWND ODFrameCreateWindow(HANDLE hInstance);
static void ODFrameDestroyWindow(HWND hwndFrame);
static void ODFrameMessageLoop(HANDLE hInstance, HWND hwndFrame);
DWORD OD_THREAD_FUNC ODFrameThreadProc(void *pParam);
BOOL CALLBACK ODFrameMessageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam);
/* ----------------------------------------------------------------------------
* ODFrameCreateWindow() *** PRIVATE FUNCTION ***
*
* Creates the OpenDoors frame window and its children.
*
* Parameters: hInstance - Handle to application instance.
*
* Return: A handle to the newly created window, or NULL on failure.
*/
static HWND ODFrameCreateWindow(HANDLE hInstance)
{
HWND hwndFrameWindow = NULL;
WNDCLASS wcFrameWindow;
tODFrameWindowInfo *pWindowInfo = NULL;
tODThreadHandle hScreenThread;
HKEY hOpenDoorsKey;
DWORD cbData;
/* Register the main frame window's window class. */
memset(&wcFrameWindow, 0, sizeof(wcFrameWindow));
wcFrameWindow.style = CS_HREDRAW | CS_VREDRAW;
wcFrameWindow.lpfnWndProc = ODFrameWindowProc;
wcFrameWindow.cbClsExtra = 0;
wcFrameWindow.cbWndExtra = 0;
wcFrameWindow.hInstance = hInstance;
if(od_control.od_app_icon != NULL)
{
wcFrameWindow.hIcon = od_control.od_app_icon;
}
else
{
wcFrameWindow.hIcon
= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_OPENDOORS));
}
wcFrameWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
wcFrameWindow.hbrBackground = NULL;
wcFrameWindow.lpszMenuName = MAKEINTRESOURCE(IDR_FRAME_MENU);
wcFrameWindow.lpszClassName = "ODFrame";
RegisterClass(&wcFrameWindow);
/* Setup window information structure. */
pWindowInfo = malloc(sizeof(tODFrameWindowInfo));
if(!pWindowInfo)
{
return(NULL);
}
pWindowInfo->hInstance = hInstance;
pWindowInfo->hwndTimeEdit = NULL;
pWindowInfo->hwndTimeUpDown = NULL;
pWindowInfo->bWantsChatIndicator = FALSE;
pWindowInfo->hwndMessageWindow = NULL;
/* Determine whether or not the toolbar and status bar are on. */
RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
&hOpenDoorsKey);
cbData = sizeof(pWindowInfo->bToolbarOn);
if(RegQueryValueEx(hOpenDoorsKey, "ToolBarOn", NULL, NULL,
(LPBYTE)&pWindowInfo->bToolbarOn,
&cbData) != ERROR_SUCCESS)
{
pWindowInfo->bToolbarOn = TRUE;
RegSetValueEx(hOpenDoorsKey, "ToolBarOn", 0, REG_DWORD,
(LPBYTE)&pWindowInfo->bToolbarOn,
sizeof(pWindowInfo->bToolbarOn));
}
cbData = sizeof(pWindowInfo->bStatusBarOn);
if(RegQueryValueEx(hOpenDoorsKey, "StatusBarOn", NULL, NULL,
(LPBYTE)&pWindowInfo->bStatusBarOn,
&cbData) != ERROR_SUCCESS)
{
pWindowInfo->bStatusBarOn = TRUE;
RegSetValueEx(hOpenDoorsKey, "StatusBarOn", 0, REG_DWORD,
(LPBYTE)&pWindowInfo->bStatusBarOn,
sizeof(pWindowInfo->bStatusBarOn));
}
RegCloseKey(hOpenDoorsKey);
/* Create the main frame window. */
if((hwndFrameWindow = CreateWindowEx(
0L,
wcFrameWindow.lpszClassName,
od_control.od_prog_name,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX,
CW_USEDEFAULT,
0,
0,
0,
NULL,
NULL,
hInstance,
pWindowInfo)) == NULL)
{
/* On window creation failure, return NULL. */
return(NULL);
}
/* Load accelerator table for the frame window. */
pWindowInfo->hacclFrameCommands
= LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_FRAME));
/* Create the OpenDoors toolbar. On failure, we will continue anyhow. */
if(pWindowInfo->bToolbarOn)
{
pWindowInfo->hwndToolbar =
ODFrameCreateToolbar(hwndFrameWindow, hInstance, pWindowInfo);
}
/* Create the status bar. On failure, we will continue anyhow. */
if(pWindowInfo->bStatusBarOn)
{
pWindowInfo->hwndStatusBar =
ODFrameCreateStatusBar(hwndFrameWindow, hInstance);
}
/* Updates state of the window from whether or not the user has */
/* requested a chat with the sysop. */
ODFrameUpdateWantChat();
/* Create the local screen window, which occupies the remaining */
/* client area of the frame window. */
ODScrnStartWindow(hInstance, &hScreenThread, hwndFrameWindow);
return(hwndFrameWindow);
}
/* ----------------------------------------------------------------------------
* ODFrameCreateToolbar() *** PRIVATE FUNCTION ***
*
* Creates the OpenDoors toolbar.
*
* Parameters: hwndParent - Handle to the parent window.
*
* hInstance - Handle to the executable file's module instance.
*
* pWindowInfo - Pointer to frame window information structure.
*
* Return: A handle to the toolbar on success, or NULL on failure.
*/
static HWND ODFrameCreateToolbar(HWND hwndParent, HANDLE hInstance,
tODFrameWindowInfo *pWindowInfo)
{
HWND hwndToolbar = NULL;
HWND hwndTimeEdit = NULL;
HWND hwndTimeUpDown = NULL;
HWND hwndToolTip;
BOOL bSuccess = FALSE;
ASSERT(hwndParent != NULL);
ASSERT(hInstance != NULL);
ASSERT(pWindowInfo != NULL);
/* First, attempt to create the toolbar window. */
hwndToolbar = CreateToolbarEx(hwndParent,
WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS,
ID_TOOLBAR, NUM_TOOLBAR_BITMAPS, hInstance, IDB_TOOLBAR,
atbButtons, DIM(atbButtons), 0, 0, 0, 0, sizeof(TBBUTTON));
if(hwndToolbar == NULL)
{
goto CleanUp;
}
/* Change the window proc for the toolbar window to our own, keeping a */
/* pointer to the original window proc. */
pfnDefToolbarProc = (WNDPROC)GetWindowLong(hwndToolbar, GWL_WNDPROC);
SetWindowLong(hwndToolbar, GWL_WNDPROC, (LONG)ODFrameToolbarProc);
/* Next, create an edit control on the toolbar, to allow the user's */
/* time remaining online to be adjusted. */
hwndTimeEdit = CreateWindowEx(WS_EX_STATICEDGE, "EDIT", "",
WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT,
0, 0, 70, 22, hwndToolbar, (HMENU)ID_TIME_EDIT, hInstance, NULL);
if(hwndTimeEdit == NULL)
{
goto CleanUp;
}
/* Now that the edit window has the appropriate parent, we set its */
/* position accordingly. */
SetWindowPos(hwndTimeEdit, NULL, 2, 2, 0, 0,
SWP_NOZORDER | SWP_NOSIZE);
/* Set font of the edit control to be the standard non-bold font. */
SendMessage(hwndTimeEdit, WM_SETFONT,
(WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0));
/* Change the window proc for the edit window to our own, keeping a */
/* pointer to the original window proc. */
pfnDefEditProc = (WNDPROC)GetWindowLong(hwndTimeEdit, GWL_WNDPROC);
SetWindowLong(hwndTimeEdit, GWL_WNDPROC, (LONG)ODFrameTimeEditProc);
/* Add the time edit control to the tooltip control. */
/* Obtain a handle to the toolbar's tooltip control. */
hwndToolTip = (HWND)SendMessage(hwndToolbar, TB_GETTOOLTIPS, 0, 0);
if(hwndToolTip)
{
TOOLINFO ToolInfo;
/* Fill TOOLINFO structure. */
ToolInfo.cbSize = sizeof(ToolInfo);
ToolInfo.uFlags = TTF_IDISHWND | TTF_CENTERTIP;
ToolInfo.lpszText = "User's Time Remaining";
ToolInfo.hwnd = hwndParent;
ToolInfo.uId = (UINT)hwndTimeEdit;
ToolInfo.hinst = hInstance;
/* Setup tooltips for the time edit box. */
SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ToolInfo);
}
/* Now, we create an up-down control to buddy with the edit control. */
hwndTimeUpDown = CreateWindowEx(0L, UPDOWN_CLASS, "",
WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_ARROWKEYS |
UDS_ALIGNRIGHT, 0, 0, 8, 8,
hwndToolbar, (HMENU)ID_TIME_UPDOWN, hInstance, NULL);
if(hwndTimeUpDown == NULL)
{
goto CleanUp;
}
/* Set the up-down control's buddy control to be the edit control that */
/* we just created. */
SendMessage(hwndTimeUpDown, UDM_SETBUDDY, (LONG)hwndTimeEdit, 0L);
/* Set the valid range of values for the edit control. */
SendMessage(hwndTimeUpDown, UDM_SETRANGE, 0L, MAKELONG(MAX_TIME, MIN_TIME));
/* Store handles to time limit edit and up-down controls. */
pWindowInfo->hwndTimeEdit = hwndTimeEdit;
pWindowInfo->hwndTimeUpDown = hwndTimeUpDown;
/* Next, we set the default text for the edit control. */
ODFrameUpdateTimeLeft(pWindowInfo);
/* Return with success. */
bSuccess = TRUE;
CleanUp:
if(!bSuccess)
{
/* On failure, free any allocated resources. */
if(hwndTimeUpDown != NULL)
{
DestroyWindow(hwndTimeUpDown);
}
if(hwndTimeEdit != NULL)
{
DestroyWindow(hwndTimeUpDown);
}
if(hwndToolbar != NULL)
{
DestroyWindow(hwndToolbar);
hwndToolbar = NULL;
}
}
/* Return handle to newly created toolbar, or NULL on failure. */
return(hwndToolbar);
}
/* ----------------------------------------------------------------------------
* ODFrameDestroyToolbar() *** PRIVATE FUNCTION ***
*
* Destroys the OpenDoors toolbar.
*
* Parameters: hwndToolbar - Handle to previously created toolbar.
*
* pWindowInfo - Pointer to frame window information structure.
*
* Return: void.
*/
static void ODFrameDestroyToolbar(HWND hwndToolbar,
tODFrameWindowInfo *pWindowInfo)
{
ASSERT(hwndToolbar != NULL);
ASSERT(pWindowInfo != NULL);
/* Destroy the time up-down control, and NULL its handle in the frame */
/* window information structure. */
DestroyWindow(pWindowInfo->hwndTimeUpDown);
pWindowInfo->hwndTimeUpDown = NULL;
/* Destroy the time edit control, and NULL its handle in the frame window */
/* information structure. */
DestroyWindow(pWindowInfo->hwndTimeEdit);
pWindowInfo->hwndTimeEdit = NULL;
/* Now, destroy the toolbar itself. */
DestroyWindow(hwndToolbar);
}
/* ----------------------------------------------------------------------------
* ODFrameCreateStatusBar() *** PRIVATE FUNCTION ***
*
* Creates the OpenDoors status bar.
*
* Parameters: hwndParent - Handle to the parent window.
*
* hInstance - Handle to the executable file's module instance.
*
* Return: A handle to the status bar on success, or NULL on failure.
*/
static HWND ODFrameCreateStatusBar(HWND hwndParent, HANDLE hInstance)
{
HWND hwndStatusBar = NULL;
char szStatusText[20];
ASSERT(hwndParent != NULL);
/* Create the status bar window. */
hwndStatusBar = CreateWindowEx(0L, STATUSCLASSNAME, "",
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
hwndParent, (HMENU)ID_STATUSBAR, hInstance, NULL);
if(hwndStatusBar == NULL)
{
return(NULL);
}
/* Set the size of the status bar parts from the size of the frame */
/* window. */
ODFrameSizeStatusBar(hwndStatusBar);
/* Add the user's name, location and connection info string. */
ODFrameSetMainStatusText(hwndStatusBar);
/* Add the node number string. */
sprintf(szStatusText, "Node %d", od_control.od_node);
SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)1, (LPARAM)szStatusText);
return(hwndStatusBar);
}
/* ----------------------------------------------------------------------------
* ODFrameSetMainStatusText() *** PRIVATE FUNCTION ***
*
* Updates the text that is displayed in the main pane of the status bar.
*
* Parameters: hwndStatusBar - Handle to the status bar.
*
* Return: void.
*/
static void ODFrameSetMainStatusText(HWND hwndStatusBar)
{
char szStatusText[160];
ASSERT(hwndStatusBar != NULL);
/* Generate base status bar text, with the user's name, location and */
/* connection information. */
if(od_control.baud == 0)
{
sprintf(szStatusText, "%s of %s in local mode",
od_control.user_name,
od_control.user_location);
}
else
{
sprintf(szStatusText, "%s of %s at %ldbps",
od_control.user_name,
od_control.user_location,
od_control.od_connect_speed);
}
/* If the user has paged the sysop, then include reason for chat if */
/* it is available. */
if(od_control.user_wantchat && strlen(od_control.user_reasonforchat) > 0)
{
strcat(szStatusText, " (Reason for chat: \"");
strcat(szStatusText, od_control.user_reasonforchat);
strcat(szStatusText, "\")");
}
/* Update status bar text in the main status bar pane with the newly */
/* generated string. */
SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
}
/* ----------------------------------------------------------------------------
* ODFrameDestroyStatusBar() *** PRIVATE FUNCTION ***
*
* Destroys the OpenDoors status bar.
*
* Parameters: hwndStatusBar - Handle to previously created status bar.
*
* Return: void.
*/
static void ODFrameDestroyStatusBar(HWND hwndStatusBar)
{
DestroyWindow(hwndStatusBar);
}
/* ----------------------------------------------------------------------------
* ODFrameSizeStatusBar() *** PRIVATE FUNCTION ***
*
* Creates the OpenDoors status bar.
*
* Parameters: hwndStatusBar - Handle to existing status bar window.
*
* Return: void.
*/
static void ODFrameSizeStatusBar(HWND hwndStatusBar)
{
int anWidths[NUM_STATUS_PARTS];
int nStatusWidth;
RECT rcStatusBar;
/* Determine the total width of the status bar. */
GetWindowRect(hwndStatusBar, &rcStatusBar);
nStatusWidth = rcStatusBar.right - rcStatusBar.left;
/* Calculate the width of the parts from the total width. */
anWidths[0] = nStatusWidth - NODE_PART_WIDTH;
anWidths[1] = -1;
/* Update the status bar part settings. */
SendMessage(hwndStatusBar, SB_SETPARTS, NUM_STATUS_PARTS,
(LPARAM)anWidths);
}
/* ----------------------------------------------------------------------------
* ODFrameGetUsedClientAtTop()
*
* Determines height in pixels of the space used at the top of the
* frame window's client area, by the toolbar, etc.
*
* Parameters: hwndFrame - Handle to the OpenDoors frame window.
*
* Return: The height of the used space, in pixels.
*/
INT ODFrameGetUsedClientAtTop(HWND hwndFrame)
{
tODFrameWindowInfo *pWindowInfo;
RECT rcWindow;
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
if(!pWindowInfo->bToolbarOn) return(0);
GetWindowRect(pWindowInfo->hwndToolbar, &rcWindow);
return(rcWindow.bottom - rcWindow.top - 2);
}
/* ----------------------------------------------------------------------------
* ODFrameGetUsedClientAtBottom()
*
* Determines height in pixels of the space used at the bottom of the
* frame window's client area, by the status bar, etc.
*
* Parameters: hwndFrame - Handle to the OpenDoors frame window.
*
* Return: The height of the used space, in pixels.
*/
INT ODFrameGetUsedClientAtBottom(HWND hwndFrame)
{
tODFrameWindowInfo *pWindowInfo;
RECT rcWindow;
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
if(!pWindowInfo->bStatusBarOn) return(0);
GetWindowRect(pWindowInfo->hwndStatusBar, &rcWindow);
return(rcWindow.bottom - rcWindow.top - 1);
}
/* ----------------------------------------------------------------------------
* ODFrameWindowProc() *** PRIVATE FUNCTION ***
*
* The OpenDoors frame window proceedure.
*
* Parameters: hwnd - Handle to the OpenDoors frame window.
*
* uMsg - Specifies the message.
*
* wParam - Specifies additional message information. The content
* of this parameter depends on the value of the uMsg
* parameter.
*
* lParam - Specifies additional message information. The content
* of this parameter depends on the value of the uMsg
* parameter.
*
* Return: The return value is the result of the message processing and
* depends on the message.
*/
LRESULT CALLBACK ODFrameWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
tODFrameWindowInfo *pWindowInfo;
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwnd, GWL_USERDATA);
switch(uMsg)
{
case WM_CREATE:
{
/* At window creation time, store a pointer to the window */
/* information structure in window's user data. */
CREATESTRUCT *pCreateStruct = (CREATESTRUCT *)lParam;
pWindowInfo = (tODFrameWindowInfo *)pCreateStruct->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)pWindowInfo);
/* Update the enabled and checked states of frame window commands. */
ODFrameUpdateCmdUI();
/* If the client has not provided a help callback function, then */
/* remove the Contents item from the help menu. */
if(od_control.od_help_callback == NULL)
{
RemoveMenu(GetMenu(hwnd), ID_HELP_CONTENTS, MF_BYCOMMAND);
}
if(od_control.od_config_callback == NULL)
{
RemoveMenu(GetMenu(hwnd), ID_DOOR_CONFIG, MF_BYCOMMAND);
}
break;
}
case WM_CLOSE:
/* If door exit has been chosen, confirm with local user. */
if(MessageBox(hwnd,
"You are about to terminate this session and return the user to the BBS.\nDo you wish to proceed?",
od_control.od_prog_name,
MB_ICONQUESTION | MB_YESNO) == IDYES)
{
/* Normal door exit (drop to BBS) is implemented by the */
/* WM_DESTROY handler. */
ODFrameDestroyWindow(hwnd);
}
break;
case WM_DESTROY:
/* If toolbar is on, then it must be destroyed when the frame */
/* window is destroyed. */
if(pWindowInfo->bToolbarOn)
{
ODFrameDestroyToolbar(GetDlgItem(hwnd, ID_TOOLBAR), pWindowInfo);
}
/* If status bar is on, then it must be destroyed when the frame */
/* window is destroyed. */
if(pWindowInfo->bStatusBarOn)
{
ODFrameDestroyStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
}
/* Now, force OpenDoors to shutdown. */
ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_DROPTOBBS);
/* When the frame window is destroyed, it is the window proc's */
/* responsiblity to deallocate the window information structure. */
free(pWindowInfo);
SetWindowLong(hwnd, GWL_USERDATA, (LONG)NULL);
/* Reset current frame window handle. */
hwndCurrentFrame = NULL;
break;
case WM_SETFOCUS:
/* Whenver input focus is set to the frame window, pass the input */
/* focus on to the screen window, which fills most of our client */
/* area. */
ODScrnSetFocusToWindow();
break;
case WM_TIMER:
/* If the window flash timer has elapsed, then flash the window. */
FlashWindow(hwnd, TRUE);
break;
case WM_COMMAND:
/* An OpenDoors-defined command has been selected, so switch on */
/* the command ID. */
switch(LOWORD(wParam))
{
case ID_HELP_ABOUT:
/* Display the OpenDoors default about box. */
DialogBox(pWindowInfo->hInstance, MAKEINTRESOURCE(IDD_ABOUT),
hwnd, ODFrameAboutDlgProc);
break;
case ID_HELP_CONTENTS:
/* Call the client's help callback function, if one was */
/* provided. */
if(od_control.od_help_callback != NULL)
{
(*od_control.od_help_callback)();
}
break;
case ID_DOOR_CONFIG:
if(od_control.od_config_callback != NULL)
{
(*od_control.od_config_callback)();
}
break;
case ID_DOOR_EXIT:
/* On request for normal door exit (drop to BBS), just send */
/* a close message to this window. This will prompt to */
/* confirm exit, and then shutdown OpenDoors if appropriate. */
PostMessage(hwnd, WM_CLOSE, 0, 0L);
break;
case ID_DOOR_CHATMODE:
/* If chat mode is currently active, then end it. */
if(od_control.od_chat_active)
{
ODKrnlEndChatMode();
}
/* If chat mode is not currently active, then start it. */
else
{
ODKrnlStartChatThread(TRUE);
}
break;
case ID_DOOR_USERKEYBOARDOFF:
/* If user keyboard off command has been chosen, then toggle */
/* keyboard off mode on or off. */
od_control.od_user_keyboard_on
= !od_control.od_user_keyboard_on;
/* Update the keyboard off menu item and toolbar button. */
CheckMenuItem(GetMenu(hwnd), ID_DOOR_USERKEYBOARDOFF,
MF_BYCOMMAND | (od_control.od_user_keyboard_on
? MF_UNCHECKED : MF_CHECKED));
SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), TB_CHECKBUTTON,
ID_DOOR_USERKEYBOARDOFF,
MAKELONG(!od_control.od_user_keyboard_on, 0));
break;
case ID_DOOR_SYSOPNEXT:
/* If sysop next command has been chosen, then toggle the */
/* sysop next flag on or off. */
od_control.sysop_next = !od_control.sysop_next;
/* Update the sysop next menu item and toolbar button. */
CheckMenuItem(GetMenu(hwnd), ID_DOOR_SYSOPNEXT, MF_BYCOMMAND |
(od_control.sysop_next ? MF_CHECKED : MF_UNCHECKED));
SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), TB_CHECKBUTTON,
ID_DOOR_SYSOPNEXT, MAKELONG(od_control.sysop_next, 0));
break;
case ID_DOOR_HANGUP:
/* If hangup command has been chosen, then confirm with the */
/* local user. */
if(MessageBox(hwnd,
"You are about to disconnect this user. Do you wish to proceed?",
od_control.od_prog_name,
MB_ICONQUESTION | MB_YESNO) == IDYES)
{
ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
}
break;
case ID_DOOR_LOCKOUT:
/* If lockout command has been chosen, the confirm with the */
/* local user. */
if(MessageBox(hwnd,
"You are about to lock out this user. Do you wish to proceed?",
od_control.od_prog_name,
MB_ICONQUESTION | MB_YESNO) == IDYES)
{
/* Set the user's access security level to 0. */
od_control.user_security = 0;
ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
}
break;
case ID_VIEW_TOOL_BAR:
{
HKEY hOpenDoorsKey;
/* If toolbar on/off command has been chosen ... */
if(pWindowInfo->bToolbarOn)
{
/* If the toolbar is on, then turn it off. */
ODFrameDestroyToolbar(GetDlgItem(hwnd, ID_TOOLBAR),
pWindowInfo);
pWindowInfo->bToolbarOn = FALSE;
CheckMenuItem(GetMenu(hwnd), ID_VIEW_TOOL_BAR,
MF_BYCOMMAND | MF_UNCHECKED);
}
else
{
/* If the toolbar is off, then turn it on. */
pWindowInfo->hwndToolbar = ODFrameCreateToolbar(hwnd,
pWindowInfo->hInstance, pWindowInfo);
pWindowInfo->bToolbarOn = TRUE;
CheckMenuItem(GetMenu(hwnd), ID_VIEW_TOOL_BAR,
MF_BYCOMMAND | MF_CHECKED);
ODFrameUpdateCmdUI();
}
/* Adjust window sizes accordingly. */
ODScrnAdjustWindows();
/* Update the toolbar setting in the registry. */
RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
&hOpenDoorsKey);
RegSetValueEx(hOpenDoorsKey, "ToolBarOn", 0, REG_DWORD,
(LPBYTE)&pWindowInfo->bToolbarOn,
sizeof(pWindowInfo->bToolbarOn));
RegCloseKey(hOpenDoorsKey);
break;
}
case ID_VIEW_STAT_BAR:
{
HKEY hOpenDoorsKey;
/* If the status bar on/off command has been chosen ... */
if(pWindowInfo->bStatusBarOn)
{
/* If the status bar is on, then turn it off. */
pWindowInfo->bStatusBarOn = FALSE;
CheckMenuItem(GetMenu(hwnd), ID_VIEW_STAT_BAR,
MF_BYCOMMAND | MF_UNCHECKED);
ODFrameDestroyStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
}
else
{
/* If the status bar is off, then turn it on. */
pWindowInfo->bStatusBarOn = TRUE;
CheckMenuItem(GetMenu(hwnd), ID_VIEW_STAT_BAR,
MF_BYCOMMAND | MF_CHECKED);
pWindowInfo->hwndStatusBar =
ODFrameCreateStatusBar(hwnd, pWindowInfo->hInstance);
}
/* Adjust window sizes accordingly. */
ODScrnAdjustWindows();
/* Update the status bar setting in the registry. */
RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
&hOpenDoorsKey);
RegSetValueEx(hOpenDoorsKey, "StatusBarOn", 0, REG_DWORD,
(LPBYTE)&pWindowInfo->bStatusBarOn,
sizeof(pWindowInfo->bStatusBarOn));
RegCloseKey(hOpenDoorsKey);
break;
}
case ID_USER_ADDONEMINUTE:
/* If add one minute command has been chosen, then */
/* increment the user's time, up to the maximum allowable */
/* time. */
if(od_control.user_timelimit < MAX_TIME)
{
od_control.user_timelimit++;
ODFrameUpdateTimeLeft(pWindowInfo);
}
break;
case ID_USER_ADDFIVEMINUTES:
/* If add five minutes command has been chosen, then */
/* adjust the user's time accordingly. */
od_control.user_timelimit =
MIN(od_control.user_timelimit + 5, MAX_TIME);
ODFrameUpdateTimeLeft(pWindowInfo);
break;
case ID_USER_SUBTRACTONEMINUTE:
/* If subtract one minute command has been chosen, then */
/* adjust the user's time accordingly. */
if(od_control.user_timelimit > MIN_TIME)
{
od_control.user_timelimit--;
ODFrameUpdateTimeLeft(pWindowInfo);
}
break;
case ID_USER_SUBTRACTFIVEMINUTES:
/* If the subtract five mintues command has been chosen, */
/* then adjust the user's time accordingly. */
od_control.user_timelimit =
MAX(od_control.user_timelimit - 5, MIN_TIME);
ODFrameUpdateTimeLeft(pWindowInfo);
break;
case ID_USER_INACTIVITYTIMER:
/* If the user inactivity timer command has been chosen, */
/* then toggle the timer on or off. */
od_control.od_disable_inactivity =
!od_control.od_disable_inactivity;
CheckMenuItem(GetMenu(hwnd), ID_USER_INACTIVITYTIMER,
MF_BYCOMMAND | (od_control.od_disable_inactivity ?
MF_UNCHECKED : MF_CHECKED));
break;
case ID_TIME_EDIT:
{
/* If the user's time remaining has been directly edited, */
/* then adjust the time limit accordingly. */
if(HIWORD(wParam) == EN_CHANGE)
{
char szTimeText[40];
GetWindowText((HWND)lParam, szTimeText, sizeof(szTimeText));
od_control.user_timelimit = atoi(szTimeText);
/* Do not allow the time limit to fall outside of the */
/* valid range. */
od_control.user_timelimit =
MAX(MIN_TIME, od_control.user_timelimit);
od_control.user_timelimit =
MIN(MAX_TIME, od_control.user_timelimit);
/* Update the position of the up-down control. */
SendMessage(pWindowInfo->hwndTimeUpDown, UDM_SETPOS, 0,
(LPARAM)MAKELONG(od_control.user_timelimit, 0));
}
}
default:
return(TRUE);
}
return(FALSE);
case WM_NOTIFY:
/* A control parent notification message has been sent. */
switch(((LPNMHDR)lParam)->code)
{
case TTN_NEEDTEXT:
{
/* This is the message from the tool tip control, requesting */
/* the appropriate string to display for the current toolbar */
/* item. */
LPTOOLTIPTEXT lpToolTipText = (LPTOOLTIPTEXT)lParam;
switch(lpToolTipText->hdr.idFrom)
{
case ID_DOOR_EXIT:
lpToolTipText->lpszText = "Exit To BBS";
break;
case ID_DOOR_CHATMODE:
lpToolTipText->lpszText = "Chat Mode";
break;
case ID_DOOR_USERKEYBOARDOFF:
lpToolTipText->lpszText = "User Keyboard Off";
break;
case ID_DOOR_SYSOPNEXT:
lpToolTipText->lpszText = "Sysop Next";
break;
case ID_DOOR_HANGUP:
lpToolTipText->lpszText = "Hangup";
break;
case ID_DOOR_LOCKOUT:
lpToolTipText->lpszText = "Lockout";
break;
}
break;
}
}
break;
case WM_VSCROLL:
/* A scrolling action has taken place. */
/* If it is the time limit up-down control that has scrolled. */
if((HWND)lParam == pWindowInfo->hwndTimeUpDown)
{
int nPos = HIWORD(wParam);
/* Adjust the user's time limit. */
od_control.user_timelimit = MAX(MIN(nPos, MAX_TIME), MIN_TIME);
/* Update the time left displayed in the edit box. */
ODFrameUpdateTimeLeft(pWindowInfo);
}
break;
case WM_SIZE:
/* The OpenDoors frame window has been resized, so its contents */
/* must now be resized accordingly. */
/* Pass the message on to the status bar window, so that it will */
/* automatically adjust its own position and overall size. */
SendMessage(GetDlgItem(hwnd, ID_STATUSBAR), WM_SIZE, wParam, lParam);
/* Now, adjust the size of each part of the status bar. */
ODFrameSizeStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
/* Pass the message on to the toolbar, so that it will resize */
/* iteself. */
SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), WM_SIZE, wParam, lParam);
break;
case WM_MENUSELECT:
/* If the user has selected an item on the menu, then we should */
/* update the status bar accordingly. */
if(HIWORD(wParam) == 0xFFFF)
{
/* If menu is being exited, then turn off the status bar simple */
/* mode. */
HWND hwndStatusBar = GetDlgItem(hwnd, ID_STATUSBAR);
SendMessage(hwndStatusBar, SB_SIMPLE, (WPARAM)FALSE, 0L);
}
else
{
char szCommandString[160] = "";
HWND hwndStatusBar = GetDlgItem(hwnd, ID_STATUSBAR);
/* A new menu item is being selected. */
/* If this item is on the system menu, then provide the strings */
/* for any of those menu items. */
if(HIWORD(wParam) & MF_SYSMENU)
{
switch(LOWORD(wParam))
{
case SC_SIZE:
strcpy(szCommandString,
"Resizes this window.");
break;
case SC_MOVE:
strcpy(szCommandString,
"Moves this window.");
break;
case SC_MINIMIZE:
strcpy(szCommandString,
"Collapses this window to an icon.");
break;
case SC_MAXIMIZE:
strcpy(szCommandString,
"Expands this window to fill the screen.");
break;
case SC_CLOSE:
strcpy(szCommandString,
"Closes this window, and returns the user to the BBS.");
break;
case SC_RESTORE:
strcpy(szCommandString,
"Restores this window to normal size.");
break;
case SC_TASKLIST:
strcpy(szCommandString,
"");
break;
}
}
else
{
/* If this item is on the window menu provided by OpenDoors, */
/* then load the status bar string for this command ID. */
LoadString(pWindowInfo->hInstance, LOWORD(wParam),
szCommandString, sizeof(szCommandString));
}
/* Switch the status bar into simple (single-paned) mode. */
SendMessage(hwndStatusBar, SB_SIMPLE, (WPARAM)TRUE, 0L);
/* Set the text for the status bar. */
SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)255 | SBT_NOBORDERS,
(LPARAM)szCommandString);
}
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
case WM_SHOW_MESSAGE:
if(pWindowInfo->hwndMessageWindow == NULL)
{
pWindowInfo->pszCurrentMessage = (char *)lParam;
pWindowInfo->nCurrentMessageFlags = (int)wParam;
/* Create the message window. */
DialogBoxParam(pWindowInfo->hInstance,
MAKEINTRESOURCE(IDD_MESSAGE), hwnd, ODFrameMessageDlgProc,
(LPARAM)pWindowInfo);
}
break;
case WM_REMOVE_MESSAGE:
if(pWindowInfo->hwndMessageWindow != NULL)
{
PostMessage(pWindowInfo->hwndMessageWindow, WM_COMMAND,
MAKELONG(IDOK, 0), 0L);
pWindowInfo->hwndMessageWindow = NULL;
}
break;
default:
/* Pass messages that we don't explicitly handle on to the */
/* default window proc. */
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
return(0);
}
/* ----------------------------------------------------------------------------
* ODFrameUpdateCmdUI()
*
* Updates the enabled and checked state of OpenDoors commands that may change.
*
* Parameters: None.
*
* Return: void.
*/
void ODFrameUpdateCmdUI(void)
{
HWND hwndFrame = hwndCurrentFrame;
HMENU hMenu = GetMenu(hwndFrame);
HWND hwndToolbar = GetDlgItem(hwndFrame, ID_TOOLBAR);
tODFrameWindowInfo *pWindowInfo;
if(hwndFrame == NULL) return;
/* Obtain window information structure. */
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
if(pWindowInfo == NULL) return;
/* Check or uncheck the toolbar and status bar menu items. */
CheckMenuItem(hMenu, ID_VIEW_TOOL_BAR, MF_BYCOMMAND |
(pWindowInfo->bToolbarOn ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hMenu, ID_VIEW_STAT_BAR, MF_BYCOMMAND |
(pWindowInfo->bStatusBarOn ? MF_CHECKED : MF_UNCHECKED));
/* Check or uncheck the inactivity timer menu item. */
CheckMenuItem(hMenu, ID_USER_INACTIVITYTIMER, MF_BYCOMMAND |
(od_control.od_disable_inactivity ? MF_UNCHECKED : MF_CHECKED));
/* Check or uncheck the sysop next menu item and toolbar button. */
CheckMenuItem(hMenu, ID_DOOR_SYSOPNEXT, MF_BYCOMMAND |
(od_control.sysop_next ? MF_CHECKED : MF_UNCHECKED));
SendMessage(hwndToolbar, TB_CHECKBUTTON,
ID_DOOR_SYSOPNEXT, MAKELONG(od_control.sysop_next, 0));
/* Check or uncheck the keyboard off menu item and toolbar button. */
CheckMenuItem(hMenu, ID_DOOR_USERKEYBOARDOFF, MF_BYCOMMAND |
(od_control.od_user_keyboard_on ? MF_UNCHECKED : MF_CHECKED));
SendMessage(hwndToolbar, TB_CHECKBUTTON,
ID_DOOR_USERKEYBOARDOFF,
MAKELONG(!od_control.od_user_keyboard_on, 0));
/* Update the chat mode menu item and toolbar button. */
CheckMenuItem(hMenu, ID_DOOR_CHATMODE, MF_BYCOMMAND |
(od_control.od_chat_active ? MF_CHECKED : MF_UNCHECKED));
SendMessage(hwndToolbar, TB_CHECKBUTTON, ID_DOOR_CHATMODE,
MAKELONG(od_control.od_chat_active, 0));
}
/* ----------------------------------------------------------------------------
* ODFrameUpdateTimeDisplay()
*
* Updates the remaining time online that is displayed anywhere by the frame
* window. Uses ODFrameUpdateTimeLeft().
*
* Parameters: None.
*
* Return: void.
*/
void ODFrameUpdateTimeDisplay(void)
{
tODFrameWindowInfo *pWindowInfo;
/* If there is no current frame window, then return without doing */
/* anything. */
if(hwndCurrentFrame == NULL) return;
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndCurrentFrame,
GWL_USERDATA);
ASSERT(pWindowInfo != NULL);
ODFrameUpdateTimeLeft(pWindowInfo);
}
/* ----------------------------------------------------------------------------
* ODFrameUpdateWantChat()
*
* Updates the state of the flashing wants-chat indicator on the frame window.
*
* Parameters: None.
*
* Return: void.
*/
void ODFrameUpdateWantChat(void)
{
tODFrameWindowInfo *pWindowInfo;
/* If there is no current frame window, then return without doing */
/* anything. */
if(hwndCurrentFrame == NULL) return;
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndCurrentFrame,
GWL_USERDATA);
ASSERT(pWindowInfo != NULL);
/* If the status bar is on, then update the text displayed in the */
/* status bar's main pane. */
if(pWindowInfo->bStatusBarOn)
{
ODFrameSetMainStatusText(pWindowInfo->hwndStatusBar);
}
/* Toggle the state of the wants-chat indicator, of needed. */
if(pWindowInfo->bWantsChatIndicator && !od_control.user_wantchat)
{
/* Restore original window text. */
SetWindowText(hwndCurrentFrame, od_control.od_prog_name);
/* Restore the window flash to its original state. */
FlashWindow(hwndCurrentFrame, FALSE);
/* Destroy the Windows timer. */
KillTimer(hwndCurrentFrame, 1);
/* Record that wants chat indicator is now off. */
pWindowInfo->bWantsChatIndicator = FALSE;
}
else if (!pWindowInfo->bWantsChatIndicator && od_control.user_wantchat)
{
/* Set window title to include the wants chat indicator. */
char szNewWindowTitle[sizeof(od_control.od_prog_name) + 20];
sprintf(szNewWindowTitle, "%s - User Wants Chat",
od_control.od_prog_name);
SetWindowText(hwndCurrentFrame, szNewWindowTitle);
/* Start the flashing the window. */
SetTimer(hwndCurrentFrame, 1,
GetCaretBlinkTime(), NULL);
/* Record that wants chat indicator is now on. */
pWindowInfo->bWantsChatIndicator = TRUE;
}
}
/* ----------------------------------------------------------------------------
* ODFrameDestroyWindow() *** PRIVATE FUNCTION ***
*
* Destroys the OpenDoors frame window and its children.
*
* Parameters: hwndFrame - Handle to the window previously created by
* ODFrameCreateWindow().
*
* Return: void.
*/
static void ODFrameDestroyWindow(HWND hwndFrame)
{
tODFrameWindowInfo *pWindowInfo;
ASSERT(hwndFrame != NULL);
/* Obtain a pointer to the frame window information structure. */
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
/* At this point, deallocate the accelerator table. */
if(pWindowInfo->hacclFrameCommands != NULL)
{
DestroyAcceleratorTable(pWindowInfo->hacclFrameCommands);
}
/* Destroying the main frame window will automatically cause its */
/* children to be destroyed. */
DestroyWindow(hwndFrame);
}
/* ----------------------------------------------------------------------------
* ODFrameToolbarProc() *** PRIVATE FUNCTION ***
*
* The toolbar window proceedure.
*
* Parameters: hwnd - Handle to the toolbar window.
*
* uMsg - Specifies the message.
*
* wParam - Specifies additional message information. The content
* of this parameter depends on the value of the uMsg
* parameter.
*
* lParam - Specifies additional message information. The content
* of this parameter depends on the value of the uMsg
* parameter.
*
* Return: The return value is the result of the message processing and
* depends on the message.
*/
LRESULT CALLBACK ODFrameToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
/* Forward needed message to the main frame window proceedure. */
case WM_VSCROLL:
case WM_COMMAND:
SendMessage(GetParent(hwnd), uMsg, wParam, lParam);
break;
}
/* Pass all messages on to the default toolbar window proceedure. */
return(CallWindowProc(pfnDefToolbarProc, hwnd, uMsg, wParam, lParam));
}
/* ----------------------------------------------------------------------------
* ODFrameUpdateTimeLeft() *** PRIVATE FUNCTION ***
*
* Updates the displayed time remaining from od_control.user_timelimit.
*
* Parameters: pWindowInfo - Pointer to frame window information structure.
*
* Return: void.
*/
static void ODFrameUpdateTimeLeft(tODFrameWindowInfo *pWindowInfo)
{
char szTimeLeft[12];
RECT rcWindow;
if(pWindowInfo->hwndTimeEdit == NULL)
{
/* If the time limit edit control does not exist (i.e., if the */
/* toolbar is not currently on), then there is nothing for us to do. */
return;
}
/* Generate the string to be displayed in the edit control. */
sprintf(szTimeLeft, "%d min.", od_control.user_timelimit);
/* Set the edit control's text to the new string. */
SetWindowText(pWindowInfo->hwndTimeEdit, szTimeLeft);
/* Force edit control to be redrawn. (Except for rightmost pixel */
/* column.) */
GetWindowRect(pWindowInfo->hwndTimeEdit, &rcWindow);
rcWindow.right--;
InvalidateRect(pWindowInfo->hwndTimeEdit, &rcWindow, TRUE);
/* Set the position of the up-down control to match. */
SendMessage(pWindowInfo->hwndTimeUpDown, UDM_SETPOS, 0,
(LPARAM)MAKELONG(od_control.user_timelimit, 0));
}
/* ----------------------------------------------------------------------------
* ODFrameTimeEditProc() *** PRIVATE FUNCTION ***
*
* The time edit window proceedure. Relays mouse messages from the edit box
* to the tooltip control, and then passes all messages on to the standard
* edit box window proceedure.
*
* Parameters: hwnd - Handle to the time edit window.
*
* uMsg - Specifies the message.
*
* wParam - Specifies additional message information. The content
* of this parameter depends on the value of the uMsg
* parameter.
*
* lParam - Specifies additional message information. The content
* of this parameter depends on the value of the uMsg
* parameter.
*
* Return: The return value is the result of the message processing and
* depends on the message.
*/
LRESULT CALLBACK ODFrameTimeEditProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
{
MSG msg;
HWND hwndToolTip;
/* Setup message structure. */
msg.lParam = lParam;
msg.wParam = wParam;
msg.message = uMsg;
msg.hwnd = hwnd;
/* Obtain handle to the tooltip window. */
hwndToolTip = (HWND)SendMessage(GetParent(hwnd), TB_GETTOOLTIPS,
0, 0);
/* Relay the message to the tooltip window. */
SendMessage(hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg);
break;
}
}
/* Pass all messages on to the default edit box window proceedure. */
return(CallWindowProc(pfnDefEditProc, hwnd, uMsg, wParam, lParam));
}
/* ----------------------------------------------------------------------------
* ODFrameAboutDlgProc()
*
* DialogProc for the OpenDoors default Help About dialog box.
*
* Parameters: hwndDlg - Window handle to the dialog box.
*
* uMsg - Message ID.
*
* wParam - First message parameter.
*
* lParam - Second message parameter.
*
* Return: TRUE if message is processed, FALSE otherwise.
*/
BOOL CALLBACK ODFrameAboutDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
/* At dialog box creation time, update the text in the about */
/* box with any information provided by the OpenDoors programmer. */
/* If a program name has been provided, then display it. */
if(strcmp(od_control.od_prog_name, OD_VER_SHORTNAME) != 0)
{
SetWindowText(GetDlgItem(hwndDlg, IDC_DOORNAME),
od_control.od_prog_name);
}
/* If copyright information has been provided, then display it. */
if(strlen(od_control.od_prog_copyright) > 0)
{
SetWindowText(GetDlgItem(hwndDlg, IDC_COPYRIGHT),
od_control.od_prog_copyright);
}
/* If program version information has been provided, then display */
/* it. */
if(strlen(od_control.od_prog_version) > 0)
{
SetWindowText(GetDlgItem(hwndDlg, IDC_VERSION),
od_control.od_prog_version);
}
/* Center the about dialog box in the area occupied by the */
/* main frame window. */
ODFrameCenterWindowInParent(hwndDlg);
return(TRUE);
case WM_COMMAND:
/* If a command has been chosen. */
switch(LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
/* If the OK button has been pressed, then close the dialog. */
EndDialog(hwndDlg, IDOK);
break;
}
return(TRUE);
default:
/* Otherwise, indicate that this message has not been processed. */
return(FALSE);
}
}
/* ----------------------------------------------------------------------------
* ODFrameCenterWindowInParent() *** PRIVATE FUNCTION ***
*
* Repositions the specified window so that it is centered in its parent.
*
* Parameters: hwndChild - The window to reposition.
*
* Return: void.
*/
void ODFrameCenterWindowInParent(HWND hwndChild)
{
HWND hwndParent;
RECT rcParent;
RECT rcChild;
INT nChildWidth;
INT nChildHeight;
INT nParentWidth;
INT nParentHeight;
ASSERT(hwndChild != NULL);
/* Obtain a handle to the parent window. */
hwndParent = GetParent(hwndChild);
ASSERT(hwndParent != NULL);
/* Obtain the bounding boxes of both windows. */
GetWindowRect(hwndChild, &rcChild);
GetWindowRect(hwndParent, &rcParent);
/* Determine the height and width of both windows. */
nChildWidth = rcChild.right - rcChild.left;
nChildHeight = rcChild.bottom - rcChild.top;
nParentWidth = rcParent.right - rcParent.left;
nParentHeight = rcParent.bottom - rcParent.top;
/* Move the child to the center of the parent. */
SetWindowPos(hwndChild, NULL,
rcParent.left + (nParentWidth - nChildWidth) / 2,
rcParent.top + (nParentHeight - nChildHeight) / 2,
0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
/* ----------------------------------------------------------------------------
* ODFrameMessageLoop() *** PRIVATE FUNCTION ***
*
* Message loop for OpenDoors local UI thread (frame window handling).
*
* Parameters: hInstance - Handle to current instance.
*
* hwndFrame - Handle to the frame window.
*
* Return: void.
*/
static void ODFrameMessageLoop(HANDLE hInstance, HWND hwndFrame)
{
MSG msg;
ASSERT(hInstance != NULL);
ASSERT(hwndFrame != NULL);
/* Loop, fetching, translating and dispatching messages for any windows */
/* created by this thread. (GetMessage() blocks when no messages are */
/* available.) */
while(GetMessage(&msg, NULL, 0, 0))
{
if(!ODFrameTranslateAccelerator(hwndFrame, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
/* ----------------------------------------------------------------------------
* ODFrameTranslateAccelerator()
*
* Translates WM_KEYDOWN or WM_SYSKEYDOWN messages to frame window commands,
* if needed, based on the frame window's accelerator table.
*
* Parameters: hwndFrame - Handle to the OpenDoors main frame window.
*
* pMsg - Pointer to the message that may require
* translation.
*
* Return: TRUE if message was translated, FALSE if not.
*/
BOOL ODFrameTranslateAccelerator(HWND hwndFrame, LPMSG pMsg)
{
tODFrameWindowInfo *pWindowInfo;
ASSERT(hwndFrame != NULL);
ASSERT(pMsg != NULL);
/* Obtain a pointer to the frame window information structure. */
pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
ASSERT(pWindowInfo != NULL);
/* Perform accelerator translation, based on the frame window's */
/* accelerator table, sending any resulting WM_COMMAND messages */
/* to the frame window. */
return(TranslateAccelerator(hwndFrame, pWindowInfo->hacclFrameCommands,
pMsg) != 0);
}
/* ----------------------------------------------------------------------------
* ODFrameThreadProc() *** PRIVATE FUNCTION ***
*
* Function that execute the OpenDoors frame window thread.
*
* Parameters: pParam - The thread parameter, which must be the handle to the
* current application instance.
*
* Return: TRUE on success, or FALSE on failure.
*/
DWORD OD_THREAD_FUNC ODFrameThreadProc(void *pParam)
{
HWND hwndFrame;
HANDLE hInstance = (HANDLE)pParam;
/* Create the frame window. */
hwndFrame = ODFrameCreateWindow(hInstance);
if(hwndFrame == NULL)
{
return(FALSE);
}
/* Store a pointer to the frame window. */
hwndCurrentFrame = hwndFrame;
/* Loop, processing messages for the frame window. */
ODFrameMessageLoop(hInstance, hwndFrame);
/* Destroy the frame window. */
ODFrameDestroyWindow(hwndFrame);
return(TRUE);
}
/* ----------------------------------------------------------------------------
* ODFrameStart()
*
* Function that starts up the frame window.
*
* Parameters: hInstance - Handle to the current application instance.
*
* phFrameThread - Pointer to the frame thread handle.
*
* Return: kODRCSuccess on success, or an error code on failure.
*/
tODResult ODFrameStart(HANDLE hInstance, tODThreadHandle *phFrameThread)
{
return(ODThreadCreate(phFrameThread, ODFrameThreadProc,
(void *)hInstance));
}
/* ----------------------------------------------------------------------------
* ODFrameMessageDlgProc()
*
* Dialog proceedure for the OpenDoors message window.
*
* Parameters: hwndDlg - Window handle to the dialog box.
*
* uMsg - Message ID.
*
* wParam - First message parameter.
*
* lParam - Second message parameter.
*
* Return: TRUE if message is processed, FALSE otherwise.
*/
BOOL CALLBACK ODFrameMessageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
tODFrameWindowInfo *pWindowInfo;
pWindowInfo = (tODFrameWindowInfo *)lParam;
ASSERT(pWindowInfo != NULL);
pWindowInfo->hwndMessageWindow = hwndDlg;
/* Set the message window title. */
SetWindowText(hwndDlg, od_control.od_prog_name);
/* Change the text displayed in the message window. */
SetWindowText(GetDlgItem(hwndDlg, IDC_MESSAGE_TEXT1),
(char *)pWindowInfo->pszCurrentMessage);
/* Center window in parent window. */
ODFrameCenterWindowInParent(hwndDlg);
return(FALSE);
}
case WM_COMMAND:
/* If a command has been chosen. */
switch(LOWORD(wParam))
{
case IDOK:
/* If the OK button has been pressed, then close the dialog. */
EndDialog(hwndDlg, IDOK);
break;
}
return(TRUE);
default:
/* Indicate that this message has not been processed. */
return(FALSE);
}
return(TRUE);
}
#endif /* ODPLAT_WIN32 */