You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2286 lines
68 KiB
2286 lines
68 KiB
/*---------------------------------------------------------------------------*\
|
|
| WINCHAT APPLICATION MODULE
|
|
| This is the main module file for the application. The application was
|
|
| originally written by ClausGi for the Windows-For-WorkGroup product.
|
|
| In the port to NT, all references to PEN-awareness and Protocol were
|
|
| removed. Extensive cleanup and documenting was also added in the port.
|
|
|
|
|
| FUNCTIONS
|
|
| ---------
|
|
| myatol
|
|
| UpdateButtonStates
|
|
| appGetComputerName
|
|
| AdjustEditWindows
|
|
|
|
|
|
|
|
| Copyright (c) Microsoft Corp., 1990-1993
|
|
|
|
|
| created: 01-Nov-91
|
|
| history: 01-Nov-91 <clausgi> created.
|
|
| 29-Dec-92 <chriswil> port to NT, cleanup.
|
|
| 19-Oct-93 <chriswil> unicode enhancements from a-dianeo.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include <windows.h>
|
|
#include <mmsystem.h>
|
|
#include <stdio.h>
|
|
#include <ddeml.h>
|
|
#include <commdlg.h>
|
|
#include <commctrl.h>
|
|
#include <shellapi.h>
|
|
#include <nddeapi.h>
|
|
#include <richedit.h>
|
|
#include "winchat.h"
|
|
#include "dialogs.h"
|
|
#include "globals.h"
|
|
#include "nddeagnt.h"
|
|
|
|
#include <imm.h>
|
|
#include <htmlhelp.h>
|
|
|
|
#define ASSERT(x)
|
|
|
|
// This is used in the port to NT. Since NT doesn't haven a dialogbox for
|
|
// this function, we'll use the lanman export.
|
|
//
|
|
#ifdef WIN32
|
|
#define FOCUSDLG_DOMAINS_ONLY (1)
|
|
#define FOCUSDLG_SERVERS_ONLY (2)
|
|
#define FOCUSDLG_SERVERS_AND_DOMAINS (3)
|
|
|
|
#define FOCUSDLG_BROWSE_LOGON_DOMAIN 0x00010000
|
|
#define FOCUSDLG_BROWSE_WKSTA_DOMAIN 0x00020000
|
|
#define FOCUSDLG_BROWSE_OTHER_DOMAINS 0x00040000
|
|
#define FOCUSDLG_BROWSE_TRUSTING_DOMAINS 0x00080000
|
|
#define FOCUSDLG_BROWSE_WORKGROUP_DOMAINS 0x00100000
|
|
|
|
#define FOCUSDLG_BROWSE_LM2X_DOMAINS (FOCUSDLG_BROWSE_LOGON_DOMAIN | FOCUSDLG_BROWSE_WKSTA_DOMAIN | FOCUSDLG_BROWSE_OTHER_DOMAINS)
|
|
#define FOCUSDLG_BROWSE_ALL_DOMAINS (FOCUSDLG_BROWSE_LOCAL_DOMAINS | FOCUSDLG_BROWSE_WORKGROUP_DOMAINS)
|
|
#define FOCUSDLG_BROWSE_LOCAL_DOMAINS (FOCUSDLG_BROWSE_LM2X_DOMAINS | FOCUSDLG_BROWSE_TRUSTING_DOMAINS)
|
|
|
|
#define MY_LOGONTYPE (FOCUSDLG_BROWSE_ALL_DOMAINS | FOCUSDLG_SERVERS_ONLY)
|
|
|
|
UINT APIENTRY I_SystemFocusDialog(HWND,UINT,LPWSTR,UINT,PBOOL,LPWSTR,DWORD);
|
|
#endif
|
|
|
|
BOOL TranslateWideCharPosToMultiBytePos(HWND,DWORD,DWORD,LPDWORD,LPDWORD);
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| WINDOWS MAIN
|
|
| This is the main event-processing loop for the application.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
|
|
|
|
msg.wParam = 0;
|
|
|
|
if(InitApplication(hInstance))
|
|
{
|
|
if(InitInstance(hInstance,nCmdShow))
|
|
{
|
|
while(GetMessage(&msg,NULL,0,0))
|
|
{
|
|
if(!TranslateAccelerator(hwndApp,hAccel,&msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
if(hszConvPartner)
|
|
DdeFreeStringHandle(idInst,hszConvPartner);
|
|
|
|
DdeFreeStringHandle(idInst,hszChatTopic);
|
|
DdeFreeStringHandle(idInst,hszChatShare);
|
|
DdeFreeStringHandle(idInst,hszLocalName );
|
|
DdeFreeStringHandle(idInst,hszTextItem);
|
|
DdeFreeStringHandle(idInst,hszConnectTest);
|
|
DdeUninitialize(idInst);
|
|
|
|
EndIniMapping();
|
|
}
|
|
}
|
|
|
|
return((int)msg.wParam);
|
|
}
|
|
|
|
|
|
#ifdef WIN16
|
|
#pragma alloc_text ( _INIT, InitApplication )
|
|
#endif
|
|
/*---------------------------------------------------------------------------*\
|
|
| INITIALIZE APPLICATION
|
|
| This routine registers the application with user.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
BOOL FAR InitApplication(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon(hInstance, TEXT("PHONE1"));
|
|
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
|
|
wc.lpszMenuName = szWinChatMenu;
|
|
wc.lpszClassName = szWinChatClass;
|
|
|
|
return(RegisterClass(&wc));
|
|
}
|
|
|
|
|
|
#define IMMMODULENAME L"IMM32.DLL"
|
|
#define PATHDLM L'\\'
|
|
#define IMMMODULENAMELEN ((sizeof PATHDLM + sizeof IMMMODULENAME) / sizeof(WCHAR))
|
|
|
|
VOID GetImmFileName(PWSTR wszImmFile)
|
|
{
|
|
UINT i = GetSystemDirectoryW(wszImmFile, MAX_PATH);
|
|
if (i > 0 && i < MAX_PATH - IMMMODULENAMELEN) {
|
|
wszImmFile += i;
|
|
if (wszImmFile[-1] != PATHDLM) {
|
|
*wszImmFile++ = PATHDLM;
|
|
}
|
|
}
|
|
StringCchCopyW(wszImmFile, MAX_PATH, IMMMODULENAME);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| IsTSRemoteSession
|
|
|
|
|
| Input: None
|
|
| Output: BOOL - TRUE if in a Terminal Server remote session (SessionId != 0)
|
|
| FALSE - if error OR not in a TS rermote session
|
|
| Function: To determine whether we are running in a TS remote session or not.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
BOOL IsTSRemoteSession()
|
|
{
|
|
BOOL bRetVal;
|
|
DWORD dwSessionID;
|
|
HINSTANCE hInst;
|
|
FARPROC lpfnProcessIdToSessionId;
|
|
|
|
//assume failure
|
|
bRetVal = FALSE;
|
|
|
|
// load library and get proc address
|
|
hInst=LoadLibrary(TEXT("kernel32.dll"));
|
|
|
|
if (hInst)
|
|
{
|
|
lpfnProcessIdToSessionId = GetProcAddress(hInst,"ProcessIdToSessionId");
|
|
|
|
if (lpfnProcessIdToSessionId )
|
|
{
|
|
if (lpfnProcessIdToSessionId(GetCurrentProcessId(),&dwSessionID))
|
|
{
|
|
if(dwSessionID!=0)
|
|
{
|
|
bRetVal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// free the library
|
|
FreeLibrary(hInst);
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef WIN16
|
|
#pragma alloc_text ( _INIT, InitInstance )
|
|
#endif
|
|
/*---------------------------------------------------------------------------*\
|
|
| INITIALIZE APPLICATION INTSTANCE
|
|
| This routine initializes instance information.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
BOOL FAR InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|
{
|
|
HWND hwnd;
|
|
HMENU hMenu;
|
|
HINSTANCE hmodNetDriver;
|
|
int cAppQueue;
|
|
BOOL bRet;
|
|
|
|
hInst = hInstance;
|
|
|
|
|
|
//
|
|
// get DBCS flag
|
|
//
|
|
gfDbcsEnabled = GetSystemMetrics(SM_DBCSENABLED);
|
|
|
|
if (GetSystemMetrics(SM_IMMENABLED)) {
|
|
//
|
|
// if IME is enabled, get real API addresses
|
|
//
|
|
WCHAR wszImmFile[MAX_PATH];
|
|
HINSTANCE hInstImm32;
|
|
GetImmFileName(wszImmFile);
|
|
hInstImm32 = GetModuleHandle(wszImmFile);
|
|
if (hInstImm32) {
|
|
pfnImmGetContext = (PVOID)GetProcAddress(hInstImm32, "ImmGetContext");
|
|
ASSERT(pfnImmGetContext);
|
|
pfnImmReleaseContext = (PVOID)GetProcAddress(hInstImm32, "ImmReleaseContext");
|
|
ASSERT(pfnImmReleaseContext);
|
|
pfnImmGetCompositionStringW = (PVOID)GetProcAddress(hInstImm32, "ImmGetCompositionStringW");
|
|
ASSERT(pfnImmGetCompositionStringW);
|
|
}
|
|
}
|
|
|
|
// increase our app queue for better performance...
|
|
//
|
|
for(cAppQueue=128; !SETMESSAGEQUEUE(cAppQueue); cAppQueue >>= 1);
|
|
|
|
|
|
//
|
|
//
|
|
bRet = FALSE;
|
|
if(cAppQueue >= 8)
|
|
{
|
|
bRet = TRUE;
|
|
|
|
cxIcon = GetSystemMetrics(SM_CXICON);
|
|
cyIcon = GetSystemMetrics(SM_CYICON);
|
|
hAccel = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDACCELERATORS));
|
|
|
|
|
|
|
|
LoadIntlStrings();
|
|
StartIniMapping();
|
|
|
|
|
|
InitFontFromIni();
|
|
|
|
|
|
// check if it's a Terminal Server remote session
|
|
if (IsTSRemoteSession())
|
|
{
|
|
TCHAR szTSNotSupported[SZBUFSIZ];
|
|
|
|
LoadString(hInst, IDS_TSNOTSUPPORTED, szTSNotSupported, SZBUFSIZ);
|
|
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox(NULL, szTSNotSupported, szAppName, MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
// get our machine name and map to correct character set.
|
|
//
|
|
if(!appGetComputerName(szLocalName))
|
|
{
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
// initialize DDEML.
|
|
//
|
|
if(DdeInitialize(&idInst,(PFNCALLBACK)MakeProcInstance((FARPROC)DdeCallback,hInst),APPCLASS_STANDARD,0L))
|
|
{
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
ChatState.fMinimized = (nCmdShow == SW_MINIMIZE) ? TRUE : FALSE;
|
|
ChatState.fMMSound = waveOutGetNumDevs();
|
|
ChatState.fSound = GetPrivateProfileInt(szPref,szSnd ,1,szIni);
|
|
ChatState.fToolBar = GetPrivateProfileInt(szPref,szTool ,1,szIni);
|
|
ChatState.fStatusBar = GetPrivateProfileInt(szPref,szStat ,1,szIni);
|
|
ChatState.fTopMost = GetPrivateProfileInt(szPref,szTop ,0,szIni);
|
|
ChatState.fSideBySide = GetPrivateProfileInt(szPref,szSbS ,0,szIni);
|
|
ChatState.fUseOwnFont = GetPrivateProfileInt(szPref,szUseOF,0,szIni);
|
|
|
|
hszLocalName = DdeCreateStringHandle(idInst,szLocalName ,0);
|
|
hszChatTopic = DdeCreateStringHandle(idInst,szChatTopic ,0);
|
|
hszChatShare = DdeCreateStringHandle(idInst,szChatShare ,0);
|
|
hszServiceName = DdeCreateStringHandle(idInst,szServiceName,0);
|
|
hszConnectTest = DdeCreateStringHandle(idInst,szConnectTest,0);
|
|
hszTextItem = DdeCreateStringHandle(idInst,szChatText ,0);
|
|
|
|
if(!hszLocalName || !hszChatTopic || !hszServiceName || !hszTextItem || !hszChatShare)
|
|
{
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
DdeNameService(idInst,hszServiceName,(HSZ)0,DNS_REGISTER);
|
|
|
|
|
|
if(DdeGetLastError(idInst) != DMLERR_NO_ERROR)
|
|
{
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox (NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
cf_chatdata = RegisterClipboardFormat(TEXT("Chat Data"));
|
|
if(!(cf_chatdata))
|
|
{
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
// get winnet extension browse dialog entry point
|
|
//
|
|
WNetServerBrowseDialog = NULL;
|
|
hmodNetDriver = WNETGETCAPS(0xFFFF);
|
|
|
|
if(hmodNetDriver != NULL)
|
|
WNetServerBrowseDialog = (WNETCALL)GetProcAddress(hmodNetDriver,(LPSTR)146);
|
|
|
|
|
|
|
|
// create main window
|
|
hwnd = CreateWindow(
|
|
szWinChatClass,
|
|
szAppName,
|
|
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL
|
|
);
|
|
|
|
if(!hwnd)
|
|
{
|
|
MessageBeep(MB_ICONSTOP);
|
|
MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
|
|
return(FALSE);
|
|
}
|
|
|
|
hwndApp = hwnd; // save global
|
|
|
|
// font choice struct init
|
|
//
|
|
chf.lStructSize = sizeof(CHOOSEFONT);
|
|
chf.lpLogFont = &lfSnd;
|
|
chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
|
|
chf.rgbColors = GetSysColor(COLOR_WINDOWTEXT);
|
|
chf.lCustData = 0L;
|
|
chf.lpfnHook = NULL;
|
|
chf.lpTemplateName = NULL;
|
|
chf.hInstance = NULL;
|
|
chf.lpszStyle = NULL;
|
|
chf.nFontType = SCREEN_FONTTYPE;
|
|
chf.nSizeMin = 0;
|
|
chf.nSizeMax = 0;
|
|
|
|
|
|
// color choice init
|
|
//
|
|
chc.lStructSize = sizeof(CHOOSECOLOR);
|
|
chc.hwndOwner = hwndApp;
|
|
chc.hInstance = hInst;
|
|
chc.lpCustColors = (LPDWORD)CustColors;
|
|
chc.Flags = CC_RGBINIT | CC_PREVENTFULLOPEN;
|
|
chc.lCustData = 0;
|
|
chc.lpfnHook = NULL;
|
|
chc.lpTemplateName = NULL;
|
|
|
|
|
|
// window placement...
|
|
//
|
|
if(ReadWindowPlacement(&Wpl))
|
|
{
|
|
// override these - CODEWORK don't need to save
|
|
// them to .ini, but will mis-parse old .ini files
|
|
// if change is made.
|
|
//
|
|
Wpl.showCmd = nCmdShow;
|
|
Wpl.ptMaxPosition.x = -1;
|
|
Wpl.ptMaxPosition.y = -1;
|
|
Wpl.flags = 0;
|
|
|
|
SetWindowPlacement(hwnd,&Wpl);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
else
|
|
ShowWindow(hwnd,nCmdShow);
|
|
|
|
//
|
|
//
|
|
hMenu = GetSystemMenu(hwnd,FALSE);
|
|
AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
|
|
|
|
if(ChatState.fTopMost)
|
|
AppendMenu(hMenu,MF_ENABLED | MF_CHECKED | MF_STRING,IDM_TOPMOST,szAlwaysOnTop);
|
|
else
|
|
AppendMenu(hMenu,MF_ENABLED | MF_UNCHECKED | MF_STRING,IDM_TOPMOST,szAlwaysOnTop);
|
|
|
|
|
|
// Set topmost style...
|
|
//
|
|
SetWindowPos(hwndApp,ChatState.fTopMost ? HWND_TOPMOST : HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
|
|
UpdateButtonStates();
|
|
|
|
#if !defined(_WIN64)
|
|
|
|
{
|
|
static NDDESHAREINFO nddeShareInfo = {
|
|
1, // revision
|
|
szChatShare,
|
|
SHARE_TYPE_STATIC,
|
|
TEXT("WinChat|Chat\0\0"),
|
|
TRUE, // shared
|
|
FALSE, // not a service
|
|
TRUE, // can be started
|
|
SW_SHOWNORMAL,
|
|
{0,0}, // mod id
|
|
0, // no item list
|
|
TEXT("")
|
|
};
|
|
|
|
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 3] = TEXT("\\\\");
|
|
DWORD cbName = MAX_COMPUTERNAME_LENGTH + 1;
|
|
|
|
//
|
|
// Make sure NetDDE DSDM has trusted shares set up properly for us.
|
|
// This fix allows us to work with floating profiles.
|
|
//
|
|
|
|
START_NETDDE_SERVICES(hwnd);
|
|
GetComputerName(&szComputerName[2],&cbName);
|
|
NDdeShareAdd(szComputerName,2,NULL,(LPBYTE)&nddeShareInfo,sizeof(NDDESHAREINFO));
|
|
NDdeSetTrustedShare(szComputerName, szChatShare,
|
|
NDDE_TRUST_SHARE_START | NDDE_TRUST_SHARE_INIT);
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| MAIN WINDOW PROC
|
|
| This is the main event-handler for the application.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT lResult;
|
|
|
|
|
|
lResult = 0l;
|
|
switch(message)
|
|
{
|
|
case WM_CREATE:
|
|
appWMCreateProc(hwnd);
|
|
break;
|
|
|
|
case WM_WININICHANGE:
|
|
appWMWinIniChangeProc(hwnd);
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
if((lResult = (LRESULT)appWMEraseBkGndProc(hwnd)) == 0)
|
|
lResult = DefWindowProc(hwnd,message,wParam,lParam);
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
appWMSetFocusProc(hwnd);
|
|
break;
|
|
|
|
case WM_MENUSELECT:
|
|
appWMMenuSelectProc(hwnd,wParam,lParam);
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
appWMTimerProc(hwnd);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
appWMPaintProc(hwnd);
|
|
break;
|
|
|
|
case WM_QUERYDRAGICON:
|
|
lResult = (LRESULT)(LPVOID)appWMQueryDragIconProc(hwnd);
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
appWMSizeProc(hwnd,wParam,lParam);
|
|
break;
|
|
|
|
case WM_INITMENU:
|
|
appWMInitMenuProc((HMENU)wParam);
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
if(!appWMSysCommandProc(hwnd,wParam,lParam))
|
|
lResult = DefWindowProc(hwnd,message,wParam,lParam);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if(!appWMCommandProc(hwnd,wParam,lParam))
|
|
lResult = DefWindowProc(hwnd,message,wParam,lParam);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPTOOLTIPTEXT lpTTT = (LPTOOLTIPTEXT) lParam;
|
|
|
|
if (lpTTT->hdr.code == TTN_NEEDTEXT) {
|
|
LoadString (hInst, (UINT)(MH_BASE + lpTTT->hdr.idFrom), lpTTT->szText, 80);
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
#ifdef WIN32
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORSTATIC:
|
|
#else
|
|
case WM_CTLCOLOR:
|
|
#endif
|
|
if((lResult = (LRESULT)(LPVOID)appWMCtlColorProc(hwnd,wParam,lParam)) == 0l)
|
|
lResult = DefWindowProc(hwnd,message,wParam,lParam);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
appWMDestroyProc(hwnd);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
WinHelp(hwnd,(LPTSTR)szHelpFile,HELP_QUIT,0L);
|
|
|
|
// Fall through for final close.
|
|
//
|
|
|
|
|
|
default:
|
|
lResult = DefWindowProc(hwnd,message,wParam,lParam);
|
|
break;
|
|
}
|
|
|
|
return(lResult);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| EDIT-HOOK PROCEDURE
|
|
| This is the main event-handler for the edit-control hook.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
LRESULT CALLBACK EditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WPARAM wSet;
|
|
LPARAM lSet;
|
|
GETTEXTLENGTHEX gettextlengthex;
|
|
LRESULT lResult;
|
|
LPTSTR lpszText;
|
|
HANDLE hText;
|
|
INT count;
|
|
LPTSTR lpszStartSel;
|
|
DWORD dwTemp1;
|
|
DWORD dwTemp2;
|
|
|
|
switch(msg) {
|
|
case WM_IME_COMPOSITION:
|
|
{
|
|
LPWSTR lpStrParam;
|
|
LPSTR lpStrTmp;
|
|
HANDLE hTmp;
|
|
|
|
if (lParam & GCS_RESULTSTR)
|
|
{
|
|
HIMC hImc;
|
|
ULONG cCharsMbcs, cChars;
|
|
|
|
//
|
|
// Get input context of hwnd
|
|
//
|
|
|
|
if ((hImc = pfnImmGetContext(hwnd)) == 0)
|
|
break;
|
|
|
|
//
|
|
//ImmGetComposition returns the size of buffer needed in byte
|
|
//
|
|
|
|
cCharsMbcs = pfnImmGetCompositionStringW(hImc,GCS_RESULTSTR, NULL , 0);
|
|
if(!(cCharsMbcs))
|
|
{
|
|
pfnImmReleaseContext(hwnd, hImc);
|
|
break;
|
|
}
|
|
|
|
lpStrParam = (LPWSTR)GlobalAlloc(GPTR,//HEAP_ZERO_MEMORY,
|
|
cCharsMbcs + sizeof(WCHAR));
|
|
|
|
if (lpStrParam==NULL)
|
|
{
|
|
pfnImmReleaseContext(hwnd, hImc);
|
|
break;
|
|
}
|
|
|
|
pfnImmGetCompositionStringW(hImc, GCS_RESULTSTR, lpStrParam,
|
|
cCharsMbcs);
|
|
|
|
//
|
|
// Compute character count including NULL char.
|
|
//
|
|
|
|
cChars = wcslen(lpStrParam) + 1;
|
|
|
|
//
|
|
// Set ChatData packet
|
|
//
|
|
|
|
ChatData.type = CHT_DBCS_STRING;
|
|
|
|
//
|
|
// Get current cursor position
|
|
//
|
|
// !!! BUG BUG BUG !!!
|
|
//
|
|
// This position data is only nice for Unicode Edit control.
|
|
// is the partner has not Unicode Edit control. the string
|
|
// will be truncated.
|
|
//
|
|
|
|
SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
|
|
ChatData.uval.cd_dbcs.SelPos = MAKELONG((WORD)dwTemp1, (WORD)dwTemp2 );
|
|
|
|
if (gfDbcsEnabled) {
|
|
//
|
|
// since text is passed as multi byte character string,
|
|
// position fixup is needed if DBCS is enabled
|
|
//
|
|
DWORD dwStart, dwEnd;
|
|
|
|
TranslateWideCharPosToMultiBytePos( hwndSnd,
|
|
(DWORD)LOWORD(ChatData.uval.cd_dbcs.SelPos),
|
|
(DWORD)HIWORD(ChatData.uval.cd_dbcs.SelPos),
|
|
&dwStart, &dwEnd );
|
|
ChatData.uval.cd_dbcs.SelPos
|
|
= MAKELONG((WORD)dwStart, (WORD)dwEnd );
|
|
}
|
|
|
|
//
|
|
// Allocate string buffer for DDE.
|
|
//
|
|
|
|
if((hTmp = GlobalAlloc( GMEM_ZEROINIT |
|
|
GMEM_MOVEABLE |
|
|
GMEM_DDESHARE ,
|
|
(DWORD)cCharsMbcs)) == NULL)
|
|
{
|
|
pfnImmReleaseContext(hwnd, hImc);
|
|
GlobalFree(lpStrParam);
|
|
break;
|
|
}
|
|
|
|
lpStrTmp = GlobalLock(hTmp);
|
|
|
|
//
|
|
// Store MBCS string into DDE buffer.
|
|
//
|
|
// In CHT_DBCS_STRING context, we should send mbcs string
|
|
// for downlevel connectivity.
|
|
//
|
|
|
|
WideCharToMultiByte(CP_ACP,0,lpStrParam,cChars/* + 1*/,
|
|
lpStrTmp ,cCharsMbcs/* + 1*/,
|
|
NULL,NULL);
|
|
|
|
//
|
|
// Keep the buffer handle in to DDE message packet.
|
|
//
|
|
|
|
GlobalUnlock(hTmp);
|
|
ChatData.uval.cd_dbcs.hString = hTmp;
|
|
|
|
//
|
|
// Now, we have a packet to send server/client, just send it.
|
|
//
|
|
|
|
wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_DBCS_STRING,hwnd);
|
|
lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_DBCS_STRING,hwnd);
|
|
SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
|
|
|
|
//
|
|
// if we have still a connection to server/client. repaint text.
|
|
//
|
|
|
|
if(ChatState.fConnected)
|
|
SendMessage(hwndSnd,EM_REPLACESEL,0,(LPARAM)lpStrParam);
|
|
|
|
pfnImmReleaseContext(hwnd, hImc);
|
|
GlobalFree(lpStrParam);
|
|
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_KEYDOWN:
|
|
if (wParam == VK_DELETE) {
|
|
DWORD dwLastError;
|
|
ChatData.type = CHT_CHAR;
|
|
|
|
SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
|
|
ChatData.uval.cd_dbcs.SelPos = MAKELONG((WORD)dwTemp1, (WORD)dwTemp2 );
|
|
|
|
lResult=SendMessage(hwndSnd,WM_GETTEXTLENGTH,0,0);
|
|
// if we are trying to delete at the end of the line then ignore it
|
|
if(lResult<=LOWORD(ChatData.uval.cd_char.SelPos)) break;
|
|
|
|
if (LOWORD(ChatData.uval.cd_char.SelPos) == HIWORD(ChatData.uval.cd_char.SelPos)) {
|
|
|
|
// get handle to the text
|
|
hText = (HANDLE)SendMessage( hwndSnd, EM_GETHANDLE, 0, 0);
|
|
if( !(hText) )
|
|
break;
|
|
|
|
lpszText = LocalLock( hText);
|
|
if( !(lpszText))
|
|
{
|
|
LocalUnlock(hText);
|
|
break;
|
|
}
|
|
lpszStartSel=lpszText;
|
|
for(count=0;count<LOWORD(ChatData.uval.cd_char.SelPos);count++)
|
|
{
|
|
lpszStartSel=CharNext(lpszStartSel);
|
|
if(lpszStartSel[0] == TEXT('\0')) break; // if at the end then break since something is mesed
|
|
}
|
|
|
|
if(lpszStartSel[0] != TEXT('\0') && lpszStartSel[0] == TEXT('\r'))
|
|
{
|
|
if(lpszStartSel[1] != TEXT('\0') && lpszStartSel[1] == TEXT('\n'))
|
|
{
|
|
ChatData.uval.cd_char.SelPos=MAKELONG(LOWORD(ChatData.uval.cd_char.SelPos),
|
|
HIWORD(ChatData.uval.cd_char.SelPos)+2);
|
|
}
|
|
else
|
|
{
|
|
ChatData.uval.cd_char.SelPos=MAKELONG(LOWORD(ChatData.uval.cd_char.SelPos)+1,
|
|
HIWORD(ChatData.uval.cd_char.SelPos)+1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ChatData.uval.cd_char.SelPos=MAKELONG(LOWORD(ChatData.uval.cd_char.SelPos)+1,
|
|
HIWORD(ChatData.uval.cd_char.SelPos)+1);
|
|
}
|
|
|
|
|
|
LocalUnlock( hText );
|
|
}
|
|
|
|
|
|
if (gfDbcsEnabled) {
|
|
DWORD dwStart, dwEnd;
|
|
|
|
TranslateWideCharPosToMultiBytePos( hwndSnd,
|
|
(DWORD)LOWORD(ChatData.uval.cd_dbcs.SelPos),
|
|
(DWORD)HIWORD(ChatData.uval.cd_dbcs.SelPos),
|
|
&dwStart, &dwEnd );
|
|
ChatData.uval.cd_dbcs.SelPos
|
|
= MAKELONG((WORD)dwStart, (WORD)dwEnd);
|
|
}
|
|
|
|
ChatData.uval.cd_char.Char = VK_BACK;
|
|
|
|
wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_CHAR,hwnd);
|
|
lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_CHAR,hwnd);
|
|
|
|
SendMessage(hwndApp,WM_COMMAND,(WPARAM)wSet,(LPARAM)lSet);
|
|
}
|
|
break;
|
|
case WM_CHAR:
|
|
if(wParam != CTRL_V)
|
|
{
|
|
ChatData.type = CHT_CHAR;
|
|
SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
|
|
ChatData.uval.cd_dbcs.SelPos = MAKELONG((WORD)dwTemp1, (WORD)dwTemp2 );
|
|
|
|
if (gfDbcsEnabled) {
|
|
DWORD dwStart, dwEnd;
|
|
|
|
TranslateWideCharPosToMultiBytePos( hwndSnd,
|
|
(DWORD)LOWORD(ChatData.uval.cd_dbcs.SelPos),
|
|
(DWORD)HIWORD(ChatData.uval.cd_dbcs.SelPos),
|
|
&dwStart, &dwEnd );
|
|
ChatData.uval.cd_dbcs.SelPos
|
|
= MAKELONG((WORD)dwStart, (WORD)dwEnd);
|
|
}
|
|
|
|
ChatData.uval.cd_char.Char = (WORD)wParam;
|
|
|
|
wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_CHAR,hwnd);
|
|
lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_CHAR,hwnd);
|
|
|
|
SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_PASTE:
|
|
ChatData.type = (WORD)(ChatState.fUnicode ? CHT_PASTEW : CHT_PASTEA);
|
|
SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
|
|
ChatData.uval.cd_paste.SelPos = MAKELONG(dwTemp1,dwTemp2);
|
|
wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_PASTE,hwnd);
|
|
lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_PASTE,hwnd);
|
|
|
|
SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
|
|
break;
|
|
}
|
|
|
|
return(CallWindowProc(lpfnOldEditProc,hwnd,msg,wParam,lParam));
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION CREATE PROCEDURE
|
|
| This is the main event-handler for the WM_CREATE event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMCreateProc(HWND hwnd)
|
|
{
|
|
HDC hdc;
|
|
TCHAR buf[16] = {0};
|
|
RECT rc;
|
|
|
|
|
|
// read from ini
|
|
//
|
|
StringCchPrintf(buf, ARRAYSIZE(buf), TEXT("%ld"),GetSysColor(COLOR_WINDOW));
|
|
GetPrivateProfileString(szPref,szBkgnd,buf,szBuf,SZBUFSIZ,szIni);
|
|
SndBrushColor = myatol(szBuf);
|
|
|
|
|
|
// just in case display driver changed, set the send-color.
|
|
//
|
|
hdc = GetDC (hwnd);
|
|
if(hdc)
|
|
{
|
|
SndBrushColor = GetNearestColor(hdc,SndBrushColor);
|
|
ReleaseDC(hwnd,hdc);
|
|
}
|
|
|
|
if(ChatState.fUseOwnFont)
|
|
{
|
|
RcvBrushColor = SndBrushColor;
|
|
RcvColorref = SndColorref;
|
|
}
|
|
else
|
|
RcvBrushColor = GetSysColor ( COLOR_WINDOW );
|
|
|
|
ChatState.fConnected = FALSE;
|
|
ChatState.fConnectPending = FALSE;
|
|
ChatState.fIsServer = FALSE;
|
|
ChatState.fServerVerified = TRUE;
|
|
ChatState.fInProcessOfDialing = FALSE;
|
|
ChatState.fUnicode = FALSE;
|
|
|
|
CreateTools(hwnd);
|
|
CreateChildWindows(hwnd);
|
|
|
|
UpdateButtonStates();
|
|
|
|
// determine height of toolbar window and save...
|
|
//
|
|
GetClientRect(hwndToolbar, &rc);
|
|
dyButtonBar = rc.bottom - rc.top;
|
|
|
|
// determine height of statusbar window and save...
|
|
GetClientRect(hwndStatus, &rc);
|
|
dyStatus = rc.bottom - rc.top;
|
|
|
|
|
|
// stuff our local font into one or both edit controls
|
|
//
|
|
hEditSndFont = CreateFontIndirect((LPLOGFONT)&lfSnd);
|
|
if(hEditSndFont)
|
|
{
|
|
SendMessage(hwndSnd,WM_SETFONT,(WPARAM)hEditSndFont,1L);
|
|
if(ChatState.fUseOwnFont)
|
|
SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditSndFont,1L);
|
|
}
|
|
|
|
|
|
hwndActiveEdit = hwndSnd;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION WININICHANGE PROCEDURE
|
|
| This is the main event-handler for the WM_WININICHANGE event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMWinIniChangeProc(HWND hwnd)
|
|
{
|
|
|
|
if(hEditSndFont)
|
|
{
|
|
DeleteObject(hEditSndFont);
|
|
hEditSndFont = CreateFontIndirect((LPLOGFONT)&lfSnd);
|
|
if(hEditSndFont)
|
|
SendMessage(hwndSnd,WM_SETFONT,(WPARAM)hEditSndFont,1L);
|
|
}
|
|
|
|
|
|
if(hEditRcvFont)
|
|
{
|
|
DeleteObject(hEditRcvFont);
|
|
hEditRcvFont = CreateFontIndirect((LPLOGFONT)&lfRcv);
|
|
}
|
|
|
|
|
|
if(ChatState.fUseOwnFont && hEditSndFont)
|
|
SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditSndFont,1L);
|
|
else
|
|
{
|
|
if(hEditRcvFont)
|
|
SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditRcvFont,1L);
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION ERASEBKGND PROCEDURE
|
|
| This is the main event-handler for the WM_ERASEBKBND event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
BOOL appWMEraseBkGndProc(HWND hwnd)
|
|
{
|
|
BOOL bErase;
|
|
|
|
|
|
bErase = IsIconic(hwnd) ? TRUE : FALSE;
|
|
|
|
return(bErase);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION SETFOCUS PROCEDURE
|
|
| This is the main event-handler for the WM_SETFOCUS event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMSetFocusProc(HWND hwnd)
|
|
{
|
|
SetFocus(hwndActiveEdit);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION CTLCOLOR PROCEDURE
|
|
| This is the main event-handler for the WM_CTLCOLOR event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
HBRUSH appWMCtlColorProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hDC;
|
|
HWND hWndCtl;
|
|
HBRUSH hBrush;
|
|
|
|
|
|
hBrush = NULL;
|
|
hDC = GET_WM_CTLCOLOREDIT_HDC(wParam,lParam);
|
|
hWndCtl = GET_WM_CTLCOLOREDIT_HWND(wParam,lParam);
|
|
|
|
|
|
if(hWndCtl == hwndSnd)
|
|
{
|
|
SetTextColor(hDC,SndColorref);
|
|
SetBkColor(hDC,SndBrushColor);
|
|
|
|
hBrush = hEditSndBrush;
|
|
}
|
|
else
|
|
if(hWndCtl == hwndRcv)
|
|
{
|
|
if(ChatState.fUseOwnFont)
|
|
{
|
|
SetTextColor(hDC,SndColorref);
|
|
SetBkColor(hDC,SndBrushColor);
|
|
}
|
|
else
|
|
{
|
|
SetTextColor(hDC,RcvColorref);
|
|
SetBkColor(hDC,RcvBrushColor);
|
|
}
|
|
|
|
hBrush = hEditRcvBrush;
|
|
}
|
|
|
|
return(hBrush);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION SELECTMENU PROCEDURE
|
|
| This is the main event-handler for the WM_MENUSELECT event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMMenuSelectProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if(wParam == IDM_TOPMOST)
|
|
{
|
|
if(LoadString(hInst,MH_BASE+IDM_TOPMOST,szBuf,SZBUFSIZ))
|
|
SendMessage(hwndStatus,SB_SETTEXT,SBT_NOBORDERS|255,(LPARAM)(LPSTR)szBuf);
|
|
}
|
|
|
|
MenuHelp((WORD)WM_MENUSELECT,wParam,lParam,GetMenu(hwnd),hInst,hwndStatus,(LPUINT)nIDs);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION PAINT PROCEDURE
|
|
| This is the main event-handler for the WM_PAINT event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMPaintProc(HWND hwnd)
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
RECT rc;
|
|
|
|
hdc = BeginPaint(hwnd,&ps);
|
|
if(hdc)
|
|
{
|
|
if(IsIconic(hwnd))
|
|
{
|
|
//
|
|
//
|
|
DefWindowProc(hwnd,WM_ICONERASEBKGND,(WPARAM)ps.hdc,0L);
|
|
BitBlt(hMemDC,0,0,cxIcon,cyIcon,hdc,0,0,SRCCOPY);
|
|
DrawIcon(hdc,0,0,hPhones[0]);
|
|
|
|
|
|
// make 2 more copies.
|
|
//
|
|
BitBlt(hMemDC,cxIcon ,0,cxIcon,cyIcon,hMemDC,0,0,SRCCOPY);
|
|
BitBlt(hMemDC,2*cxIcon,0,cxIcon,cyIcon,hMemDC,0,0,SRCCOPY);
|
|
|
|
// draw phones into them.
|
|
//
|
|
DrawIcon(hMemDC,0 ,0,hPhones[0]);
|
|
DrawIcon(hMemDC,cxIcon ,0,hPhones[1]);
|
|
DrawIcon(hMemDC,2*cxIcon,0,hPhones[2]);
|
|
}
|
|
else
|
|
{
|
|
|
|
#if BRD > 2
|
|
rc = SndRc;
|
|
rc.top--;
|
|
rc.left--;
|
|
DrawShadowRect(hdc,&rc);
|
|
rc = RcvRc;
|
|
rc.top--;
|
|
rc.left--;
|
|
DrawShadowRect(hdc,&rc);
|
|
#endif
|
|
}
|
|
|
|
EndPaint ( hwnd, &ps );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION TIMER PROCEDURE
|
|
| This is the main event-handler for the WM_TIMER event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMTimerProc(HWND hwnd)
|
|
{
|
|
HDC hdc;
|
|
DWORD dummy;
|
|
|
|
|
|
// Animate the phone icon.
|
|
//
|
|
if(cAnimate)
|
|
{
|
|
if(--cAnimate == 0)
|
|
{
|
|
KillTimer(hwnd,idTimer);
|
|
FlashWindow(hwnd,FALSE);
|
|
}
|
|
|
|
if(IsIconic(hwnd))
|
|
{
|
|
hdc = GetDC(hwndApp);
|
|
if(hdc)
|
|
{
|
|
BitBlt(hdc,0,0,cxIcon,cyIcon,hMemDC,ASeq[cAnimate % 4] * cxIcon,0,SRCCOPY);
|
|
ReleaseDC(hwndApp,hdc);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
// We must be ringing...
|
|
//
|
|
if(!ChatState.fConnectPending)
|
|
{
|
|
KillTimer(hwnd,idTimer);
|
|
return;
|
|
}
|
|
|
|
|
|
// has the existence of the server been verified (by completion
|
|
// of the async advstart xact)?
|
|
//
|
|
if(!ChatState.fServerVerified)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// don't want to lose this...
|
|
//
|
|
DdeKeepStringHandle(idInst,hszLocalName);
|
|
|
|
if(DdeClientTransaction(NULL,0L,ghConv,hszLocalName,cf_chatdata,XTYP_ADVSTART,(DWORD)3000L,(LPDWORD)&dummy) == (HDDEDATA)TRUE)
|
|
{
|
|
ChatState.fConnected = TRUE;
|
|
ChatState.fConnectPending = FALSE;
|
|
UpdateButtonStates();
|
|
|
|
KILLSOUND;
|
|
|
|
SendFontToPartner();
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, szConnectedTo,(LPSTR)szConvPartner);
|
|
SetStatusWindowText(szBuf);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%s - [%s]"),(LPTSTR)szAppName,(LPTSTR)szConvPartner);
|
|
SetWindowText(hwnd,szBuf);
|
|
|
|
|
|
// allow text entry...
|
|
//
|
|
SendMessage(hwndSnd,EM_SETREADONLY,(WPARAM)FALSE,0L);
|
|
|
|
KillTimer(hwnd,idTimer);
|
|
|
|
AnnounceSupport();
|
|
}
|
|
else
|
|
{
|
|
// The other party has not answered yet... ring every 6 seconds.
|
|
// Ring local,
|
|
//
|
|
if(!(nConnectAttempt++ % 6))
|
|
DoRing(szWcRingOut);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION QUERYDRAGICON PROCEDURE
|
|
| This is the main event-handler for the WM_QUERYDRAGICON event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
HICON appWMQueryDragIconProc(HWND hwnd)
|
|
{
|
|
HICON hIcon;
|
|
|
|
|
|
hIcon = hPhones[0];
|
|
|
|
return(hIcon);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION SIZE PROCEDURE
|
|
| This is the main event-handler for the WM_SIZE event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMSizeProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if(ChatState.fMinimized && ChatState.fConnectPending && ChatState.fIsServer)
|
|
{
|
|
ChatState.fAllowAnswer = TRUE;
|
|
SetStatusWindowText(szConnecting);
|
|
|
|
|
|
// stop the ringing immediately.
|
|
//
|
|
KILLSOUND;
|
|
if(ChatState.fMMSound)
|
|
sndPlaySound(NULL,SND_ASYNC);
|
|
|
|
// cut the animation short.
|
|
//
|
|
if(cAnimate)
|
|
cAnimate = 1;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
InvalidateRect(hwnd,NULL,TRUE);
|
|
SendMessage(hwndToolbar,WM_SIZE,0,0L);
|
|
SendMessage(hwndStatus ,WM_SIZE,0,0L);
|
|
AdjustEditWindows();
|
|
|
|
ChatState.fMinimized = (wParam == SIZE_MINIMIZED) ? TRUE : FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION INITMENU PROCEDURE
|
|
| This is the main event-handler for the WM_INITMENU event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMInitMenuProc(HMENU hmenu)
|
|
{
|
|
UINT status;
|
|
LONG l;
|
|
TCHAR szTest[] = TEXT(" ");
|
|
DWORD dwTemp1,dwTemp2;
|
|
|
|
SendMessage(hwndActiveEdit,EM_GETSEL,(LPARAM)&dwTemp1,(WPARAM)&dwTemp2);
|
|
l = MAKELONG(dwTemp1,dwTemp2);
|
|
|
|
if(HIWORD(l) != LOWORD(l))
|
|
status = MF_ENABLED;
|
|
else
|
|
status = MF_GRAYED;
|
|
|
|
EnableMenuItem(hmenu,IDM_EDITCUT ,(hwndActiveEdit == hwndSnd && ChatState.fConnected) ? status : MF_GRAYED);
|
|
EnableMenuItem(hmenu,IDM_EDITCOPY,status);
|
|
|
|
status = MF_GRAYED;
|
|
if(hwndActiveEdit == hwndSnd && ChatState.fConnected && IsClipboardFormatAvailable(CF_TEXT))
|
|
{
|
|
status = MF_ENABLED;
|
|
}
|
|
EnableMenuItem(hmenu,IDM_EDITPASTE,status);
|
|
|
|
|
|
// select all enabled if control non-empty.
|
|
//
|
|
status = MF_GRAYED;
|
|
if(SendMessage(hwndActiveEdit,WM_GETTEXT,2,(LPARAM)szTest))
|
|
status = MF_ENABLED;
|
|
EnableMenuItem(hmenu,IDM_EDITSELECT,status);
|
|
|
|
|
|
// can we dial, answer and hangup.
|
|
//
|
|
EnableMenuItem(hmenu,IDM_DIAL ,(!ChatState.fConnected && !ChatState.fConnectPending) ? MF_ENABLED : MF_GRAYED);
|
|
EnableMenuItem(hmenu,IDM_ANSWER,(ChatState.fConnectPending && ChatState.fIsServer) ? MF_ENABLED : MF_GRAYED);
|
|
EnableMenuItem(hmenu,IDM_HANGUP,(ChatState.fConnected || ChatState.fConnectPending) ? MF_ENABLED : MF_GRAYED);
|
|
|
|
|
|
// Is toolbar, statusbar and sound allowed?
|
|
//
|
|
CheckMenuItem(hmenu,IDM_SOUND ,(ChatState.fSound) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hmenu,IDM_TOOLBAR ,(ChatState.fToolBar) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hmenu,IDM_STATUSBAR,(ChatState.fStatusBar) ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION SYSCOMMAND PROCEDURE
|
|
| This is the main event-handler for the WM_SYSCOMMAND event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
LRESULT appWMSysCommandProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT lResult;
|
|
HMENU hmenu;
|
|
|
|
|
|
lResult = 0l;
|
|
switch(wParam)
|
|
{
|
|
case IDM_TOPMOST:
|
|
ChatState.fTopMost = ChatState.fTopMost ? FALSE : TRUE;
|
|
|
|
hmenu = GetSystemMenu(hwnd,FALSE);
|
|
if(hmenu)
|
|
CheckMenuItem(hmenu,IDM_TOPMOST,(ChatState.fTopMost) ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
SetWindowPos(hwnd,ChatState.fTopMost ? HWND_TOPMOST : HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
break;
|
|
}
|
|
|
|
return(lResult);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION COMMAND PROCEDURE
|
|
| This is the main event-handler for the WM_COMMAND event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
BOOL appWMCommandProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc;
|
|
int tmp;
|
|
UINT uNotify;
|
|
DWORD dummy;
|
|
DWORD dwBufSize;
|
|
HDDEDATA hDdeData;
|
|
BOOL bHandled,bOK,bOKPressed=FALSE;
|
|
WPARAM wSelStart;
|
|
LPARAM lSelEnd;
|
|
|
|
|
|
bHandled = TRUE;
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case ID_EDITRCV:
|
|
uNotify = GET_EN_SETFOCUS_NOTIFY(wParam,lParam);
|
|
switch(uNotify)
|
|
{
|
|
case EN_SETFOCUS:
|
|
hwndActiveEdit = hwndRcv;
|
|
break;
|
|
|
|
|
|
// If the control is out of space, honk.
|
|
//
|
|
case EN_ERRSPACE:
|
|
MessageBeep(0);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
case ID_EDITSND:
|
|
uNotify = GET_EN_SETFOCUS_NOTIFY(wParam,lParam);
|
|
switch(uNotify)
|
|
{
|
|
// This string came from the edit-hook
|
|
// procedure.
|
|
//
|
|
case EN_DBCS_STRING:
|
|
if(ChatState.fConnected)
|
|
{
|
|
if(!ChatState.fIsServer)
|
|
{
|
|
hDdeData = CreateDbcsStringData();
|
|
if(hDdeData)
|
|
DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
|
|
}
|
|
else
|
|
{
|
|
hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
|
|
DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
// This character came from the edit-hook
|
|
// procedure.
|
|
//
|
|
case EN_CHAR:
|
|
if(ChatState.fConnected)
|
|
{
|
|
if(!ChatState.fIsServer)
|
|
{
|
|
hDdeData = CreateCharData();
|
|
if(hDdeData)
|
|
DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
|
|
}
|
|
else
|
|
{
|
|
hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
|
|
DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EN_PASTE:
|
|
if(ChatState.fConnected)
|
|
{
|
|
if(!ChatState.fIsServer)
|
|
{
|
|
if(IsClipboardFormatAvailable(CF_UNICODETEXT))
|
|
{
|
|
hDdeData = CreatePasteData();
|
|
if(hDdeData)
|
|
DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&StrXactID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
|
|
DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EN_SETFOCUS:
|
|
hwndActiveEdit = hwndSnd;
|
|
break;
|
|
|
|
case EN_ERRSPACE:
|
|
// If the control is out of space, honk.
|
|
//
|
|
MessageBeep(0);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
case IDC_TOOLBAR:
|
|
MenuHelp(WM_COMMAND,wParam,lParam,GetMenu(hwnd),hInst,hwndStatus,(LPUINT)nIDs);
|
|
break;
|
|
|
|
|
|
case IDM_EXIT:
|
|
SendMessage(hwnd,WM_CLOSE,0,0L);
|
|
break;
|
|
|
|
|
|
case IDM_TOOLBAR:
|
|
if(ChatState.fToolBar)
|
|
{
|
|
ChatState.fToolBar = FALSE;
|
|
ShowWindow(hwndToolbar,SW_HIDE);
|
|
InvalidateRect(hwnd,NULL,TRUE);
|
|
AdjustEditWindows();
|
|
}
|
|
else
|
|
{
|
|
ChatState.fToolBar = TRUE;
|
|
InvalidateRect(hwnd,NULL,TRUE);
|
|
AdjustEditWindows();
|
|
ShowWindow(hwndToolbar,SW_SHOW);
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_STATUSBAR:
|
|
if(ChatState.fStatusBar)
|
|
{
|
|
ChatState.fStatusBar = FALSE;
|
|
ShowWindow(hwndStatus,SW_HIDE);
|
|
InvalidateRect(hwnd,NULL,TRUE);
|
|
AdjustEditWindows();
|
|
}
|
|
else
|
|
{
|
|
ChatState.fStatusBar = TRUE;
|
|
InvalidateRect(hwnd,NULL,TRUE);
|
|
AdjustEditWindows();
|
|
ShowWindow(hwndStatus,SW_SHOW);
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_SWITCHWIN:
|
|
if(hwndActiveEdit == hwndSnd)
|
|
SetFocus(hwndActiveEdit = hwndRcv);
|
|
else
|
|
SetFocus(hwndActiveEdit = hwndSnd);
|
|
break;
|
|
|
|
|
|
case IDM_SOUND:
|
|
ChatState.fSound = ChatState.fSound ? FALSE : TRUE;
|
|
break;
|
|
|
|
|
|
case IDM_COLOR:
|
|
SetFocus(hwndActiveEdit);
|
|
chc.rgbResult = SndBrushColor;
|
|
|
|
tmp = ChooseColor((LPCHOOSECOLOR)&chc);
|
|
if(tmp)
|
|
{
|
|
hdc = GetDC(hwnd);
|
|
if(hdc)
|
|
{
|
|
// must map to solid color (edit-control limitation).
|
|
//
|
|
SndBrushColor = GetNearestColor(hdc,chc.rgbResult);
|
|
ReleaseDC(hwnd,hdc);
|
|
}
|
|
|
|
DeleteObject(hEditSndBrush);
|
|
hEditSndBrush = CreateSolidBrush(SndBrushColor);
|
|
InvalidateRect(hwndSnd,NULL,TRUE);
|
|
|
|
SaveBkGndToIni();
|
|
|
|
if(ChatState.fUseOwnFont)
|
|
{
|
|
RcvBrushColor = SndBrushColor;
|
|
DeleteObject(hEditRcvBrush);
|
|
hEditRcvBrush = CreateSolidBrush(RcvBrushColor);
|
|
InvalidateRect(hwndRcv, NULL, TRUE);
|
|
}
|
|
|
|
if(ChatState.fConnected)
|
|
SendFontToPartner();
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_FONT:
|
|
SetFocus(hwndActiveEdit);
|
|
chf.hwndOwner = hwndSnd;
|
|
chf.rgbColors = SndColorref;
|
|
|
|
tmp = ChooseFont((LPCHOOSEFONT)&chf);
|
|
if(tmp)
|
|
{
|
|
if(hEditSndFont)
|
|
DeleteObject(hEditSndFont);
|
|
|
|
hEditSndFont = CreateFontIndirect((LPLOGFONT)&lfSnd);
|
|
if(hEditSndFont)
|
|
{
|
|
SndColorref = chf.rgbColors;
|
|
SaveFontToIni();
|
|
|
|
SendMessage(hwndSnd,WM_SETFONT,(WPARAM)hEditSndFont,1L);
|
|
if(ChatState.fUseOwnFont)
|
|
{
|
|
SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditSndFont,1L);
|
|
RcvColorref = SndColorref;
|
|
}
|
|
|
|
|
|
// notify partner of the change
|
|
//
|
|
if(ChatState.fConnected)
|
|
SendFontToPartner();
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_DIAL:
|
|
if(ChatState.fConnected)
|
|
{
|
|
SetStatusWindowText(szAlreadyConnect);
|
|
break;
|
|
}
|
|
|
|
if(ChatState.fConnectPending)
|
|
{
|
|
SetStatusWindowText ( szAbandonFirst);
|
|
break;
|
|
}
|
|
|
|
dwBufSize = SZBUFSIZ;
|
|
|
|
WNETGETUSER((LPTSTR)NULL,(LPTSTR)szBuf,&dwBufSize);
|
|
|
|
if(GetLastError() == ERROR_NO_NETWORK)
|
|
{
|
|
if(MessageBox(hwnd,szNoNet,TEXT("Chat"),MB_YESNO | MB_ICONQUESTION) == IDNO)
|
|
break;
|
|
}
|
|
|
|
|
|
ChatState.fInProcessOfDialing = TRUE;
|
|
if(WNetServerBrowseDialog == NULL || (*WNetServerBrowseDialog)(hwnd,TEXT("MRU_Chat"),szBuf,SZBUFSIZ,0L) == WN_NOT_SUPPORTED)
|
|
{
|
|
#if WIN32
|
|
bOKPressed = FALSE;
|
|
*szBuf = TEXT('\0');
|
|
|
|
|
|
StringCchCopy(szHelp, SZBUFSIZ, TEXT("winchat.hlp"));
|
|
I_SystemFocusDialog(hwnd,MY_LOGONTYPE,(LPWSTR)szBuf,SZBUFSIZ,&bOKPressed,(LPWSTR)szHelp,IDH_SELECTCOMPUTER);
|
|
|
|
if(bOKPressed)
|
|
{
|
|
bOK = TRUE;
|
|
StringCchCopy(szConvPartner, UNCNLEN, szBuf);
|
|
}
|
|
#else
|
|
dlgDisplayBox(hInst,hwnd,(LPSTR)MAKEINTRESOURCE(IDD_CONNECT),dlgConnectProc,0l);
|
|
#endif
|
|
}
|
|
|
|
SetFocus(hwndActiveEdit);
|
|
|
|
if(*szBuf && bOKPressed)
|
|
{
|
|
CharUpper(szBuf);
|
|
|
|
if((lstrlen(szBuf) > 2) && (szBuf[0] == TEXT('\\')) && (szBuf[1] == TEXT('\\')))
|
|
StringCchCopy(szConvPartner, UNCNLEN, szBuf+2);
|
|
else
|
|
StringCchCopy(szConvPartner, UNCNLEN, szBuf);
|
|
|
|
ClearEditControls();
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ,szDialing,(LPSTR)szConvPartner);
|
|
SetStatusWindowText(szBuf);
|
|
|
|
#if TESTLOCAL
|
|
StringCchPrintf(szBuf, SZBUFSIZ,TEXT("%s"),(LPTSTR)szServiceName);
|
|
hszConnect = DdeCreateStringHandle(idInst,szBuf,0);
|
|
ghConv = DdeConnect(idInst,hszConnect,hszChatTopic,NULL);
|
|
#else
|
|
StringCchPrintf(szBuf, SZBUFSIZ,TEXT("\\\\%s\\NDDE$"),(LPTSTR)szConvPartner);
|
|
hszConnect = DdeCreateStringHandle(idInst,szBuf,0);
|
|
ghConv = DdeConnect(idInst,hszConnect,hszChatShare,NULL);
|
|
#endif
|
|
|
|
if(ghConv == (HCONV)0)
|
|
{
|
|
SetStatusWindowText(szNoConnect);
|
|
DdeFreeStringHandle(idInst,hszConnect);
|
|
ChatState.fInProcessOfDialing = FALSE;
|
|
break;
|
|
}
|
|
|
|
ChatState.fConnectPending = TRUE;
|
|
UpdateButtonStates();
|
|
|
|
// set up server verify async xaction.
|
|
//
|
|
ChatState.fServerVerified = FALSE;
|
|
DdeKeepStringHandle(idInst,hszConnectTest);
|
|
DdeClientTransaction(NULL,0L,ghConv,hszConnectTest,cf_chatdata,XTYP_ADVSTART,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&XactID);
|
|
|
|
|
|
// Indicate that this is a Unicode conversation.
|
|
//
|
|
ChatData.type = CHT_UNICODE;
|
|
hDdeData = CreateCharData ();
|
|
if(hDdeData)
|
|
DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
|
|
|
|
|
|
// set ring timer...
|
|
// connect attempts every second - will be divided by
|
|
// 6 for actual phone rings. This is done to speed the
|
|
// connection process
|
|
// want first message immediately...
|
|
//
|
|
idTimer = SetTimer(hwnd,1,1000,NULL);
|
|
PostMessage(hwnd,WM_TIMER,1,0L);
|
|
nConnectAttempt = 0;
|
|
}
|
|
|
|
ChatState.fInProcessOfDialing = FALSE;
|
|
DdeFreeStringHandle(idInst,hszConnect);
|
|
break;
|
|
|
|
|
|
case IDM_ANSWER:
|
|
if(ChatState.fConnectPending)
|
|
{
|
|
if(!ChatState.fIsServer)
|
|
{
|
|
SetStatusWindowText(szYouCaller);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// allow the connection.
|
|
//
|
|
ChatState.fAllowAnswer = TRUE;
|
|
SetStatusWindowText(szConnecting);
|
|
|
|
|
|
// stop the ringing immediately.
|
|
//
|
|
if(ChatState.fMMSound)
|
|
sndPlaySound(NULL,SND_ASYNC);
|
|
|
|
|
|
// cut the animation short.
|
|
//
|
|
if(cAnimate)
|
|
cAnimate = 1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_HANGUP:
|
|
if(!ChatState.fConnected && !ChatState.fConnectPending)
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
if(ChatState.fConnectPending && !ChatState.fConnected)
|
|
{
|
|
SetStatusWindowText(szConnectAbandon);
|
|
}
|
|
else
|
|
{
|
|
SetStatusWindowText(szHangingUp);
|
|
}
|
|
|
|
|
|
KILLSOUND;
|
|
|
|
DdeDisconnect(ghConv);
|
|
|
|
ChatState.fConnectPending = FALSE;
|
|
ChatState.fConnected = FALSE;
|
|
ChatState.fIsServer = FALSE;
|
|
ChatState.fUnicode = FALSE;
|
|
|
|
#ifdef PROTOCOL_NEGOTIATE
|
|
ChatState.fProtocolSent = FALSE;
|
|
#endif
|
|
|
|
// suspend text entry.
|
|
//
|
|
UpdateButtonStates();
|
|
SendMessage(hwndSnd,EM_SETREADONLY,TRUE,0L);
|
|
SetWindowText(hwndApp,szAppName);
|
|
break;
|
|
|
|
|
|
case IDX_UNICODECONV:
|
|
ChatData.type = CHT_UNICODE;
|
|
hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
|
|
DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
|
|
break;
|
|
|
|
|
|
case IDX_DEFERFONTCHANGE:
|
|
SendFontToPartner();
|
|
break;
|
|
|
|
#ifdef PROTOCOL_NEGOTIATE
|
|
case IDX_DEFERPROTOCOL:
|
|
AnnounceSupport();
|
|
break;
|
|
#endif
|
|
|
|
case IDM_CONTENTS:
|
|
HtmlHelpA(GetDesktopWindow(),"winchat.chm",HH_DISPLAY_TOPIC,0L);
|
|
break;
|
|
|
|
|
|
case IDM_ABOUT:
|
|
ShellAbout(hwndSnd,szAppName,szNull,hPhones[0]);
|
|
SetFocus(hwndActiveEdit);
|
|
break;
|
|
|
|
|
|
case IDM_PREFERENCES:
|
|
DialogBoxParam(hInst,(LPTSTR)MAKEINTRESOURCE(IDD_PREFERENCES),hwnd,dlgPreferencesProc,(LPARAM)0);
|
|
break;
|
|
|
|
|
|
case IDM_EDITCOPY:
|
|
SendMessage(hwndActiveEdit,WM_COPY,0,0L);
|
|
break;
|
|
|
|
|
|
case IDM_EDITPASTE:
|
|
SendMessage(hwndActiveEdit,WM_PASTE,0,0L);
|
|
break;
|
|
|
|
|
|
case IDM_EDITCUT:
|
|
SendMessage(hwndActiveEdit,WM_CUT,0,0L);
|
|
break;
|
|
|
|
|
|
case IDM_EDITSELECT:
|
|
wSelStart = SET_EM_SETSEL_WPARAM(0,-1);
|
|
lSelEnd = SET_EM_SETSEL_LPARAM(0,-1);
|
|
SendMessage(hwndActiveEdit,EM_SETSEL,wSelStart,lSelEnd);
|
|
break;
|
|
|
|
|
|
case IDM_EDITUNDO:
|
|
SendMessage(hwndActiveEdit,EM_UNDO,0,0L);
|
|
break;
|
|
|
|
|
|
default:
|
|
bHandled = FALSE;
|
|
break;
|
|
}
|
|
|
|
return(bHandled);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| APPLICATION DESTROY PROCEDURE
|
|
| This is the main event-handler for the WM_DESTROY event.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID appWMDestroyProc(HWND hwnd)
|
|
{
|
|
|
|
// Abandon transaction if in progress. Force hangup
|
|
// of conversation.
|
|
//
|
|
if(!ChatState.fServerVerified)
|
|
DdeAbandonTransaction(idInst,ghConv,XactID);
|
|
SendMessage(hwnd,WM_COMMAND,IDM_HANGUP,0L);
|
|
|
|
|
|
// Destroy resources allocated on behalf of app.
|
|
//
|
|
KILLSOUND;
|
|
DeleteTools(hwnd);
|
|
|
|
|
|
// Save the state information.
|
|
//
|
|
Wpl.length = sizeof(Wpl);
|
|
if(GetWindowPlacement(hwnd,&Wpl))
|
|
SaveWindowPlacement(&Wpl);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%d"), (UINT)ChatState.fSound);
|
|
WritePrivateProfileString(szPref, szSnd, szBuf, szIni);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%d"), (UINT)ChatState.fToolBar);
|
|
WritePrivateProfileString(szPref, szTool, szBuf, szIni);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%d"), (UINT)ChatState.fStatusBar);
|
|
WritePrivateProfileString(szPref, szStat, szBuf, szIni);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%d"), (UINT)ChatState.fTopMost);
|
|
WritePrivateProfileString(szPref, szTop, szBuf, szIni);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%d"), (UINT)ChatState.fSideBySide);
|
|
WritePrivateProfileString(szPref, szSbS, szBuf, szIni);
|
|
|
|
StringCchPrintf(szBuf, SZBUFSIZ, TEXT("%d"), (UINT)ChatState.fUseOwnFont);
|
|
WritePrivateProfileString(szPref, szUseOF, szBuf, szIni);
|
|
|
|
PostQuitMessage(0);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| ASCII TO LONG
|
|
| This routine converts an ascii string to long.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
LONG FAR myatol(LPTSTR s)
|
|
{
|
|
LONG ret = 0L;
|
|
|
|
|
|
while(*s) ret = ret * 10 + (*s++ - TEXT('0'));
|
|
|
|
return(ret);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| UPDATE BUTTON STATES
|
|
| This routine updates the menu/toolbar buttons.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID FAR UpdateButtonStates(VOID)
|
|
{
|
|
BOOL DialState = FALSE;
|
|
BOOL AnswerState = FALSE;
|
|
BOOL HangUpState = FALSE;
|
|
|
|
|
|
if(ChatState.fConnected)
|
|
HangUpState = TRUE;
|
|
else
|
|
if(ChatState.fConnectPending)
|
|
{
|
|
if(!ChatState.fIsServer)
|
|
HangUpState = TRUE;
|
|
else
|
|
AnswerState = TRUE;
|
|
}
|
|
else
|
|
DialState = TRUE;
|
|
|
|
SendMessage(hwndToolbar,TB_ENABLEBUTTON,IDM_DIAL ,DialState);
|
|
SendMessage(hwndToolbar,TB_ENABLEBUTTON,IDM_ANSWER,AnswerState);
|
|
SendMessage(hwndToolbar,TB_ENABLEBUTTON,IDM_HANGUP,HangUpState);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| GET COMPUTER NAME
|
|
| This routine returns the computer name of the machine.
|
|
|
|
|
| created: 31-Dec-92
|
|
| history: 31-Dec-92 <chriswil> created.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
BOOL FAR appGetComputerName(LPTSTR lpszName)
|
|
{
|
|
BOOL bGet;
|
|
DWORD dwSize;
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
dwSize = MAX_COMPUTERNAME_LENGTH+1;
|
|
bGet = GetComputerName(lpszName,&dwSize);
|
|
|
|
#else
|
|
|
|
bGet = TRUE;
|
|
dwSize = 0l;
|
|
if(GetPrivateProfileString(szVredir,szComputerName,szNull,lpszName,UNCNLEN,szSysIni))
|
|
OemToAnsi(lpszName,lpszName);
|
|
|
|
#endif
|
|
|
|
return(bGet);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| ADJUST EDIT WINDOWS
|
|
| This routine sizes the edit-controls.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID FAR AdjustEditWindows(VOID)
|
|
{
|
|
int tmpsplit;
|
|
RECT rc;
|
|
|
|
|
|
GetClientRect(hwndApp,&rc);
|
|
|
|
rc.top += ChatState.fToolBar ? dyButtonBar + BRD : BRD;
|
|
rc.bottom -= ChatState.fStatusBar ? dyStatus + BRD : BRD;
|
|
|
|
if(!ChatState.fSideBySide)
|
|
{
|
|
tmpsplit = rc.top + (rc.bottom - rc.top) / 2;
|
|
|
|
SndRc.left = RcvRc.left = rc.left - 1 + BRD;
|
|
SndRc.right = RcvRc.right = rc.right + 1 - BRD;
|
|
SndRc.top = rc.top;
|
|
SndRc.bottom = tmpsplit;
|
|
RcvRc.top = tmpsplit + BRD;
|
|
RcvRc.bottom = rc.bottom;
|
|
}
|
|
else
|
|
{
|
|
tmpsplit = rc.left + (rc.right - rc.left) / 2;
|
|
|
|
SndRc.left = rc.left - 1 + BRD;
|
|
SndRc.right = tmpsplit - BRD / 2;
|
|
RcvRc.left = tmpsplit + BRD / 2;
|
|
RcvRc.right = rc.right + 1 - BRD;
|
|
SndRc.top = RcvRc.top = rc.top;
|
|
SndRc.bottom = RcvRc.bottom = rc.bottom;
|
|
|
|
}
|
|
|
|
MoveWindow(hwndSnd,SndRc.left,SndRc.top,SndRc.right-SndRc.left,SndRc.bottom-SndRc.top,TRUE);
|
|
MoveWindow(hwndRcv,RcvRc.left,RcvRc.top,RcvRc.right-RcvRc.left,RcvRc.bottom-RcvRc.top,TRUE);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| CLEAR EDIT CONTROLS
|
|
| This routine clears the send/receive edit controls.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID ClearEditControls(VOID)
|
|
{
|
|
SendMessage(hwndSnd,EM_SETREADONLY,FALSE,0L);
|
|
SendMessage(hwndSnd,WM_SETTEXT ,0 ,(LPARAM)(LPSTR)szNull);
|
|
SendMessage(hwndSnd,EM_SETREADONLY,TRUE ,0L);
|
|
|
|
SendMessage(hwndRcv,EM_SETREADONLY,FALSE,0L);
|
|
SendMessage(hwndRcv,WM_SETTEXT ,0 ,(LPARAM)(LPSTR)szNull);
|
|
SendMessage(hwndRcv,EM_SETREADONLY,TRUE ,0L);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| DO RING
|
|
| This routine performs the phone ringing.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID DoRing(LPCTSTR sound)
|
|
{
|
|
if(ChatState.fSound)
|
|
{
|
|
if(ChatState.fMMSound)
|
|
sndPlaySound(sound,SND_ASYNC);
|
|
else
|
|
MessageBeep(0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| DRAW SHADOW RECT
|
|
| This routine draws a shadow outline.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID DrawShadowRect(HDC hdc, LPRECT rc)
|
|
{
|
|
HPEN hSavePen = SelectObject(hdc,hShadowPen);
|
|
|
|
|
|
MoveToEx(hdc,rc->left,rc->bottom,NULL);
|
|
LineTo(hdc,rc->left,rc->top );
|
|
LineTo(hdc,rc->right,rc->top );
|
|
SelectObject(hdc,hHilitePen);
|
|
LineTo(hdc,rc->right,rc->bottom);
|
|
LineTo(hdc,rc->left-1,rc->bottom);
|
|
SelectObject(hdc,hSavePen);
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef PROTOCOL_NEGOTIATE
|
|
/*---------------------------------------------------------------------------*\
|
|
| ANNOUNCE SUPPORT
|
|
| This routine announces to the partner what we support.
|
|
|
|
|
| created: 11-Nov-91
|
|
| history: 29-Dec-92 <chriswil> ported to NT.
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID AnnounceSupport(VOID)
|
|
{
|
|
HDDEDATA hDdeData;
|
|
DWORD dummy;
|
|
|
|
|
|
if(ChatState.fConnected)
|
|
{
|
|
ChatData.type = CHT_PROTOCOL;
|
|
|
|
if(!ChatState.fIsServer)
|
|
{
|
|
hDdeData = CreateProtocolData();
|
|
if(hDdeData)
|
|
DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1L,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
|
|
}
|
|
else
|
|
{
|
|
hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
|
|
if(hszConvPartner)
|
|
DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
|
|
}
|
|
|
|
ChatState.fProtocolSent = TRUE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| START INI-FILE MAPPING
|
|
| This routines sets the private-profile settings to go to the registry on\
|
|
| a per-user basis.
|
|
|
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID StartIniMapping(VOID)
|
|
{
|
|
HKEY hKey1,hKey2,hKey3,hKeySnd;
|
|
DWORD dwDisp,dwSize;
|
|
|
|
|
|
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,szIniSection,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey1,&dwDisp) == ERROR_SUCCESS)
|
|
{
|
|
if(dwDisp == REG_CREATED_NEW_KEY)
|
|
{
|
|
RegSetValueEx(hKey1,TEXT("Preferences"),0,REG_SZ,(LPBYTE)szIniKey1,ByteCountOf(lstrlen(szIniKey1)+1));
|
|
RegSetValueEx(hKey1,TEXT("Font") ,0,REG_SZ,(LPBYTE)szIniKey2,ByteCountOf(lstrlen(szIniKey2)+1));
|
|
}
|
|
|
|
if(RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\Microsoft\\Winchat"),0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey1,&dwDisp) == ERROR_SUCCESS)
|
|
{
|
|
if(dwDisp == REG_CREATED_NEW_KEY)
|
|
{
|
|
RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\Microsoft\\Winchat\\Preferences"),0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey2,&dwDisp);
|
|
RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\Microsoft\\Winchat\\Font") ,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey3,&dwDisp);
|
|
|
|
RegCloseKey(hKey2);
|
|
RegCloseKey(hKey3);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey1);
|
|
}
|
|
|
|
|
|
// The sndPlaySound() first looks in the registry for the wav-files. The
|
|
// NT version doesn't have these here at setup, so Winchat will write out
|
|
// the defaults when the strings don't exist. This will allow uses to change
|
|
// sounds for ringing-in and ringing-out.
|
|
//
|
|
if(RegOpenKeyEx(HKEY_CURRENT_USER,TEXT("Control Panel\\Sounds"),0,KEY_WRITE | KEY_QUERY_VALUE,&hKeySnd) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = 0;
|
|
dwDisp = REG_SZ;
|
|
if(RegQueryValueEx(hKeySnd,TEXT("RingIn"),NULL,&dwDisp,NULL,&dwSize) != ERROR_SUCCESS)
|
|
{
|
|
if(dwSize == 0)
|
|
{
|
|
// Set the wav-file values. Add (1) extra count to account for the null
|
|
// terminator.
|
|
//
|
|
RegSetValueEx(hKeySnd,TEXT("RingIn") ,0,REG_SZ,(LPBYTE)szIniRingIn ,ByteCountOf(lstrlen(szIniRingIn)+1));
|
|
RegSetValueEx(hKeySnd,TEXT("RingOut"),0,REG_SZ,(LPBYTE)szIniRingOut,ByteCountOf(lstrlen(szIniRingOut)+1));
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeySnd);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
| END INI-FILE MAPPING
|
|
| This routines ends the ini-file mapping. It doesn't do anything at this
|
|
| point, but I've kept it in for some reason.
|
|
|
|
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
VOID EndIniMapping(VOID)
|
|
{
|
|
return;
|
|
}
|