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

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