2020-09-30 17:12:29 +02:00

2072 lines
51 KiB
C

/****************************************************************************
PROGRAM: WinVTP.c
PURPOSE: WinVTP template for Windows applications
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
COMMENTS:
Windows can have several copies of your application running at the
same time. The variable hInst keeps track of which instance this
application is so that processing will be to the correct window.
TABS:
Set for 4 spaces.
****************************************************************************/
#include <windows.h> /* required for all Windows applications */
#include <commdlg.h>
#include <stdlib.h>
#include "NetBIOS.h"
#include "netobj.h"
#include "WinVTP.h" /* specific to this program */
#include "winvtpsz.h"
/* Typedef for the ShellAbout function */
typedef void (WINAPI *LPFNSHELLABOUT)(HWND, LPTSTR, LPTSTR, HICON);
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
COMMENTS:
Windows recognizes this function by name as the initial entry point
for the program. This function calls the application initialization
routine, if no other instance of the program is running, and always
calls the instance initialization routine. It then executes a message
retrieval and dispatch loop that is the top-level control structure
for the remainder of execution. The loop is terminated when a WM_QUIT
message is received, at which time this function exits the application
instance by returning the value passed by PostQuitMessage().
If this function must abort before entering the message loop, it
returns the conventional value NULL.
****************************************************************************/
int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
if ( !hPrevInstance )
{
if ( !FInitApplication(hInstance) )
return (FALSE);
}
/* Perform initializations that apply to a specific instance */
if ( !FInitInstance(hInstance, nCmdShow) )
return (FALSE);
/* Acquire and dispatch messages until a WM_QUIT message is received. */
while ( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (msg.wParam); /* Returns the value from PostQuitMessage */
}
/****************************************************************************
FUNCTION: FInitApplication(HINSTANCE)
PURPOSE: Initializes window data and registers window class
COMMENTS:
This function is called at initialization time only if no other
instances of the application are running. This function performs
initialization tasks that can be done once for any number of running
instances.
In this case, we initialize a window class by filling out a data
structure of type WNDCLASS and calling the Windows RegisterClass()
function. Since all instances of this application use the same window
class, we only need to do this when the first instance is initialized.
****************************************************************************/
BOOL
FInitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
rgchHostName[0] = '\0';
if (__argc > 1)
{
memcpy(rgchHostName, __argv[1], min(lstrlen(__argv[1]), cchMaxHostName-1));
rgchHostName[cchMaxHostName-1] = '\0';
}
/* Fill in window class structure with parameters that describe the
* main window.
*/
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(HANDLE)+sizeof(SVI *);
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, szAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground= NULL;
wc.lpszMenuName = szMenuName;
wc.lpszClassName= szClassName;
/* Register the window class and return success/failure code. */
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: FInitInstance(HINSTANCE, int)
PURPOSE: Saves instance handle and creates main window
COMMENTS:
This function is called at initialization time for every instance of
this application. This function performs initialization tasks that
cannot be shared by multiple instances.
In this case, we save the instance handle in a static variable and
create and display the main program window.
****************************************************************************/
BOOL
FInitInstance(HINSTANCE hInstance, int nCmdShow)
{
/* Set the default user settings */
memset(&ui, 0, sizeof(UI));
ui.lf.lfCharSet = ANSI_CHARSET;
ui.lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
ui.lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
ui.lf.lfQuality = DEFAULT_QUALITY;
ui.lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
lstrcpy(ui.lf.lfFaceName, szDefaultFont);
ui.dwMaxRow = 25;
ui.dwMaxCol = 80;
ui.dwTop = (DWORD)CW_USEDEFAULT;
ui.dwLeft = (DWORD)CW_USEDEFAULT;
ui.clrBk = RGB(0, 0, 0); /* Black */
ui.clrText = RGB(255, 255, 255); /* White */
ui.dwRetrySeconds = dwRetrySecondsDefault;
/* N.B. Don't need to init the strings since the memset() call
* takes care of that
*/
/* Get any user settings */
GetUserSettings(hInstance, &ui);
/*
* If XNS isn't available, check to see if it's available now
* and enable the use of XNS if it is available.
*/
if (!(ui.fXNS & fdwXNSAvailable) && FIsXenixAvailable())
{
ui.fXNS = fdwXNSConnect;
}
/* Set which menu has the list of most-recently used machines */
imenuMRU = (ui.fXNS & fdwXNSAvailable) ? imenuMachine : imenuFile;
/* Save the instance handle in static variable, which will be used in
* many subsequent calls from this application to Windows.
*/
/* Create a main window for this application instance. */
hwndMain = CreateWindow(szClassName, szTitleNone,
WS_OVERLAPPEDWINDOW | WS_POPUP | WS_HSCROLL | WS_VSCROLL ,
ui.dwLeft, ui.dwTop, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if ( !hwndMain )
return (FALSE);
/* Make the window visible; update its client area; and return "success" */
ShowWindow(hwndMain, nCmdShow);
UpdateWindow( hwndMain );
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages
COMMENTS:
To process the IDM_ABOUT message, call MakeProcInstance() to get the
current instance address of the About() function. Then call Dialog
box which will create the box according to the information in your
WinVTP.rc file and turn control over to the About() function. When
it returns, free the intance address.
****************************************************************************/
LONG FAR PASCAL
MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HANDLE hInst = NULL;
static BOOL fInited = FALSE;
static WI *pwi = NULL;
static HMENU hSavedMenu = NULL;
DWORD i;
DWORD j;
HMENU hmenu;
BOOL fRet = FALSE;
int iMinPos, iMaxPos;
switch ( message )
{
case WM_CREATE:
hInst = ((LPCREATESTRUCT)lParam)->hInstance;
fHungUp = FALSE;
hfontDisplay = CreateFontIndirect( &ui.lf );
aixPos = LocalAlloc(LPTR, sizeof(DWORD)*(1+ui.dwMaxCol));
aiyPos = LocalAlloc(LPTR, sizeof(DWORD)*(1+ui.dwMaxRow));
apcRows = LocalAlloc(LPTR, sizeof(UCHAR *)*ui.dwMaxRow);
pchNBBuffer = LocalAlloc(LPTR, sizeof(UCHAR)*DATA_BUF_SZ);
rgchRowEmpty = LocalAlloc(LPTR, sizeof(UCHAR) * 2 * ui.dwMaxCol);
pwi = LocalAlloc(LPTR, sizeof(WI));
if ((hfontDisplay == NULL) || (aixPos == NULL) || (aiyPos == NULL) ||
(apcRows == NULL) || (pchNBBuffer == NULL) ||
(rgchRowEmpty == NULL) || (pwi == NULL))
{
DestroyWindow( hwnd );
break;
}
memset(rgchRowEmpty, ' ', sizeof(UCHAR)*ui.dwMaxCol);
SetWindowLong(hwnd, WL_VTPWI, (LONG)pwi);
pwi->trm.puchCharSet = rgchNormalChars;
pwi->trm.uTimer = SetTimer(hwnd, uTerminalTimerID,
uCursorBlinkMsecs, NULL);
pwi->cf.lStructSize = sizeof(pwi->cf);
pwi->cf.hwndOwner = hwnd;
pwi->cf.hDC = NULL;
pwi->cf.lpLogFont = &ui.lf;
pwi->cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
pwi->cf.nFontType = SCREEN_FONTTYPE;
for (i=0; i<ui.dwMaxRow; ++i)
{
if (apcRows[i] = LocalAlloc(LPTR, sizeof(UCHAR)*2*ui.dwMaxCol))
memcpy(apcRows[i], rgchRowEmpty, sizeof(UCHAR)*2*ui.dwMaxCol);
else
break;
}
if (i != ui.dwMaxRow)
{
DestroyWindow( hwnd );
break;
}
RecalcWindowSize( hwnd );
SetDisplaySize(hwnd, ui.dwMaxRow, &pwi->trm.dwCurLine);
DoTermReset(hwnd, &pwi->trm, NULL);
if (pwi->nd.lpReadBuffer = LocalAlloc(LPTR, sizeof(UCHAR)*READ_BUF_SZ))
{
pwi->nd.SessionNumber = nSessionNone;
pwi->nd.iHead = 0;
pwi->nd.iTail = 1;
fRet = TRUE;
}
else
{
DestroyWindow( hwnd );
break;
}
hmenu = GetMenu( hwnd );
if (ui.fXNS & fdwXNSAvailable)
{
CheckMenuItem(hmenu, IDM_SMOOTHSCROLL,
ui.fSmoothScroll ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_NODOWNLOADPROMPT,
(ui.fPrompt & fdwSuppressDestDirPrompt)
? MF_CHECKED : MF_UNCHECKED);
/* spell words correctly... */
ModifyMenu(hmenu, IDM_TEXTCOLOUR, MF_BYCOMMAND, IDM_TEXTCOLOUR,
szTextColour);
ModifyMenu(hmenu, IDM_BACKCOLOUR, MF_BYCOMMAND, IDM_BACKCOLOUR,
szBackgroundColour);
}
else
{
ui.fSmoothScroll = TRUE;
DeleteMenu(hmenu, IDM_SMOOTHSCROLL, MF_BYCOMMAND);
DeleteMenu(hmenu, IDM_NODOWNLOADPROMPT, MF_BYCOMMAND);
DeleteMenu(hmenu, imenuMachine, MF_BYPOSITION);
}
// propogate old binary ConnectLost state to new way
if (ui.fPrompt &fdwNoConnectLostDlg)
SetConnectLostMode(ui, IDM_CONNECTLOSTDLG);
ui.fPrompt &= ~fdwNoConnectLostDlg;
CheckMenuItem(hmenu, ConnectLostMode(ui), MF_CHECKED);
CheckMenuItem(hmenu, IDM_CONNECTLOSTRETRY, MF_GRAYED);
CheckMenuItem(hmenu, IDM_AUTOFONTS,
(ui.fPrompt & fdwAutoFonts)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_NOCONNECTRETRYDLG,
(ui.fPrompt & fdwNoConnectRetryDlg)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_LOCALECHO,
(ui.fDebug & fdwLocalEcho)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_UNDERLINECURSOR,
(ui.fCursorEdit & fdwCursorUnderline)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_BLINKCURSOR,
(ui.fCursorEdit & fdwCursorBlink)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_QUICKEDIT,
(ui.fCursorEdit & fdwQuickEditMode)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_TRIMSPACE,
(ui.fCursorEdit & fdwTrimEndWhitespace)
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_VT100CURSORKEYS,
(ui.fDebug & fdwVT100CursorKeys)
? MF_CHECKED : MF_UNCHECKED);
#ifdef VT52
CheckMenuItem(hmenu, IDM_VT52MODE,
(ui.fDebug & fdwVT52Mode)
? MF_CHECKED : MF_UNCHECKED);
#endif
if (ui.fDebug & fdwVT100CursorKeys)
{
ClearVTArrow(&pwi->trm);
}
else
{
SetVTArrow(&pwi->trm);
}
#ifdef VT52
if (ui.fDebug & fdwVT52Mode)
{
SetVT52(&pwi->trm);
}
else
{
ClearVT52(&pwi->trm);
}
#endif /* VT52 */
/* Append the most recently connected machines to the Machine menu */
hmenu = HmenuGetMRUMenu(hwnd, &ui);
/*
* If XNS isn't available, then the MRUMenu will be the File menu,
* since it doesn't have a menu separator after the Exit menu
* item, we need to add one now.
*/
if ( !(ui.fXNS & fdwXNSAvailable) )
{
AppendMenu(hmenu, MF_SEPARATOR, 0, 0);
}
for (i=0; i<ui.cMachines; ++i)
{
wsprintf(pchNBBuffer, szMachineMenuItem, i+1,
ui.rgchMachine[i]);
AppendMenu(hmenu, MF_ENABLED | MF_STRING, IDM_MACHINE1+i,
pchNBBuffer);
}
hmenu = GetSystemMenu(hwnd, FALSE);
/* Stick in the cascading Edit menu into the System menu */
AppendMenu(hmenu, MF_POPUP | MF_ENABLED | MF_STRING,
(UINT)GetSubMenu(GetMenu(hwnd), imenuEdit), szEditMenu);
AppendMenu(hmenu, MF_ENABLED | MF_STRING, IDM_HIDEMENU, "&HideMenu");
DrawMenuBar( hwnd );
/*
* If the user passed a host to connect to on the cmd line
* send a message to try and connect, otherwise just make
* a copy of the last machine connected to in the last session
*/
if ( rgchHostName[0] )
{
PostMessage(hwnd, NM_CONNECT, 0, 0);
}
else
{
lstrcpy(rgchHostName, ui.rgchLastMachine);
}
fInited = TRUE;
break;
case WM_INITMENUPOPUP:
if (hmenu = GetMenu(hwnd))
hmenu = GetSubMenu(hmenu, imenuEdit);
/*
* If the menu being popped up is the Edit menu,
* either the one in the System menu or the one
* from the main menu bar, update its menu items
* accordingly.
*/
if (hmenu == (HMENU)wParam)
{
/* Enable only if we're not downloading via sendvtp */
EnableMenuItem(hmenu, IDM_MARK,
MF_BYCOMMAND |
((pwi->svi.hthread == NULL) ? MF_ENABLED : MF_GRAYED));
/* Enable only if an area has been selected */
EnableMenuItem(hmenu, IDM_COPY,
MF_BYCOMMAND |
(FSelected(pwi->spb) ? MF_ENABLED : MF_GRAYED));
/*
* Enable only if there's CF_TEXT in the clipboard
* and we're connected to a machine (the data has
* to go somewhere) and we're not downloading
* anything via sendvtp and we're not in Mark mode.
*/
EnableMenuItem(hmenu, IDM_PASTE,
MF_BYCOMMAND |
(FCanPaste(pwi) ? MF_ENABLED : MF_GRAYED));
/* Enable only if we're doing delayed pasting */
EnableMenuItem(hmenu, IDM_STOPPASTE,
MF_BYCOMMAND |
((szTextPaste != NULL) ? MF_ENABLED : MF_GRAYED));
}
else
{
goto defresp;
}
break;
case WM_SYSCOMMAND:
/* Handle the Edit menu items from the System menu */
i = LOWORD(wParam);
switch(i)
{
default:
goto defresp;
case IDM_MARK:
case IDM_COPY:
case IDM_PASTE:
case IDM_HIDEMENU:
break;
}
/* fall through */
case WM_COMMAND: /* message: command from application menu */
switch( LOWORD(wParam) )
{
case IDM_CONNECT:
if ( DialogBox(hInst,
(ui.fXNS & fdwXNSAvailable)
? MAKEINTRESOURCE(IDD_CONNECTXNS)
: MAKEINTRESOURCE(IDD_CONNECT),
hwnd, (DLGPROC)Connect) )
{
if (pwi->ichVTPXfer != 0)
{
(void)FVtpXferEnd(hwnd, SV_CONNECT);
}
fHungUp = fConnected;
fConnected = FConnectToServer(hwnd, rgchHostName,
&pwi->nd, fConnected);
}
break;
case IDM_HANGUP:
PostMessage(hwnd, NM_HANGUP, 0, 0);
break;
case IDM_MARK:
/* If doing delayed pasting, turn it off */
StopPaste( hwnd );
CursorOff( hwnd );
MarkModeOn(hwnd, 0);
break;
case IDM_COPY:
/* Copy selection, if any, to clipboard */
DoCopy( hwnd );
CursorOn( hwnd );
break;
case IDM_PASTE:
case IDM_STOPPASTE:
/* If doing delayed pasting, turn it off */
StopPaste( hwnd );
if ((LOWORD(wParam) == IDM_PASTE) &&
(pwi->nd.SessionNumber != nSessionNone))
{
DoPaste( hwnd );
}
break;
case IDM_CUSTOMLINES:
/* Save current value of ui.dwMaxRow */
i = ui.dwMaxRow;
if (DialogBox(hInst, MAKEINTRESOURCE(IDD_DISPLAYLINES),
hwnd, (DLGPROC)DisplayLines) != IDOK)
{
break;
}
/* Restore old value of ui.dwMaxRow
* SetDisplaySize will change the old ui.dwMaxRow to
* the new value
*/
rgdwDisplayRows[idwDRCustom] = ui.dwMaxRow;
ui.dwMaxRow = i;
/* fall through to next case */
case IDM_25LINES:
case IDM_43LINES:
case IDM_50LINES:
/*************************************************************
* This assumes that IDM_25LINES, IDM_43LINES, IDM_50LINES & *
* IDM_CUSTOMLINES are in consecutive order *
*************************************************************/
SetDisplaySize(hwnd, rgdwDisplayRows[LOWORD(wParam)-IDM_25LINES],
&pwi->trm.dwCurLine);
break;
case IDM_FONTS:
if ( ChooseFont(&pwi->cf) )
{
HFONT hfontT = CreateFontIndirect( &ui.lf );
if (hfontT != NULL)
{
DeleteObject( hfontDisplay );
hfontDisplay = hfontT;
/* Now get new data about font size */
RecalcWindowSize( hwnd );
}
else
{
(void)MessageBox(hwnd, szNoFont, szAppName, MB_OK);
}
}
break;
case IDM_AUTOFONTS:
ui.fPrompt ^= fdwAutoFonts;
j = IDM_AUTOFONTS;
i = (ui.fPrompt & fdwAutoFonts);
ResizeWindow(hwnd);
goto menuchange;
case IDM_SMOOTHSCROLL:
ui.fSmoothScroll = !ui.fSmoothScroll;
j = IDM_SMOOTHSCROLL;
i = ui.fSmoothScroll;
goto menuchange;
case IDM_NODOWNLOADPROMPT:
ui.fPrompt ^= fdwSuppressDestDirPrompt;
j = IDM_NODOWNLOADPROMPT;
i = (ui.fPrompt & fdwSuppressDestDirPrompt);
goto menuchange;
case IDM_CONNECTLOSTNONE:
case IDM_CONNECTLOSTDLG:
case IDM_CONNECTLOSTRETRY:
case IDM_CONNECTLOSTEXIT:
CheckMenuItem(GetMenu(hwnd), ConnectLostMode(ui), MF_UNCHECKED);
SetConnectLostMode(ui, wParam);
j = wParam;
i = 1;
goto menuchange;
case IDM_NOCONNECTRETRYDLG:
ui.fPrompt ^= fdwNoConnectRetryDlg;
j = IDM_NOCONNECTRETRYDLG;
i = (ui.fPrompt & fdwNoConnectRetryDlg);
goto menuchange;
case IDM_LOCALECHO:
ui.fDebug ^= fdwLocalEcho;
j = IDM_LOCALECHO;
i = (ui.fDebug & fdwLocalEcho);
goto menuchange;
case IDM_TEXTCOLOUR:
case IDM_BACKCOLOUR:
{
CHOOSECOLOR cc;
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.rgbResult = (LOWORD(wParam) == IDM_TEXTCOLOUR)
? ui.clrText : ui.clrBk;
cc.lpCustColors = rgdwCustColours;
cc.Flags = CC_RGBINIT;
cc.lCustData = 0;
cc.lpfnHook = NULL;
cc.lpTemplateName = NULL;
if ( ChooseColor(&cc) )
{
if (LOWORD(wParam) == IDM_TEXTCOLOUR)
ui.clrText = cc.rgbResult;
else
ui.clrBk = cc.rgbResult;
InvalidateRect(hwnd, NULL, TRUE);
}
}
break;
case IDM_HIDEMENU:
goto HideMenu;
case IDM_UNDERLINECURSOR:
CursorOff( hwnd );
ui.fCursorEdit ^= fdwCursorUnderline;
j = IDM_UNDERLINECURSOR;
i = (ui.fCursorEdit & fdwCursorUnderline);
goto menuchange;
case IDM_BLINKCURSOR:
CursorOff( hwnd );
ui.fCursorEdit ^= fdwCursorBlink;
j = IDM_BLINKCURSOR;
i = (ui.fCursorEdit & fdwCursorBlink);
goto menuchange;
case IDM_VT100CURSORKEYS:
ui.fDebug ^= fdwVT100CursorKeys;
j = IDM_VT100CURSORKEYS;
i = (ui.fDebug & fdwVT100CursorKeys);
if ( i )
{
ClearVTArrow(&pwi->trm);
}
else
{
SetVTArrow(&pwi->trm);
}
goto menuchange;
#ifdef VT52
case IDM_VT52MODE:
ui.fDebug ^= fdwVT52Mode;
j = IDM_VT52MODE;
i = (ui.fDebug & fdwVT52Mode);
if ( i )
{
SetVT52(&pwi->trm);
}
else
{
ClearVT52(&pwi->trm);
}
goto menuchange;
#endif /* VT52 */
case IDM_TRIMSPACE:
ui.fCursorEdit ^= fdwTrimEndWhitespace;
j = IDM_TRIMSPACE;
i = (ui.fCursorEdit & fdwTrimEndWhitespace);
goto menuchange;
case IDM_QUICKEDIT:
ui.fCursorEdit ^= fdwQuickEditMode;
j = IDM_QUICKEDIT;
i = (ui.fCursorEdit & fdwQuickEditMode);
menuchange:
CheckMenuItem(GetMenu(hwnd), j, i ? MF_CHECKED : MF_UNCHECKED);
DrawMenuBar( hwnd );
break;
case IDM_BBS1:
case IDM_BBS2:
case IDM_CHAT1:
case IDM_HEXNUT:
case IDM_INGATE:
case IDM_WINGNUT:
if ( !(ui.fXNS & fdwXNSAvailable) )
break;
if (pwi->ichVTPXfer != 0)
{
if (!FVtpXferEnd(hwnd, SV_DISCONNECT))
break;
}
/* save value of ui.fXNS, set fdwUseXNS for duration of connect */
i = ui.fXNS;
ui.fXNS |= fdwUseXNS;
lstrcpy(rgchHostName, rgszXNSMachines[LOWORD(wParam)-IDM_BBS1]);
if (pwi->nd.ncbRecv.ncb_cmd_cplt == NRC_PENDING)
fHungUp = fConnected;
else
fHungUp = FALSE;
fConnected = FConnectToServer(hwnd, rgchHostName,
&pwi->nd, fConnected);
/* restore value of ui.fXNS */
ui.fXNS = i;
break;
case IDM_MACHINE1:
case IDM_MACHINE2:
case IDM_MACHINE3:
case IDM_MACHINE4:
if (pwi->ichVTPXfer != 0)
{
if (!FVtpXferEnd(hwnd, SV_DISCONNECT))
break;
}
lstrcpy(rgchHostName, ui.rgchMachine[LOWORD(wParam)-IDM_MACHINE1]);
if (pwi->nd.ncbRecv.ncb_cmd_cplt == NRC_PENDING)
fHungUp = fConnected;
else
fHungUp = FALSE;
if (ui.fXNS & fdwXNSAvailable)
{
i = ui.fXNS;
if (GetAsyncKeyState(VK_CONTROL) < 0)
{
ui.fXNS &= ~fdwUseXNS;
}
else
{
ui.fXNS |= fdwUseXNS;
}
}
fConnected = FConnectToServer(hwnd, rgchHostName,
&pwi->nd, fConnected);
if (ui.fXNS & fdwXNSAvailable)
{
ui.fXNS = i;
}
break;
case IDM_ABOUT:
if ((GetKeyState(VK_SHIFT) <0) &&
(GetKeyState(VK_CONTROL) <0) &&
!(ui.fXNS & fdwXNSAvailable))
{
ui.fXNS = fdwXNSConnect;
}
{
HMODULE hMod;
LPFNSHELLABOUT lpfn;
if (hMod = LoadLibrary("SHELL32"))
{
if (lpfn = (LPFNSHELLABOUT)GetProcAddress(hMod,
"ShellAboutA"))
{
(*lpfn)(hwnd, szAppName,
(ui.fXNS & fdwXNSAvailable) ? szVersion : NULL,
LoadIcon(hInst, szAppName));
}
FreeLibrary(hMod);
}
else
{
MessageBeep( MB_ICONEXCLAMATION );
}
}
break;
case IDM_HELP:
WinHelp(hwnd, "winvtp.hlp", HELP_CONTENTS, 0);
break;
case IDM_EXIT:
lbl_Exit:
if (pwi->ichVTPXfer != 0)
{
if (!FVtpXferEnd(hwnd, SV_DISCONNECT))
break;
}
DestroyWindow( hwnd );
break;
default:
fRet = DefWindowProc(hwnd, message, wParam, lParam);
break;
}
break;
case WM_TIMER:
if (fFlashWindow == TRUE)
{
/*
* This is a bit of a HACK here.
* FlashWindow() will cause a WM_NCACTIVATE to be sent.
* The WM_NCACTIVATE handler will set fFlashWindow to
* FALSE. Since we know we're in this FlashWindow(),
* we reset fFlashWindow to TRUE.
* If the user switches to the app, fFlashWindow
* won't be reset to TRUE.
*/
FlashWindow(hwnd, TRUE);
fFlashWindow = TRUE;
}
/*
* The priority-based system for what to do in idle time.
* 1. If we're in Mark mode and we're not using the
* mouse to select the area to mark, make the Mark
* cursor flicker - BUT only if we're in the foreground.
* 2. If we're in delayed paste mode...
* If we've just started doing delayed pasting, i.e.
* the pchTextPaste pointer is at the beginning of
* the buffer, szTextPaste, then reset the timer
* so we can send data quicker.
* Send a character at a time down the wire.
* When we reach the null-terminator, stop pasting.
* 3. If we're not hiding the terminal's cursor and
* we are the active window, do any terminal
* cursor drawing and flickering.
*/
if (FInMarkMode(pwi->spb) && !FMouseSelected(pwi->spb))
{
if ( FShowCursor(pwi->spb) )
DoCursorFlicker(hwnd, dwForceNone);
}
else if ((szTextPaste != NULL) &&
(pwi->nd.SessionNumber != nSessionNone))
{
if (pchTextPaste == szTextPaste)
{
KillTimer(hwnd, uTerminalTimerID);
pwi->trm.uTimer = SetTimer(hwnd, uTerminalTimerID, 1, NULL);
}
if (*pchTextPaste != '\0')
{
NetBIOSWrite(pwi->nd.SessionNumber, (LPSTR)pchTextPaste++, 1);
}
else
{
StopPaste( hwnd );
MessageBeep( 0xFFFFFFFF );
MessageBeep( 0xFFFFFFFF );
}
}
else if ((pwi->trm.fHideCursor == FALSE) && (fInBackground == FALSE))
{
if (ui.fCursorEdit & fdwCursorBlink)
{
if (pwi->trm.fCursorOn == FALSE)
CursorOn( hwnd );
else
CursorOff( hwnd );
}
else
{
CursorOn( hwnd );
}
}
break;
case WM_KEYDOWN:
if ( FInMarkMode(pwi->spb) )
{
HandleMCPKeyEvent(hwnd, wParam, lParam);
break;
}
else
{
if ( FHandleKeyDownEvent(hwnd, pwi, wParam, lParam) )
break;
}
goto defresp;
case WM_CHAR:
#ifdef NBTEST
OutputDebugString("WM_CHAR In\n");
#endif
/* Don't let the user type anything while downloading */
if (pwi->svi.hthread != NULL)
break;
/*
* If we're in Mark mode, then only two characters are valid,
* Enter and Escape. Enter will copy any selected area's text
* to the clipboard. Escape will turn off Mark mode.
*/
if ( FInMarkMode(pwi->spb) )
{
/*
* No need to beep if the mouse was captured since
* the WM_KEYDOWN should've handled it.
*/
if ( !FMouseCaptured(pwi->spb) )
{
switch ( LOWORD(wParam) )
{
case '\r': /* Carriage Return */
DoCopy( hwnd );
CursorOn( hwnd );
break;
case 0x1B: /* ESCAPE */
MarkModeOff( hwnd );
CursorOn( hwnd );
break;
}
}
break;
}
if (pwi->nd.SessionNumber == nSessionNone)
{
MessageBeep( 0xFFFFFFFF );
}
else
{
HandleCharEvent(hwnd, pwi, wParam, lParam);
}
#ifdef NBTEST
OutputDebugString("WM_CHAR Out\n");
#endif
break;
case WM_RBUTTONDOWN:
/*
* If the user activated WinVTP by clicking the right
* mouse button, ignore the initial mouse button down.
*
* If we're in Mark mode and a selection range
* exists, then copy it to the clipboard.
* This will also turn off Mark mode thereby
* resetting WinVTP's window caption.
* The terminal's cursor is also turned back on.
*
* If we're in QuickEdit mode and there's text to
* paste, do the Paste.
*/
if (FMouseBtnDwnIgnore(pwi->spb))
{
/* If we're supposed to ignore this button down, fine */
pwi->spb.dwFlags &= ~fdwMouseBtnDwnIgnore;
break;
}
else if ( FInMarkMode(pwi->spb) )
{
DoCopy( hwnd );
CursorOn( hwnd );
}
else if ((ui.fCursorEdit & fdwQuickEditMode) && FCanPaste(pwi))
{
DoPaste( hwnd );
}
else
{
goto defresp;
}
break;
case WM_LBUTTONDBLCLK:
if (FInMarkMode(pwi->spb))
{
MarkModeOff(hwnd);
CursorOn(hwnd);
}
/* fall through */
HideMenu:
hmenu = GetSystemMenu(hwnd, FALSE);
DeleteMenu(hmenu, IDM_HIDEMENU, MF_BYCOMMAND);
DrawMenuBar( hwnd );
if (hSavedMenu)
{
SetMenu(hwnd, hSavedMenu);
hSavedMenu = NULL;
AppendMenu(hmenu, MF_ENABLED | MF_STRING, IDM_HIDEMENU, "&Hide Menu");
}
else
{
hSavedMenu = GetMenu(hwnd);
SetMenu(hwnd, NULL);
AppendMenu(hmenu, MF_ENABLED | MF_STRING, IDM_HIDEMENU, "S&how Menu");
}
break;
case WM_LBUTTONDOWN:
if (FMouseBtnDwnIgnore(pwi->spb))
{
/* If we're supposed to ignore this button down, fine */
pwi->spb.dwFlags &= ~fdwMouseBtnDwnIgnore;
break;
}
else if ( FInMarkMode(pwi->spb) )
{
/*
* Otherwise, if we're already in Mark mode,
* reset state info, and turn on Mark mode again
* but state that we're using the mouse to mark now.
*/
i = fdwMouseSelected;
if (wParam & MK_SHIFT)
i |= fdwDontResetSelection;
else
DoCursorFlicker(hwnd, dwForceOff);
MarkModeOn(hwnd, i);
}
else if ((ui.fCursorEdit & fdwQuickEditMode) &&
(pwi->svi.hthread == NULL))
{
/*
* If we're in QuickEdit Mode and we're
* not downloading anything via sendvtp,
* then stop pasting anything, turn off
* the terminal's cursor and turn on Mark
* mode stating we're using the mouse to mark.
*/
i = fdwMouseSelected;
StopPaste( hwnd );
CursorOff( hwnd );
MarkModeOn(hwnd, i);
wParam &= ~MK_SHIFT;
}
/*
* If we're in Mark mode, change WinVTP's window caption
* and update the selection area as appropriate.
*/
if ( FInMarkMode(pwi->spb) )
{
HandleMCPMouseEvent(hwnd, message, wParam, lParam);
}
break;
case WM_MOUSEMOVE:
/*
* If the left mouse button is down and we're in Mark
* mode and the mouse is still captured (we could've
* lost the mouse capture if the user had ALT-TAB'ed
* or CTRL-ESCAPE'ed away) then update the selection
* area as appropriate.
*/
if ((wParam & MK_LBUTTON) && FInMarkMode(pwi->spb) &&
FMouseCaptured(pwi->spb))
{
HandleMCPMouseEvent(hwnd, message, wParam, lParam);
}
break;
case WM_LBUTTONUP:
case WM_CANCELMODE:
/*
* If we're in Mark mode and we've captured the mouse,
* release the mouse and update the status flags
* to show that we've given up the mouse.
* It turns out that handling left mouse button up
* and WM_CANCELMODE (sent when a dialog like the
* Task Manager is brought up when the mouse is
* captured) in the same manner seems to be fine.
*/
if (FInMarkMode(pwi->spb) && FMouseCaptured(pwi->spb))
{
ReleaseCapture();
pwi->spb.dwFlags &= ~fdwMouseCaptured;
}
else
{
goto defresp;
}
break;
case WM_NCACTIVATE:
/*
* WinVTP uses the WM_NCACTIVATE message to determine
* when we've been put in the "background".
* This isn't the same as being active or the app being
* active.
* When WinVTP is in the background, the non-client
* area is displayed in the inactive state.
* Win32 will send WM_ACTIVATE and WM_ACTIVATEAPP
* messages that don't end up changing the display
* of the non-client area. Don't ask me why.
*/
if (((BOOL)wParam) == FALSE)
{
fInBackground = TRUE;
}
else
{
fInBackground = FALSE;
fFlashWindow = FALSE;
}
goto defresp;
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE)
{
/*
* If the main display window is being deactivated and
* the activated window's HWND is passed in, center the
* active window over the main display window
*/
if (lParam != 0)
{
CenterDialog(hwnd, (HWND)lParam);
}
/* Turn off the display/mark mode cursor when deactivated */
if (FInMarkMode(pwi->spb) && FShowCursor(pwi->spb))
{
DoCursorFlicker(hwnd, dwForceOff);
}
else if (pwi->trm.fHideCursor == FALSE)
{
CursorOff( hwnd );
}
}
else if ((LOWORD(wParam) == WA_CLICKACTIVE) &&
(FInMarkMode(pwi->spb) ||
(ui.fCursorEdit & fdwQuickEditMode)))
{
pwi->spb.dwFlags |= fdwMouseBtnDwnIgnore;
}
goto defresp;
case WM_SIZE:
if (!IsIconic(hwnd))
ResizeWindow(hwnd);
return (DefWindowProc(hwnd, message, wParam, lParam));
case WM_MOVE:
/*
* If the window's position changes, and it's not iconic,
* save the window position for the registry
*/
if ( !IsIconic(hwnd) )
{
RECT rect;
GetWindowRect(hwnd, &rect);
ui.dwTop = rect.top;
ui.dwLeft = rect.left;
}
break;
case WM_HSCROLL:
GetScrollRange(hwnd, SB_HORZ, &iMinPos, &iMaxPos);
switch(LOWORD(wParam))
{
case SB_BOTTOM: hPos = 0; break;
case SB_PAGEDOWN:
case SB_PAGEUP:
{
RECT rect;
int size;
GetClientRect(hwnd, &rect);
size = (rect.right-rect.left)/iCursorWidth;
if (LOWORD(wParam) == SB_PAGEDOWN)
hPos+=size*iCursorWidth;
else
hPos-=size*iCursorWidth;
}
break;
case SB_LINEDOWN: hPos+=iCursorWidth; break;
case SB_LINEUP: hPos-=iCursorWidth; break;
case SB_THUMBPOSITION: hPos = HIWORD(wParam); break;
}
if (hPos < 0) hPos = 0;
if (hPos >iMaxPos) hPos = iMaxPos;
SetScrollPos(hwnd, SB_HORZ, hPos, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_VSCROLL:
GetScrollRange(hwnd, SB_VERT, &iMinPos, &iMaxPos);
switch(LOWORD(wParam))
{
case SB_PAGEDOWN:
case SB_PAGEUP:
{
RECT rect;
int size;
GetClientRect(hwnd, &rect);
size = (rect.bottom-rect.top)/iCursorHeight;
if (LOWORD(wParam) == SB_PAGEDOWN)
vPos+=size*iCursorHeight;
else
vPos-=size*iCursorHeight;
}
break;
case SB_LINEDOWN: vPos+=iCursorHeight; break;
case SB_LINEUP: vPos-=iCursorWidth; break;
case SB_THUMBPOSITION: vPos = HIWORD(wParam); break;
}
if (vPos < 0) vPos = 0;
if (vPos >iMaxPos) vPos = iMaxPos;
SetScrollPos(hwnd, SB_VERT, vPos, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_CLOSE:
if (pwi->ichVTPXfer != 0)
{
if (!FVtpXferEnd(hwnd, SV_DISCONNECT))
break;
}
DestroyWindow( hwnd );
break;
case WM_DESTROY:
/*
* See ya! Wouldn't want to be ya!
*/
if (pwi != NULL)
{
if (pwi->trm.uTimer != 0)
{
KillTimer(hwnd, uTerminalTimerID);
pwi->trm.uTimer = 0;
}
if ( FInMarkMode(pwi->spb) )
{
MarkModeOff( hwnd );
CursorOn( hwnd );
}
if (pwi->ichVTPXfer != 0)
{
(void)FVtpXferEnd(hwnd, SV_QUIT);
}
/*
* If in session then cancel current transmission and
* hangup on the host, close shop and head out of town...
*/
if (fInited == TRUE)
{
SetUserSettings(hInst, &ui);
NetBIOSDelName( pwi->nd.szMyName );
if (pwi->nd.SessionNumber != nSessionNone)
NetBIOSHangup( pwi->nd.SessionNumber );
}
LocalFree( (HANDLE)pwi );
WinHelp(hwnd, "winvtp.hlp", HELP_QUIT, 0);
}
if (hSavedMenu)
DestroyMenu(hSavedMenu);
hSavedMenu = NULL;
SetWindowLong(hwnd, WL_VTPWI, 0L);
if (rgchRowEmpty != NULL)
LocalFree( (HANDLE)rgchRowEmpty );
if (pchNBBuffer != NULL)
LocalFree( (HANDLE)pchNBBuffer );
if (aixPos != NULL)
LocalFree( (HANDLE)aixPos );
if (aiyPos != NULL)
LocalFree( (HANDLE)aiyPos );
if (apcRows != NULL)
{
for (i=0; i<ui.dwMaxRow; ++i)
{
if (apcRows[i] != NULL)
LocalFree( (HANDLE)apcRows[i] );
}
LocalFree( (HANDLE)apcRows );
}
if (hfontDisplay != NULL)
DeleteObject( hfontDisplay );
PostQuitMessage( 0 );
break;
case SV_PROGRESS:
i = wsprintf(pchNBBuffer, szProgressDisplay, lParam);
DoIBMANSIOutput(hwnd, &pwi->trm, i, pchNBBuffer);
break;
case SV_END:
if (pwi->ichVTPXfer != 0)
{
(void)FVtpXferEnd(hwnd, SV_DONE);
}
break;
case NN_RECV:
{
DWORD cBytes;
UCHAR *pchT;
#ifdef NBTEST
OutputDebugString("NN_RECV In\n");
#endif
#if 0
wsprintf(rgchDbgBfr,"%ld\n", wParam);
OutputDebugString(rgchDbgBfr);
#endif
if ( FInMarkMode(pwi->spb) )
{
pwi->spb.dwFlags |= fdwDataPending;
pwi->spb.wData = wParam;
break;
}
/* N.B. wParam holds the count of bytes received */
if (cBytes = (DWORD)WGetData(&pwi->nd, (LPSTR)pchNBBuffer, (WORD)wParam))
{
DoIBMANSIOutput(hwnd, &pwi->trm, cBytes, pchNBBuffer);
/* Look for SendVTP signature... */
if ((ui.fXNS & fdwXNSAvailable) && (pwi->trm.cTilde == 2))
{
for (pchT = pchNBBuffer; (pchT-pchNBBuffer) < cBytes; ++pchT)
{
if (szVTPXfer[pwi->ichVTPXfer] != *pchT)
{
pwi->ichVTPXfer = 0;
}
else if (szVTPXfer[++pwi->ichVTPXfer] == '\0')
{
StopPaste( hwnd );
if (!FVtpXferStart(hwnd, pwi, pwi->nd.SessionNumber))
{
PostMessage(hwnd, SV_END, 0, 0L);
}
break;
}
}
}
else
{
pwi->ichVTPXfer = 0;
}
/* If no SendVTP desired, do another async read... */
if (szVTPXfer[pwi->ichVTPXfer] != '\0')
(void)FPostReceive( &pwi->nd );
}
#ifdef NBTEST
OutputDebugString("NN_RECV Out\n");
#endif
}
break;
case WM_PAINT:
Paint(hwnd, pwi);
break;
case NM_CONNECT:
if (ui.fXNS & fdwXNSAvailable)
{
i = ui.fXNS;
if ( !(ui.fXNS & fdwUseXNS) )
{
for (j=0; j<cXNSMachines; ++j)
{
if (!lstrcmpi(rgszXNSMachines[j], rgchHostName))
break;
}
if (j != cXNSMachines)
{
if (GetAsyncKeyState(VK_CONTROL) < 0)
{
ui.fXNS &= ~fdwUseXNS;
}
else
{
ui.fXNS |= fdwUseXNS;
}
}
}
}
/*
* Don't to do StopPaste() here since NM_CONNECT
* is only posted at startup time and we couldn't
* have a connection beforehand.
*/
fConnected = FConnectToServer(hwnd, rgchHostName,
&pwi->nd, fConnected);
if (ui.fXNS & fdwXNSAvailable)
{
ui.fXNS = i;
}
break;
case NN_LOST: /* Connection Lost */
StopPaste( hwnd );
if (fConnected && !fHungUp)
switch(ConnectLostMode(ui))
{
case IDM_CONNECTLOSTDLG:
(void)MessageBox(hwnd, szConnectionLost, szAppName, MB_OK);
break;
case IDM_CONNECTLOSTEXIT:
goto lbl_Exit;
case IDM_CONNECTLOSTRETRY:
if (pwi->ichVTPXfer != 0)
{
(void)FVtpXferEnd(hwnd, SV_CONNECT);
}
if (pwi->nd.ncbRecv.ncb_cmd_cplt == NRC_PENDING)
fHungUp = fConnected;
else
fHungUp = FALSE;
if (ui.fXNS & fdwXNSAvailable)
{
i = ui.fXNS;
if (GetAsyncKeyState(VK_CONTROL) < 0)
{
ui.fXNS &= ~fdwUseXNS;
}
else
{
ui.fXNS |= fdwUseXNS;
}
}
fConnected = FConnectToServer(hwnd, rgchHostName,
&pwi->nd, fConnected);
if (ui.fXNS & fdwXNSAvailable)
{
ui.fXNS = i;
}
return(0);
}
/*
* If a connection attempt is made when we already have a
* connection, we hang up the connection and then attempt
* to connect to the desired machine. A side effect of the
* hang up of the previous connection is that we get a
* NN_LOST notification. So after a
* connection-hangup-connection, we ignore the first NN_LOST
* notification.
*/
if ( fHungUp )
{
fHungUp = FALSE;
break;
}
/* fall through */
case NM_HANGUP: /* hangup on host */
/*
* If the PostReceive() routine used an event, you wouldn't
* need to do this
*/
if (LOWORD(wParam) != NN_LOST)
StopPaste( hwnd );
if (pwi->ichVTPXfer != 0)
{
(void)FVtpXferEnd(hwnd, SV_HANGUP);
}
fConnected = FHangupConnection(hwnd, &pwi->nd);
break;
default: /* Passes it on if unprocessed */
defresp:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
return (0);
}
#define lNotInList ((LONG)-1)
BOOL APIENTRY
Connect(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch ( message )
{
case WM_INITDIALOG:
{
LONG i;
LONG lPosInList = lNotInList;
LPSTR sz;
LONG cMachines;
if (ui.fXNS & fdwXNSAvailable)
{
/* insert six main MS Xenix machines into drop-down combobox */
cMachines = (LONG)cXNSMachines;
}
else
{
/* insert most recently used machines into drop-down combo */
cMachines = (LONG)ui.cMachines;
}
for (i=0; i<cMachines; ++i)
{
sz = (ui.fXNS & fdwXNSAvailable)
? rgszXNSMachines[i] : ui.rgchMachine[i];
SendDlgItemMessage(hDlg, CID_HOSTNAME, CB_ADDSTRING, 0,
(LPARAM)sz);
if (!lstrcmpi(sz, rgchHostName))
lPosInList = i;
}
/*
* rgchHostName isn't in list already
* so if there's a host name, insert it at
* the beginning of the list
* and select the first item in the list
*/
if (lPosInList == lNotInList)
{
if (rgchHostName[0] != '\0')
{
SendDlgItemMessage(hDlg, CID_HOSTNAME, CB_INSERTSTRING,
0, (LPARAM)rgchHostName);
}
lPosInList = 0;
}
SendDlgItemMessage(hDlg, CID_HOSTNAME, CB_SETCURSEL,
lPosInList, 0L);
SendDlgItemMessage(hDlg, CID_HOSTNAME, CB_SETEDITSEL, 0, -1);
if ((ui.fXNS & fdwXNSAvailable) && !(ui.fXNS & fdwUseXNS))
CheckDlgButton(hDlg, CID_USESTDNETBIOS, 1);
}
/* limit # chars */
SendDlgItemMessage(hDlg, CID_HOSTNAME, CB_LIMITTEXT,
cchMaxHostName, 0);
SetFocus( GetDlgItem(hDlg, CID_HOSTNAME) );
return (TRUE);
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
WORD cBytes;
if (cBytes = GetDlgItemText(hDlg, CID_HOSTNAME, rgchHostName,
sizeof(rgchHostName)))
{
rgchHostName[cBytes] = 0;
EndDialog(hDlg, TRUE);
}
else
{
(void)MessageBox(hDlg, szNoHostName, szConnectDlg, MB_OK);
}
if (ui.fXNS & fdwXNSAvailable)
{
if ( IsDlgButtonChecked(hDlg, CID_USESTDNETBIOS) )
ui.fXNS &= ~fdwUseXNS;
else
ui.fXNS |= fdwUseXNS;
}
return (TRUE);
}
if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, FALSE);
return (TRUE);
}
break;
}
/* Didn't process a message */
return (FALSE);
}
BOOL APIENTRY
DisplayLines(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch ( message )
{
case WM_INITDIALOG:
SetDlgItemInt(hDlg, CID_DISPLAYLINE,
(ui.dwMaxRow <100) ? ui.dwMaxRow : 99, FALSE);
SendDlgItemMessage(hDlg, CID_DISPLAYLINE, EM_SETSEL, 0, -1);
/* allow only two chars for # of lines */
SendDlgItemMessage(hDlg, CID_DISPLAYLINE, EM_LIMITTEXT, 2, 0);
SetFocus( GetDlgItem(hDlg, CID_DISPLAYLINE) );
return (TRUE);
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
DWORD cLines;
BOOL fTranslate;
cLines = GetDlgItemInt(hDlg, CID_DISPLAYLINE, &fTranslate, FALSE);
if (cLines >= dwMinRows)
{
ui.dwMaxRow = cLines;
EndDialog(hDlg, TRUE);
}
else
{
MessageBox(hDlg, szRestrictLines, szDisplayLinesDlg, MB_OK);
}
return (TRUE);
}
if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, FALSE);
return (TRUE);
}
break;
}
/* Didn't process the message */
return (FALSE);
}
/*
- CenterDialog
-
* Purpose:
* Moves the dialog specified by hwndDlg so that it is centered on
* the window specified by hwndParent. If hwndParent is null,
* hwndDlg gets centered on the screen.
*
* Should be called while processing the WM_INITDIALOG message
* from the dialog's DlgProc().
*
* Arguments:
* HWND parent hwnd
* HWND dialog's hwnd
*
* Returns:
* Nothing.
*
* Side effects:
* None.
*
* Errors:
* None.
*/
void
CenterDialog(HWND hwndParent, HWND hwndDlg)
{
int dx;
int dy;
RECT rectDlg;
RECT rect;
RECT rectDesktop;
if (hwndParent == NULL)
{
rect.top = rect.left = 0;
rect.right = GetSystemMetrics(SM_CXSCREEN);
rect.bottom = GetSystemMetrics(SM_CYSCREEN);
}
else
{
GetWindowRect(hwndParent, &rect);
}
GetWindowRect(GetDesktopWindow(), &rectDesktop);
GetWindowRect(hwndDlg, &rectDlg);
OffsetRect(&rectDlg, -rectDlg.left, -rectDlg.top);
dx = (rect.left + ((rect.right - rect.left -
rectDlg.right) / 2) + 4) & ~7;
dy = rect.top + ((rect.bottom - rect.top -
rectDlg.bottom) / 2);
/* Range checking */
if (dx < rectDesktop.left)
dx = rectDesktop.left;
else if ((dx + rectDlg.right) > rectDesktop.right)
dx = rectDesktop.right - rectDlg.right;
if (dy < rectDesktop.top)
dy = rectDesktop.top;
else if ((dy + rectDlg.bottom) > rectDesktop.bottom)
dy = rectDesktop.bottom - rectDlg.bottom;
MoveWindow(hwndDlg, dx, dy, rectDlg.right, rectDlg.bottom, 0);
}
/* UNDONE: it's worth thinking about how to encode all of this as
* a table somehow */
void
GetUserSettings(HINSTANCE hInstance, UI *pui)
{
LONG lErr;
HKEY hkey = 0;
DWORD dwDisp = 0;
DWORD dwType;
char rgchValue[48];
short i;
DWORD dwLimit;
LoadString(hInstance, IDS_KEY, rgchValue, sizeof(rgchValue));
lErr = RegCreateKeyEx(HKEY_CURRENT_USER, rgchValue,
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE | KEY_SET_VALUE,
NULL, &hkey, &dwDisp);
if (lErr != ERROR_SUCCESS)
{
(void)MessageBox(NULL, szCantAccessSettings, szAppName, MB_OK);
return;
}
/* Get the value of the top of the Window */
LoadString(hInstance, IDS_WINPOSTOP, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->dwTop);
lErr = RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->dwTop, &dwDisp);
if (lErr == ERROR_SUCCESS)
{
dwLimit = (DWORD)GetSystemMetrics(SM_CYFULLSCREEN);
if (pui->dwTop > dwLimit)
pui->dwTop = 0;
}
/* Get the value of the left size of the Window */
LoadString(hInstance, IDS_WINPOSLEFT, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->dwLeft);
lErr = RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->dwLeft, &dwDisp);
if (lErr == ERROR_SUCCESS)
{
dwLimit = (DWORD)GetSystemMetrics(SM_CXFULLSCREEN);
if (pui->dwLeft > dwLimit)
pui->dwLeft = 0;
}
LoadString(hInstance, IDS_ROWS, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->dwMaxRow);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->dwMaxRow, &dwDisp);
/* Make sure value is within bounds */
if ((pui->dwMaxRow < dwMinRows) || (pui->dwMaxRow > dwMaxRows))
pui->dwMaxRow = dwDefaultRows;
LoadString(hInstance, IDS_COLUMNS, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->dwMaxCol);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->dwMaxCol, &dwDisp);
/* Make sure value is within bounds */
if ((pui->dwMaxCol < dwMinColumns) || (pui->dwMaxCol > dwMaxColumns))
pui->dwMaxCol = dwDefaultColumns;
pui->cMachines = 0;
for (i=IDS_MACHINE1; i<=IDS_MACHINE4; ++i)
{
LoadString(hInstance, i, rgchValue, sizeof(rgchValue));
dwDisp = cchMaxHostName;
lErr = RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)pui->rgchMachine[pui->cMachines], &dwDisp);
if (lErr == ERROR_SUCCESS)
pui->cMachines += 1;
}
LoadString(hInstance, IDS_LASTMACHINE, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->rgchLastMachine);
lErr = RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)pui->rgchLastMachine, &dwDisp);
if (lErr != ERROR_SUCCESS)
pui->rgchLastMachine[0] = '\0';
LoadString(hInstance, IDS_TEXTCOLOUR, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->clrText);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->clrText, &dwDisp);
LoadString(hInstance, IDS_BKGCOLOUR, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->clrBk);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->clrBk, &dwDisp);
LoadString(hInstance, IDS_FONTNAME, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->lf.lfFaceName);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)pui->lf.lfFaceName, &dwDisp);
LoadString(hInstance, IDS_FONTHEIGHT, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->lf.lfHeight);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->lf.lfHeight, &dwDisp);
LoadString(hInstance, IDS_FONTWEIGHT, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->lf.lfFaceName);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->lf.lfWeight, &dwDisp);
LoadString(hInstance, IDS_FONTSTYLE, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(dwLimit);
dwLimit = 0;
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&dwLimit, &dwDisp);
pui->lf.lfItalic = (dwLimit & fdwItalic) ? TRUE : FALSE;
pui->lf.lfUnderline = (dwLimit & fdwUnderline) ? TRUE : FALSE;
pui->lf.lfStrikeOut = (dwLimit & fdwStrikeOut) ? TRUE : FALSE;
LoadString(hInstance, IDS_SMOOTHSCROLL, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->fSmoothScroll);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->fSmoothScroll, &dwDisp);
/* convert to canonical TRUE value, if necessary */
if (pui->fSmoothScroll != FALSE)
pui->fSmoothScroll = TRUE;
LoadString(hInstance, IDS_DEBUGFLAGS, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->fDebug);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->fDebug, &dwDisp);
LoadString(hInstance, IDS_PROMPTFLAGS, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->fPrompt);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->fPrompt, &dwDisp);
LoadString(hInstance, IDS_RETRYSECONDS, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->dwRetrySeconds);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->dwRetrySeconds, &dwDisp);
if (pui->dwRetrySeconds < 1)
pui->dwRetrySeconds = 1;
if (pui->dwRetrySeconds >60)
pui->dwRetrySeconds = 60;
LoadString(hInstance, IDS_XNSSTATE, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->fXNS);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->fXNS, &dwDisp);
LoadString(hInstance, IDS_CURSOREDIT, rgchValue, sizeof(rgchValue));
dwDisp = sizeof(pui->fCursorEdit);
(void)RegQueryValueEx(hkey, rgchValue, NULL, &dwType,
(LPBYTE)&pui->fCursorEdit, &dwDisp);
RegCloseKey( hkey );
}
void
SetUserSettings(HINSTANCE hInstance, UI *pui)
{
LONG lErr;
HKEY hkey = 0;
char rgchValue[48];
DWORD dwFlags;
short i;
LoadString(hInstance, IDS_KEY, rgchValue, sizeof(rgchValue));
lErr = RegOpenKeyEx(HKEY_CURRENT_USER, rgchValue,
0, KEY_SET_VALUE, &hkey);
if (lErr != ERROR_SUCCESS)
{
(void)MessageBox(NULL, szCantAccessSettings, szAppName, MB_OK);
return;
}
/* Get the value of the top of the Window */
LoadString(hInstance, IDS_WINPOSTOP, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->dwTop, sizeof(pui->dwTop));
/* Get the value of the left size of the Window */
LoadString(hInstance, IDS_WINPOSLEFT, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->dwLeft, sizeof(pui->dwLeft));
LoadString(hInstance, IDS_ROWS, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->dwMaxRow, sizeof(pui->dwMaxRow));
LoadString(hInstance, IDS_COLUMNS, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->dwMaxCol, sizeof(pui->dwMaxCol));
for (i=IDS_MACHINE1; i<=IDS_MACHINE4; ++i)
{
if (pui->rgchMachine[i-IDS_MACHINE1][0] != '\0')
{
LoadString(hInstance, i, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_SZ,
(CONST LPBYTE)pui->rgchMachine[i-IDS_MACHINE1],
lstrlen(pui->rgchMachine[i-IDS_MACHINE1])+1);
}
}
if (pui->rgchLastMachine[0] != '\0')
{
LoadString(hInstance, IDS_LASTMACHINE, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_SZ,
(CONST LPBYTE)pui->rgchLastMachine,
lstrlen(pui->rgchLastMachine)+1);
}
LoadString(hInstance, IDS_TEXTCOLOUR, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->clrText, sizeof(pui->clrText));
LoadString(hInstance, IDS_BKGCOLOUR, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->clrBk, sizeof(pui->clrBk));
LoadString(hInstance, IDS_FONTNAME, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_SZ,
(CONST LPBYTE)pui->lf.lfFaceName,
lstrlen(pui->lf.lfFaceName)+1);
LoadString(hInstance, IDS_FONTHEIGHT, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->lf.lfHeight, sizeof(DWORD));
LoadString(hInstance, IDS_FONTWEIGHT, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&pui->lf.lfWeight, sizeof(DWORD));
dwFlags = 0;
if (pui->lf.lfItalic == TRUE)
dwFlags |= fdwItalic;
if (pui->lf.lfUnderline == TRUE)
dwFlags |= fdwUnderline;
if (pui->lf.lfStrikeOut == TRUE)
dwFlags |= fdwStrikeOut;
LoadString(hInstance, IDS_FONTSTYLE, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(CONST LPBYTE)&dwFlags, sizeof(DWORD));
LoadString(hInstance, IDS_SMOOTHSCROLL, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(LPBYTE)&pui->fSmoothScroll, sizeof(DWORD));
LoadString(hInstance, IDS_DEBUGFLAGS, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(LPBYTE)&pui->fDebug, sizeof(DWORD));
LoadString(hInstance, IDS_PROMPTFLAGS, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(LPBYTE)&pui->fPrompt, sizeof(DWORD));
LoadString(hInstance, IDS_RETRYSECONDS, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(LPBYTE)&pui->dwRetrySeconds, sizeof(DWORD));
if (pui->fXNS & fdwXNSAvailable)
{
LoadString(hInstance, IDS_XNSSTATE, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(LPBYTE)&pui->fXNS, sizeof(DWORD));
}
LoadString(hInstance, IDS_CURSOREDIT, rgchValue, sizeof(rgchValue));
(void)RegSetValueEx(hkey, rgchValue, 0, REG_DWORD,
(LPBYTE)&pui->fCursorEdit, sizeof(DWORD));
RegCloseKey( hkey );
}
/*
* HmenuGetMRUMenu
*
* Purpose:
* Returns the menu handle where Frequently-Used Machines are
* displayed
* Arguments:
* HWND
* UI *
* Returns:
* HMENU
*/
HMENU
HmenuGetMRUMenu(HWND hwnd, UI *pui)
{
HMENU hmenu = GetMenu(hwnd);
hmenu = GetSubMenu(hmenu, imenuMRU);
return hmenu;
}