/* File: D:\WACKER\tdll\termproc.c (Created: 06-Dec-1993) * * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 8 $ * $Date: 5/29/02 2:17p $ */ #include #include #pragma hdrstop // #define DEBUGSTR 1 #include "stdtyp.h" #include "sf.h" #include "sess_ids.h" #include "assert.h" #include "session.h" #include "backscrl.h" #include "timers.h" #if defined(INCL_KEY_MACROS) #include "keyutil.h" #endif #include "chars.h" #include "cloop.h" #include "misc.h" #include #include "term.h" #include "term.hh" // When parsing values for mouse moves, scrolls, etc. HIWORD and LOWORD // clip the sign extension since these are 16 bit values. These macros // cast the result to a short so that sign extension works correctly #define LOSHORT(x) ((short)LOWORD(x)) #define HISHORT(x) ((short)HIWORD(x)) // HORZPAGESIZE represents the size in columns of one page horizontally. // We need this for two reasons. 1) We need a page size so we know how far // to skip when user "pages" horizontally using the scrollbar. 2) So we // have a size to set for the thumb size. Ten is arbritary but seems // about right. - mrw #define HORZPAGESIZE 10 /* --- static function prototypes ---*/ static void TP_WM_CREATE(const HWND hwnd); static void TP_WM_CHAR(const HWND hwnd, const UINT message, const WPARAM wPar, const LPARAM lPar); static void TP_WM_IME_CHAR(const HWND hwnd, const UINT message, const WPARAM wPar, const LPARAM lPar); static int kabExpandMacroKey( const HSESSION hSession, KEY_T aKey ); static void TP_WM_TERM_KEY(const HWND hwnd, KEY_T Key); static void TP_WM_SETFOCUS(const HWND hwnd); static void TP_WM_KILLFOCUS(const HWND hwnd); static void TP_WM_VSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl); static void TP_WM_HSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl); static void TP_WM_TERM_TRACK(const HHTERM hhTerm, const int fForce); static void TP_WM_EMU_SETTINGS(const HHTERM hhTerm); static int TP_WM_TERM_LOAD_SETTINGS(const HHTERM hhTerm); static int TP_WM_TERM_SAVE_SETTINGS(const HHTERM hhTerm); static void TP_WM_TERM_FORCE_WMSIZE(const HHTERM hhTerm); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TermProc * * DESCRIPTION: * Terminal window * * ARGUMENTS: * Standard CALLBACK args * * RETURNS: * Standard CALLBACK codes * */ LRESULT CALLBACK TermProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar) { HHTERM hhTerm; switch (uMsg) { case WM_HELP: // We do not want start the help engine due to F1 when function // keys are being interpreted as terminal keys // (NOT Windows keys). JRJ 12/94 // hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(emuIsEmuKey(sessQueryEmuHdl(hhTerm->hSession), VIRTUAL_KEY | VK_F1)) { return 0; } break; case WM_CREATE: TP_WM_CREATE(hwnd); return 0; case WM_SIZE: TP_WM_SIZE(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar)); return 0; case WM_IME_CHAR: TP_WM_IME_CHAR(hwnd, uMsg, wPar, lPar); return 0; case WM_KEYDOWN: case WM_CHAR: TP_WM_CHAR(hwnd, uMsg, wPar, lPar); return 0; case WM_PAINT: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termPaint(hhTerm, hwnd); return 0; case WM_SYSCOLORCHANGE: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termSysColorChng(hhTerm); return 0; case WM_SETFOCUS: TP_WM_SETFOCUS(hwnd); return 0; case WM_KILLFOCUS: TP_WM_KILLFOCUS(hwnd); return 0; case WM_VSCROLL: TP_WM_VSCROLL(hwnd, LOWORD(wPar), HISHORT(wPar), (HWND)lPar); return 0; case WM_HSCROLL: TP_WM_HSCROLL(hwnd, LOWORD(wPar), HISHORT(wPar), (HWND)lPar); return 0; case WM_LBUTTONDOWN: TP_WM_LBTNDN(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar)); return 0; case WM_MOUSEMOVE: TP_WM_MOUSEMOVE(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar)); return 0; case WM_LBUTTONUP: TP_WM_LBTNUP(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar)); return 0; case WM_LBUTTONDBLCLK: TP_WM_LBTNDBLCLK(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar)); return 0; case WM_DESTROY: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); DestroyTerminalHdl(hhTerm); hhTerm = NULL; return 0; /* --- Public terminal messages --- */ case WM_TERM_GETUPDATE: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termGetUpdate(hhTerm, TRUE); return 0; case WM_TERM_BEZEL: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); hhTerm->xBezel = (hhTerm->xBezel) ? 0 : BEZEL_SIZE; // Need to recompute scrollbar min's and max's since the // presence/absence of the bezel affects these items. This // is done in the WM_SIZE handler and can be called directly // with the current client size. TP_WM_SIZE(hwnd, SIZE_RESTORED, hhTerm->cx, hhTerm->cy); InvalidateRect(hwnd, 0, FALSE); return 0; case WM_TERM_Q_BEZEL: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); return hhTerm->xBezel; case WM_TERM_Q_SNAP: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termQuerySnapRect(hhTerm, (LPRECT)lPar); return 0; case WM_TERM_KEY: TP_WM_TERM_KEY(hwnd, (unsigned)wPar); return 0; case WM_TERM_CLRATTR: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termSetClrAttr(hhTerm); return 0; case WM_TERM_GETLOGFONT: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); *(PLOGFONT)lPar = hhTerm->lf; return 0; case WM_TERM_SETLOGFONT: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termSetFont(hhTerm, (PLOGFONT)lPar); return 0; case WM_TERM_Q_MARKED: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); return hhTerm->fMarkingLock; case WM_TERM_UNMARK: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); LinkCursors(hhTerm); return 0; case WM_TERM_MARK_ALL: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); MarkTextAll(hhTerm); return 0; case WM_TERM_TRACK: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); TP_WM_TERM_TRACK(hhTerm, (int)wPar); return 0; case WM_TERM_EMU_SETTINGS: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); TP_WM_EMU_SETTINGS(hhTerm); return 0; case WM_TERM_Q_MARKED_RANGE: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); *(PPOINT)wPar = hhTerm->ptBeg; *(PPOINT)lPar = hhTerm->ptEnd; return 0; case WM_TERM_LOAD_SETTINGS: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); TP_WM_TERM_LOAD_SETTINGS(hhTerm); return 0; case WM_TERM_SAVE_SETTINGS: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); TP_WM_TERM_SAVE_SETTINGS(hhTerm); return 0; case WM_TERM_FORCE_WMSIZE: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); TP_WM_TERM_FORCE_WMSIZE(hhTerm); return 0; /* --- Private terminal messages --- */ case WM_TERM_SCRLMARK: MarkingTimerProc((void *)hwnd, 0); return 0; case WM_TERM_KLUDGE_FONT: hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); termSetFont(hhTerm, &hhTerm->lfHold); RefreshTermWindow(hwnd); return 0; default: break; } return DefWindowProc(hwnd, uMsg, wPar, lPar); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_CREATE * * DESCRIPTION: * Create message processor for terminal window. * * ARGUMENTS: * hwnd - terminal window handle * * RETURNS: * void * */ static void TP_WM_CREATE(const HWND hwnd) { HHTERM hhTerm; SCROLLINFO scrinf; #if(WINVER >= 0x0500) LONG_PTR ExStyle; ExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE); // // [mhamid] If it is mirrored then turn off mirroing. // if (ExStyle & WS_EX_LAYOUTRTL) { SetWindowLongPtr(hwnd, GWL_EXSTYLE, (LONG_PTR)(ExStyle & ~WS_EX_LAYOUTRTL)); } #endif // WINVER >= 0x0500 // Create an internal handle for instance data storage. hhTerm = CreateTerminalHdl(hwnd); // Need to set this even if hTerm is 0 so WM_DESTROY works. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)hhTerm); if (hhTerm == 0) { assert(FALSE); ExitProcess(1); } scrinf.cbSize = sizeof(scrinf); scrinf.fMask = SIF_DISABLENOSCROLL; SetScrollInfo(hwnd, SB_VERT, &scrinf, 0); return; } #if 0 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_CMD * * DESCRIPTION: * WM_COMMAND processor for TermProc() * * ARGUMENTS: * hwnd - terminal window handle * nId - item, control, or accelerator identifier * nNotify - notification code * hwndCtrl - handle of control * * RETURNS: * void * */ static void TP_WM_CMD(const HWND hwnd, const int nId, const int nNotify, const HWND hwndCtrl) { const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (nId) { case WM_USER: break; } return; } #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_SIZE * * DESCRIPTION: * WM_SIZE message processor for termproc. If iWidth and iHite are zero, * then the window sizes itself to fit the session window accounting for * statusbars and toolbars. * * ARGUMENTS: * hwnd - terminal window * fwSizeType - from WM_SIZE * iWidth - width of window * iHite - hite of window * * RETURNS: * void * */ void TP_WM_SIZE(const HWND hwnd, const unsigned fwSizeType, const int iWidth, const int iHite) { RECT rc, rcTmp; int i, j, k; SCROLLINFO scrinf; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); const HWND hwndToolbar = sessQueryHwndToolbar(hhTerm->hSession); const HWND hwndStatusbar = sessQueryHwndStatusbar(hhTerm->hSession); const HWND hwndSidebar = sessQuerySidebarHwnd(hhTerm->hSession); // If the window is hidden, we really don't need to do anything. if (!IsWindowVisible(hwnd)) return; // If we get a message with 0, 0 for width, hite, make terminal window // fit the session window less the toolbar and statusbar if present. if (iWidth == 0 && iHite == 0) { GetClientRect(hhTerm->hwndSession, &rc); // Note: See if we can use sessQuery funcs for // this if (IsWindow(hwndToolbar) && IsWindowVisible(hwndToolbar)) { GetWindowRect(hwndToolbar, &rcTmp); rc.top += (rcTmp.bottom - rcTmp.top); } if (IsWindow(hwndStatusbar) && IsWindowVisible(hwndStatusbar)) { GetWindowRect(hwndStatusbar, &rcTmp); rc.bottom -= (rcTmp.bottom - rcTmp.top); rc.bottom += 2 * GetSystemMetrics(SM_CYBORDER); } if (IsWindow(hwndSidebar) && IsWindowVisible(hwndSidebar)) { GetWindowRect(hwndSidebar, &rcTmp); rc.left += (rcTmp.right - rcTmp.left); } MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); } // Compute size related items. else { hhTerm->cx = iWidth; hhTerm->cy = iHite; // Set Min's and Max's now. i = hhTerm->iTermHite; // save old height for bottom line alignment hhTerm->iTermHite = hhTerm->cy / hhTerm->yChar; // If bezel is drawn, make sure we have room j = 0; if (hhTerm->xBezel) { if ((hhTerm->cy % hhTerm->yChar) < (hhTerm->xBezel + 1)) j = 1; } hhTerm->iVScrlMin = min(-hhTerm->iBkLines, hhTerm->iRows - hhTerm->iTermHite + 1 + j); // Little hack here to make sure that if we were at the bottom // we show the bottom. k = (hhTerm->iVScrlMax == hhTerm->iVScrlPos); hhTerm->iVScrlMax = max(hhTerm->iVScrlMin, hhTerm->iRows + 1 + j - hhTerm->iTermHite); // First time through set to bottom if (k) hhTerm->iVScrlPos = hhTerm->iVScrlMax; else hhTerm->iVScrlPos -= hhTerm->iTermHite - i; hhTerm->iVScrlPos = max(hhTerm->iVScrlPos, hhTerm->iVScrlMin); hhTerm->iVScrlPos = min(hhTerm->iVScrlPos, hhTerm->iVScrlMax); // hhTerm->iHScrlMax = #Cols - #Cols Showing hhTerm->iHScrlMax = max(0, hhTerm->iCols - ((hhTerm->cx - hhTerm->xIndent - (2 * hhTerm->xBezel)) / hhTerm->xChar)); hhTerm->iHScrlPos = min(hhTerm->iHScrlPos, hhTerm->iHScrlMax); // Check to see if we scrolled entirely into backscroll // region. If so, set fBackscrlLock for this view. And refill // its backscroll buffer (important). if ((hhTerm->iVScrlPos + hhTerm->iTermHite) <= 0) { hhTerm->fBackscrlLock = TRUE; termFillBk(hhTerm, hhTerm->iVScrlPos); } else { hhTerm->fBackscrlLock = FALSE; termFillBk(hhTerm, -hhTerm->iTermHite); } /* --- Vertical scroll bar --- */ scrinf.cbSize= sizeof(scrinf); scrinf.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE; scrinf.nMin = hhTerm->iVScrlMin; scrinf.nMax = hhTerm->iVScrlMax + hhTerm->iTermHite - 1; scrinf.nPos = hhTerm->iVScrlPos; scrinf.nPage = hhTerm->iTermHite; SetScrollInfo(hwnd, SB_VERT, &scrinf, TRUE); /* --- Horizontal scroll bar --- */ i = hhTerm->iHScrlMax - hhTerm->iHScrlMin; scrinf.cbSize= sizeof(scrinf); scrinf.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; scrinf.nMin = hhTerm->iHScrlMin; scrinf.nMax = hhTerm->iHScrlMax + HORZPAGESIZE - 1; scrinf.nPos = hhTerm->iHScrlPos; scrinf.nPage = HORZPAGESIZE; SetScrollInfo(hwnd, SB_HORZ, &scrinf, TRUE); } return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_SETFOCUS * * DESCRIPTION: * Handler for WM_SETFOCUS message * * ARGUMENTS: * hwnd - terminal window handle. * * RETURNS: * void * */ static void TP_WM_SETFOCUS(const HWND hwnd) { int i; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); hhTerm->fFocus = TRUE; // Use Multiplexer timer for cursor and blinking text. if (!hhTerm->hCursorTimer) { i = TimerCreate(hhTerm->hSession, &hhTerm->hCursorTimer, (long)hhTerm->uBlinkRate, CursorTimerProc, (void *)hwnd); if (i != TIMER_OK) assert(FALSE); } ShowCursors(hhTerm); return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_KILLFOCUS * * DESCRIPTION: * Handler for WM_KILLFOCUS message. * * ARGUMENTS: * hwnd - terminal window handle. * * RETURNS: * void * */ static void TP_WM_KILLFOCUS(const HWND hwnd) { const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); hhTerm->fFocus = FALSE; if (hhTerm->hCursorTimer) { TimerDestroy(&hhTerm->hCursorTimer); } HideCursors(hhTerm); return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_VSCROLL * * DESCRIPTION: * Message handler for terminal window's WM_VSCROLL * * ARGUMENTS: * hwnd - terminal window handle * nCode - scrollbar value * nPos - scrollbox pos * hwndScrl - window handle of scrollbar * * RETURNS: * void * */ static void TP_WM_VSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl) { int i; int iScrlInc; RECT rc; SCROLLINFO scrinf; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (nCode) { case SB_TOP: iScrlInc = -(hhTerm->iVScrlPos - hhTerm->iVScrlMin); break; case SB_BOTTOM: iScrlInc = hhTerm->iVScrlMax - hhTerm->iVScrlPos; break; case SB_LINEUP: iScrlInc = -1; break; case SB_LINEDOWN: iScrlInc = 1; break; case SB_PAGEUP: iScrlInc = min(-1, -hhTerm->iTermHite); break; case SB_PAGEDOWN: iScrlInc = max(1, hhTerm->iTermHite); break; case SB_THUMBTRACK: case SB_THUMBPOSITION: iScrlInc = nPos - hhTerm->iVScrlPos; break; default: iScrlInc = 0; break; } if ((iScrlInc = max(-(hhTerm->iVScrlPos - hhTerm->iVScrlMin), min(iScrlInc, hhTerm->iVScrlMax - hhTerm->iVScrlPos))) != 0) { HideCursors(hhTerm); hhTerm->iVScrlPos += iScrlInc; GetClientRect(hwnd, &rc); i = rc.bottom; rc.bottom = hhTerm->iTermHite * hhTerm->yChar; hhTerm->yBrushOrg = (hhTerm->yBrushOrg + (-hhTerm->yChar * iScrlInc)) % 8; ScrollWindow(hwnd, 0, -hhTerm->yChar * iScrlInc, 0, &rc); scrinf.cbSize = sizeof(scrinf); scrinf.fMask = SIF_DISABLENOSCROLL | SIF_POS; scrinf.nPos = hhTerm->iVScrlPos; SetScrollInfo(hwnd, SB_VERT, &scrinf, TRUE); hhTerm->fScrolled = TRUE; // Check to see if we scrolled entirely into backscroll // region. If so, set fBackscrlLock for this view. if ((hhTerm->iVScrlPos + hhTerm->iTermHite) <= 0) { if (hhTerm->fBackscrlLock == FALSE) termFillBk(hhTerm, hhTerm->iVScrlPos); else termGetBkLines(hhTerm, iScrlInc, hhTerm->iVScrlPos, BKPOS_THUMBPOS); hhTerm->fBackscrlLock = TRUE; } else { if (hhTerm->fBackscrlLock == TRUE) termFillBk(hhTerm, -hhTerm->iTermHite); hhTerm->fBackscrlLock = FALSE; } // Make two seperate calls to WM_PAINT to optimize screen // updates in the case of a negative scroll operation. if (iScrlInc < 0) UpdateWindow(hwnd); // Fill-in fractional part of line at bottom of terminal // screen with appropriate color by invalidating that region. if (i > rc.bottom) { rc.top = rc.bottom; rc.bottom = i; InvalidateRect(hwnd, &rc, FALSE); } UpdateWindow(hwnd); ShowCursors(hhTerm); #if 0 // debugging stuff... { char ach[50]; wsprintf(ach, "pos=%d min=%d max=%d", hhTerm->iVScrlPos, hhTerm->iVScrlMin, hhTerm->iVScrlMax); SetWindowText(sessQueryHwndStatusbar(hhTerm->hSession), ach); } #endif } return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_HSCROLL * * DESCRIPTION: * Message handler for terminal window's WM_HSCROLL * * ARGUMENTS: * hwnd - terminal window handle * nCode - scrollbar value * nPos - scrollbox pos * hwndScrl - window handle of scrollbar * * RETURNS: * void * */ static void TP_WM_HSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl) { int i, j, k; int iScrlInc; RECT rc; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (nCode) { case SB_LINEUP: iScrlInc = -1; break; case SB_LINEDOWN: iScrlInc = 1; break; case SB_PAGEUP: iScrlInc = -HORZPAGESIZE; break; case SB_PAGEDOWN: iScrlInc = HORZPAGESIZE; break; case SB_THUMBTRACK: case SB_THUMBPOSITION: iScrlInc = nPos - hhTerm->iHScrlPos; break; default: iScrlInc = 0; break; } if ((iScrlInc = max(-hhTerm->iHScrlPos, min(iScrlInc, hhTerm->iHScrlMax - hhTerm->iHScrlPos))) != 0) { HideCursors(hhTerm); i = -hhTerm->xChar * iScrlInc; j = 0; hhTerm->iHScrlPos += iScrlInc; GetClientRect(hwnd, &rc); rc.left += hhTerm->xIndent; // We have to adjust for the bezel when it is visible if (hhTerm->xBezel && (hhTerm->iHScrlPos == 0 || (hhTerm->iHScrlPos - iScrlInc) == 0) || hhTerm->iHScrlPos == hhTerm->iHScrlMax || (hhTerm->iHScrlPos - iScrlInc == hhTerm->iHScrlMax)) { k = hhTerm->xBezel - hhTerm->xChar; i += (iScrlInc > 0) ? -k : k; j = 1; // set for test below } ScrollWindow(hwnd, i, 0, 0, &rc); SetScrollPos(hwnd, SB_HORZ, hhTerm->iHScrlPos, TRUE); #if defined(FAR_EAST) InvalidateRect(hwnd, NULL, FALSE); #endif hhTerm->fScrolled = TRUE; if (j == 1) { GetUpdateRect(hwnd, &rc, FALSE); rc.left = 0; // makes sure bezel is drawn. InvalidateRect(hwnd, &rc, FALSE); } UpdateWindow(hwnd); ShowCursors(hhTerm); } return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_CHAR * * DESCRIPTION: * Processes the WM_CHAR and WM_KEYDOWN messages for termproc. * * ARGUMENTS: * hwnd - terminal window handle * message - WM_CHAR or WM_KEYDOWN * wPar - wParam * lPar - lParam * * RETURNS: * void * */ static void TP_WM_CHAR(const HWND hwnd, const UINT message, const WPARAM wPar, const LPARAM lPar) { MSG msg; KEY_T Key; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); #if 0 // // Removed this which caused problems with the OnScreen Keyboard (OSK) // in Whistler. REV: 01/12/2001 // if (GetKeyState(VK_LBUTTON) < 0) return; #endif //DbgOutStr("TP_WM_CHAR 0x%x 0x%x 0x%lx\r\n", message, wPar, lPar, 0,0); msg.hwnd = hwnd; msg.message = message; msg.wParam = wPar; msg.lParam = lPar; Key = TranslateToKey(&msg); if (!termTranslateKey(hhTerm, hwnd, Key)) { CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &Key, 1, CLOOP_KEYS); LinkCursors(hhTerm); } return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_IME_CHAR * * DESCRIPTION: * Processes the WM_IME_CHAR message for FE version of WACKER * * ARGUMENTS: * hwnd - terminal window handle * message - WM_IME_CHAR * wPar - wParam * lPar - lParam * * RETURNS: * void * */ static void TP_WM_IME_CHAR(const HWND hwnd, const UINT message, const WPARAM wPar, const LPARAM lPar) { KEY_T ktCode1; KEY_T ktCode2; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); //DbgOutStr("TP_WM_IME_CHAR 0x%x 0x%x 0x%lx\r\n", message, wPar, lPar, 0,0); /* * Later on, we may decide to create or modify something like the stuff * that goes on in TP_WM_CHAR, but until we get a better understanding of * how to process this stuff, just do it right here, in line, in all of * its ugly experimental foolishness. */ ktCode1 = (KEY_T)(wPar & 0xFF); /* Lower eight bits */ ktCode2 = (KEY_T)((wPar >> 8) & 0xFF); /* Upper eight bits */ /* * The documentation says that the lower eight bits are the first char, * but I am not too sure about that. It looks like the upper eight bits * is the lead byte and the lower eight bits is not. Keep an eye on this. */ //mpt:2-7-98 apparently, the korean ime can send us single byte characters // with 'null' as the other character, for some reason most host // systems don't like it when we send that null out the port. if (ktCode2 != 0) CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &ktCode2, 1, CLOOP_KEYS); if (ktCode1 != 0) CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &ktCode1, 1, CLOOP_KEYS); return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_TERM_KEY * * DESCRIPTION: * Term keys are keys we know are going to be translated by the * session macro or emulator sequence * * ARGUMENTS: * * RETURNS: * */ static void TP_WM_TERM_KEY(const HWND hwnd, KEY_T Key) { // Until we have a real macro key expander... const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (GetKeyState(VK_LBUTTON) < 0) return; if ( kabExpandMacroKey(hhTerm->hSession, Key) == 0) { CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &Key, 1, CLOOP_KEYS); } LinkCursors(hhTerm); return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_TERM_TRACK * * DESCRIPTION: * Causes terminal to track to the cursor position. If wPar is * 0, then we track only if we are not backscroll-locked and not * Mark-locked. If wPar is not 0, then we force tracking, * unmarking and unlocking the backscroll if necessary * * ARGUMENTS: * hhTerm - private term handle * fForce - force tracking no matter what. * * RETURNS: * void * */ static void TP_WM_TERM_TRACK(const HHTERM hhTerm, const int fForce) { int i, j; if ((hhTerm->fCursorTracking == 0 || hhTerm->fBackscrlLock != 0) && fForce == 0) { return; } j = 0; // First track vertically if (hhTerm->ptHstCur.y < hhTerm->iVScrlPos) i = hhTerm->ptHstCur.y; else if ((hhTerm->ptHstCur.y - hhTerm->iTermHite + 2) > hhTerm->iVScrlPos) i = hhTerm->ptHstCur.y - hhTerm->iTermHite + 2; else i = hhTerm->iVScrlPos; if (i != hhTerm->iVScrlPos) { // If we have enough room to display the entire terminal // then go go to iVScrlMax if (hhTerm->iTermHite > hhTerm->iRows) i = hhTerm->iVScrlMax; SendMessage(hhTerm->hwnd, WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, i), 0); j = 1; } // Now check for horizontal placement and adjust to make cursor // visible. if (hhTerm->ptHstCur.x < hhTerm->iHScrlPos) { i = hhTerm->ptHstCur.x; } else if (hhTerm->ptHstCur.x >= hhTerm->iHScrlPos + hhTerm->iCols - hhTerm->iHScrlMax) { i = hhTerm->ptHstCur.x - (hhTerm->iCols - hhTerm->iHScrlMax) + 5; } else { i = hhTerm->iHScrlPos; } if (i != hhTerm->iHScrlPos) { SendMessage(hhTerm->hwnd, WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, i), 0); j = 1; } if (j) LinkCursors(hhTerm); return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_EMU_SETTINGS * * DESCRIPTION: * Something important in the emulator has changed (like loading a new * emulator or changing the number of rows or columns). * * ARGUMENTS: * hhTerm - private terminal handle. * * RETURNS: * void * */ static void TP_WM_EMU_SETTINGS(const HHTERM hhTerm) { int iRows, iCols; BOOL fChange = FALSE; int iCurType; STEMUSET stEmuUserSettings; const HEMU hEmu = sessQueryEmuHdl(hhTerm->hSession); /* --- Check rows and columns --- */ emuQueryRowsCols(hEmu, &iRows, &iCols); if (iRows != hhTerm->iRows || iCols != hhTerm->iCols) { hhTerm->iRows = iRows; hhTerm->iCols = iCols; fChange = TRUE; } /* --- Query other emulator settings --- */ iCurType = emuQueryCursorType(hEmu); emuQuerySettings(hEmu, &stEmuUserSettings); hhTerm->fBlink = stEmuUserSettings.fCursorBlink; /* --- Check cursor type --- */ if (iCurType != hhTerm->iCurType) { fChange = TRUE; hhTerm->iCurType = iCurType; switch (hhTerm->iCurType) { case EMU_CURSOR_LINE: default: hhTerm->iHstCurSiz = GetSystemMetrics(SM_CYBORDER) * 2; break; case EMU_CURSOR_BLOCK: hhTerm->iHstCurSiz = hhTerm->yChar; break; case EMU_CURSOR_NONE: hhTerm->iHstCurSiz = 0; break; } } if (fChange) RefreshTermWindow(hhTerm->hwnd); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_TERM_LOAD_SETTINGS * * DESCRIPTION: * Loads terminal settings from session file. * * ARGUMENTS: * hhTerm - private terminal handle * * RETURNS: * 0=OK * */ static int TP_WM_TERM_LOAD_SETTINGS(const HHTERM hhTerm) { LONG lSize; if (hhTerm == 0) { assert(FALSE); return 1; } lSize = sizeof(hhTerm->lfSys); if (sfGetSessionItem(sessQuerySysFileHdl(hhTerm->hSession), SFID_TERM_LOGFONT, &lSize, &hhTerm->lfSys) == 0) { termSetFont(hhTerm, &hhTerm->lfSys); RefreshTermWindow(hhTerm->hwnd); } return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_TERM_SAVE_SETTINGS * * DESCRIPTION: * Saves terminal settings to session file. * * ARGUMENTS: * hhTerm - private terminal handle * * RETURNS: * 0=OK * */ static int TP_WM_TERM_SAVE_SETTINGS(const HHTERM hhTerm) { if (hhTerm == 0) { assert(FALSE); return 1; } if (memcmp(&hhTerm->lf, &hhTerm->lfSys, sizeof(hhTerm->lf))) { sfPutSessionItem(sessQuerySysFileHdl(hhTerm->hSession), SFID_TERM_LOGFONT, sizeof(hhTerm->lf), &hhTerm->lf); } return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * TP_WM_TERM_FORCE_WMSIZE * * DESCRIPTION: * Forces the terminal through its resize code to get things properly * updated. Used only when session is first initialized. * * ARGUMENTS: * hhTerm - private terminal handle. * * RETURNS: * void * */ static void TP_WM_TERM_FORCE_WMSIZE(const HHTERM hhTerm) { RECT rc; if (!IsWindow(hhTerm->hwnd)) return; hhTerm->iVScrlPos = hhTerm->iVScrlMax; hhTerm->iHScrlPos = 0; GetClientRect(hhTerm->hwnd, &rc); termGetUpdate(hhTerm, FALSE); TP_WM_SIZE(hhTerm->hwnd, 0, rc.right, rc.bottom); InvalidateRect(hhTerm->hwnd, 0, FALSE); return; } //****************************************************************************** // Method: // kabExpandMacroKey // // Description: // Determines if the key is a macro key and if so expands the macro and send // the keys to the CLOOP // // Arguments: // hSession - Session handle // aKey - The key to be expanded // // Returns: // non zero - if the key has been expanded, zero if the key is not a macro // // Throws: // None // // Author: Dwayne M. Newsome, 06/10/1998 // // static int kabExpandMacroKey( const HSESSION hSession, KEY_T aKey ) { int lReturn = 0; #if defined INCL_KEY_MACROS keyMacro lKeyMacro; int lKeyIndex = -1; int lIndex = 0; lKeyMacro.keyName = aKey; lKeyIndex = keysFindMacro( &lKeyMacro ); if ( lKeyIndex >= 0 ) { keysGetMacro( lKeyIndex, &lKeyMacro ); // // Replace the virtual return key with '\r' so that all the // line end processing works correctly. REV: 5/16/2002 // for ( lIndex = 0; lIndex < lKeyMacro.macroLen; lIndex++ ) { if ((VK_RETURN | VIRTUAL_KEY) == lKeyMacro.keyMacro[lIndex]) { lKeyMacro.keyMacro[lIndex] = TEXT('\r'); } } CLoopSend( sessQueryCLoopHdl(hSession), &lKeyMacro.keyMacro, lKeyMacro.macroLen, CLOOP_KEYS ); lReturn = 1; } #endif return lReturn; }