/**************************************************************************** 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 /* required for all Windows applications */ #include #include #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; itrm.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; isvi.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; itrm, 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; jnd, 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= 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; }