Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1276 lines
30 KiB

  1. /* File: D:\WACKER\tdll\termproc.c (Created: 06-Dec-1993)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 8 $
  7. * $Date: 5/29/02 2:17p $
  8. */
  9. #include <windows.h>
  10. #include <imm.h>
  11. #pragma hdrstop
  12. // #define DEBUGSTR 1
  13. #include "stdtyp.h"
  14. #include "sf.h"
  15. #include "sess_ids.h"
  16. #include "assert.h"
  17. #include "session.h"
  18. #include "backscrl.h"
  19. #include "timers.h"
  20. #if defined(INCL_KEY_MACROS)
  21. #include "keyutil.h"
  22. #endif
  23. #include "chars.h"
  24. #include "cloop.h"
  25. #include "misc.h"
  26. #include <emu\emu.h>
  27. #include "term.h"
  28. #include "term.hh"
  29. // When parsing values for mouse moves, scrolls, etc. HIWORD and LOWORD
  30. // clip the sign extension since these are 16 bit values. These macros
  31. // cast the result to a short so that sign extension works correctly
  32. #define LOSHORT(x) ((short)LOWORD(x))
  33. #define HISHORT(x) ((short)HIWORD(x))
  34. // HORZPAGESIZE represents the size in columns of one page horizontally.
  35. // We need this for two reasons. 1) We need a page size so we know how far
  36. // to skip when user "pages" horizontally using the scrollbar. 2) So we
  37. // have a size to set for the thumb size. Ten is arbritary but seems
  38. // about right. - mrw
  39. #define HORZPAGESIZE 10
  40. /* --- static function prototypes ---*/
  41. static void TP_WM_CREATE(const HWND hwnd);
  42. static void TP_WM_CHAR(const HWND hwnd, const UINT message,
  43. const WPARAM wPar, const LPARAM lPar);
  44. static void TP_WM_IME_CHAR(const HWND hwnd, const UINT message,
  45. const WPARAM wPar, const LPARAM lPar);
  46. static int kabExpandMacroKey( const HSESSION hSession, KEY_T aKey );
  47. static void TP_WM_TERM_KEY(const HWND hwnd, KEY_T Key);
  48. static void TP_WM_SETFOCUS(const HWND hwnd);
  49. static void TP_WM_KILLFOCUS(const HWND hwnd);
  50. static void TP_WM_VSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl);
  51. static void TP_WM_HSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl);
  52. static void TP_WM_TERM_TRACK(const HHTERM hhTerm, const int fForce);
  53. static void TP_WM_EMU_SETTINGS(const HHTERM hhTerm);
  54. static int TP_WM_TERM_LOAD_SETTINGS(const HHTERM hhTerm);
  55. static int TP_WM_TERM_SAVE_SETTINGS(const HHTERM hhTerm);
  56. static void TP_WM_TERM_FORCE_WMSIZE(const HHTERM hhTerm);
  57. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  58. * FUNCTION:
  59. * TermProc
  60. *
  61. * DESCRIPTION:
  62. * Terminal window
  63. *
  64. * ARGUMENTS:
  65. * Standard CALLBACK args
  66. *
  67. * RETURNS:
  68. * Standard CALLBACK codes
  69. *
  70. */
  71. LRESULT CALLBACK TermProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar)
  72. {
  73. HHTERM hhTerm;
  74. switch (uMsg)
  75. {
  76. case WM_HELP:
  77. // We do not want start the help engine due to F1 when function
  78. // keys are being interpreted as terminal keys
  79. // (NOT Windows keys). JRJ 12/94
  80. //
  81. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  82. if(emuIsEmuKey(sessQueryEmuHdl(hhTerm->hSession),
  83. VIRTUAL_KEY | VK_F1))
  84. {
  85. return 0;
  86. }
  87. break;
  88. case WM_CREATE:
  89. TP_WM_CREATE(hwnd);
  90. return 0;
  91. case WM_SIZE:
  92. TP_WM_SIZE(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar));
  93. return 0;
  94. case WM_IME_CHAR:
  95. TP_WM_IME_CHAR(hwnd, uMsg, wPar, lPar);
  96. return 0;
  97. case WM_KEYDOWN:
  98. case WM_CHAR:
  99. TP_WM_CHAR(hwnd, uMsg, wPar, lPar);
  100. return 0;
  101. case WM_PAINT:
  102. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  103. termPaint(hhTerm, hwnd);
  104. return 0;
  105. case WM_SYSCOLORCHANGE:
  106. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  107. termSysColorChng(hhTerm);
  108. return 0;
  109. case WM_SETFOCUS:
  110. TP_WM_SETFOCUS(hwnd);
  111. return 0;
  112. case WM_KILLFOCUS:
  113. TP_WM_KILLFOCUS(hwnd);
  114. return 0;
  115. case WM_VSCROLL:
  116. TP_WM_VSCROLL(hwnd, LOWORD(wPar), HISHORT(wPar), (HWND)lPar);
  117. return 0;
  118. case WM_HSCROLL:
  119. TP_WM_HSCROLL(hwnd, LOWORD(wPar), HISHORT(wPar), (HWND)lPar);
  120. return 0;
  121. case WM_LBUTTONDOWN:
  122. TP_WM_LBTNDN(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar));
  123. return 0;
  124. case WM_MOUSEMOVE:
  125. TP_WM_MOUSEMOVE(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar));
  126. return 0;
  127. case WM_LBUTTONUP:
  128. TP_WM_LBTNUP(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar));
  129. return 0;
  130. case WM_LBUTTONDBLCLK:
  131. TP_WM_LBTNDBLCLK(hwnd, (unsigned)wPar, LOSHORT(lPar), HISHORT(lPar));
  132. return 0;
  133. case WM_DESTROY:
  134. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  135. DestroyTerminalHdl(hhTerm);
  136. hhTerm = NULL;
  137. return 0;
  138. /* --- Public terminal messages --- */
  139. case WM_TERM_GETUPDATE:
  140. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  141. termGetUpdate(hhTerm, TRUE);
  142. return 0;
  143. case WM_TERM_BEZEL:
  144. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  145. hhTerm->xBezel = (hhTerm->xBezel) ? 0 : BEZEL_SIZE;
  146. // Need to recompute scrollbar min's and max's since the
  147. // presence/absence of the bezel affects these items. This
  148. // is done in the WM_SIZE handler and can be called directly
  149. // with the current client size.
  150. TP_WM_SIZE(hwnd, SIZE_RESTORED, hhTerm->cx, hhTerm->cy);
  151. InvalidateRect(hwnd, 0, FALSE);
  152. return 0;
  153. case WM_TERM_Q_BEZEL:
  154. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  155. return hhTerm->xBezel;
  156. case WM_TERM_Q_SNAP:
  157. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  158. termQuerySnapRect(hhTerm, (LPRECT)lPar);
  159. return 0;
  160. case WM_TERM_KEY:
  161. TP_WM_TERM_KEY(hwnd, (unsigned)wPar);
  162. return 0;
  163. case WM_TERM_CLRATTR:
  164. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  165. termSetClrAttr(hhTerm);
  166. return 0;
  167. case WM_TERM_GETLOGFONT:
  168. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  169. *(PLOGFONT)lPar = hhTerm->lf;
  170. return 0;
  171. case WM_TERM_SETLOGFONT:
  172. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  173. termSetFont(hhTerm, (PLOGFONT)lPar);
  174. return 0;
  175. case WM_TERM_Q_MARKED:
  176. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  177. return hhTerm->fMarkingLock;
  178. case WM_TERM_UNMARK:
  179. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  180. LinkCursors(hhTerm);
  181. return 0;
  182. case WM_TERM_MARK_ALL:
  183. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  184. MarkTextAll(hhTerm);
  185. return 0;
  186. case WM_TERM_TRACK:
  187. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  188. TP_WM_TERM_TRACK(hhTerm, (int)wPar);
  189. return 0;
  190. case WM_TERM_EMU_SETTINGS:
  191. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  192. TP_WM_EMU_SETTINGS(hhTerm);
  193. return 0;
  194. case WM_TERM_Q_MARKED_RANGE:
  195. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  196. *(PPOINT)wPar = hhTerm->ptBeg;
  197. *(PPOINT)lPar = hhTerm->ptEnd;
  198. return 0;
  199. case WM_TERM_LOAD_SETTINGS:
  200. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  201. TP_WM_TERM_LOAD_SETTINGS(hhTerm);
  202. return 0;
  203. case WM_TERM_SAVE_SETTINGS:
  204. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  205. TP_WM_TERM_SAVE_SETTINGS(hhTerm);
  206. return 0;
  207. case WM_TERM_FORCE_WMSIZE:
  208. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  209. TP_WM_TERM_FORCE_WMSIZE(hhTerm);
  210. return 0;
  211. /* --- Private terminal messages --- */
  212. case WM_TERM_SCRLMARK:
  213. MarkingTimerProc((void *)hwnd, 0);
  214. return 0;
  215. case WM_TERM_KLUDGE_FONT:
  216. hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  217. termSetFont(hhTerm, &hhTerm->lfHold);
  218. RefreshTermWindow(hwnd);
  219. return 0;
  220. default:
  221. break;
  222. }
  223. return DefWindowProc(hwnd, uMsg, wPar, lPar);
  224. }
  225. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  226. * FUNCTION:
  227. * TP_WM_CREATE
  228. *
  229. * DESCRIPTION:
  230. * Create message processor for terminal window.
  231. *
  232. * ARGUMENTS:
  233. * hwnd - terminal window handle
  234. *
  235. * RETURNS:
  236. * void
  237. *
  238. */
  239. static void TP_WM_CREATE(const HWND hwnd)
  240. {
  241. HHTERM hhTerm;
  242. SCROLLINFO scrinf;
  243. #if(WINVER >= 0x0500)
  244. LONG_PTR ExStyle;
  245. ExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
  246. //
  247. // [mhamid] If it is mirrored then turn off mirroing.
  248. //
  249. if (ExStyle & WS_EX_LAYOUTRTL)
  250. {
  251. SetWindowLongPtr(hwnd, GWL_EXSTYLE, (LONG_PTR)(ExStyle & ~WS_EX_LAYOUTRTL));
  252. }
  253. #endif // WINVER >= 0x0500
  254. // Create an internal handle for instance data storage.
  255. hhTerm = CreateTerminalHdl(hwnd);
  256. // Need to set this even if hTerm is 0 so WM_DESTROY works.
  257. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)hhTerm);
  258. if (hhTerm == 0)
  259. {
  260. assert(FALSE);
  261. ExitProcess(1);
  262. }
  263. scrinf.cbSize = sizeof(scrinf);
  264. scrinf.fMask = SIF_DISABLENOSCROLL;
  265. SetScrollInfo(hwnd, SB_VERT, &scrinf, 0);
  266. return;
  267. }
  268. #if 0
  269. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  270. * FUNCTION:
  271. * TP_WM_CMD
  272. *
  273. * DESCRIPTION:
  274. * WM_COMMAND processor for TermProc()
  275. *
  276. * ARGUMENTS:
  277. * hwnd - terminal window handle
  278. * nId - item, control, or accelerator identifier
  279. * nNotify - notification code
  280. * hwndCtrl - handle of control
  281. *
  282. * RETURNS:
  283. * void
  284. *
  285. */
  286. static void TP_WM_CMD(const HWND hwnd, const int nId, const int nNotify,
  287. const HWND hwndCtrl)
  288. {
  289. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  290. switch (nId)
  291. {
  292. case WM_USER:
  293. break;
  294. }
  295. return;
  296. }
  297. #endif
  298. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  299. * FUNCTION:
  300. * TP_WM_SIZE
  301. *
  302. * DESCRIPTION:
  303. * WM_SIZE message processor for termproc. If iWidth and iHite are zero,
  304. * then the window sizes itself to fit the session window accounting for
  305. * statusbars and toolbars.
  306. *
  307. * ARGUMENTS:
  308. * hwnd - terminal window
  309. * fwSizeType - from WM_SIZE
  310. * iWidth - width of window
  311. * iHite - hite of window
  312. *
  313. * RETURNS:
  314. * void
  315. *
  316. */
  317. void TP_WM_SIZE(const HWND hwnd,
  318. const unsigned fwSizeType,
  319. const int iWidth,
  320. const int iHite)
  321. {
  322. RECT rc, rcTmp;
  323. int i, j, k;
  324. SCROLLINFO scrinf;
  325. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  326. const HWND hwndToolbar = sessQueryHwndToolbar(hhTerm->hSession);
  327. const HWND hwndStatusbar = sessQueryHwndStatusbar(hhTerm->hSession);
  328. const HWND hwndSidebar = sessQuerySidebarHwnd(hhTerm->hSession);
  329. // If the window is hidden, we really don't need to do anything.
  330. if (!IsWindowVisible(hwnd))
  331. return;
  332. // If we get a message with 0, 0 for width, hite, make terminal window
  333. // fit the session window less the toolbar and statusbar if present.
  334. if (iWidth == 0 && iHite == 0)
  335. {
  336. GetClientRect(hhTerm->hwndSession, &rc);
  337. // Note: See if we can use sessQuery funcs for
  338. // this
  339. if (IsWindow(hwndToolbar) && IsWindowVisible(hwndToolbar))
  340. {
  341. GetWindowRect(hwndToolbar, &rcTmp);
  342. rc.top += (rcTmp.bottom - rcTmp.top);
  343. }
  344. if (IsWindow(hwndStatusbar) && IsWindowVisible(hwndStatusbar))
  345. {
  346. GetWindowRect(hwndStatusbar, &rcTmp);
  347. rc.bottom -= (rcTmp.bottom - rcTmp.top);
  348. rc.bottom += 2 * GetSystemMetrics(SM_CYBORDER);
  349. }
  350. if (IsWindow(hwndSidebar) && IsWindowVisible(hwndSidebar))
  351. {
  352. GetWindowRect(hwndSidebar, &rcTmp);
  353. rc.left += (rcTmp.right - rcTmp.left);
  354. }
  355. MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
  356. TRUE);
  357. }
  358. // Compute size related items.
  359. else
  360. {
  361. hhTerm->cx = iWidth;
  362. hhTerm->cy = iHite;
  363. // Set Min's and Max's now.
  364. i = hhTerm->iTermHite; // save old height for bottom line alignment
  365. hhTerm->iTermHite = hhTerm->cy / hhTerm->yChar;
  366. // If bezel is drawn, make sure we have room
  367. j = 0;
  368. if (hhTerm->xBezel)
  369. {
  370. if ((hhTerm->cy % hhTerm->yChar) < (hhTerm->xBezel + 1))
  371. j = 1;
  372. }
  373. hhTerm->iVScrlMin = min(-hhTerm->iBkLines,
  374. hhTerm->iRows - hhTerm->iTermHite + 1 + j);
  375. // Little hack here to make sure that if we were at the bottom
  376. // we show the bottom.
  377. k = (hhTerm->iVScrlMax == hhTerm->iVScrlPos);
  378. hhTerm->iVScrlMax = max(hhTerm->iVScrlMin, hhTerm->iRows + 1 + j
  379. - hhTerm->iTermHite);
  380. // First time through set to bottom
  381. if (k)
  382. hhTerm->iVScrlPos = hhTerm->iVScrlMax;
  383. else
  384. hhTerm->iVScrlPos -= hhTerm->iTermHite - i;
  385. hhTerm->iVScrlPos = max(hhTerm->iVScrlPos, hhTerm->iVScrlMin);
  386. hhTerm->iVScrlPos = min(hhTerm->iVScrlPos, hhTerm->iVScrlMax);
  387. // hhTerm->iHScrlMax = #Cols - #Cols Showing
  388. hhTerm->iHScrlMax = max(0, hhTerm->iCols -
  389. ((hhTerm->cx - hhTerm->xIndent - (2 * hhTerm->xBezel))
  390. / hhTerm->xChar));
  391. hhTerm->iHScrlPos = min(hhTerm->iHScrlPos, hhTerm->iHScrlMax);
  392. // Check to see if we scrolled entirely into backscroll
  393. // region. If so, set fBackscrlLock for this view. And refill
  394. // its backscroll buffer (important).
  395. if ((hhTerm->iVScrlPos + hhTerm->iTermHite) <= 0)
  396. {
  397. hhTerm->fBackscrlLock = TRUE;
  398. termFillBk(hhTerm, hhTerm->iVScrlPos);
  399. }
  400. else
  401. {
  402. hhTerm->fBackscrlLock = FALSE;
  403. termFillBk(hhTerm, -hhTerm->iTermHite);
  404. }
  405. /* --- Vertical scroll bar --- */
  406. scrinf.cbSize= sizeof(scrinf);
  407. scrinf.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
  408. scrinf.nMin = hhTerm->iVScrlMin;
  409. scrinf.nMax = hhTerm->iVScrlMax + hhTerm->iTermHite - 1;
  410. scrinf.nPos = hhTerm->iVScrlPos;
  411. scrinf.nPage = hhTerm->iTermHite;
  412. SetScrollInfo(hwnd, SB_VERT, &scrinf, TRUE);
  413. /* --- Horizontal scroll bar --- */
  414. i = hhTerm->iHScrlMax - hhTerm->iHScrlMin;
  415. scrinf.cbSize= sizeof(scrinf);
  416. scrinf.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
  417. scrinf.nMin = hhTerm->iHScrlMin;
  418. scrinf.nMax = hhTerm->iHScrlMax + HORZPAGESIZE - 1;
  419. scrinf.nPos = hhTerm->iHScrlPos;
  420. scrinf.nPage = HORZPAGESIZE;
  421. SetScrollInfo(hwnd, SB_HORZ, &scrinf, TRUE);
  422. }
  423. return;
  424. }
  425. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  426. * FUNCTION:
  427. * TP_WM_SETFOCUS
  428. *
  429. * DESCRIPTION:
  430. * Handler for WM_SETFOCUS message
  431. *
  432. * ARGUMENTS:
  433. * hwnd - terminal window handle.
  434. *
  435. * RETURNS:
  436. * void
  437. *
  438. */
  439. static void TP_WM_SETFOCUS(const HWND hwnd)
  440. {
  441. int i;
  442. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  443. hhTerm->fFocus = TRUE;
  444. // Use Multiplexer timer for cursor and blinking text.
  445. if (!hhTerm->hCursorTimer)
  446. {
  447. i = TimerCreate(hhTerm->hSession,
  448. &hhTerm->hCursorTimer,
  449. (long)hhTerm->uBlinkRate,
  450. CursorTimerProc,
  451. (void *)hwnd);
  452. if (i != TIMER_OK)
  453. assert(FALSE);
  454. }
  455. ShowCursors(hhTerm);
  456. return;
  457. }
  458. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  459. * FUNCTION:
  460. * TP_WM_KILLFOCUS
  461. *
  462. * DESCRIPTION:
  463. * Handler for WM_KILLFOCUS message.
  464. *
  465. * ARGUMENTS:
  466. * hwnd - terminal window handle.
  467. *
  468. * RETURNS:
  469. * void
  470. *
  471. */
  472. static void TP_WM_KILLFOCUS(const HWND hwnd)
  473. {
  474. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  475. hhTerm->fFocus = FALSE;
  476. if (hhTerm->hCursorTimer)
  477. {
  478. TimerDestroy(&hhTerm->hCursorTimer);
  479. }
  480. HideCursors(hhTerm);
  481. return;
  482. }
  483. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  484. * FUNCTION:
  485. * TP_WM_VSCROLL
  486. *
  487. * DESCRIPTION:
  488. * Message handler for terminal window's WM_VSCROLL
  489. *
  490. * ARGUMENTS:
  491. * hwnd - terminal window handle
  492. * nCode - scrollbar value
  493. * nPos - scrollbox pos
  494. * hwndScrl - window handle of scrollbar
  495. *
  496. * RETURNS:
  497. * void
  498. *
  499. */
  500. static void TP_WM_VSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl)
  501. {
  502. int i;
  503. int iScrlInc;
  504. RECT rc;
  505. SCROLLINFO scrinf;
  506. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  507. switch (nCode)
  508. {
  509. case SB_TOP:
  510. iScrlInc = -(hhTerm->iVScrlPos - hhTerm->iVScrlMin);
  511. break;
  512. case SB_BOTTOM:
  513. iScrlInc = hhTerm->iVScrlMax - hhTerm->iVScrlPos;
  514. break;
  515. case SB_LINEUP:
  516. iScrlInc = -1;
  517. break;
  518. case SB_LINEDOWN:
  519. iScrlInc = 1;
  520. break;
  521. case SB_PAGEUP:
  522. iScrlInc = min(-1, -hhTerm->iTermHite);
  523. break;
  524. case SB_PAGEDOWN:
  525. iScrlInc = max(1, hhTerm->iTermHite);
  526. break;
  527. case SB_THUMBTRACK:
  528. case SB_THUMBPOSITION:
  529. iScrlInc = nPos - hhTerm->iVScrlPos;
  530. break;
  531. default:
  532. iScrlInc = 0;
  533. break;
  534. }
  535. if ((iScrlInc = max(-(hhTerm->iVScrlPos - hhTerm->iVScrlMin),
  536. min(iScrlInc, hhTerm->iVScrlMax - hhTerm->iVScrlPos))) != 0)
  537. {
  538. HideCursors(hhTerm);
  539. hhTerm->iVScrlPos += iScrlInc;
  540. GetClientRect(hwnd, &rc);
  541. i = rc.bottom;
  542. rc.bottom = hhTerm->iTermHite * hhTerm->yChar;
  543. hhTerm->yBrushOrg = (hhTerm->yBrushOrg +
  544. (-hhTerm->yChar * iScrlInc)) % 8;
  545. ScrollWindow(hwnd, 0, -hhTerm->yChar * iScrlInc, 0, &rc);
  546. scrinf.cbSize = sizeof(scrinf);
  547. scrinf.fMask = SIF_DISABLENOSCROLL | SIF_POS;
  548. scrinf.nPos = hhTerm->iVScrlPos;
  549. SetScrollInfo(hwnd, SB_VERT, &scrinf, TRUE);
  550. hhTerm->fScrolled = TRUE;
  551. // Check to see if we scrolled entirely into backscroll
  552. // region. If so, set fBackscrlLock for this view.
  553. if ((hhTerm->iVScrlPos + hhTerm->iTermHite) <= 0)
  554. {
  555. if (hhTerm->fBackscrlLock == FALSE)
  556. termFillBk(hhTerm, hhTerm->iVScrlPos);
  557. else
  558. termGetBkLines(hhTerm, iScrlInc, hhTerm->iVScrlPos, BKPOS_THUMBPOS);
  559. hhTerm->fBackscrlLock = TRUE;
  560. }
  561. else
  562. {
  563. if (hhTerm->fBackscrlLock == TRUE)
  564. termFillBk(hhTerm, -hhTerm->iTermHite);
  565. hhTerm->fBackscrlLock = FALSE;
  566. }
  567. // Make two seperate calls to WM_PAINT to optimize screen
  568. // updates in the case of a negative scroll operation.
  569. if (iScrlInc < 0)
  570. UpdateWindow(hwnd);
  571. // Fill-in fractional part of line at bottom of terminal
  572. // screen with appropriate color by invalidating that region.
  573. if (i > rc.bottom)
  574. {
  575. rc.top = rc.bottom;
  576. rc.bottom = i;
  577. InvalidateRect(hwnd, &rc, FALSE);
  578. }
  579. UpdateWindow(hwnd);
  580. ShowCursors(hhTerm);
  581. #if 0 // debugging stuff...
  582. {
  583. char ach[50];
  584. wsprintf(ach, "pos=%d min=%d max=%d", hhTerm->iVScrlPos,
  585. hhTerm->iVScrlMin, hhTerm->iVScrlMax);
  586. SetWindowText(sessQueryHwndStatusbar(hhTerm->hSession), ach);
  587. }
  588. #endif
  589. }
  590. return;
  591. }
  592. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  593. * FUNCTION:
  594. * TP_WM_HSCROLL
  595. *
  596. * DESCRIPTION:
  597. * Message handler for terminal window's WM_HSCROLL
  598. *
  599. * ARGUMENTS:
  600. * hwnd - terminal window handle
  601. * nCode - scrollbar value
  602. * nPos - scrollbox pos
  603. * hwndScrl - window handle of scrollbar
  604. *
  605. * RETURNS:
  606. * void
  607. *
  608. */
  609. static void TP_WM_HSCROLL(HWND hwnd, int nCode, int nPos, HWND hwndScrl)
  610. {
  611. int i, j, k;
  612. int iScrlInc;
  613. RECT rc;
  614. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  615. switch (nCode)
  616. {
  617. case SB_LINEUP:
  618. iScrlInc = -1;
  619. break;
  620. case SB_LINEDOWN:
  621. iScrlInc = 1;
  622. break;
  623. case SB_PAGEUP:
  624. iScrlInc = -HORZPAGESIZE;
  625. break;
  626. case SB_PAGEDOWN:
  627. iScrlInc = HORZPAGESIZE;
  628. break;
  629. case SB_THUMBTRACK:
  630. case SB_THUMBPOSITION:
  631. iScrlInc = nPos - hhTerm->iHScrlPos;
  632. break;
  633. default:
  634. iScrlInc = 0;
  635. break;
  636. }
  637. if ((iScrlInc = max(-hhTerm->iHScrlPos,
  638. min(iScrlInc, hhTerm->iHScrlMax - hhTerm->iHScrlPos))) != 0)
  639. {
  640. HideCursors(hhTerm);
  641. i = -hhTerm->xChar * iScrlInc;
  642. j = 0;
  643. hhTerm->iHScrlPos += iScrlInc;
  644. GetClientRect(hwnd, &rc);
  645. rc.left += hhTerm->xIndent;
  646. // We have to adjust for the bezel when it is visible
  647. if (hhTerm->xBezel &&
  648. (hhTerm->iHScrlPos == 0 ||
  649. (hhTerm->iHScrlPos - iScrlInc) == 0) ||
  650. hhTerm->iHScrlPos == hhTerm->iHScrlMax ||
  651. (hhTerm->iHScrlPos - iScrlInc == hhTerm->iHScrlMax))
  652. {
  653. k = hhTerm->xBezel - hhTerm->xChar;
  654. i += (iScrlInc > 0) ? -k : k;
  655. j = 1; // set for test below
  656. }
  657. ScrollWindow(hwnd, i, 0, 0, &rc);
  658. SetScrollPos(hwnd, SB_HORZ, hhTerm->iHScrlPos, TRUE);
  659. #if defined(FAR_EAST)
  660. InvalidateRect(hwnd, NULL, FALSE);
  661. #endif
  662. hhTerm->fScrolled = TRUE;
  663. if (j == 1)
  664. {
  665. GetUpdateRect(hwnd, &rc, FALSE);
  666. rc.left = 0; // makes sure bezel is drawn.
  667. InvalidateRect(hwnd, &rc, FALSE);
  668. }
  669. UpdateWindow(hwnd);
  670. ShowCursors(hhTerm);
  671. }
  672. return;
  673. }
  674. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  675. * FUNCTION:
  676. * TP_WM_CHAR
  677. *
  678. * DESCRIPTION:
  679. * Processes the WM_CHAR and WM_KEYDOWN messages for termproc.
  680. *
  681. * ARGUMENTS:
  682. * hwnd - terminal window handle
  683. * message - WM_CHAR or WM_KEYDOWN
  684. * wPar - wParam
  685. * lPar - lParam
  686. *
  687. * RETURNS:
  688. * void
  689. *
  690. */
  691. static void TP_WM_CHAR(const HWND hwnd, const UINT message,
  692. const WPARAM wPar, const LPARAM lPar)
  693. {
  694. MSG msg;
  695. KEY_T Key;
  696. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  697. #if 0
  698. //
  699. // Removed this which caused problems with the OnScreen Keyboard (OSK)
  700. // in Whistler. REV: 01/12/2001
  701. //
  702. if (GetKeyState(VK_LBUTTON) < 0)
  703. return;
  704. #endif
  705. //DbgOutStr("TP_WM_CHAR 0x%x 0x%x 0x%lx\r\n", message, wPar, lPar, 0,0);
  706. msg.hwnd = hwnd;
  707. msg.message = message;
  708. msg.wParam = wPar;
  709. msg.lParam = lPar;
  710. Key = TranslateToKey(&msg);
  711. if (!termTranslateKey(hhTerm, hwnd, Key))
  712. {
  713. CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &Key, 1, CLOOP_KEYS);
  714. LinkCursors(hhTerm);
  715. }
  716. return;
  717. }
  718. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  719. * FUNCTION:
  720. * TP_WM_IME_CHAR
  721. *
  722. * DESCRIPTION:
  723. * Processes the WM_IME_CHAR message for FE version of WACKER
  724. *
  725. * ARGUMENTS:
  726. * hwnd - terminal window handle
  727. * message - WM_IME_CHAR
  728. * wPar - wParam
  729. * lPar - lParam
  730. *
  731. * RETURNS:
  732. * void
  733. *
  734. */
  735. static void TP_WM_IME_CHAR(const HWND hwnd, const UINT message,
  736. const WPARAM wPar, const LPARAM lPar)
  737. {
  738. KEY_T ktCode1;
  739. KEY_T ktCode2;
  740. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  741. //DbgOutStr("TP_WM_IME_CHAR 0x%x 0x%x 0x%lx\r\n", message, wPar, lPar, 0,0);
  742. /*
  743. * Later on, we may decide to create or modify something like the stuff
  744. * that goes on in TP_WM_CHAR, but until we get a better understanding of
  745. * how to process this stuff, just do it right here, in line, in all of
  746. * its ugly experimental foolishness.
  747. */
  748. ktCode1 = (KEY_T)(wPar & 0xFF); /* Lower eight bits */
  749. ktCode2 = (KEY_T)((wPar >> 8) & 0xFF); /* Upper eight bits */
  750. /*
  751. * The documentation says that the lower eight bits are the first char,
  752. * but I am not too sure about that. It looks like the upper eight bits
  753. * is the lead byte and the lower eight bits is not. Keep an eye on this.
  754. */
  755. //mpt:2-7-98 apparently, the korean ime can send us single byte characters
  756. // with 'null' as the other character, for some reason most host
  757. // systems don't like it when we send that null out the port.
  758. if (ktCode2 != 0)
  759. CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &ktCode2, 1, CLOOP_KEYS);
  760. if (ktCode1 != 0)
  761. CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &ktCode1, 1, CLOOP_KEYS);
  762. return;
  763. }
  764. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  765. * FUNCTION:
  766. * TP_WM_TERM_KEY
  767. *
  768. * DESCRIPTION:
  769. * Term keys are keys we know are going to be translated by the
  770. * session macro or emulator sequence
  771. *
  772. * ARGUMENTS:
  773. *
  774. * RETURNS:
  775. *
  776. */
  777. static void TP_WM_TERM_KEY(const HWND hwnd, KEY_T Key)
  778. {
  779. // Until we have a real macro key expander...
  780. const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  781. if (GetKeyState(VK_LBUTTON) < 0)
  782. return;
  783. if ( kabExpandMacroKey(hhTerm->hSession, Key) == 0)
  784. {
  785. CLoopSend(sessQueryCLoopHdl(hhTerm->hSession), &Key, 1, CLOOP_KEYS);
  786. }
  787. LinkCursors(hhTerm);
  788. return;
  789. }
  790. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  791. * FUNCTION:
  792. * TP_WM_TERM_TRACK
  793. *
  794. * DESCRIPTION:
  795. * Causes terminal to track to the cursor position. If wPar is
  796. * 0, then we track only if we are not backscroll-locked and not
  797. * Mark-locked. If wPar is not 0, then we force tracking,
  798. * unmarking and unlocking the backscroll if necessary
  799. *
  800. * ARGUMENTS:
  801. * hhTerm - private term handle
  802. * fForce - force tracking no matter what.
  803. *
  804. * RETURNS:
  805. * void
  806. *
  807. */
  808. static void TP_WM_TERM_TRACK(const HHTERM hhTerm, const int fForce)
  809. {
  810. int i, j;
  811. if ((hhTerm->fCursorTracking == 0 || hhTerm->fBackscrlLock != 0)
  812. && fForce == 0)
  813. {
  814. return;
  815. }
  816. j = 0;
  817. // First track vertically
  818. if (hhTerm->ptHstCur.y < hhTerm->iVScrlPos)
  819. i = hhTerm->ptHstCur.y;
  820. else if ((hhTerm->ptHstCur.y - hhTerm->iTermHite + 2) > hhTerm->iVScrlPos)
  821. i = hhTerm->ptHstCur.y - hhTerm->iTermHite + 2;
  822. else
  823. i = hhTerm->iVScrlPos;
  824. if (i != hhTerm->iVScrlPos)
  825. {
  826. // If we have enough room to display the entire terminal
  827. // then go go to iVScrlMax
  828. if (hhTerm->iTermHite > hhTerm->iRows)
  829. i = hhTerm->iVScrlMax;
  830. SendMessage(hhTerm->hwnd, WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, i), 0);
  831. j = 1;
  832. }
  833. // Now check for horizontal placement and adjust to make cursor
  834. // visible.
  835. if (hhTerm->ptHstCur.x < hhTerm->iHScrlPos)
  836. {
  837. i = hhTerm->ptHstCur.x;
  838. }
  839. else if (hhTerm->ptHstCur.x >= hhTerm->iHScrlPos +
  840. hhTerm->iCols - hhTerm->iHScrlMax)
  841. {
  842. i = hhTerm->ptHstCur.x - (hhTerm->iCols - hhTerm->iHScrlMax) + 5;
  843. }
  844. else
  845. {
  846. i = hhTerm->iHScrlPos;
  847. }
  848. if (i != hhTerm->iHScrlPos)
  849. {
  850. SendMessage(hhTerm->hwnd, WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, i), 0);
  851. j = 1;
  852. }
  853. if (j)
  854. LinkCursors(hhTerm);
  855. return;
  856. }
  857. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  858. * FUNCTION:
  859. * TP_WM_EMU_SETTINGS
  860. *
  861. * DESCRIPTION:
  862. * Something important in the emulator has changed (like loading a new
  863. * emulator or changing the number of rows or columns).
  864. *
  865. * ARGUMENTS:
  866. * hhTerm - private terminal handle.
  867. *
  868. * RETURNS:
  869. * void
  870. *
  871. */
  872. static void TP_WM_EMU_SETTINGS(const HHTERM hhTerm)
  873. {
  874. int iRows, iCols;
  875. BOOL fChange = FALSE;
  876. int iCurType;
  877. STEMUSET stEmuUserSettings;
  878. const HEMU hEmu = sessQueryEmuHdl(hhTerm->hSession);
  879. /* --- Check rows and columns --- */
  880. emuQueryRowsCols(hEmu, &iRows, &iCols);
  881. if (iRows != hhTerm->iRows || iCols != hhTerm->iCols)
  882. {
  883. hhTerm->iRows = iRows;
  884. hhTerm->iCols = iCols;
  885. fChange = TRUE;
  886. }
  887. /* --- Query other emulator settings --- */
  888. iCurType = emuQueryCursorType(hEmu);
  889. emuQuerySettings(hEmu, &stEmuUserSettings);
  890. hhTerm->fBlink = stEmuUserSettings.fCursorBlink;
  891. /* --- Check cursor type --- */
  892. if (iCurType != hhTerm->iCurType)
  893. {
  894. fChange = TRUE;
  895. hhTerm->iCurType = iCurType;
  896. switch (hhTerm->iCurType)
  897. {
  898. case EMU_CURSOR_LINE:
  899. default:
  900. hhTerm->iHstCurSiz = GetSystemMetrics(SM_CYBORDER) * 2;
  901. break;
  902. case EMU_CURSOR_BLOCK:
  903. hhTerm->iHstCurSiz = hhTerm->yChar;
  904. break;
  905. case EMU_CURSOR_NONE:
  906. hhTerm->iHstCurSiz = 0;
  907. break;
  908. }
  909. }
  910. if (fChange)
  911. RefreshTermWindow(hhTerm->hwnd);
  912. }
  913. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  914. * FUNCTION:
  915. * TP_WM_TERM_LOAD_SETTINGS
  916. *
  917. * DESCRIPTION:
  918. * Loads terminal settings from session file.
  919. *
  920. * ARGUMENTS:
  921. * hhTerm - private terminal handle
  922. *
  923. * RETURNS:
  924. * 0=OK
  925. *
  926. */
  927. static int TP_WM_TERM_LOAD_SETTINGS(const HHTERM hhTerm)
  928. {
  929. LONG lSize;
  930. if (hhTerm == 0)
  931. {
  932. assert(FALSE);
  933. return 1;
  934. }
  935. lSize = sizeof(hhTerm->lfSys);
  936. if (sfGetSessionItem(sessQuerySysFileHdl(hhTerm->hSession),
  937. SFID_TERM_LOGFONT, &lSize, &hhTerm->lfSys) == 0)
  938. {
  939. termSetFont(hhTerm, &hhTerm->lfSys);
  940. RefreshTermWindow(hhTerm->hwnd);
  941. }
  942. return 0;
  943. }
  944. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  945. * FUNCTION:
  946. * TP_WM_TERM_SAVE_SETTINGS
  947. *
  948. * DESCRIPTION:
  949. * Saves terminal settings to session file.
  950. *
  951. * ARGUMENTS:
  952. * hhTerm - private terminal handle
  953. *
  954. * RETURNS:
  955. * 0=OK
  956. *
  957. */
  958. static int TP_WM_TERM_SAVE_SETTINGS(const HHTERM hhTerm)
  959. {
  960. if (hhTerm == 0)
  961. {
  962. assert(FALSE);
  963. return 1;
  964. }
  965. if (memcmp(&hhTerm->lf, &hhTerm->lfSys, sizeof(hhTerm->lf)))
  966. {
  967. sfPutSessionItem(sessQuerySysFileHdl(hhTerm->hSession),
  968. SFID_TERM_LOGFONT, sizeof(hhTerm->lf), &hhTerm->lf);
  969. }
  970. return 0;
  971. }
  972. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  973. * FUNCTION:
  974. * TP_WM_TERM_FORCE_WMSIZE
  975. *
  976. * DESCRIPTION:
  977. * Forces the terminal through its resize code to get things properly
  978. * updated. Used only when session is first initialized.
  979. *
  980. * ARGUMENTS:
  981. * hhTerm - private terminal handle.
  982. *
  983. * RETURNS:
  984. * void
  985. *
  986. */
  987. static void TP_WM_TERM_FORCE_WMSIZE(const HHTERM hhTerm)
  988. {
  989. RECT rc;
  990. if (!IsWindow(hhTerm->hwnd))
  991. return;
  992. hhTerm->iVScrlPos = hhTerm->iVScrlMax;
  993. hhTerm->iHScrlPos = 0;
  994. GetClientRect(hhTerm->hwnd, &rc);
  995. termGetUpdate(hhTerm, FALSE);
  996. TP_WM_SIZE(hhTerm->hwnd, 0, rc.right, rc.bottom);
  997. InvalidateRect(hhTerm->hwnd, 0, FALSE);
  998. return;
  999. }
  1000. //******************************************************************************
  1001. // Method:
  1002. // kabExpandMacroKey
  1003. //
  1004. // Description:
  1005. // Determines if the key is a macro key and if so expands the macro and send
  1006. // the keys to the CLOOP
  1007. //
  1008. // Arguments:
  1009. // hSession - Session handle
  1010. // aKey - The key to be expanded
  1011. //
  1012. // Returns:
  1013. // non zero - if the key has been expanded, zero if the key is not a macro
  1014. //
  1015. // Throws:
  1016. // None
  1017. //
  1018. // Author: Dwayne M. Newsome, 06/10/1998
  1019. //
  1020. //
  1021. static int kabExpandMacroKey( const HSESSION hSession, KEY_T aKey )
  1022. {
  1023. int lReturn = 0;
  1024. #if defined INCL_KEY_MACROS
  1025. keyMacro lKeyMacro;
  1026. int lKeyIndex = -1;
  1027. int lIndex = 0;
  1028. lKeyMacro.keyName = aKey;
  1029. lKeyIndex = keysFindMacro( &lKeyMacro );
  1030. if ( lKeyIndex >= 0 )
  1031. {
  1032. keysGetMacro( lKeyIndex, &lKeyMacro );
  1033. //
  1034. // Replace the virtual return key with '\r' so that all the
  1035. // line end processing works correctly. REV: 5/16/2002
  1036. //
  1037. for ( lIndex = 0; lIndex < lKeyMacro.macroLen; lIndex++ )
  1038. {
  1039. if ((VK_RETURN | VIRTUAL_KEY) == lKeyMacro.keyMacro[lIndex])
  1040. {
  1041. lKeyMacro.keyMacro[lIndex] = TEXT('\r');
  1042. }
  1043. }
  1044. CLoopSend( sessQueryCLoopHdl(hSession), &lKeyMacro.keyMacro,
  1045. lKeyMacro.macroLen, CLOOP_KEYS );
  1046. lReturn = 1;
  1047. }
  1048. #endif
  1049. return lReturn;
  1050. }