Source code of Windows XP (NT5)
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.

3383 lines
85 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module HOST.C -- Text Host for CreateWindow() Rich Edit Control |
  5. * Implements CTxtWinHost message and ITextHost interfaces
  6. *
  7. * Original Author: <nl>
  8. * Original RichEdit code: David R. Fulmer
  9. * Christian Fortini
  10. * Murray Sargent
  11. *
  12. * History: <nl>
  13. * 8/1/95 ricksa Documented and brought to new ITextHost definition
  14. * 10/28/95 murrays cleaned up and moved default char/paraformat cache
  15. * cache code into text services
  16. *
  17. * Set tabs every four (4) columns
  18. *
  19. * Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
  20. */
  21. #include "_common.h"
  22. #include "_host.h"
  23. #include "imm.h"
  24. #include "_format.h"
  25. #include "_edit.h"
  26. #include "_cfpf.h"
  27. #ifndef NOWINDOWHOSTS
  28. ASSERTDATA
  29. CTxtWinHost *g_phostdel = NULL;
  30. #define EN_CLIPFORMAT 0x0712
  31. #define ENM_CLIPFORMAT 0x00000080
  32. void DeleteDanglingHosts()
  33. {
  34. CLock lock;
  35. CTxtWinHost *phostdel = g_phostdel;
  36. while(phostdel)
  37. {
  38. CTxtWinHost *phost = phostdel;
  39. phostdel = phostdel->_pnextdel;
  40. CTxtWinHost::OnNCDestroy(phost);
  41. }
  42. g_phostdel = NULL;
  43. }
  44. #ifndef NOANSIWINDOWS
  45. //////////////////////////// System Window Procs ////////////////////////////
  46. LRESULT CreateAnsiWindow(
  47. HWND hwnd,
  48. UINT msg,
  49. CREATESTRUCTA *pcsa,
  50. BOOL fIs10)
  51. {
  52. AssertSz((WM_CREATE == msg) || (WM_NCCREATE == msg),
  53. "CreateAnsiWindow called with invalid message!");
  54. CTxtWinHost *phost = (CTxtWinHost *) GetWindowLongPtr(hwnd, ibPed);
  55. // The only thing we need to convert are the strings,
  56. // so just do a structure copy and replace the strings.
  57. CREATESTRUCTW csw = *(CREATESTRUCTW *)pcsa;
  58. CStrInW strinwName(pcsa->lpszName, GetKeyboardCodePage());
  59. CStrInW strinwClass(pcsa->lpszClass, CP_ACP);
  60. csw.lpszName = (WCHAR *)strinwName;
  61. csw.lpszClass = (WCHAR *)strinwClass;
  62. if (!phost)
  63. {
  64. // No host yet so create it
  65. phost = CTxtWinHost::OnNCCreate(hwnd, &csw, TRUE, fIs10);
  66. }
  67. if (WM_NCCREATE == msg)
  68. {
  69. return phost != NULL;
  70. }
  71. if (NULL == phost)
  72. {
  73. // For WM_CREATE -1 indicates failure
  74. return -1;
  75. }
  76. // Do the stuff specific to create
  77. return phost->OnCreate(&csw);
  78. }
  79. extern "C" LRESULT CALLBACK RichEdit10ANSIWndProc(
  80. HWND hwnd,
  81. UINT msg,
  82. WPARAM wparam,
  83. LPARAM lparam)
  84. {
  85. TRACEBEGINPARAM(TRCSUBSYSHOST, TRCSCOPEINTERN, "RichEdit10ANSIWndProc", msg);
  86. if ((WM_CREATE == msg) || (WM_NCCREATE == msg))
  87. {
  88. return CreateAnsiWindow(hwnd, msg, (CREATESTRUCTA *) lparam, TRUE);
  89. }
  90. // ignore WM_DESTROY and wait for WM_NCDESTROY
  91. if (WM_DESTROY == msg)
  92. {
  93. #ifndef NOWINDOWHOSTS
  94. CLock lock;
  95. CTxtWinHost *phost = (CTxtWinHost *) GetWindowLongPtr(hwnd, ibPed);
  96. phost->_pnextdel = g_phostdel;
  97. g_phostdel = phost;
  98. #endif
  99. return 0;
  100. }
  101. if (WM_NCDESTROY == msg)
  102. msg = WM_DESTROY;
  103. return W32->ANSIWndProc( hwnd, msg, wparam, lparam, TRUE);
  104. }
  105. LRESULT CALLBACK RichEditANSIWndProc(
  106. HWND hwnd,
  107. UINT msg,
  108. WPARAM wparam,
  109. LPARAM lparam)
  110. {
  111. TRACEBEGINPARAM(TRCSUBSYSHOST, TRCSCOPEINTERN, "RichEditANSIWndProc", msg);
  112. if ((WM_CREATE == msg) || (WM_NCCREATE == msg))
  113. {
  114. return CreateAnsiWindow(hwnd, msg, (CREATESTRUCTA *) lparam, FALSE);
  115. }
  116. return W32->ANSIWndProc( hwnd, msg, wparam, lparam, FALSE);
  117. }
  118. #else // NOANSIWINDOWS
  119. extern "C" LRESULT CALLBACK RichEdit10ANSIWndProc(
  120. HWND ,
  121. UINT ,
  122. WPARAM ,
  123. LPARAM)
  124. {
  125. return 0;
  126. }
  127. LRESULT CALLBACK RichEditANSIWndProc(
  128. HWND ,
  129. UINT ,
  130. WPARAM ,
  131. LPARAM)
  132. {
  133. return 0;
  134. }
  135. #endif // NOANSIWINDOWS
  136. /*
  137. * RichEditWndProc (hwnd, msg, wparam, lparam)
  138. *
  139. * @mfunc
  140. * Handle window messages pertinent to the host and pass others on to
  141. * text services.
  142. *
  143. * #rdesc
  144. * LRESULT = (code processed) ? 0 : 1
  145. */
  146. LRESULT CALLBACK RichEditWndProc(
  147. HWND hwnd,
  148. UINT msg,
  149. WPARAM wparam,
  150. LPARAM lparam)
  151. {
  152. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "RichEditWndProc");
  153. LRESULT lres = 0;
  154. HRESULT hr;
  155. SETTEXTEX st;
  156. CTxtWinHost *phost = hwnd ? (CTxtWinHost *) GetWindowLongPtr(hwnd, ibPed) : NULL;
  157. #ifdef DEBUG
  158. Tracef(TRCSEVINFO, "hwnd %lx, msg %lx, wparam %lx, lparam %lx", hwnd, msg, wparam, lparam);
  159. #endif // DEBUG
  160. switch(msg)
  161. {
  162. #ifdef WM_NCCREATE
  163. case WM_NCCREATE:
  164. return CTxtWinHost::OnNCCreate(hwnd, (CREATESTRUCT *)lparam, FALSE, FALSE) != NULL;
  165. #endif
  166. case WM_CREATE:
  167. // We may be on a system with no WM_NCCREATE (e.g. WinCE)
  168. if (!phost)
  169. {
  170. phost = CTxtWinHost::OnNCCreate(hwnd, (CREATESTRUCT *) lparam, FALSE, FALSE);
  171. }
  172. break;
  173. case WM_DESTROY:
  174. if(phost)
  175. {
  176. #ifndef NOWINDOWHOSTS
  177. CLock lock;
  178. CTxtWinHost *phostdel = g_phostdel;
  179. if (phostdel == phost)
  180. g_phostdel = phost->_pnextdel;
  181. else
  182. {
  183. while (phostdel)
  184. {
  185. if (phostdel->_pnextdel == phost)
  186. {
  187. phostdel->_pnextdel = phost->_pnextdel;
  188. break;
  189. }
  190. phostdel = phostdel->_pnextdel;
  191. }
  192. }
  193. #endif
  194. CTxtWinHost::OnNCDestroy(phost);
  195. }
  196. return 0;
  197. }
  198. if (!phost)
  199. return ::DefWindowProc(hwnd, msg, wparam, lparam);
  200. // In certain out-of-memory situations, clients may try to re-enter us
  201. // with calls. Just bail on the call if we don't have a text services
  202. // pointer.
  203. if(!phost->_pserv)
  204. return 0;
  205. // stabilize ourselves
  206. phost->AddRef();
  207. // Handle mouse/keyboard/scroll message-filter notifications
  208. if(phost->_fKeyMaskSet || phost->_fMouseMaskSet || phost->_fScrollMaskSet)
  209. {
  210. // We may need to fire a MSGFILTER notification. In the tests
  211. // below, we check to see if mouse, keyboard, or scroll events
  212. // are hit and enabled for notifications. If so, we fire the
  213. // msgfilter notification. The list of events was generated
  214. // from RichEdit 1.0 sources. The code gets all keyboard and
  215. // mouse actions, whereas the RichEdit 1.0 code only got
  216. // WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
  217. // WM_MOUSEACTIVATE, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE,
  218. // WM_RBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP. Note that the
  219. // following code doesn't send a notification for AltGr characters
  220. // (LeftCtrl+RightAlt+vkey), since some hosts misinterpret these
  221. // characters as hot keys.
  222. if (phost->_fKeyMaskSet && IN_RANGE(WM_KEYFIRST, msg, WM_KEYLAST) &&
  223. (msg != WM_KEYDOWN ||
  224. (GetKeyboardFlags() & (ALT | CTRL)) != (LCTRL | RALT)) || // AltGr
  225. phost->_fMouseMaskSet && (msg == WM_MOUSEACTIVATE ||
  226. IN_RANGE(WM_MOUSEFIRST, msg, WM_MOUSELAST)) ||
  227. phost->_fScrollMaskSet && IN_RANGE(WM_HSCROLL, msg, WM_VSCROLL))
  228. {
  229. MSGFILTER msgfltr;
  230. ZeroMemory(&msgfltr.nmhdr, sizeof(NMHDR));
  231. msgfltr.msg = msg;
  232. msgfltr.wParam = wparam;
  233. msgfltr.lParam = lparam;
  234. // The MSDN document on MSGFILTER is wrong, if the
  235. // send message returns 0 (NOERROR via TxNotify in this
  236. // case), it means process the event. Otherwise, return.
  237. //
  238. // The documentation states the reverse.
  239. //
  240. if(phost->TxNotify(EN_MSGFILTER, &msgfltr) == NOERROR)
  241. {
  242. // Since client is allowed to modify the contents of
  243. // msgfltr, we must use the returned values.
  244. msg = msgfltr.msg;
  245. wparam = msgfltr.wParam;
  246. lparam = msgfltr.lParam;
  247. }
  248. else
  249. {
  250. lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
  251. goto Exit;
  252. }
  253. }
  254. }
  255. switch(msg)
  256. {
  257. case EM_SETEVENTMASK:
  258. phost->_fKeyMaskSet = !!(lparam & ENM_KEYEVENTS);
  259. phost->_fMouseMaskSet = !!(lparam & ENM_MOUSEEVENTS);
  260. phost->_fScrollMaskSet = !!(lparam & ENM_SCROLLEVENTS);
  261. goto serv;
  262. case EM_SETSEL:
  263. // When we are in a dialog box that is empty, EM_SETSEL will not select
  264. // the final always existing EOP if the control is rich.
  265. if (phost->_fUseSpecialSetSel &&
  266. ((CTxtEdit *)phost->_pserv)->GetAdjustedTextLength() == 0 &&
  267. wparam != -1)
  268. {
  269. lparam = 0;
  270. wparam = 0;
  271. }
  272. goto serv;
  273. case WM_CREATE:
  274. {
  275. //bug fix #5386
  276. //need to convert ANSI -> UNICODE for Win9x systems which didn't go through
  277. //the ANSI wndProc
  278. #ifndef NOANSIWINDOWS
  279. if (W32->OnWin9x() && !phost->_fANSIwindow)
  280. {
  281. CREATESTRUCT cs = *(CREATESTRUCT*)lparam;
  282. CStrInW strinwName(((CREATESTRUCTA*)lparam)->lpszName, GetKeyboardCodePage());
  283. CStrInW strinwClass(((CREATESTRUCTA*)lparam)->lpszClass, CP_ACP);
  284. cs.lpszName = (WCHAR*)strinwName;
  285. cs.lpszClass = (WCHAR*)strinwClass;
  286. lres = phost->OnCreate(&cs);
  287. }
  288. else
  289. #endif
  290. lres = phost->OnCreate((CREATESTRUCT*)lparam);
  291. }
  292. break;
  293. case WM_KEYDOWN:
  294. lres = phost->OnKeyDown((WORD) wparam, (DWORD) lparam);
  295. if(lres) // Didn't process code:
  296. goto serv; // give it to text services
  297. break;
  298. case WM_GETTEXT:
  299. #ifndef NOANSIWINDOWS
  300. GETTEXTEX gt;
  301. if (W32->OnWin9x() || phost->_fANSIwindow)
  302. W32->AnsiFilter( msg, wparam, lparam, (void *) &gt );
  303. #endif
  304. goto serv;
  305. case WM_COPYDATA:
  306. PCOPYDATASTRUCT pcds;
  307. pcds = (PCOPYDATASTRUCT) lparam;
  308. if (HIWORD(pcds->dwData) == 1200 && // Unicode code page
  309. LOWORD(pcds->dwData) == WM_SETTEXT) // Only message we know about
  310. {
  311. st.flags = ST_CHECKPROTECTION;
  312. st.codepage = 1200;
  313. msg = EM_SETTEXTEX;
  314. wparam = (WPARAM) &st;
  315. lparam = (LPARAM) pcds->lpData;
  316. goto serv;
  317. }
  318. else
  319. lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
  320. break;
  321. case WM_GETTEXTLENGTH:
  322. #ifndef NOANSIWINDOWS
  323. GETTEXTLENGTHEX gtl;
  324. if (W32->OnWin9x() || phost->_fANSIwindow)
  325. W32->AnsiFilter( msg, wparam, lparam, (void *) &gtl );
  326. #endif
  327. goto serv;
  328. case WM_CHAR:
  329. if(GetKeyboardFlags() & ALTNUMPAD) // Handle Alt+0ddd in CTxtEdit
  330. goto serv; // so that other hosts also work
  331. #ifndef NOANSIWINDOWS
  332. else if (W32->OnWin9x() || phost->_fANSIwindow)
  333. {
  334. CW32System::WM_CHAR_INFO wmci;
  335. wmci._fAccumulate = phost->_fAccumulateDBC != 0;
  336. W32->AnsiFilter( msg, wparam, lparam, (void *) &wmci,
  337. ((CTxtEdit *)phost->_pserv)->Get10Mode() );
  338. if (wmci._fLeadByte)
  339. {
  340. phost->_fAccumulateDBC = TRUE;
  341. phost->_chLeadByte = wparam << 8;
  342. goto Exit; // Wait for trail byte
  343. }
  344. else if (wmci._fTrailByte)
  345. {
  346. wparam = phost->_chLeadByte | wparam;
  347. phost->_fAccumulateDBC = FALSE;
  348. phost->_chLeadByte = 0;
  349. msg = WM_IME_CHAR;
  350. goto serv;
  351. }
  352. else if (wmci._fIMEChar)
  353. {
  354. msg = WM_IME_CHAR;
  355. goto serv;
  356. }
  357. }
  358. #endif
  359. lres = phost->OnChar((WORD) wparam, (DWORD) lparam);
  360. if(lres) // Didn't process code:
  361. goto serv; // give it to text services
  362. break;
  363. case WM_ENABLE:
  364. if(!wparam ^ phost->_fDisabled)
  365. {
  366. // Stated of window changed so invalidate it so it will
  367. // get redrawn.
  368. phost->TxInvalidateRect(NULL, TRUE);
  369. phost->SetScrollBarsForWmEnable(wparam);
  370. }
  371. phost->_fDisabled = !wparam; // Set disabled flag
  372. lres = 0; // Return value for message
  373. // Fall thru to WM_SYSCOLORCHANGE?
  374. case WM_SYSCOLORCHANGE:
  375. phost->OnSysColorChange();
  376. goto serv; // Notify text services that
  377. // system colors have changed
  378. case WM_GETDLGCODE:
  379. lres = phost->OnGetDlgCode(wparam, lparam);
  380. break;
  381. case EM_GETOPTIONS:
  382. lres = phost->OnGetOptions();
  383. break;
  384. case EM_GETPASSWORDCHAR:
  385. lres = phost->_chPassword;
  386. break;
  387. case EM_GETRECT:
  388. phost->OnGetRect((LPRECT)lparam);
  389. break;
  390. case EM_HIDESELECTION:
  391. if(lparam)
  392. {
  393. DWORD dwPropertyBits = 0;
  394. phost->_dwStyle |= ES_NOHIDESEL;
  395. if(wparam)
  396. {
  397. phost->_dwStyle &= ~ES_NOHIDESEL;
  398. dwPropertyBits = TXTBIT_HIDESELECTION;
  399. }
  400. // Notify text services of change in status.
  401. phost->_pserv->OnTxPropertyBitsChange(TXTBIT_HIDESELECTION,
  402. dwPropertyBits);
  403. }
  404. goto serv;
  405. case EM_SETBKGNDCOLOR:
  406. lres = (LRESULT) phost->_crBackground;
  407. phost->_fNotSysBkgnd = !wparam;
  408. phost->_crBackground = (COLORREF) lparam;
  409. if(wparam)
  410. phost->_crBackground = GetSysColor(COLOR_WINDOW);
  411. if(lres != (LRESULT) phost->_crBackground)
  412. {
  413. // Notify text services that color has changed
  414. LRESULT lres1 = 0;
  415. phost->_pserv->TxSendMessage(WM_SYSCOLORCHANGE, 0, 0, &lres1);
  416. phost->TxInvalidateRect(NULL, TRUE);
  417. }
  418. break;
  419. case WM_STYLECHANGING:
  420. // Just pass this one to the default window proc
  421. lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
  422. break;
  423. case WM_STYLECHANGED:
  424. //
  425. // For now, we only interested in GWL_EXSTYLE Transparent mode changed.
  426. // This is to fix Bug 753 since Window95 is not passing us
  427. // the WS_EX_TRANSPARENT.
  428. //
  429. lres = 1;
  430. if(GWL_EXSTYLE == wparam)
  431. {
  432. LPSTYLESTRUCT lpss = (LPSTYLESTRUCT) lparam;
  433. if(phost->IsTransparentMode() != (BOOL)(lpss->styleNew & WS_EX_TRANSPARENT))
  434. {
  435. phost->_dwExStyle = lpss->styleNew;
  436. ((CTxtEdit *)phost->_pserv)->OnTxBackStyleChange(TRUE);
  437. // Return 0 to indicate we have handled this message
  438. lres = 0;
  439. }
  440. }
  441. break;
  442. case EM_SHOWSCROLLBAR:
  443. {
  444. Assert(wparam == SB_VERT || wparam == SB_HORZ);
  445. DWORD dwBit = wparam == SB_VERT ? WS_VSCROLL : WS_HSCROLL;
  446. phost->_dwStyle |= dwBit;
  447. if(!lparam)
  448. phost->_dwStyle &= ~dwBit;
  449. phost->TxShowScrollBar((int) wparam, lparam);
  450. if (lparam)
  451. phost->TxSetScrollRange((int) wparam, 0, 0, TRUE);
  452. }
  453. break;
  454. case EM_SETOPTIONS:
  455. phost->OnSetOptions((WORD) wparam, (DWORD) lparam);
  456. lres = (phost->_dwStyle & ECO_STYLES);
  457. if(phost->_fEnableAutoWordSel)
  458. lres |= ECO_AUTOWORDSELECTION;
  459. break;
  460. case EM_SETPASSWORDCHAR:
  461. if(phost->_chPassword != (TCHAR)wparam)
  462. {
  463. phost->_chPassword = (TCHAR)wparam;
  464. phost->_pserv->OnTxPropertyBitsChange(TXTBIT_USEPASSWORD,
  465. phost->_chPassword ? TXTBIT_USEPASSWORD : 0);
  466. }
  467. break;
  468. case EM_SETREADONLY:
  469. phost->OnSetReadOnly(BOOL(wparam));
  470. lres = 1;
  471. break;
  472. case EM_SETRECTNP:
  473. case EM_SETRECT:
  474. phost->OnSetRect((LPRECT)lparam, wparam == 1, msg == EM_SETRECT);
  475. break;
  476. case WM_SIZE:
  477. phost->_pserv->TxSendMessage(msg, wparam, lparam, &lres);
  478. lres = phost->OnSize(hwnd, wparam, (int)LOWORD(lparam), (int)HIWORD(lparam));
  479. break;
  480. case WM_WINDOWPOSCHANGING:
  481. lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
  482. // richedit 1.0 didn't cause InvalidateRect which OnSunkenWindowPosChanging will do
  483. if(phost->TxGetEffects() == TXTEFFECT_SUNKEN && !((CTxtEdit *)phost->_pserv)->Get10Mode())
  484. phost->OnSunkenWindowPosChanging(hwnd, (WINDOWPOS *) lparam);
  485. break;
  486. case WM_SETCURSOR:
  487. // Only set cursor when over us rather than a child; this
  488. // helps prevent us from fighting it out with an inplace child
  489. if((HWND)wparam == hwnd)
  490. {
  491. if(!(lres = ::DefWindowProc(hwnd, msg, wparam, lparam)))
  492. {
  493. POINT pt;
  494. GetCursorPos(&pt);
  495. ::ScreenToClient(hwnd, &pt);
  496. phost->_pserv->OnTxSetCursor(
  497. DVASPECT_CONTENT,
  498. -1,
  499. NULL,
  500. NULL,
  501. NULL,
  502. NULL,
  503. NULL, // Client rect - no redraw
  504. pt.x,
  505. pt.y);
  506. lres = TRUE;
  507. }
  508. }
  509. break;
  510. case WM_SHOWWINDOW:
  511. hr = phost->OnTxVisibleChange((BOOL)wparam);
  512. break;
  513. case WM_NCPAINT:
  514. lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
  515. break;
  516. case WM_PRINTCLIENT:
  517. case WM_PAINT:
  518. {
  519. PAINTSTRUCT ps;
  520. HPALETTE hpalOld = NULL;
  521. HDC hdc;
  522. RECT rcClient;
  523. //RAID 6964: WM_PRINTCLIENT should not call BeginPaint. If a HDC is passed
  524. //down in the wparam, use it instead of calling BeginPaint.
  525. if (!wparam || ((CTxtEdit *)phost->_pserv)->Get10Mode())
  526. hdc = BeginPaint(hwnd, &ps);
  527. else
  528. hdc = (HDC) wparam;
  529. // Set up the palette for drawing our data
  530. if(phost->_hpal)
  531. {
  532. hpalOld = SelectPalette(hdc, phost->_hpal, TRUE);
  533. RealizePalette(hdc);
  534. }
  535. // Since we are using the CS_PARENTDC style, make sure
  536. // the clip region is limited to our client window.
  537. GetClientRect(hwnd, &rcClient);
  538. SaveDC(hdc);
  539. IntersectClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
  540. phost->_pserv->TxDraw(
  541. DVASPECT_CONTENT, // Draw Aspect
  542. -1, // Lindex
  543. NULL, // Info for drawing optimazation
  544. NULL, // target device information
  545. hdc, // Draw device HDC
  546. NULL, // Target device HDC
  547. (const RECTL *) &rcClient,// Bounding client rectangle
  548. NULL, // Clipping rectangle for metafiles
  549. &ps.rcPaint, // Update rectangle
  550. NULL, // Call back function
  551. NULL, // Call back parameter
  552. TXTVIEW_ACTIVE); // What view - the active one!
  553. // Restore palette if there is one
  554. #ifndef NOPALETTE
  555. if(hpalOld)
  556. SelectPalette(hdc, hpalOld, TRUE);
  557. #endif
  558. RestoreDC(hdc, -1);
  559. if (!wparam || ((CTxtEdit *)phost->_pserv)->Get10Mode())
  560. EndPaint(hwnd, &ps);
  561. }
  562. break;
  563. case EM_SETMARGINS:
  564. phost->OnSetMargins(wparam, LOWORD(lparam), HIWORD(lparam));
  565. break;
  566. case EM_SETPALETTE:
  567. // Application is setting a palette for us to use.
  568. phost->_hpal = (HPALETTE) wparam;
  569. // Invalidate the window & repaint to reflect the new palette.
  570. InvalidateRect(hwnd, NULL, TRUE);
  571. break;
  572. default:
  573. serv:
  574. hr = phost->_pserv->TxSendMessage(msg, wparam, lparam, &lres);
  575. if(hr == S_FALSE)
  576. {
  577. // Message was not processed by text services so send it
  578. // to the default window proc.
  579. lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
  580. }
  581. }
  582. Exit:
  583. phost->Release();
  584. return lres;
  585. }
  586. static BOOL GetIconic(
  587. HWND hwnd)
  588. {
  589. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "GetIconic");
  590. while(hwnd)
  591. {
  592. if(IsIconic(hwnd))
  593. return TRUE;
  594. hwnd = GetParent(hwnd);
  595. }
  596. return FALSE;
  597. }
  598. //////////////// CTxtWinHost Creation/Initialization/Destruction ///////////////////////
  599. /*
  600. * CTxtWinHost::OnNCCreate (hwnd, pcs)
  601. *
  602. * @mfunc
  603. * Static global method to handle WM_NCCREATE message (see remain.c)
  604. */
  605. CTxtWinHost *CTxtWinHost::OnNCCreate(
  606. HWND hwnd,
  607. const CREATESTRUCT *pcs,
  608. BOOL fIsAnsi,
  609. BOOL fIs10Mode)
  610. {
  611. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnNCCreate");
  612. #if defined DEBUG && !defined(NOFULLDEBUG)
  613. GdiSetBatchLimit(1);
  614. #endif
  615. CTxtWinHost *phost = new CTxtWinHost();
  616. if(!phost)
  617. return 0;
  618. CREATESTRUCT cs = *pcs; // prefer C++ compiler not to modify constant
  619. #ifndef NOCOMPLEXSCRIPTS
  620. BOOL fMirrorWnd = !!(cs.dwExStyle & WS_EX_LAYOUTRTL); // Inherit parent window's mirroring
  621. if (fMirrorWnd)
  622. {
  623. // Force RTL reading
  624. cs.style |= ES_RIGHT;
  625. cs.dwExStyle |= WS_EX_RTLREADING;
  626. }
  627. #endif
  628. #ifndef NOANSIWINDOWS
  629. //bug fix #5386
  630. // Window wasn't created with the Richedit20A window class
  631. // and we are under Win9x, need to convert string to UNICODE
  632. CStrInW strinwName(((LPSTR)pcs->lpszName), GetKeyboardCodePage());
  633. CStrInW strinwClass(((LPSTR)pcs->lpszClass), CP_ACP);
  634. if (!fIsAnsi && W32->OnWin9x())
  635. {
  636. cs.lpszName = (WCHAR *)strinwName;
  637. cs.lpszClass = (WCHAR *)strinwClass;
  638. }
  639. #endif
  640. // Stores phost in associated window data
  641. if(!phost->Init(hwnd, (const CREATESTRUCT*)&cs, fIsAnsi, fIs10Mode))
  642. {
  643. phost->Shutdown();
  644. delete phost;
  645. phost = NULL;
  646. }
  647. #ifndef NOCOMPLEXSCRIPTS
  648. if (phost && fMirrorWnd)
  649. {
  650. // Disable mirroring layout to avoid mirrored mapping mode
  651. SetWindowLong(hwnd, GWL_STYLE, cs.style | ES_RIGHT);
  652. SetWindowLong(hwnd, GWL_EXSTYLE, (cs.dwExStyle & ~WS_EX_LAYOUTRTL) | WS_EX_LEFTSCROLLBAR);
  653. }
  654. #endif
  655. return phost;
  656. }
  657. /*
  658. * CTxtWinHost::OnNCDestroy (phost)
  659. *
  660. * @mfunc
  661. * Static global method to handle WM_CREATE message
  662. *
  663. * @devnote
  664. * phost ptr is stored in window data (GetWindowLong())
  665. */
  666. void CTxtWinHost::OnNCDestroy(
  667. CTxtWinHost *phost)
  668. {
  669. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnNCDestroy");
  670. phost->Shutdown();
  671. phost->Release();
  672. }
  673. /*
  674. * CTxtWinHost::CTxtWinHost()
  675. *
  676. * @mfunc
  677. * constructor
  678. */
  679. CTxtWinHost::CTxtWinHost()
  680. {
  681. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::CTxtWinHost");
  682. #ifndef NOACCESSIBILITY
  683. _pTypeInfo = NULL;
  684. #endif
  685. _fRegisteredForDrop = FALSE;
  686. _crefs = 1;
  687. if(!_fNotSysBkgnd)
  688. _crBackground = GetSysColor(COLOR_WINDOW);
  689. }
  690. /*
  691. * CTxtWinHost::~CTxtWinHost()
  692. *
  693. * @mfunc
  694. * destructor
  695. */
  696. CTxtWinHost::~CTxtWinHost()
  697. {
  698. AssertSz(_pserv == NULL,
  699. "CTxtWinHost::~CTxtWinHost - shutdown not called till destructor");
  700. if(_pserv)
  701. Shutdown();
  702. }
  703. /*
  704. * CTxtWinHost::Shutdown()
  705. *
  706. * @mfunc Shut down this object, but doesn't delete memory
  707. */
  708. void CTxtWinHost::Shutdown()
  709. {
  710. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::Shutdown");
  711. ITextServices *pserv;
  712. HostRevokeDragDrop(); // Revoke our drop target
  713. if(_pserv)
  714. {
  715. // Guarantee that no recursive callbacks can happen during shutdown.
  716. pserv = _pserv;
  717. _pserv = NULL;
  718. pserv->OnTxInPlaceDeactivate();
  719. pserv->Release();
  720. // Host release was not the final release so notify
  721. // text services that they need to keep their reference
  722. // to the host valid.
  723. if (!_fTextServiceFree)
  724. {
  725. ((CTxtEdit *)pserv)->SetReleaseHost();
  726. }
  727. }
  728. #if 0
  729. ImmTerminate(); // Terminate only useful on Mac.
  730. #endif
  731. if(_hwnd)
  732. SetWindowLongPtr(_hwnd, ibPed, 0);
  733. }
  734. /*
  735. * CTxtWinHost::Init (hwnd, pcs)
  736. *
  737. * @mfunc
  738. * Initialize this CTxtWinHost
  739. */
  740. BOOL CTxtWinHost::Init(
  741. HWND hwnd, //@parm Window handle for this control
  742. const CREATESTRUCT *pcs, //@parm Corresponding CREATESTRUCT
  743. BOOL fIsAnsi, //@parm is ansi window
  744. BOOL fIs10Mode) //@parm is 1.0 mode window
  745. {
  746. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::Init");
  747. AssertSz(!fIs10Mode || (fIsAnsi && fIs10Mode),
  748. "CTxtWinHost::Init input flags are out of sync!");
  749. if(!pcs->lpszClass)
  750. return FALSE;
  751. // Set pointer back to CTxtWinHost from the window
  752. if(hwnd)
  753. SetWindowLongPtr(hwnd, ibPed, (INT_PTR)this);
  754. _hwnd = hwnd;
  755. // Here we want to keep track of the "RichEdit20A"window class
  756. // The RICHEDIT window class is handled by a wrapper dll.
  757. // If the class name is "RICHEDIT", then we need to turn on the
  758. // RichEdit 1.0 compatibility bit. IsAnsiWindowClass tests that class as well.
  759. _fANSIwindow = fIsAnsi;
  760. // Edit controls created without a window are multiline by default
  761. // so that paragraph formats can be
  762. _dwStyle = ES_MULTILINE;
  763. _fHidden = TRUE;
  764. if(pcs)
  765. {
  766. _hwndParent = pcs->hwndParent;
  767. _dwExStyle = pcs->dwExStyle;
  768. _dwStyle = pcs->style;
  769. if (!fIs10Mode)
  770. {
  771. // Only set this for 2.0 windows
  772. // According to the edit control documentation WS_HSCROLL implies that
  773. // ES_AUTOSCROLL is set and WS_VSCROLL implies that ES_AUTOVSCROLL is
  774. // set. Here, we make this so.
  775. if(_dwStyle & WS_HSCROLL)
  776. _dwStyle |= ES_AUTOHSCROLL;
  777. // handle default disabled
  778. if(_dwStyle & WS_DISABLED)
  779. _fDisabled = TRUE;
  780. }
  781. else
  782. {
  783. if (GetBkMode(GetDC(hwnd)) == TRANSPARENT)
  784. _dwExStyle |= WS_EX_TRANSPARENT;
  785. else
  786. _dwExStyle &= ~WS_EX_TRANSPARENT;
  787. }
  788. if(_dwStyle & WS_VSCROLL)
  789. _dwStyle |= ES_AUTOVSCROLL;
  790. _fBorder = !!(_dwStyle & WS_BORDER);
  791. if((_dwStyle & ES_SUNKEN) || (_dwExStyle & WS_EX_CLIENTEDGE))
  792. _fBorder = TRUE;
  793. // handle default passwords
  794. if(_dwStyle & ES_PASSWORD)
  795. _chPassword = TEXT('*');
  796. // On Win95 ES_SUNKEN and WS_BORDER get mapped to WS_EX_CLIENTEDGE
  797. if(_fBorder && W32->_dwMajorVersion >= VERS4)
  798. {
  799. _dwExStyle |= WS_EX_CLIENTEDGE;
  800. SetWindowLong(_hwnd, GWL_EXSTYLE, _dwExStyle);
  801. }
  802. #ifndef NORIGHTTOLEFT
  803. // Process some flags for mirrored control
  804. if (_dwExStyle & WS_EX_LAYOUTRTL)
  805. {
  806. // Swap whatever RTL params we have
  807. _dwStyle = (_dwStyle & ~ES_RIGHT) | (_dwStyle & ES_RIGHT ^ ES_RIGHT);
  808. _dwExStyle = (_dwExStyle & ~WS_EX_RTLREADING) | (_dwExStyle & WS_EX_RTLREADING ^ WS_EX_RTLREADING);
  809. _dwExStyle = (_dwExStyle & ~WS_EX_LEFTSCROLLBAR) |
  810. (_dwStyle & ES_RIGHT ? WS_EX_LEFTSCROLLBAR : 0);
  811. // Disable mirroring layout to avoid GDI mirroring mapping mode
  812. _dwExStyle &= ~WS_EX_LAYOUTRTL;
  813. SetWindowLong(_hwnd, GWL_STYLE, _dwStyle);
  814. SetWindowLong(_hwnd, GWL_EXSTYLE, _dwExStyle);
  815. }
  816. #endif
  817. }
  818. // Create Text Services component
  819. // Watch out for sys param and sys font initialization!! see below.
  820. if(FAILED(CreateTextServices()))
  821. return FALSE;
  822. _xInset = (char)W32->GetCxBorder();
  823. _yInset = (char)W32->GetCyBorder();
  824. if (!_fBorder)
  825. {
  826. _xInset += _xInset;
  827. _yInset += _yInset;
  828. }
  829. // At this point the border flag is set and so is the pixels per inch
  830. // so we can initalize the inset.
  831. // This must be done after CreatingTextServices so sys params are valid
  832. SetDefaultInset();
  833. // Set alignment and paragraph direction
  834. PARAFORMAT PF2;
  835. PF2.dwMask = 0;
  836. #ifndef NOCOMPLEXSCRIPTS
  837. BOOL fRCAlign = _dwStyle & (ES_RIGHT | ES_CENTER) || _dwExStyle & WS_EX_RIGHT;
  838. if(fRCAlign)
  839. {
  840. PF2.dwMask |= PFM_ALIGNMENT;
  841. PF2.wAlignment = (WORD)(_dwStyle & ES_CENTER ? PFA_CENTER : PFA_RIGHT); // right or center-aligned
  842. }
  843. if(_dwExStyle & WS_EX_RTLREADING)
  844. {
  845. PF2.dwMask |= PFM_RTLPARA;
  846. PF2.wEffects = PFE_RTLPARA; // RTL reading order
  847. }
  848. #endif
  849. if (PF2.dwMask)
  850. {
  851. PF2.cbSize = sizeof(PARAFORMAT2);
  852. // tell text services
  853. _pserv->TxSendMessage(EM_SETPARAFORMAT, SPF_SETDEFAULT, (LPARAM)&PF2, NULL);
  854. }
  855. if (fIs10Mode)
  856. {
  857. ((CTxtEdit *)_pserv)->Set10Mode();
  858. // Remove the WS_VSCROLL and WS_HSCROLL initially
  859. if (_hwnd && !(_dwStyle & ES_DISABLENOSCROLL))
  860. {
  861. SetScrollRange(_hwnd, SB_VERT, 0, 0, TRUE);
  862. SetScrollRange(_hwnd, SB_HORZ, 0, 0, TRUE);
  863. DWORD dwStyle = _dwStyle & ~(WS_VSCROLL | WS_HSCROLL);
  864. SetWindowLong(_hwnd, GWL_STYLE, dwStyle);
  865. // bug fix:
  866. // On some systems, ie Digital PII-266, we don't get a WM_PAINT message
  867. // when we change the window style. So force a WM_PAINT into the message queue
  868. TxInvalidateRect(NULL, TRUE);
  869. }
  870. }
  871. // Set window text
  872. if(pcs && pcs->lpszName)
  873. {
  874. if(FAILED(_pserv->TxSetText((TCHAR *)pcs->lpszName)))
  875. {
  876. SafeReleaseAndNULL((IUnknown **)&_pserv);
  877. return FALSE;
  878. }
  879. }
  880. if(_dwStyle & ES_LOWERCASE)
  881. _pserv->TxSendMessage(EM_SETEDITSTYLE, SES_LOWERCASE,
  882. SES_LOWERCASE | SES_UPPERCASE, NULL);
  883. #if 0
  884. if(!ImmInitialize()) // Mac Only
  885. {
  886. #if defined(DEBUG)
  887. OutputDebugString(TEXT("Could not register Imm ImmInitializeForMac.\r\n"));
  888. #endif // DEBUG
  889. }
  890. #endif
  891. return TRUE;
  892. }
  893. HRESULT CTxtWinHost::CreateTextServices()
  894. {
  895. IUnknown *pUnk;
  896. HRESULT hr = ::CreateTextServices(NULL, this, &pUnk);
  897. if(hr != NOERROR)
  898. return hr;
  899. // Get text services interface
  900. hr = pUnk->QueryInterface(IID_ITextServices, (void **)&_pserv);
  901. // Regardless of whether the previous call succeeded or failed, we are
  902. // done with the private interface.
  903. pUnk->Release();
  904. #ifndef NOCOMPLEXSCRIPTS
  905. if(hr == NOERROR)
  906. {
  907. ((CTxtEdit *)_pserv)->_fInOurHost = TRUE;
  908. // FE extended styles might set the fFE bit
  909. if(_dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR))
  910. _pserv->TxSendMessage(EM_SETEDITSTYLE, SES_BIDI, SES_BIDI, NULL);
  911. }
  912. #endif
  913. return hr;
  914. }
  915. /*
  916. * CTxtWinHost::OnCreate (pcs)
  917. *
  918. * @mfunc
  919. * Handle WM_CREATE message
  920. *
  921. * @rdesc
  922. * LRESULT = -1 if failed to in-place activate; else 0
  923. */
  924. LRESULT CTxtWinHost::OnCreate(
  925. const CREATESTRUCT *pcs)
  926. {
  927. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnCreate");
  928. RECT rcClient;
  929. // sometimes, these values are -1 (from windows itself); just treat them
  930. // as zero in that case
  931. LONG cy = (pcs->cy < 0) ? 0 : pcs->cy;
  932. LONG cx = (pcs->cx < 0) ? 0 : pcs->cx;
  933. rcClient.top = pcs->y;
  934. rcClient.bottom = rcClient.top + cy;
  935. rcClient.left = pcs->x;
  936. rcClient.right = rcClient.left + cx;
  937. // Notify Text Services that we are in place active
  938. if(FAILED(_pserv->OnTxInPlaceActivate(&rcClient)))
  939. return -1;
  940. DWORD dwStyle = GetWindowLong(_hwnd, GWL_STYLE);
  941. // Hide all scrollbars to start
  942. if(_hwnd && !(dwStyle & ES_DISABLENOSCROLL) && !((CTxtEdit *)_pserv)->Get10Mode())
  943. {
  944. SetScrollRange(_hwnd, SB_VERT, 0, 0, TRUE);
  945. SetScrollRange(_hwnd, SB_HORZ, 0, 0, TRUE);
  946. dwStyle &= ~(WS_VSCROLL | WS_HSCROLL);
  947. SetWindowLong(_hwnd, GWL_STYLE, dwStyle);
  948. }
  949. if(!(dwStyle & (ES_READONLY | ES_NOOLEDRAGDROP)))
  950. {
  951. // This isn't a read only window or a no drop window,
  952. // so we need a drop target.
  953. HostRegisterDragDrop();
  954. }
  955. _usIMEMode = 0;
  956. if(dwStyle & ES_NOIME)
  957. {
  958. _usIMEMode = ES_NOIME;
  959. // Tell textservices to turnoff ime
  960. _pserv->TxSendMessage(EM_SETEDITSTYLE, SES_NOIME, SES_NOIME, NULL);
  961. }
  962. else if(dwStyle & ES_SELFIME)
  963. _usIMEMode = ES_SELFIME;
  964. return 0;
  965. }
  966. ///////////////////////////////// IUnknown ////////////////////////////////
  967. HRESULT CTxtWinHost::QueryInterface(REFIID riid, void **ppv)
  968. {
  969. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::QueryInterface");
  970. if(IsEqualIID(riid, IID_IUnknown))
  971. *ppv = (IUnknown *)(ITextHost2*)this;
  972. else if(IsEqualIID(riid, IID_ITextHost) )
  973. *ppv = (ITextHost *)(CTxtWinHost*)this;
  974. else if(IsEqualIID(riid, IID_ITextHost2) )
  975. *ppv = (ITextHost2 *)(CTxtWinHost*)this;
  976. else
  977. *ppv = NULL;
  978. if(*ppv)
  979. {
  980. AddRef();
  981. return NOERROR;
  982. }
  983. return E_NOINTERFACE;
  984. }
  985. ULONG CTxtWinHost::AddRef(void)
  986. {
  987. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::AddRef");
  988. return ++_crefs;
  989. }
  990. ULONG CTxtWinHost::Release(void)
  991. {
  992. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::Release");
  993. --_crefs;
  994. if(!_crefs)
  995. {
  996. #ifndef NOACCESSIBILITY
  997. if(_pTypeInfo)
  998. {
  999. _pTypeInfo->Release();
  1000. _pTypeInfo = NULL;
  1001. }
  1002. #endif
  1003. delete this;
  1004. return 0;
  1005. }
  1006. return _crefs;
  1007. }
  1008. //////////////////////////////// Activation ////////////////////////////////
  1009. //////////////////////////////// Properties ////////////////////////////////
  1010. TXTEFFECT CTxtWinHost::TxGetEffects() const
  1011. {
  1012. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxGetEffects");
  1013. if((_dwStyle & ES_SUNKEN) || (_dwExStyle & WS_EX_CLIENTEDGE))
  1014. return TXTEFFECT_SUNKEN;
  1015. return TXTEFFECT_NONE;
  1016. }
  1017. /////////////////////////////// Keyboard Messages //////////////////////////////////
  1018. /*
  1019. * CTxtWinHost::OnKeyDown (vkey, dwFlags)
  1020. *
  1021. * @mfunc
  1022. * Handle WM_KEYDOWN messages that need to send a message to the parent
  1023. * window (may happen when control is in a dialog box)
  1024. *
  1025. * #rdesc
  1026. * LRESULT = (code processed) ? 0 : 1
  1027. */
  1028. LRESULT CTxtWinHost::OnKeyDown(
  1029. WORD vkey, //@parm WM_KEYDOWN wparam (virtual key code)
  1030. DWORD dwFlags) //@parm WM_KEYDOWN flags
  1031. {
  1032. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnKeyDown");
  1033. if(!_fInDialogBox) // Not in a dialog box
  1034. return 1; // Signal key-down msg not processed
  1035. DWORD dwKeyFlags = GetKeyboardFlags();
  1036. switch(vkey)
  1037. {
  1038. case VK_ESCAPE:
  1039. PostMessage(_hwndParent, WM_CLOSE, 0, 0);
  1040. return 0;
  1041. case VK_RETURN:
  1042. if(!(dwKeyFlags & CTRL) && !(_dwStyle & ES_WANTRETURN))
  1043. {
  1044. // Send to default button
  1045. HWND hwndT;
  1046. LRESULT id = SendMessage(_hwndParent, DM_GETDEFID, 0, 0);
  1047. if(LOWORD(id) && (hwndT = GetDlgItem(_hwndParent, LOWORD(id))))
  1048. {
  1049. SendMessage(_hwndParent, WM_NEXTDLGCTL, (WPARAM) hwndT, (LPARAM) 1);
  1050. if(GetFocus() != _hwnd)
  1051. PostMessage(hwndT, WM_KEYDOWN, (WPARAM) VK_RETURN, 0);
  1052. }
  1053. return 0;
  1054. }
  1055. break;
  1056. case VK_TAB:
  1057. if(!(dwKeyFlags & CTRL))
  1058. {
  1059. SendMessage(_hwndParent, WM_NEXTDLGCTL,
  1060. !!(dwKeyFlags & SHIFT), 0);
  1061. return 0;
  1062. }
  1063. break;
  1064. }
  1065. return 1;
  1066. }
  1067. /*
  1068. * CTxtWinHost::OnChar (vkey, dwFlags)
  1069. *
  1070. * @mfunc
  1071. * Eat some WM_CHAR messages for a control in a dialog box
  1072. *
  1073. * #rdesc
  1074. * LRESULT = (code processed) ? 0 : 1
  1075. */
  1076. LRESULT CTxtWinHost::OnChar(
  1077. WORD vkey, //@parm WM_CHAR wparam (translated key code)
  1078. DWORD dwFlags) //@parm WM_CHAR flags
  1079. {
  1080. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnChar");
  1081. if(!_fInDialogBox || (GetKeyboardFlags() & CTRL))
  1082. return 1;
  1083. switch(vkey)
  1084. {
  1085. case 'J' - 0x40: // Ctrl-Return generates Ctrl-J (LF):
  1086. case VK_RETURN: // treat it as an ordinary return
  1087. // We need to filter-out cases where we don't want to insert <cr> in
  1088. // 1.0 mode here since the info isn't available within the ped
  1089. if (((CTxtEdit*)_pserv)->Get10Mode())
  1090. {
  1091. if (_fInDialogBox && dwFlags != MK_CONTROL && !(_dwStyle & ES_WANTRETURN))
  1092. return 0;
  1093. if (!(_dwStyle & ES_MULTILINE))
  1094. {
  1095. //richedit beeps in this case
  1096. ((CTxtEdit*)_pserv)->Beep();
  1097. return 0;
  1098. }
  1099. }
  1100. else if (!(_dwStyle & ES_WANTRETURN))
  1101. return 0; // Signal char processed (eaten)
  1102. break;
  1103. case VK_TAB:
  1104. return 0;
  1105. }
  1106. return 1; // Signal char not processed
  1107. }
  1108. ///////////////////////////////// View rectangle //////////////////////////////////////
  1109. void CTxtWinHost::OnGetRect(
  1110. LPRECT prc)
  1111. {
  1112. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnGetRect");
  1113. RECT rcInset;
  1114. LONG lSelBarWidth = 0;
  1115. if(_fEmSetRectCalled)
  1116. {
  1117. // Get the selection bar width and add it back to the view inset so
  1118. // we return the rectangle that the application set.
  1119. TxGetSelectionBarWidth(&lSelBarWidth);
  1120. }
  1121. // Get view inset (in HIMETRIC)
  1122. TxGetViewInset(&rcInset);
  1123. // Get client rect in pixels
  1124. TxGetClientRect(prc);
  1125. // Modify the client rect by the inset converted to pixels
  1126. prc->left += W32->HimetricToDevice(rcInset.left + lSelBarWidth, W32->GetXPerInchScreenDC());
  1127. prc->top += W32->HimetricToDevice(rcInset.top, W32->GetYPerInchScreenDC());
  1128. prc->right -= W32->HimetricToDevice(rcInset.right, W32->GetXPerInchScreenDC());
  1129. prc->bottom -= W32->HimetricToDevice(rcInset.bottom, W32->GetYPerInchScreenDC());
  1130. }
  1131. void CTxtWinHost::OnSetRect(
  1132. LPRECT prc, //@parm Desired formatting RECT
  1133. BOOL fNewBehavior, //@parm If TRUE, prc is inset RECT directly
  1134. BOOL fRedraw) //@parm If TRUE, redraw after setting RECT
  1135. {
  1136. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSetRect");
  1137. RECT rcClient;
  1138. LONG lSelBarWidth;
  1139. // Assuming this is not set to the default, turn on special EM_SETRECT
  1140. // processing. The important part of this is that we subtract the selection
  1141. // bar from the view inset because the EM_SETRECT rectangle does not
  1142. // include the selection bar.
  1143. _fEmSetRectCalled = TRUE;
  1144. if(!prc)
  1145. {
  1146. // We are back to the default so turn off special EM_SETRECT procesing.
  1147. _fEmSetRectCalled = FALSE;
  1148. SetDefaultInset();
  1149. }
  1150. else
  1151. {
  1152. // For screen display, the following intersects new view RECT
  1153. // with adjusted client area RECT
  1154. TxGetClientRect(&rcClient);
  1155. // Adjust client rect. Factors in space for borders
  1156. if(_fBorder)
  1157. {
  1158. rcClient.top += _yInset;
  1159. rcClient.bottom -= _yInset - 1;
  1160. rcClient.left += _xInset;
  1161. rcClient.right -= _xInset;
  1162. }
  1163. if(!fNewBehavior)
  1164. {
  1165. // Intersect new view rectangle with adjusted client area rectangle
  1166. if(!IntersectRect(&_rcViewInset, &rcClient, prc))
  1167. _rcViewInset = rcClient;
  1168. }
  1169. else
  1170. _rcViewInset = *prc;
  1171. // Get selection bar width
  1172. TxGetSelectionBarWidth(&lSelBarWidth);
  1173. // Compute inset in pixels and convert to HIMETRIC.
  1174. _rcViewInset.left = W32->DeviceToHimetric(_rcViewInset.left - rcClient.left, W32->GetXPerInchScreenDC()) - lSelBarWidth;
  1175. _rcViewInset.top = W32->DeviceToHimetric(_rcViewInset.top - rcClient.top, W32->GetYPerInchScreenDC());
  1176. _rcViewInset.right = W32->DeviceToHimetric(rcClient.right - _rcViewInset.right, W32->GetXPerInchScreenDC());
  1177. _rcViewInset.bottom = W32->DeviceToHimetric(rcClient.bottom - _rcViewInset.bottom, W32->GetYPerInchScreenDC());
  1178. }
  1179. if(fRedraw)
  1180. {
  1181. _pserv->OnTxPropertyBitsChange(TXTBIT_VIEWINSETCHANGE,
  1182. TXTBIT_VIEWINSETCHANGE);
  1183. }
  1184. }
  1185. /////////////////////////////// System notifications //////////////////////////////////
  1186. void CTxtWinHost::OnSysColorChange()
  1187. {
  1188. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSysColorChange");
  1189. if(!_fNotSysBkgnd)
  1190. _crBackground = GetSysColor(COLOR_WINDOW);
  1191. TxInvalidateRect(NULL, TRUE);
  1192. }
  1193. /*
  1194. * CTxtWinHost::OnGetDlgCode (wparam, lparam)
  1195. *
  1196. * @mfunc
  1197. * Handle some WM_GETDLGCODE messages
  1198. *
  1199. * #rdesc
  1200. * LRESULT = dialog code
  1201. */
  1202. LRESULT CTxtWinHost::OnGetDlgCode(
  1203. WPARAM wparam,
  1204. LPARAM lparam)
  1205. {
  1206. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnGetDlgCode");
  1207. LRESULT lres = DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_WANTTAB;
  1208. if(_dwStyle & ES_MULTILINE)
  1209. lres |= DLGC_WANTALLKEYS;
  1210. if(!(_dwStyle & ES_SAVESEL))
  1211. lres |= DLGC_HASSETSEL;
  1212. // HACK: If we get one of these messages then we turn on the special
  1213. // EM_SETSEL behavior. The problem is that _fInDialogBox gets turned
  1214. // on after the EM_SETSEL has occurred.
  1215. _fUseSpecialSetSel = TRUE;
  1216. /*
  1217. ** -------------------------------------------- JEFFBOG HACK ----
  1218. ** Only set Dialog Box Flag if GETDLGCODE message is generated by
  1219. ** IsDialogMessage -- if so, the lParam will be a pointer to the
  1220. ** message structure passed to IsDialogMessage; otherwise, lParam
  1221. ** will be NULL. Reason for the HACK alert: the wParam & lParam
  1222. ** for GETDLGCODE is still not clearly defined and may end up
  1223. ** changing in a way that would throw this off
  1224. ** -------------------------------------------- JEFFBOG HACK ----
  1225. */
  1226. if(lparam)
  1227. _fInDialogBox = TRUE;
  1228. /*
  1229. ** If this is a WM_SYSCHAR message generated by the UNDO keystroke
  1230. ** we want this message so we can EAT IT in remain.c, case WM_SYSCHAR:
  1231. */
  1232. if (lparam &&
  1233. (((LPMSG)lparam)->message == WM_SYSCHAR) &&
  1234. (((LPMSG)lparam)->lParam & SYS_ALTERNATE) &&
  1235. wparam == VK_BACK)
  1236. {
  1237. lres |= DLGC_WANTMESSAGE;
  1238. }
  1239. return lres;
  1240. }
  1241. ///////////////////////////////// Other messages //////////////////////////////////////
  1242. LRESULT CTxtWinHost::OnGetOptions() const
  1243. {
  1244. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnGetOptions");
  1245. LRESULT lres = (_dwStyle & ECO_STYLES);
  1246. if(_fEnableAutoWordSel)
  1247. lres |= ECO_AUTOWORDSELECTION;
  1248. return lres;
  1249. }
  1250. void CTxtWinHost::OnSetOptions(
  1251. WORD wOp,
  1252. DWORD eco)
  1253. {
  1254. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSetOptions");
  1255. DWORD dwChangeMask = 0;
  1256. DWORD dwProp = 0;
  1257. DWORD dwStyle;
  1258. DWORD dwStyleNew = _dwStyle;
  1259. const BOOL fAutoWordSel = !!(eco & ECO_AUTOWORDSELECTION);
  1260. BOOL bNeedToTurnOffIME = FALSE;
  1261. // We keep track of the bits changed and then if any have changed we
  1262. // query for all of our property bits and then send them. This simplifies
  1263. // the code because we don't have to set all the bits specially. If the
  1264. // code is changed to make the properties more in line with the new
  1265. // model, we want to look at this code again.
  1266. // Single line controls can't have a selection bar or do vertical writing
  1267. if(!(_dwStyle & ES_MULTILINE))
  1268. eco &= ~ECO_SELECTIONBAR;
  1269. Assert((DWORD)fAutoWordSel <= 1); // Make sure that BOOL is 1/0
  1270. dwStyle = (eco & ECO_STYLES);
  1271. switch(wOp)
  1272. {
  1273. case ECOOP_SET:
  1274. dwStyleNew = (dwStyleNew & ~ECO_STYLES) | dwStyle;
  1275. _fEnableAutoWordSel = fAutoWordSel;
  1276. break;
  1277. case ECOOP_OR:
  1278. dwStyleNew |= dwStyle; // Setting a :1 flag = TRUE
  1279. if(fAutoWordSel) // or FALSE is 1 instruction
  1280. _fEnableAutoWordSel = TRUE; // Setting it to a BOOL
  1281. break; // averages 9 instructions!
  1282. case ECOOP_AND:
  1283. dwStyleNew &= (dwStyle | ~ECO_STYLES);
  1284. if(!fAutoWordSel)
  1285. _fEnableAutoWordSel = FALSE;
  1286. break;
  1287. case ECOOP_XOR:
  1288. dwStyleNew ^= dwStyle;
  1289. if(fAutoWordSel)
  1290. _fEnableAutoWordSel ^= 1;
  1291. break;
  1292. }
  1293. if(_fEnableAutoWordSel != (unsigned)fAutoWordSel)
  1294. dwChangeMask |= TXTBIT_AUTOWORDSEL;
  1295. if(dwStyleNew != _dwStyle)
  1296. {
  1297. DWORD dwChange = dwStyleNew ^ _dwStyle;
  1298. AssertSz(!(dwChange & ~ECO_STYLES), "non-eco style changed");
  1299. if(!(dwStyleNew & ES_MULTILINE))
  1300. dwStyleNew &= ~ES_VERTICAL;
  1301. _dwStyle = dwStyleNew;
  1302. SetWindowLong(_hwnd, GWL_STYLE, dwStyleNew & ~ES_VERTICAL);
  1303. if(dwChange & ES_NOHIDESEL)
  1304. dwChangeMask |= TXTBIT_HIDESELECTION;
  1305. // These two local variables to use to keep track of
  1306. // previous setting of ES_READONLY
  1307. BOOL bReadOnly = (_dwStyle & ES_READONLY);
  1308. if(dwChange & ES_READONLY)
  1309. {
  1310. dwChangeMask |= TXTBIT_READONLY;
  1311. // Change drop target state as appropriate.
  1312. if(dwStyleNew & ES_READONLY)
  1313. HostRevokeDragDrop();
  1314. else
  1315. HostRegisterDragDrop();
  1316. bReadOnly = (dwStyleNew & ES_READONLY);
  1317. }
  1318. if(dwChange & ES_VERTICAL)
  1319. dwChangeMask |= TXTBIT_VERTICAL;
  1320. if(dwChange & ES_NOIME)
  1321. {
  1322. _usIMEMode = (dwStyleNew & ES_NOIME) ? ES_NOIME : 0;
  1323. bNeedToTurnOffIME = (_usIMEMode ==ES_NOIME);
  1324. }
  1325. else if(dwChange & ES_SELFIME)
  1326. _usIMEMode = (dwStyleNew & ES_SELFIME) ? ES_SELFIME : 0;
  1327. // No action required for ES_WANTRETURN nor for ES_SAVESEL
  1328. // Do this last
  1329. if(dwChange & ES_SELECTIONBAR)
  1330. dwChangeMask |= TXTBIT_SELBARCHANGE;
  1331. }
  1332. if (dwChangeMask)
  1333. {
  1334. TxGetPropertyBits(dwChangeMask, &dwProp);
  1335. _pserv->OnTxPropertyBitsChange(dwChangeMask, dwProp);
  1336. }
  1337. if (bNeedToTurnOffIME)
  1338. // Tell textservices to turnoff ime
  1339. _pserv->TxSendMessage(EM_SETEDITSTYLE, SES_NOIME, SES_NOIME, NULL);
  1340. }
  1341. void CTxtWinHost::OnSetReadOnly(
  1342. BOOL fReadOnly)
  1343. {
  1344. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSetReadOnly");
  1345. DWORD dwT = GetWindowLong(_hwnd, GWL_STYLE);
  1346. DWORD dwUpdatedBits = 0;
  1347. if(fReadOnly)
  1348. {
  1349. dwT |= ES_READONLY;
  1350. _dwStyle |= ES_READONLY;
  1351. // Turn off Drag Drop
  1352. HostRevokeDragDrop();
  1353. dwUpdatedBits |= TXTBIT_READONLY;
  1354. }
  1355. else
  1356. {
  1357. dwT &= ~ES_READONLY;
  1358. _dwStyle &= ~ES_READONLY;
  1359. // Turn drag drop back on
  1360. HostRegisterDragDrop();
  1361. }
  1362. _pserv->OnTxPropertyBitsChange(TXTBIT_READONLY, dwUpdatedBits);
  1363. SetWindowLong(_hwnd, GWL_STYLE, dwT);
  1364. }
  1365. //////////////////////////////////// Helpers /////////////////////////////////////////
  1366. void CTxtWinHost::SetDefaultInset()
  1367. {
  1368. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::SetDefaultInset");
  1369. // Generate default view rect from client rect
  1370. if(_fBorder)
  1371. {
  1372. // Factors in space for borders
  1373. _rcViewInset.top = W32->DeviceToHimetric(_yInset, W32->GetYPerInchScreenDC());
  1374. _rcViewInset.bottom = W32->DeviceToHimetric(_yInset - 1, W32->GetYPerInchScreenDC());
  1375. _rcViewInset.left = W32->DeviceToHimetric(_xInset, W32->GetXPerInchScreenDC());
  1376. _rcViewInset.right = W32->DeviceToHimetric(_xInset, W32->GetXPerInchScreenDC());
  1377. }
  1378. else
  1379. {
  1380. // Default the top and bottom inset to 0 and the left and right
  1381. // to the size of the border.
  1382. _rcViewInset.top = 0;
  1383. _rcViewInset.bottom = 0;
  1384. _rcViewInset.left = W32->DeviceToHimetric(W32->GetCxBorder(), W32->GetXPerInchScreenDC());
  1385. _rcViewInset.right = W32->DeviceToHimetric(W32->GetCxBorder(), W32->GetXPerInchScreenDC());
  1386. }
  1387. }
  1388. ///////////////////////////////// East Asia Support //////////////////////////////////////
  1389. HIMC CTxtWinHost::TxImmGetContext()
  1390. {
  1391. #ifndef NOFEPROCESSING
  1392. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxImmGetContext");
  1393. HIMC himc;
  1394. Assert(_hwnd);
  1395. himc = ImmGetContext(_hwnd, FALSE);
  1396. return himc;
  1397. #else
  1398. return NULL;
  1399. #endif
  1400. }
  1401. void CTxtWinHost::TxImmReleaseContext(
  1402. HIMC himc)
  1403. {
  1404. #ifndef NOFEPROCESSING
  1405. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxImmReleaseContext");
  1406. Assert(_hwnd);
  1407. ImmReleaseContext(_hwnd, himc, FALSE);
  1408. #endif
  1409. }
  1410. void CTxtWinHost::HostRevokeDragDrop()
  1411. {
  1412. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::HostRevokeDragDrop");
  1413. if(_fRegisteredForDrop)
  1414. {
  1415. // Note that if the revoke fails we want to know about this in debug
  1416. // builds so we can fix any problems. In retail, we can't really do
  1417. // so we just ignore it.
  1418. #if !defined(NOFULLDEBUG) && defined(DEBUG)
  1419. HRESULT hr =
  1420. #endif // DEBUG
  1421. RevokeDragDrop(_hwnd);
  1422. #if !defined(NOFULLDEBUG) && defined(DEBUG)
  1423. TESTANDTRACEHR(hr);
  1424. #endif // DEBUG
  1425. _fRegisteredForDrop = FALSE;
  1426. }
  1427. }
  1428. void CTxtWinHost::HostRegisterDragDrop()
  1429. {
  1430. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::RegisterDragDrop");
  1431. IDropTarget *pdt = NULL;
  1432. if(!_fRegisteredForDrop && _pserv->TxGetDropTarget(&pdt) == NOERROR)
  1433. {
  1434. // The most likely reason for RegisterDragDrop to fail is some kind of
  1435. // bug in our program.
  1436. HRESULT hr = RegisterDragDrop(_hwnd, pdt);
  1437. if(hr == NOERROR)
  1438. _fRegisteredForDrop = TRUE;
  1439. if (pdt)
  1440. pdt->Release();
  1441. }
  1442. }
  1443. #define cmultBorder 1
  1444. void CTxtWinHost::OnSunkenWindowPosChanging(
  1445. HWND hwnd,
  1446. WINDOWPOS *pwndpos)
  1447. {
  1448. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSunkenWindowPosChanging");
  1449. if(IsWindowVisible(hwnd))
  1450. {
  1451. RECT rc;
  1452. HWND hwndParent;
  1453. GetWindowRect(hwnd, &rc);
  1454. InflateRect(&rc, W32->GetCxBorder() * cmultBorder, W32->GetCyBorder() * cmultBorder);
  1455. hwndParent = GetParent(hwnd);
  1456. MapWindowPoints(HWND_DESKTOP, hwndParent, (POINT *) &rc, 2);
  1457. InvalidateRect(hwndParent, &rc, TRUE);
  1458. }
  1459. }
  1460. LRESULT CTxtWinHost::OnSize(
  1461. HWND hwnd,
  1462. WORD fwSizeType,
  1463. int nWidth,
  1464. int nHeight)
  1465. {
  1466. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSize");
  1467. BOOL fIconic = GetIconic(hwnd);
  1468. DWORD dw = TXTBIT_CLIENTRECTCHANGE;
  1469. if(_sWidth != nWidth && !fIconic && !_fIconic)
  1470. {
  1471. _sWidth = (short)nWidth; // Be sure to update _sWidth
  1472. dw = TXTBIT_EXTENTCHANGE;
  1473. }
  1474. if(!_fVisible)
  1475. {
  1476. if(!fIconic)
  1477. _fResized = TRUE;
  1478. }
  1479. else if(!fIconic)
  1480. {
  1481. // We use this property because this will force a recalc.
  1482. // We don't actually recalc on a client rect change because
  1483. // most of the time it is pointless. We force one here because
  1484. // some applications use size changes to calculate the optimal
  1485. // size of the window.
  1486. _pserv->OnTxPropertyBitsChange(dw, dw);
  1487. if(_fIconic)
  1488. {
  1489. TRACEINFOSZ("Restoring from iconic");
  1490. InvalidateRect(hwnd, NULL, TRUE);
  1491. }
  1492. }
  1493. _fIconic = fIconic; // Update _fIconic
  1494. return 0;
  1495. }
  1496. HRESULT CTxtWinHost::OnTxVisibleChange(
  1497. BOOL fVisible)
  1498. {
  1499. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnTxVisibleChange");
  1500. _fVisible = fVisible;
  1501. if(!_fVisible && _fResized)
  1502. {
  1503. RECT rc;
  1504. // Control was resized while hidden, need to really resize now
  1505. TxGetClientRect(&rc);
  1506. _fResized = FALSE;
  1507. _pserv->OnTxPropertyBitsChange(TXTBIT_CLIENTRECTCHANGE,
  1508. TXTBIT_CLIENTRECTCHANGE);
  1509. }
  1510. return S_OK;
  1511. }
  1512. //////////////////////////// ITextHost Interface ////////////////////////////
  1513. // @doc EXTERNAL
  1514. /*
  1515. * CTxtWinHost::TxGetDC()
  1516. *
  1517. * @mfunc
  1518. * Abstracts GetDC so Text Services does not need a window handle.
  1519. *
  1520. * @rdesc
  1521. * A DC or NULL in the event of an error.
  1522. *
  1523. * @comm
  1524. * This method is only valid when the control is in-place active;
  1525. * calls while inactive may fail.
  1526. */
  1527. HDC CTxtWinHost::TxGetDC()
  1528. {
  1529. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetDC");
  1530. Assert(_hwnd);
  1531. return ::GetDC(_hwnd);
  1532. }
  1533. /*
  1534. * CTxtWinHost::TxReleaseDC (hdc)
  1535. *
  1536. * @mfunc
  1537. * Release DC gotten by TxGetDC.
  1538. *
  1539. * @rdesc
  1540. * 1 - HDC was released. <nl>
  1541. * 0 - HDC was not released. <nl>
  1542. *
  1543. * @comm
  1544. * This method is only valid when the control is in-place active;
  1545. * calls while inactive may fail.
  1546. */
  1547. int CTxtWinHost::TxReleaseDC(
  1548. HDC hdc) //@parm DC to release
  1549. {
  1550. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxReleaseDC");
  1551. Assert(_hwnd);
  1552. return ::ReleaseDC (_hwnd, hdc);
  1553. }
  1554. /*
  1555. * CTxtWinHost::TxShowScrollBar (fnBar, fShow)
  1556. *
  1557. * @mfunc
  1558. * Shows or Hides scroll bar in Text Host window
  1559. *
  1560. * @rdesc
  1561. * TRUE on success, FALSE otherwise
  1562. *
  1563. * @comm
  1564. * This method is only valid when the control is in-place active;
  1565. * calls while inactive may fail.
  1566. */
  1567. BOOL CTxtWinHost::TxShowScrollBar(
  1568. INT fnBar, //@parm Specifies scroll bar(s) to be shown or hidden
  1569. BOOL fShow) //@parm Specifies whether scroll bar is shown or hidden
  1570. {
  1571. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxShowScrollBar");
  1572. Assert(_hwnd);
  1573. LONG nMax;
  1574. if(fnBar == SB_HORZ)
  1575. _pserv->TxGetHScroll(NULL, &nMax, NULL, NULL, NULL);
  1576. else
  1577. _pserv->TxGetVScroll(NULL, &nMax, NULL, NULL, NULL);
  1578. return W32->ShowScrollBar(_hwnd, fnBar, fShow, nMax);
  1579. }
  1580. /*
  1581. * CTxtWinHost::TxEnableScrollBar (fuSBFlags, fuArrowflags)
  1582. *
  1583. * @mfunc
  1584. * Enables or disables one or both scroll bar arrows
  1585. * in Text Host window.
  1586. *
  1587. * @rdesc
  1588. * If the arrows are enabled or disabled as specified, the return
  1589. * value is TRUE. If the arrows are already in the requested state or an
  1590. * error occurs, the return value is FALSE.
  1591. *
  1592. * @comm
  1593. * This method is only valid when the control is in-place active;
  1594. * calls while inactive may fail.
  1595. */
  1596. BOOL CTxtWinHost::TxEnableScrollBar (
  1597. INT fuSBFlags, //@parm Specifies scroll bar type
  1598. INT fuArrowflags) //@parm Specifies whether and which scroll bar arrows
  1599. // are enabled or disabled
  1600. {
  1601. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxEnableScrollBar");
  1602. Assert(_hwnd);
  1603. return W32->EnableScrollBar(_hwnd, fuSBFlags, fuArrowflags);
  1604. }
  1605. /*
  1606. * CTxtWinHost::TxSetScrollRange (fnBar, nMinPos, nMaxPos, fRedraw)
  1607. *
  1608. * @mfunc
  1609. * Sets the minimum and maximum position values for the specified
  1610. * scroll bar in the text host window.
  1611. *
  1612. * @rdesc
  1613. * If the arrows are enabled or disabled as specified, the return value
  1614. * is TRUE. If the arrows are already in the requested state or an error
  1615. * occurs, the return value is FALSE.
  1616. *
  1617. * @comm
  1618. * This method is only valid when the control is in-place active;
  1619. * calls while inactive may fail.
  1620. */
  1621. BOOL CTxtWinHost::TxSetScrollRange(
  1622. INT fnBar, //@parm Scroll bar flag
  1623. LONG nMinPos, //@parm Minimum scrolling position
  1624. INT nMaxPos, //@parm Maximum scrolling position
  1625. BOOL fRedraw) //@parm Specifies whether scroll bar should be redrawn
  1626. { // to reflect change
  1627. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetScrollRange");
  1628. Assert(_hwnd);
  1629. if(NULL == _pserv)
  1630. {
  1631. // We are initializing so do this instead of callback
  1632. return ::SetScrollRange(_hwnd, fnBar, nMinPos, nMaxPos, fRedraw);
  1633. }
  1634. SetScrollInfo(fnBar, fRedraw);
  1635. return TRUE;
  1636. }
  1637. /*
  1638. * CTxtWinHost::TxSetScrollPos (fnBar, nPos, fRedraw)
  1639. *
  1640. * @mfunc
  1641. * Tells Text host to set the position of the scroll box (thumb) in the
  1642. * specified scroll bar and, if requested, redraws the scroll bar to
  1643. * reflect the new position of the scroll box.
  1644. *
  1645. * @rdesc
  1646. * TRUE on success; FALSE otherwise.
  1647. *
  1648. * @comm
  1649. * This method is only valid when the control is in-place active;
  1650. * calls while inactive may fail.
  1651. */
  1652. BOOL CTxtWinHost::TxSetScrollPos (
  1653. INT fnBar, //@parm Scroll bar flag
  1654. INT nPos, //@parm New position in scroll box
  1655. BOOL fRedraw) //@parm Redraw flag
  1656. {
  1657. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetScrollPos");
  1658. Assert(_hwnd);
  1659. if(NULL == _pserv)
  1660. {
  1661. // We are initializing so do this instead of callback
  1662. return ::SetScrollPos(_hwnd, fnBar, nPos, fRedraw);
  1663. }
  1664. SetScrollInfo(fnBar, fRedraw);
  1665. return TRUE;
  1666. }
  1667. /*
  1668. * CTxtWinHost::TxInvalidateRect (prc, fMode)
  1669. *
  1670. * @mfunc
  1671. * Adds a rectangle to the Text Host window's update region
  1672. *
  1673. * @comm
  1674. * This function may be called while inactive; however the host
  1675. * implementation is free to invalidate an area greater than
  1676. * the requested rect.
  1677. *
  1678. * Note: In transparent mode, we need to pass TRUE to InvalidateRect.
  1679. * However, in all other cases, it is best to pass FALSE, because we always
  1680. * repaint the backgrounds of our displays.
  1681. */
  1682. void CTxtWinHost::TxInvalidateRect(
  1683. LPCRECT prc, //@parm Address of rectangle coordinates
  1684. BOOL fMode) //@parm Erase background flag
  1685. {
  1686. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxInvalidateRect");
  1687. Assert(_hwnd);
  1688. if(!_fVisible)
  1689. {
  1690. // There doesn't seem to be a deterministic way to determine whether
  1691. // our window is visible or not via message notifications. Therefore,
  1692. // we check this each time in case it might have changed.
  1693. _fVisible = IsWindowVisible(_hwnd);
  1694. if(_fVisible)
  1695. OnTxVisibleChange(TRUE);
  1696. }
  1697. // Don't bother with invalidating rect if we aren't visible
  1698. if(_fVisible)
  1699. {
  1700. if(IsTransparentMode())
  1701. {
  1702. RECT rcParent;
  1703. HWND hParent = ::GetParent(_hwnd);
  1704. Assert(hParent);
  1705. // For transparent mode, we need to invalidate the parent
  1706. // so it will paint the background.
  1707. if(prc)
  1708. rcParent = *prc;
  1709. else
  1710. TxGetClientRect(&rcParent);
  1711. ::MapWindowPoints(_hwnd, hParent, (LPPOINT)&rcParent, 2);
  1712. ::InvalidateRect(hParent, &rcParent, TRUE);
  1713. // ::HideCaret(_hwnd);
  1714. }
  1715. ::InvalidateRect(_hwnd, prc, FALSE);
  1716. }
  1717. }
  1718. /*
  1719. * CTxtWinHost::TxViewChange (fUpdate)
  1720. *
  1721. * @mfunc
  1722. * Notify Text Host that update region should be repainted.
  1723. *
  1724. * @comm
  1725. * It is the responsibility of the text services to call
  1726. * TxViewChanged every time it decides that it's visual representation
  1727. * has changed, regardless of whether the control is active or
  1728. * not. If the control is active, the text services has the additional
  1729. * responsibility of making sure the controls window is updated.
  1730. * It can do this in a number of ways: 1) get a DC for the control's
  1731. * window and start blasting pixels (TxGetDC and TxReleaseDC), 2)
  1732. * invalidate the control's window (TxInvalidate), or 3) scroll
  1733. * the control's window (TxScrollWindowEx).
  1734. *
  1735. * Text services can choose to call TxViewChange after it has
  1736. * performed any operations to update the active view and pass a
  1737. * true along with the call. By passing true, the text host
  1738. * calls UpdateWindow to make sure any unpainted areas of the
  1739. * active control are repainted.
  1740. */
  1741. void CTxtWinHost::TxViewChange(
  1742. BOOL fUpdate) //@parm TRUE = call update window
  1743. {
  1744. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxViewChange");
  1745. Assert(_hwnd);
  1746. // Don't bother with paint since we aren't visible
  1747. if(_fVisible)
  1748. {
  1749. // For updates requests that are FALSE, we will let the next WM_PAINT
  1750. // message pick up the draw.
  1751. if(fUpdate)
  1752. {
  1753. if(IsTransparentMode())
  1754. {
  1755. HWND hParent = GetParent (_hwnd);
  1756. Assert(hParent);
  1757. // For transparent mode, we need to update the parent first
  1758. // before we can update ourself. Otherwise, what we painted will
  1759. // be erased by the parent's background later.
  1760. ::UpdateWindow (hParent);
  1761. }
  1762. ::UpdateWindow (_hwnd);
  1763. }
  1764. }
  1765. }
  1766. /*
  1767. * CTxtWinHost::TxCreateCaret (hbmp, xWidth, yHeight)
  1768. *
  1769. * @mfunc
  1770. * Create new shape for Text Host's caret
  1771. *
  1772. * @rdesc
  1773. * TRUE on success, FALSE otherwise.
  1774. *
  1775. * @comm
  1776. * This method is only valid when the control is in-place active;
  1777. * calls while inactive may fail.
  1778. */
  1779. BOOL CTxtWinHost::TxCreateCaret(
  1780. HBITMAP hbmp, //@parm Handle of bitmap for caret shape
  1781. INT xWidth, //@parm Caret width
  1782. INT yHeight) //@parm Caret height
  1783. {
  1784. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxCreateCaret");
  1785. Assert(_hwnd);
  1786. return ::CreateCaret (_hwnd, hbmp, xWidth, yHeight);
  1787. }
  1788. /*
  1789. * CTxtWinHost::TxShowCaret (fShow)
  1790. *
  1791. * @mfunc
  1792. * Make caret visible/invisible at caret position in Text Host window.
  1793. *
  1794. * @rdesc
  1795. * TRUE - call succeeded <nl>
  1796. * FALSE - call failed <nl>
  1797. *
  1798. * @comm
  1799. * This method is only valid when the control is in-place active;
  1800. * calls while inactive may fail.
  1801. */
  1802. BOOL CTxtWinHost::TxShowCaret(
  1803. BOOL fShow) //@parm Flag whether caret is visible
  1804. {
  1805. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxShowCaret");
  1806. return fShow ? ::ShowCaret(_hwnd) : ::HideCaret(_hwnd);
  1807. }
  1808. /*
  1809. * CTxtWinHost::TxSetCaretPos (x, y)
  1810. *
  1811. * @mfunc
  1812. * Move caret position to specified coordinates in Text Host window.
  1813. *
  1814. * @rdesc
  1815. * TRUE - call succeeded <nl>
  1816. * FALSE - call failed <nl>
  1817. *
  1818. * @comm
  1819. * This method is only valid when the control is in-place active;
  1820. * calls while inactive may fail.
  1821. */
  1822. BOOL CTxtWinHost::TxSetCaretPos(
  1823. INT x, //@parm Horizontal position (in client coordinates)
  1824. INT y) //@parm Vertical position (in client coordinates)
  1825. {
  1826. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetCaretPos");
  1827. return ::SetCaretPos(x, y);
  1828. }
  1829. /*
  1830. * CTxtWinHost::TxSetTimer (idTimer, uTimeout)
  1831. *
  1832. * @mfunc
  1833. * Request Text Host to creates a timer with specified time out.
  1834. *
  1835. * @rdesc
  1836. * TRUE - call succeeded <nl>
  1837. * FALSE - call failed <nl>
  1838. */
  1839. BOOL CTxtWinHost::TxSetTimer(
  1840. UINT idTimer, //@parm Timer identifier
  1841. UINT uTimeout) //@parm Timeout in msec
  1842. {
  1843. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetTimer");
  1844. Assert(_hwnd);
  1845. return ::SetTimer(_hwnd, idTimer, uTimeout, NULL);
  1846. }
  1847. /*
  1848. * CTxtWinHost::TxKillTimer (idTimer)
  1849. *
  1850. * @mfunc
  1851. * Destroy specified timer
  1852. *
  1853. * @rdesc
  1854. * TRUE - call succeeded <nl>
  1855. * FALSE - call failed <nl>
  1856. *
  1857. * @comm
  1858. * This method may be called at any time irrespective of active versus
  1859. * inactive state.
  1860. */
  1861. void CTxtWinHost::TxKillTimer(
  1862. UINT idTimer) //@parm id of timer
  1863. {
  1864. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxKillTimer");
  1865. Assert(_hwnd);
  1866. ::KillTimer(_hwnd, idTimer);
  1867. }
  1868. /*
  1869. * CTxtWinHost::TxScrollWindowEx (dx, dy, lprcScroll, lprcClip, hrgnUpdate,
  1870. * lprcUpdate, fuScroll)
  1871. * @mfunc
  1872. * Request Text Host to scroll the content of the specified client area
  1873. *
  1874. * @comm
  1875. * This method is only valid when the control is in-place active;
  1876. * calls while inactive may fail.
  1877. */
  1878. void CTxtWinHost::TxScrollWindowEx (
  1879. INT dx, //@parm Amount of horizontal scrolling
  1880. INT dy, //@parm Amount of vertical scrolling
  1881. LPCRECT lprcScroll, //@parm Scroll rectangle
  1882. LPCRECT lprcClip, //@parm Clip rectangle
  1883. HRGN hrgnUpdate, //@parm Handle of update region
  1884. LPRECT lprcUpdate, //@parm Update rectangle
  1885. UINT fuScroll) //@parm Scrolling flags
  1886. {
  1887. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxScrollWindowEx");
  1888. Assert(_hwnd);
  1889. ::ScrollWindowEx(_hwnd, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate, fuScroll);
  1890. }
  1891. /*
  1892. * CTxtWinHost::TxSetCapture (fCapture)
  1893. *
  1894. * @mfunc
  1895. * Set mouse capture in Text Host's window.
  1896. *
  1897. * @comm
  1898. * This method is only valid when the control is in-place active;
  1899. * calls while inactive may do nothing.
  1900. */
  1901. void CTxtWinHost::TxSetCapture(
  1902. BOOL fCapture) //@parm Whether to get or release capture
  1903. {
  1904. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetCapture");
  1905. Assert(_hwnd);
  1906. if (fCapture)
  1907. ::SetCapture(_hwnd);
  1908. else
  1909. ::ReleaseCapture();
  1910. }
  1911. /*
  1912. * CTxtWinHost::TxSetFocus ()
  1913. *
  1914. * @mfunc
  1915. * Set focus in text host window.
  1916. *
  1917. * @comm
  1918. * This method is only valid when the control is in-place active;
  1919. * calls while inactive may fail.
  1920. */
  1921. void CTxtWinHost::TxSetFocus()
  1922. {
  1923. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetFocus");
  1924. Assert(_hwnd);
  1925. ::SetFocus(_hwnd);
  1926. }
  1927. /*
  1928. * CTxtWinHost::TxSetCursor (hcur, fText)
  1929. *
  1930. * @mfunc
  1931. * Establish a new cursor shape in the Text Host's window.
  1932. *
  1933. * @comm
  1934. * This method may be called at any time, irrespective of
  1935. * active vs. inactive state.
  1936. *
  1937. * ITextHost::TxSetCursor should be called back by the Text Services
  1938. * to actually set the mouse cursor. If the fText parameter is TRUE,
  1939. * Text Services is trying to set the "text" cursor (cursor over text
  1940. * that is not selected, currently an IBEAM). In that case, the host
  1941. * can set it to whatever the control MousePointer property is. This is
  1942. * required by VB compatibility since, via the MousePointer property,
  1943. * the VB programmer has control over the shape of the mouse cursor,
  1944. * whenever it would normally be set to an IBEAM.
  1945. */
  1946. void CTxtWinHost::TxSetCursor(
  1947. HCURSOR hcur, //@parm Handle to cursor
  1948. BOOL fText) //@parm Indicates caller wants to set text cursor
  1949. // (IBeam) if true.
  1950. {
  1951. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetCursor");
  1952. ::SetCursor(hcur);
  1953. }
  1954. /*
  1955. * CTxtWinHost::TxScreenToClient (lppt)
  1956. *
  1957. * @mfunc
  1958. * Convert screen coordinates to Text Host window coordinates.
  1959. *
  1960. * @rdesc
  1961. * TRUE - call succeeded <nl>
  1962. * FALSE - call failed <nl>
  1963. */
  1964. BOOL CTxtWinHost::TxScreenToClient(
  1965. LPPOINT lppt) //@parm Coordinates for point
  1966. {
  1967. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxScreenToClient");
  1968. Assert(_hwnd);
  1969. return ::ScreenToClient(_hwnd, lppt);
  1970. }
  1971. /*
  1972. * CTxtWinHost::TxClientToScreen (lppt)
  1973. *
  1974. * @mfunc
  1975. * Convert Text Host coordinates to screen coordinates
  1976. *
  1977. * @rdesc
  1978. * TRUE - call succeeded <nl>
  1979. * FALSE - call failed <nl>
  1980. *
  1981. * @comm
  1982. * This call is valid at any time, although it is allowed to
  1983. * fail. In general, if text services has coordinates it needs
  1984. * to translate from client coordinates (e.g. for TOM's
  1985. * PointFromRange method) the text services will actually be
  1986. * visible.
  1987. *
  1988. * However, if no conversion is possible, then the method will fail.
  1989. */
  1990. BOOL CTxtWinHost::TxClientToScreen(
  1991. LPPOINT lppt) //@parm Client coordinates to convert.
  1992. {
  1993. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxClientToScreen");
  1994. Assert(_hwnd);
  1995. return ::ClientToScreen(_hwnd, lppt);
  1996. }
  1997. /*
  1998. * CTxtWinHost::TxActivate (plOldState)
  1999. *
  2000. * @mfunc
  2001. * Notify Text Host that control is active
  2002. *
  2003. * @rdesc
  2004. * S_OK - call succeeded. <nl>
  2005. * E_FAIL - activation is not possible at this time
  2006. *
  2007. * @comm
  2008. * It is legal for the host to refuse an activation request;
  2009. * the control may be minimized and thus invisible, for instance.
  2010. *
  2011. * The caller should be able to gracefully handle failure to activate.
  2012. *
  2013. * Calling this method more than once does not cumulate; only
  2014. * once TxDeactivate call is necessary to deactive.
  2015. *
  2016. * This function returns an opaque handle in <p plOldState>. The caller
  2017. * (Text Services) should hang onto this handle and return it in a
  2018. * subsequent call to TxDeactivate.
  2019. */
  2020. HRESULT CTxtWinHost::TxActivate(
  2021. LONG *plOldState) //@parm Where to put previous activation state
  2022. {
  2023. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxActivate");
  2024. return S_OK;
  2025. }
  2026. /*
  2027. * CTxtWinHost::TxDeactivate (lNewState)
  2028. *
  2029. * @mfunc
  2030. * Notify Text Host that control is now inactive
  2031. *
  2032. * @rdesc
  2033. * S_OK - call succeeded. <nl>
  2034. * E_FAIL <nl>
  2035. *
  2036. * @comm
  2037. * Calling this method more than once does not cumulate
  2038. */
  2039. HRESULT CTxtWinHost::TxDeactivate(
  2040. LONG lNewState) //@parm New state (typically value returned by
  2041. // TxActivate
  2042. {
  2043. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxDeactivate");
  2044. return S_OK;
  2045. }
  2046. /*
  2047. * CTxtWinHost::TxGetClientRect (prc)
  2048. *
  2049. * @mfunc
  2050. * Retrieve client coordinates of Text Host's client area.
  2051. *
  2052. * @rdesc
  2053. * HRESULT = (success) ? S_OK : E_FAIL
  2054. */
  2055. HRESULT CTxtWinHost::TxGetClientRect(
  2056. LPRECT prc) //@parm Where to put client coordinates
  2057. {
  2058. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetClientRect");
  2059. Assert(_hwnd && prc);
  2060. return ::GetClientRect(_hwnd, prc) ? S_OK : E_FAIL;
  2061. }
  2062. /*
  2063. * CTxtWinHost::TxGetViewInset (prc)
  2064. *
  2065. * @mfunc
  2066. * Get inset for Text Host window. Inset is the "white space"
  2067. * around text.
  2068. *
  2069. * @rdesc
  2070. * HRESULT = NOERROR
  2071. *
  2072. * @comm
  2073. * The Inset rectangle is not strictly a rectangle. The top, bottom,
  2074. * left, and right fields of the rect structure indicate how far in
  2075. * each direction drawing should be inset. Inset sizes are in client
  2076. * coordinates.
  2077. */
  2078. HRESULT CTxtWinHost::TxGetViewInset(
  2079. LPRECT prc) //@parm Where to put inset rectangle
  2080. {
  2081. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetViewInset");
  2082. Assert(prc);
  2083. *prc = _rcViewInset;
  2084. return NOERROR;
  2085. }
  2086. /*
  2087. * CTxtWinHost::TxGetCharFormat (ppCF)
  2088. *
  2089. * @mfunc
  2090. * Get Text Host's default character format
  2091. *
  2092. * @rdesc
  2093. * HRESULT = E_NOTIMPL (not needed in simple Windows host, since text
  2094. * services provides desired default)
  2095. *
  2096. * @comm
  2097. * The callee retains ownwership of the charformat returned. However,
  2098. * the pointer returned must remain valid until the callee notifies
  2099. * Text Services via OnTxPropertyBitsChange that the default character
  2100. * format has changed.
  2101. */
  2102. HRESULT CTxtWinHost::TxGetCharFormat(
  2103. const CHARFORMAT **ppCF) //@parm Where to put ptr to default
  2104. // character format
  2105. {
  2106. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetCharFormat");
  2107. return E_NOTIMPL;
  2108. }
  2109. /*
  2110. * CTxtWinHost::TxGetParaFormat (ppPF)
  2111. *
  2112. * @mfunc
  2113. * Get Text Host default paragraph format
  2114. *
  2115. * @rdesc
  2116. * HRESULT = E_NOTIMPL (not needed in simple Windows host, since text
  2117. * services provides desired default)
  2118. *
  2119. * @comm
  2120. * The host object (callee) retains ownership of the PARAFORMAT returned.
  2121. * However, the pointer returned must remain valid until the host notifies
  2122. * Text Services (the caller) via OnTxPropertyBitsChange that the default
  2123. * paragraph format has changed.
  2124. */
  2125. HRESULT CTxtWinHost::TxGetParaFormat(
  2126. const PARAFORMAT **ppPF) //@parm Where to put ptr to default
  2127. // paragraph format
  2128. {
  2129. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetParaFormat");
  2130. return E_NOTIMPL;
  2131. }
  2132. /*
  2133. * CTxtWinHost::TxGetSysColor (nIndex)
  2134. *
  2135. * @mfunc
  2136. * Get specified color identifer from Text Host.
  2137. *
  2138. * @rdesc
  2139. * Color identifier
  2140. *
  2141. * @comm
  2142. * Note that the color returned may be *different* than the
  2143. * color that would be returned from a call to GetSysColor.
  2144. * This allows hosts to override default system behavior.
  2145. *
  2146. * Needless to say, hosts should be very careful about overriding
  2147. * normal system behavior as it could result in inconsistent UI
  2148. * (particularly with respect to Accessibility options).
  2149. */
  2150. COLORREF CTxtWinHost::TxGetSysColor(
  2151. int nIndex) //@parm Color to get, same parameter as
  2152. // GetSysColor Win32 API
  2153. {
  2154. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetSysColor");
  2155. if (!_fDisabled ||
  2156. nIndex != COLOR_WINDOW && nIndex != COLOR_WINDOWTEXT)
  2157. {
  2158. // This window is not disabled or the color is not interesting
  2159. // in the disabled case.
  2160. return (nIndex == COLOR_WINDOW && _fNotSysBkgnd)
  2161. ? _crBackground : GetSysColor(nIndex);
  2162. }
  2163. // Disabled case
  2164. if (COLOR_WINDOWTEXT == nIndex)
  2165. {
  2166. // Color of text for disabled window
  2167. return GetSysColor(COLOR_GRAYTEXT);
  2168. }
  2169. // Background color for disabled window
  2170. return GetSysColor(COLOR_3DFACE);
  2171. }
  2172. /*
  2173. * CTxtWinHost::TxGetBackStyle (pstyle)
  2174. *
  2175. * @mfunc
  2176. * Get Text Host background style.
  2177. *
  2178. * @rdesc
  2179. * HRESULT = S_OK
  2180. *
  2181. * @xref <e TXTBACKSTYLE>
  2182. */
  2183. HRESULT CTxtWinHost::TxGetBackStyle(
  2184. TXTBACKSTYLE *pstyle) //@parm Where to put background style
  2185. {
  2186. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetBackStyle");
  2187. *pstyle = (_dwExStyle & WS_EX_TRANSPARENT)
  2188. ? TXTBACK_TRANSPARENT : TXTBACK_OPAQUE;
  2189. return NOERROR;
  2190. }
  2191. /*
  2192. * CTxtWinHost::TxGetMaxLength (pLength)
  2193. *
  2194. * @mfunc
  2195. * Get Text Host's maximum allowed length.
  2196. *
  2197. * @rdesc
  2198. * HRESULT = S_OK
  2199. *
  2200. * @comm
  2201. * This method parallels the EM_LIMITTEXT message.
  2202. * If INFINITE (0xFFFFFFFF) is returned, then text services
  2203. * will use as much memory as needed to store any given text.
  2204. *
  2205. * If the limit returned is less than the number of characters
  2206. * currently in the text engine, no data is lost. Instead,
  2207. * no edits will be allowed to the text *other* than deletion
  2208. * until the text is reduced to below the limit.
  2209. */
  2210. HRESULT CTxtWinHost::TxGetMaxLength(
  2211. DWORD *pLength) //@parm Maximum allowed length, in number of
  2212. // characters
  2213. {
  2214. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetMaxLength");
  2215. AssertSz(FALSE, "CTxtWinHost::TxGetMaxLength why is this being called?");
  2216. return NOERROR;
  2217. }
  2218. /*
  2219. * CTxtWinHost::TxGetScrollBars (pdwScrollBar)
  2220. *
  2221. * @mfunc
  2222. * Get Text Host's scroll bars supported.
  2223. *
  2224. * @rdesc
  2225. * HRESULT = S_OK
  2226. *
  2227. * @comm
  2228. * <p pdwScrollBar> is filled with a boolean combination of the
  2229. * window styles related to scroll bars. Specifically, these are:
  2230. *
  2231. * WS_VSCROLL <nl>
  2232. * WS_HSCROLL <nl>
  2233. * ES_AUTOVSCROLL <nl>
  2234. * ES_AUTOHSCROLL <nl>
  2235. * ES_DISABLENOSCROLL <nl>
  2236. */
  2237. HRESULT CTxtWinHost::TxGetScrollBars(
  2238. DWORD *pdwScrollBar) //@parm Where to put scrollbar information
  2239. {
  2240. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetScrollBars");
  2241. *pdwScrollBar = _dwStyle & (WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL |
  2242. ES_AUTOHSCROLL | ES_DISABLENOSCROLL);
  2243. return NOERROR;
  2244. }
  2245. /*
  2246. * CTxtWinHost::TxGetPasswordChar (pch)
  2247. *
  2248. * @mfunc
  2249. * Get Text Host's password character.
  2250. *
  2251. * @rdesc
  2252. * HRESULT = (password character not enabled) ? S_FALSE : S_OK
  2253. *
  2254. * @comm
  2255. * The password char will only be shown if the TXTBIT_USEPASSWORD bit
  2256. * is enabled in TextServices. If the password character changes,
  2257. * re-enable the TXTBIT_USEPASSWORD bit via
  2258. * ITextServices::OnTxPropertyBitsChange.
  2259. */
  2260. HRESULT CTxtWinHost::TxGetPasswordChar(
  2261. TCHAR *pch) //@parm Where to put password character
  2262. {
  2263. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetPasswordChar");
  2264. *pch = _chPassword;
  2265. return NOERROR;
  2266. }
  2267. /*
  2268. * CTxtWinHost::TxGetAcceleratorPos (pcp)
  2269. *
  2270. * @mfunc
  2271. * Get special character to use for underlining accelerator character.
  2272. *
  2273. * @rdesc
  2274. * Via <p pcp>, returns character position at which underlining
  2275. * should occur. -1 indicates that no character should be underlined.
  2276. * Return value is an HRESULT (usually S_OK).
  2277. *
  2278. * @comm
  2279. * Accelerators allow keyboard shortcuts to various UI elements (like
  2280. * buttons. Typically, the shortcut character is underlined.
  2281. *
  2282. * This function tells Text Services which character is the accelerator
  2283. * and thus should be underlined. Note that Text Services will *not*
  2284. * process accelerators; that is the responsiblity of the host.
  2285. *
  2286. * This method will typically only be called if the TXTBIT_SHOWACCELERATOR
  2287. * bit is set in text services.
  2288. *
  2289. * Note that *any* change to the text in text services will result in the
  2290. * invalidation of the accelerator underlining. In this case, it is the
  2291. * host's responsibility to recompute the appropriate character position
  2292. * and inform text services that a new accelerator is available.
  2293. */
  2294. HRESULT CTxtWinHost::TxGetAcceleratorPos(
  2295. LONG *pcp) //@parm Out parm to receive cp of character to underline
  2296. {
  2297. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetAcceleratorPos");
  2298. *pcp = -1;
  2299. return S_OK;
  2300. }
  2301. /*
  2302. * CTxtWinHost::OnTxCharFormatChange
  2303. *
  2304. * @mfunc
  2305. * Set default character format for the Text Host.
  2306. *
  2307. * @rdesc
  2308. * S_OK - call succeeded. <nl>
  2309. * E_INVALIDARG <nl>
  2310. * E_FAIL <nl>
  2311. */
  2312. HRESULT CTxtWinHost::OnTxCharFormatChange(
  2313. const CHARFORMAT *pcf) //@parm New default character format
  2314. {
  2315. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::OnTxCharFormatChange");
  2316. return S_OK;
  2317. }
  2318. /*
  2319. * CTxtWinHost::OnTxParaFormatChange
  2320. *
  2321. * @mfunc
  2322. * Set default paragraph format for the Text Host.
  2323. *
  2324. * @rdesc
  2325. * S_OK - call succeeded. <nl>
  2326. * E_INVALIDARG <nl>
  2327. * E_FAIL <nl>
  2328. */
  2329. HRESULT CTxtWinHost::OnTxParaFormatChange(
  2330. const PARAFORMAT *ppf) //@parm New default paragraph format
  2331. {
  2332. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::OnTxParaFormatChange");
  2333. return S_OK;
  2334. }
  2335. /*
  2336. * CTxtWinHost::TxGetPropertyBits (dwMask, dwBits)
  2337. *
  2338. * @mfunc
  2339. * Get the bit property settings for Text Host.
  2340. *
  2341. * @rdesc
  2342. * S_OK
  2343. *
  2344. * @comm
  2345. * This call is valid at any time, for any combination of
  2346. * requested property bits. <p dwMask> may be used by the
  2347. * caller to request specific properties.
  2348. */
  2349. HRESULT CTxtWinHost::TxGetPropertyBits(
  2350. DWORD dwMask, //@parm Mask of bit properties to get
  2351. DWORD *pdwBits) //@parm Where to put bit values
  2352. {
  2353. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetPropertyBits");
  2354. // FUTURE: Obvious optimization is to save bits in host the same way that
  2355. // they are returned and just return them instead of this mess.
  2356. // Note: this RichEdit host never sets TXTBIT_SHOWACCELERATOR or
  2357. // TXTBIT_SAVESELECTION. They are currently only used by Forms^3 host.
  2358. // This host is always rich text.
  2359. DWORD dwProperties = TXTBIT_RICHTEXT | TXTBIT_ALLOWBEEP;
  2360. #ifdef DEBUG
  2361. // make sure that TS doesn't think it's plain text mode when
  2362. // we return TXTBIT_RICHTEXT
  2363. if((dwMask & TXTBIT_RICHTEXT) && _pserv)
  2364. {
  2365. DWORD mode;
  2366. mode = _pserv->TxSendMessage(EM_GETTEXTMODE, 0, 0, NULL);
  2367. Assert(mode == TM_RICHTEXT);
  2368. }
  2369. #endif // DEBUG
  2370. if(_dwStyle & ES_MULTILINE)
  2371. dwProperties |= TXTBIT_MULTILINE;
  2372. if(_dwStyle & ES_READONLY)
  2373. dwProperties |= TXTBIT_READONLY;
  2374. if(_dwStyle & ES_PASSWORD)
  2375. dwProperties |= TXTBIT_USEPASSWORD;
  2376. if(!(_dwStyle & ES_NOHIDESEL))
  2377. dwProperties |= TXTBIT_HIDESELECTION;
  2378. if(_fEnableAutoWordSel)
  2379. dwProperties |= TXTBIT_AUTOWORDSEL;
  2380. if(!(_dwStyle & ES_AUTOHSCROLL))
  2381. dwProperties |= TXTBIT_WORDWRAP;
  2382. if(_dwStyle & ES_VERTICAL)
  2383. dwProperties |= TXTBIT_VERTICAL;
  2384. if(_dwStyle & ES_NOOLEDRAGDROP)
  2385. dwProperties |= TXTBIT_DISABLEDRAG;
  2386. *pdwBits = dwProperties & dwMask;
  2387. return NOERROR;
  2388. }
  2389. /*
  2390. * CTxtWinHost::TxNotify (iNotify, pv)
  2391. *
  2392. * @mfunc
  2393. * Notify Text Host of various events. Note that there are
  2394. * two basic categories of events, "direct" events and
  2395. * "delayed" events. Direct events are sent immediately as
  2396. * they need some processing: EN_PROTECTED is a canonical
  2397. * example. Delayed events are sent after all processing
  2398. * has occurred; the control is thus in a "stable" state.
  2399. * EN_CHANGE, EN_ERRSPACE, EN_SELCHANGED are examples
  2400. * of delayed notifications.
  2401. *
  2402. *
  2403. * @rdesc
  2404. * S_OK - call succeeded <nl>
  2405. * S_FALSE -- success, but do some different action
  2406. * depending on the event type (see below).
  2407. *
  2408. * @comm
  2409. * The notification events are the same as the notification
  2410. * messages sent to the parent window of a richedit window.
  2411. * The firing of events may be controlled with a mask set via
  2412. * the EM_SETEVENTMASK message.
  2413. *
  2414. * In general, is legal to make any calls to text services while
  2415. * processing this method; however, implementors are cautioned
  2416. * to avoid excessive recursion.
  2417. *
  2418. * Here is the complete list of notifications that may be
  2419. * sent and a brief description of each:
  2420. *
  2421. * <p EN_CHANGE> Sent when some data in the edit control
  2422. * changes (such as text or formatting). Controlled by the
  2423. * ENM_CHANGE event mask. This notification is sent _after_
  2424. * any screen updates have been requested.
  2425. *
  2426. * <p EN_CORRECTTEXT> PenWin only; currently unused.
  2427. *
  2428. * <p EN_DROPFILES> If the client registered the edit
  2429. * control via DragAcceptFiles, this event will be sent when
  2430. * a WM_DROPFILES or DragEnter(CF_HDROP) message is received.
  2431. * If S_FALSE is returned, the drop will be ignored, otherwise,
  2432. * the drop will be processed. The ENM_DROPFILES mask
  2433. * controls this event notification.
  2434. *
  2435. * <p EN_ERRSPACE> Sent when the edit control cannot
  2436. * allocate enough memory. No additional data is sent and
  2437. * there is no mask for this event.
  2438. *
  2439. * <p EN_HSCROLL> Sent when the user clicks on an edit
  2440. * control's horizontal scroll bar, but before the screen
  2441. * is updated. No additional data is sent. The ENM_SCROLL
  2442. * mask controls this event.
  2443. *
  2444. * <p EN_IMECHANGE> unused
  2445. *
  2446. * <p EN_KILLFOCUS> Sent when the edit control looses focus.
  2447. * No additional data is sent and there is no mask.
  2448. *
  2449. * <p EN_MAXTEXT> Sent when the current text insertion
  2450. * has exceeded the specified number of characters for the
  2451. * edit control. The text insertion has been truncated.
  2452. * There is no mask for this event.
  2453. *
  2454. * <p EN_MSGFILTER> NB!!! THIS MESSAGE IS NOT SENT TO
  2455. * TxNotify, but is included here for completeness. With
  2456. * ITextServices::TxSendMessage, client have complete
  2457. * flexibility in filtering all window messages.
  2458. *
  2459. * Sent on a keyboard or mouse event
  2460. * in the control. A MSGFILTER data structure is sent,
  2461. * containing the msg, wparam and lparam. If S_FALSE is
  2462. * returned from this notification, the msg is processed by
  2463. * TextServices, otherwise, the message is ignored. Note
  2464. * that in this case, the callee has the opportunity to modify
  2465. * the msg, wparam, and lparam before TextServices continues
  2466. * processing. The ENM_KEYEVENTS and ENM_MOUSEEVENTS masks
  2467. * control this event for the respective event types.
  2468. *
  2469. * <p EN_OLEOPFAILED> Sent when an OLE call fails. The
  2470. * ENOLEOPFAILED struct is passed with the index of the object
  2471. * and the error code. Mask value is nothing.
  2472. *
  2473. * <p EN_PROTECTED> Sent when the user is taking an
  2474. * action that would change a protected range of text. An
  2475. * ENPROTECTED data structure is sent, indicating the range
  2476. * of text affected and the window message (if any) affecting
  2477. * the change. If S_FALSE is returned, the edit will fail.
  2478. * The ENM_PROTECTED mask controls this event.
  2479. *
  2480. * <p EN_REQUESTRESIZE> Sent when a control's contents are
  2481. * either smaller or larger than the control's window size.
  2482. * The client is responsible for resizing the control. A
  2483. * REQRESIZE structure is sent, indicating the new size of
  2484. * the control. NB! Only the size is indicated in this
  2485. * structure; it is the host's responsibility to do any
  2486. * translation necessary to generate a new client rectangle.
  2487. * The ENM_REQUESTRESIZE mask controls this event.
  2488. *
  2489. * <p EN_SAVECLIPBOARD> Sent when an edit control is being
  2490. * destroyed, the callee should indicate whether or not
  2491. * OleFlushClipboard should be called. Data indicating the
  2492. * number of characters and objects to be flushed is sent
  2493. * in the ENSAVECLIPBOARD data structure.
  2494. * Mask value is nothing.
  2495. *
  2496. * <p EN_SELCHANGE> Sent when the current selection has
  2497. * changed. A SELCHANGE data structure is also sent, which
  2498. * indicates the new selection range at the type of data
  2499. * the selection is currently over. Controlled via the
  2500. * ENM_SELCHANGE mask.
  2501. *
  2502. * <p EN_SETFOCUS> Sent when the edit control receives the
  2503. * keyboard focus. No extra data is sent; there is no mask.
  2504. *
  2505. * <p EN_STOPNOUNDO> Sent when an action occurs for which
  2506. * the control cannot allocate enough memory to maintain the
  2507. * undo state. If S_FALSE is returned, the action will be
  2508. * stopped; otherwise, the action will continue.
  2509. *
  2510. * <p EN_UPDATE> Sent before an edit control requests a
  2511. * redraw of altered data or text. No additional data is
  2512. * sent. This event is controlled via the ENM_UPDATE mask.
  2513. *
  2514. * <p EN_VSCROLL> Sent when the user clicks an edit control's
  2515. * vertical scrollbar bar before the screen is updated.
  2516. * Controlled via the ENM_SCROLL mask; no extra data is sent.
  2517. *
  2518. * <p EN_LINK> Sent when a mouse event (or WM_SETCURSOR) happens
  2519. * over a range of text that has the EN_LINK mask bit set.
  2520. * An ENLINK data structure will be sent with relevant info.
  2521. */
  2522. HRESULT CTxtWinHost::TxNotify(
  2523. DWORD iNotify, //@parm Event to notify host of. One of the
  2524. // EN_XXX values from Win32, e.g., EN_CHANGE
  2525. void *pv) //@parm In-only parameter with extra data. Type
  2526. // dependent on <p iNotify>
  2527. {
  2528. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxNotify");
  2529. HRESULT hr = NOERROR;
  2530. LONG nId;
  2531. NMHDR * phdr;
  2532. REQRESIZE * preq;
  2533. RECT rcOld;
  2534. // We assume here that TextServices has already masked out notifications,
  2535. // so if we get one here, it should be sent
  2536. if(_hwndParent)
  2537. {
  2538. nId = GetWindowLong(_hwnd, GWL_ID);
  2539. // First, handle WM_NOTIFY style notifications
  2540. switch(iNotify)
  2541. {
  2542. case EN_REQUESTRESIZE:
  2543. // Need to map new size into correct rectangle
  2544. Assert(pv);
  2545. GetWindowRect(_hwnd, &rcOld);
  2546. MapWindowPoints(HWND_DESKTOP, _hwndParent, (POINT *) &rcOld, 2);
  2547. preq = (REQRESIZE *)pv;
  2548. preq->rc.top = rcOld.top;
  2549. preq->rc.left = rcOld.left;
  2550. preq->rc.right += rcOld.left;
  2551. preq->rc.bottom += rcOld.top;
  2552. // FALL-THROUGH!!
  2553. case EN_DROPFILES:
  2554. case EN_MSGFILTER:
  2555. case EN_OLEOPFAILED:
  2556. case EN_PROTECTED:
  2557. case EN_SAVECLIPBOARD:
  2558. case EN_SELCHANGE:
  2559. case EN_STOPNOUNDO:
  2560. case EN_LINK:
  2561. case EN_OBJECTPOSITIONS:
  2562. case EN_DRAGDROPDONE:
  2563. case EN_LOWFIRTF:
  2564. case EN_CLIPFORMAT:
  2565. if(pv) // Fill out NMHDR portion of pv
  2566. {
  2567. phdr = (NMHDR *)pv;
  2568. phdr->hwndFrom = _hwnd;
  2569. phdr->idFrom = nId;
  2570. phdr->code = iNotify;
  2571. }
  2572. if(SendMessage(_hwndParent, WM_NOTIFY, (WPARAM) nId, (LPARAM) pv))
  2573. hr = S_FALSE;
  2574. break;
  2575. default:
  2576. SendMessage(_hwndParent, WM_COMMAND,
  2577. GET_WM_COMMAND_MPS(nId, _hwnd, iNotify));
  2578. }
  2579. }
  2580. return hr;
  2581. }
  2582. /*
  2583. * CTxtWinHost::TxGetExtent (lpExtent)
  2584. *
  2585. * @mfunc
  2586. * Return native size of the control in HIMETRIC
  2587. *
  2588. * @rdesc
  2589. * S_OK <nl>
  2590. * some failure code <nl>
  2591. *
  2592. * @comm
  2593. * This method is used by Text Services to implement zooming.
  2594. * Text Services would derive the zoom factor from the ratio between
  2595. * the himetric and device pixel extent of the client rectangle.
  2596. *
  2597. * [vertical zoom factor] = [pixel height of the client rect] * 2540
  2598. * / [himetric vertical extent] * [pixel per vertical inch (from DC)]
  2599. *
  2600. * If the vertical and horizontal zoom factors are not the same, Text
  2601. * Services could ignore the horizontal zoom factor and assume it is
  2602. * the same as the vertical one.
  2603. */
  2604. HRESULT CTxtWinHost::TxGetExtent(
  2605. LPSIZEL lpExtent) //@parm Extent in himetric
  2606. {
  2607. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetExtent");
  2608. AssertSz(lpExtent, "CTxtWinHost::TxGetExtent Invalid lpExtent");
  2609. // We could implement the TxGetExtent in the following way. However, the
  2610. // call to this in ITextServices is implemented in such a way that it
  2611. // does something sensible in the face of an error in this call. That
  2612. // something sensible is that it sets the extent equal to the current
  2613. // client rectangle which is what the following does in a rather convoluted
  2614. // manner. Therefore, we dump the following and just return an error.
  2615. #if 0
  2616. // The window's host extent is always the same as the client
  2617. // rectangle.
  2618. RECT rc;
  2619. HRESULT hr = TxGetClientRect(&rc);
  2620. // Get our client rectangle
  2621. if(SUCCEEDED(hr))
  2622. {
  2623. // Calculate the length & convert to himetric
  2624. lpExtent->cx = DXtoHimetricX(rc.right - rc.left, W32->GetXPerInchScreenDC());
  2625. lpExtent->cy = DYtoHimetricY(rc.bottom - rc.top, W32->GetYPerInchScreenDC());
  2626. }
  2627. return hr;
  2628. #endif // 0
  2629. return E_NOTIMPL;
  2630. }
  2631. HRESULT CTxtWinHost::TxEBookLoadImage( LPWSTR lpszName, LPARAM * pID, SIZE * psize, DWORD *pdwFlags)
  2632. {
  2633. return E_NOTIMPL;
  2634. }
  2635. HRESULT CTxtWinHost::TxEBookImageDraw(LPARAM ID, HDC hdc, POINT *topLeft, RECT *prcRenderint,
  2636. BOOL fSelected)
  2637. {
  2638. return E_NOTIMPL;
  2639. }
  2640. HRESULT CTxtWinHost::TxGetHorzExtent(LONG *plHorzExtent)
  2641. {
  2642. return E_NOTIMPL;
  2643. }
  2644. /*
  2645. * CTxtWinHost::TxGetSelectionBarWidth (lSelBarWidth)
  2646. *
  2647. * @mfunc
  2648. * Returns size of selection bar in HIMETRIC
  2649. *
  2650. * @rdesc
  2651. * S_OK <nl>
  2652. */
  2653. HRESULT CTxtWinHost::TxGetSelectionBarWidth (
  2654. LONG *lSelBarWidth) //@parm Where to return selection bar width
  2655. // in HIMETRIC
  2656. {
  2657. *lSelBarWidth = (_dwStyle & ES_SELECTIONBAR) ? W32->GetDxSelBar() : 0;
  2658. return S_OK;
  2659. }
  2660. //
  2661. // ITextHost2 methods
  2662. //
  2663. /*
  2664. * CTxtWinHost::TxIsDoubleClickPending
  2665. *
  2666. * @mfunc Look into the message queue for this hwnd and see if a
  2667. * double click is pending. This enables TextServices to
  2668. * effeciently transition between two inplace active objects.
  2669. *
  2670. * @rdesc BOOL
  2671. */
  2672. BOOL CTxtWinHost::TxIsDoubleClickPending()
  2673. {
  2674. MSG msg;
  2675. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN,
  2676. "CTxtWinHost::TxIsDoubleClickPending");
  2677. if(PeekMessage(&msg, _hwnd, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK,
  2678. PM_NOREMOVE | PM_NOYIELD))
  2679. {
  2680. return TRUE;
  2681. }
  2682. return FALSE;
  2683. }
  2684. /*
  2685. * CTxtWinHost::TxGetWindow
  2686. *
  2687. * @mfunc Fetches the window associated with this control (or
  2688. * set of controls potentially). Useful for answering
  2689. * IOleWindow::GetWindow.
  2690. *
  2691. * @rdesc HRESULT
  2692. */
  2693. HRESULT CTxtWinHost::TxGetWindow(HWND *phwnd)
  2694. {
  2695. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::GetWindow");
  2696. *phwnd = _hwnd;
  2697. return NOERROR;
  2698. }
  2699. /*
  2700. * CTxtWinHost::SetForegroundWindow
  2701. *
  2702. * @mfunc Sets window to foreground window & gives the focus
  2703. *
  2704. * @rdesc NOERROR - succeeded
  2705. * E_FAIL - failed.
  2706. */
  2707. HRESULT CTxtWinHost::TxSetForegroundWindow()
  2708. {
  2709. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN,
  2710. "CTxtWinHost::SetForegroundWindow");
  2711. if(!SetForegroundWindow(_hwnd))
  2712. SetFocus(_hwnd);
  2713. return NOERROR;
  2714. }
  2715. /*
  2716. * CTxtWinHost::TxGetPalette
  2717. *
  2718. * @mfunc Returns application specific palette if there is one
  2719. *
  2720. * @rdesc ~NULL - there was one
  2721. * NULL - use default palette
  2722. */
  2723. HPALETTE CTxtWinHost::TxGetPalette()
  2724. {
  2725. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN,
  2726. "CTxtWinHost::TxGetPalette");
  2727. return _hpal;
  2728. }
  2729. /*
  2730. * CTxtWinHost::TxGetFEFlags
  2731. *
  2732. * @mfunc return FE settings
  2733. *
  2734. * @rdesc NOERROR - succeeded
  2735. * E_FAIL - failed.
  2736. */
  2737. HRESULT CTxtWinHost::TxGetFEFlags(LONG *pFEFlags)
  2738. {
  2739. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN,
  2740. "CTxtWinHost::TxGetFEFlags");
  2741. if (!pFEFlags)
  2742. return E_INVALIDARG;
  2743. *pFEFlags = 0;
  2744. if (_usIMEMode == ES_NOIME)
  2745. *pFEFlags |= ES_NOIME;
  2746. if (_usIMEMode == ES_SELFIME)
  2747. *pFEFlags |= ES_SELFIME;
  2748. return NOERROR;
  2749. }
  2750. // Helper function in edit.cpp
  2751. LONG GetECDefaultHeightAndWidth(
  2752. ITextServices *pts,
  2753. HDC hdc,
  2754. LONG lZoomNumerator,
  2755. LONG lZoomDenominator,
  2756. LONG yPixelsPerInch,
  2757. LONG *pxAveWidth,
  2758. LONG *pxOverhang,
  2759. LONG *pxUnderhang);
  2760. /*
  2761. * CTxtWinHost::OnSetMargins
  2762. *
  2763. * @mfunc Handle EM_SETMARGINS message
  2764. *
  2765. * @rdesc None.
  2766. */
  2767. void CTxtWinHost::OnSetMargins(
  2768. DWORD fwMargin, //@parm Type of requested operation
  2769. DWORD xLeft, //@parm Where to put left margin
  2770. DWORD xRight) //@parm Where to put right margin
  2771. {
  2772. LONG xLeftMargin = -1;
  2773. LONG xRightMargin = -1;
  2774. HDC hdc;
  2775. if(EC_USEFONTINFO == fwMargin)
  2776. {
  2777. // Get the DC since it is needed for the call
  2778. hdc = GetDC(_hwnd);
  2779. // Multiline behaves differently than single line
  2780. if (_dwStyle & ES_MULTILINE)
  2781. {
  2782. // Multiline - over/underhange controls margin
  2783. GetECDefaultHeightAndWidth(_pserv, hdc, 1, 1,
  2784. W32->GetYPerInchScreenDC(), NULL,
  2785. &xLeftMargin, &xRightMargin);
  2786. }
  2787. else
  2788. {
  2789. // Single line edit controls set the margins to
  2790. // the average character width on both left and
  2791. // right.
  2792. GetECDefaultHeightAndWidth(_pserv, hdc, 1, 1,
  2793. W32->GetYPerInchScreenDC(), &xLeftMargin, NULL, NULL);
  2794. xRightMargin = xLeftMargin;
  2795. }
  2796. ReleaseDC(_hwnd, hdc);
  2797. }
  2798. else
  2799. {
  2800. // The request is for setting exact pixels.
  2801. if(EC_LEFTMARGIN & fwMargin)
  2802. xLeftMargin = xLeft;
  2803. if(EC_RIGHTMARGIN & fwMargin)
  2804. xRightMargin = xRight;
  2805. }
  2806. // Set left margin if so requested
  2807. if (xLeftMargin != -1)
  2808. _rcViewInset.left = W32->DeviceToHimetric(xLeftMargin, W32->GetXPerInchScreenDC());
  2809. // Set right margin if so requested
  2810. if (xRightMargin != -1)
  2811. _rcViewInset.right = W32->DeviceToHimetric(xRightMargin, W32->GetXPerInchScreenDC());
  2812. if (xLeftMargin != -1 || xRightMargin != -1)
  2813. _pserv->OnTxPropertyBitsChange(TXTBIT_VIEWINSETCHANGE, TXTBIT_VIEWINSETCHANGE);
  2814. }
  2815. /*
  2816. * CTxtWinHost::SetScrollInfo
  2817. *
  2818. * @mfunc Set scrolling information for the scroll bar.
  2819. */
  2820. void CTxtWinHost::SetScrollInfo(
  2821. INT fnBar, //@parm Specifies scroll bar to be updated
  2822. BOOL fRedraw) //@parm whether redraw is necessary
  2823. {
  2824. // Set up the basic structure for the call
  2825. SCROLLINFO si;
  2826. si.cbSize = sizeof(SCROLLINFO);
  2827. si.fMask = SIF_ALL;
  2828. AssertSz(_pserv != NULL,
  2829. "CTxtWinHost::SetScrollInfo called with NULL _pserv");
  2830. // Call back to the control to get the parameters
  2831. if(fnBar == SB_HORZ)
  2832. {
  2833. _pserv->TxGetHScroll((LONG *) &si.nMin, (LONG *) &si.nMax,
  2834. (LONG *) &si.nPos, (LONG *) &si.nPage, NULL);
  2835. }
  2836. else
  2837. {
  2838. _pserv->TxGetVScroll((LONG *) &si.nMin,
  2839. (LONG *) &si.nMax, (LONG *) &si.nPos, (LONG *) &si.nPage, NULL);
  2840. }
  2841. // Do the call
  2842. ::SetScrollInfo(_hwnd, fnBar, &si, fRedraw);
  2843. }
  2844. /*
  2845. * CTxtWinHost::SetScrollBarsForWmEnable
  2846. *
  2847. * @mfunc Enable/Disable scroll bars
  2848. *
  2849. * @rdesc None.
  2850. */
  2851. void CTxtWinHost::SetScrollBarsForWmEnable(
  2852. BOOL fEnable) //@parm Whether scrollbars s/b enabled or disabled.
  2853. {
  2854. if(!_pserv) // If no edit object,
  2855. return; // no scrollbars
  2856. BOOL fHoriz = FALSE;
  2857. BOOL fVert = FALSE;
  2858. UINT wArrows = fEnable ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
  2859. _pserv->TxGetHScroll(NULL, NULL, NULL, NULL, &fHoriz);
  2860. _pserv->TxGetVScroll(NULL, NULL, NULL, NULL, &fVert);
  2861. if(fHoriz) // There is a horizontal scroll bar
  2862. W32->EnableScrollBar(_hwnd, SB_HORZ, wArrows);
  2863. if(fVert) // There is a vertical scroll bar
  2864. W32->EnableScrollBar(_hwnd, SB_VERT, wArrows);
  2865. }
  2866. /*
  2867. * CTxtWinHost::SetScrollBarsForWmEnable
  2868. *
  2869. * @mfunc Notification that Text Services is released.
  2870. *
  2871. * @rdesc None.
  2872. */
  2873. void CTxtWinHost::TxFreeTextServicesNotification()
  2874. {
  2875. _fTextServiceFree = TRUE;
  2876. }
  2877. /*
  2878. * CTxtWinHost::TxGetEditStyle
  2879. *
  2880. * @mfunc Get Edit Style flags
  2881. *
  2882. * @rdesc NOERROR is data available.
  2883. */
  2884. HRESULT CTxtWinHost::TxGetEditStyle(
  2885. DWORD dwItem,
  2886. DWORD *pdwData)
  2887. {
  2888. if (!pdwData)
  2889. return E_INVALIDARG;
  2890. *pdwData = 0;
  2891. if (dwItem & TXES_ISDIALOG && _fInDialogBox)
  2892. *pdwData |= TXES_ISDIALOG;
  2893. return NOERROR;
  2894. }
  2895. /*
  2896. * CTxtWinHost::TxGetWindowStyles
  2897. *
  2898. * @mfunc Return window style bits
  2899. *
  2900. * @rdesc NOERROR is data available.
  2901. */
  2902. HRESULT CTxtWinHost::TxGetWindowStyles(DWORD *pdwStyle, DWORD *pdwExStyle)
  2903. {
  2904. if (!pdwStyle || !pdwExStyle)
  2905. return E_INVALIDARG;
  2906. *pdwStyle = _dwStyle;
  2907. *pdwExStyle = _dwExStyle;
  2908. return NOERROR;
  2909. }
  2910. #endif // NOWINDOWHOSTS