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.

2262 lines
55 KiB

  1. /*
  2. * @doc TOM
  3. *
  4. * @module tomdoc.cpp - Implement the ITextDocument interface on CTxtEdit |
  5. *
  6. * This module contains the implementation of the TOM ITextDocument
  7. * class as well as the global TOM type-info routines
  8. *
  9. * History: <nl>
  10. * sep-95 MurrayS: stubs and auto-doc created <nl>
  11. * nov-95 MurrayS: upgrade to top-level TOM interface
  12. * dec-95 MurrayS: implemented file I/O methods
  13. *
  14. * @future
  15. * 1. Implement Begin/EndEditCollection
  16. *
  17. * Copyright (c) 1995-2000, Microsoft Corporation. All rights reserved.
  18. */
  19. #include "_common.h"
  20. #include "_range.h"
  21. #include "_edit.h"
  22. #include "_disp.h"
  23. #include "_rtfconv.h"
  24. #include "_select.h"
  25. #include "_font.h"
  26. #include "_tomfmt.h"
  27. ASSERTDATA
  28. // TOM Type Info HRESULT and pointers
  29. HRESULT g_hrGetTypeInfo = NOERROR;
  30. ITypeInfo * g_pTypeInfoDoc;
  31. ITypeInfo * g_pTypeInfoSel;
  32. ITypeInfo * g_pTypeInfoFont;
  33. ITypeInfo * g_pTypeInfoPara;
  34. ITypeLib * g_pTypeLib;
  35. BYTE szUTF8BOM[] = {0xEF, 0xBB, 0xBF}; // UTF-8 for 0xFEFF
  36. //------------------------ Global TOM Type Info Methods -----------------------------
  37. /*
  38. * GetTypeInfoPtrs()
  39. *
  40. * @func
  41. * Ensure that global TOM ITypeInfo ptrs are valid (else g_pTypeInfoDoc
  42. * is NULL). Return NOERROR immediately if g_pTypeInfoDoc is not NULL,
  43. * i.e., type info ptrs are already valid.
  44. *
  45. * @rdesc
  46. * HRESULT = (success) ? NOERROR
  47. * : (HRESULT from LoadTypeLib or GetTypeInfoOfGuid)
  48. *
  49. * @comm
  50. * This routine should be called by any routine that uses the global
  51. * type info ptrs, e.g., IDispatch::GetTypeInfo(), GetIDsOfNames, and
  52. * Invoke. That way if noone is using the type library info, it doesn't
  53. * have to be loaded.
  54. *
  55. */
  56. HRESULT GetTypeInfoPtrs()
  57. {
  58. HRESULT hr;
  59. CLock lock; // Only one thread at a time...
  60. WCHAR szModulePath[MAX_PATH];
  61. if(g_pTypeInfoDoc) // Type info ptrs already valid
  62. return NOERROR;
  63. if(g_hrGetTypeInfo != NOERROR) // Tried to get before and failed
  64. return g_hrGetTypeInfo;
  65. // Obtain the path to this module's executable file
  66. if (W32->GetModuleFileName(hinstRE, szModulePath, MAX_PATH))
  67. {
  68. // Provide the full-path name so LoadTypeLib will not register
  69. // the type library
  70. hr = LoadTypeLib(szModulePath, &g_pTypeLib);
  71. if(hr != NOERROR)
  72. goto err;
  73. // Get ITypeInfo pointers with g_pTypeInfoDoc last
  74. hr = g_pTypeLib->GetTypeInfoOfGuid(IID_ITextSelection, &g_pTypeInfoSel);
  75. if(hr == NOERROR)
  76. {
  77. g_pTypeLib->GetTypeInfoOfGuid(IID_ITextFont, &g_pTypeInfoFont);
  78. g_pTypeLib->GetTypeInfoOfGuid(IID_ITextPara, &g_pTypeInfoPara);
  79. g_pTypeLib->GetTypeInfoOfGuid(IID_ITextDocument, &g_pTypeInfoDoc);
  80. if(g_pTypeInfoFont && g_pTypeInfoPara && g_pTypeInfoDoc)
  81. return NOERROR; // Got 'em all
  82. }
  83. }
  84. hr = E_FAIL;
  85. err:
  86. Assert("Error getting type info pointers");
  87. g_pTypeInfoDoc = NULL; // Type info ptrs not valid
  88. g_hrGetTypeInfo = hr; // Save HRESULT in case called
  89. return hr; // again
  90. }
  91. /*
  92. * ReleaseTypeInfoPtrs()
  93. *
  94. * @func
  95. * Release TOM type info ptrs in case they have been defined.
  96. * Called when RichEdit dll is being unloaded.
  97. */
  98. void ReleaseTypeInfoPtrs()
  99. {
  100. if(g_pTypeInfoDoc)
  101. {
  102. g_pTypeInfoDoc->Release();
  103. g_pTypeInfoSel->Release();
  104. g_pTypeInfoFont->Release();
  105. g_pTypeInfoPara->Release();
  106. }
  107. if(g_pTypeLib)
  108. g_pTypeLib->Release();
  109. }
  110. /*
  111. * GetTypeInfo(iTypeInfo, &pTypeInfo, ppTypeInfo)
  112. *
  113. * @func
  114. * IDispatch helper function to check parameter validity and set
  115. * *ppTypeInfo = pTypeInfo if OK
  116. *
  117. * @rdesc
  118. * HRESULT
  119. */
  120. HRESULT GetTypeInfo(
  121. UINT iTypeInfo, //@parm Index of type info to return
  122. ITypeInfo *&pTypeInfo, //@parm Address of desired type info ptr
  123. ITypeInfo **ppTypeInfo) //@parm Out parm to receive type info
  124. {
  125. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetTypeInfo");
  126. if(!ppTypeInfo)
  127. return E_INVALIDARG;
  128. *ppTypeInfo = NULL;
  129. if(iTypeInfo > 1)
  130. return DISP_E_BADINDEX;
  131. HRESULT hr = GetTypeInfoPtrs(); // Ensure TypeInfo ptrs are OK
  132. if(hr == NOERROR)
  133. {
  134. *ppTypeInfo = pTypeInfo; // Have to use reference in
  135. pTypeInfo->AddRef(); // case defined in this call
  136. }
  137. return hr;
  138. }
  139. /*
  140. * MyRead(hfile, pbBuffer, cb, pcb)
  141. *
  142. * @func
  143. * Callback function for converting a file into an editstream for
  144. * input.
  145. *
  146. * @rdesc
  147. * (DWORD)HRESULT
  148. */
  149. DWORD CALLBACK MyRead(DWORD_PTR hfile, BYTE *pbBuffer, long cb, long *pcb)
  150. {
  151. if(!hfile) // No handle defined
  152. return (DWORD)E_FAIL;
  153. Assert(pcb);
  154. *pcb = 0;
  155. if(!ReadFile((HANDLE)hfile, (void *)pbBuffer, (DWORD)cb, (DWORD *)pcb, NULL))
  156. return HRESULT_FROM_WIN32(GetLastError());
  157. return (DWORD)NOERROR;
  158. }
  159. /*
  160. * MyWrite(hfile, pbBuffer, cb, pcb)
  161. *
  162. * @func
  163. * Callback function for converting a file into an editstream for
  164. * output.
  165. *
  166. * @rdesc
  167. * (DWORD)HRESULT
  168. */
  169. DWORD CALLBACK MyWrite(DWORD_PTR hfile, BYTE *pbBuffer, long cb, long *pcb)
  170. {
  171. if(!hfile) // No handle defined
  172. return (DWORD)E_FAIL;
  173. Assert(pcb);
  174. *pcb = 0;
  175. if(!WriteFile((HANDLE)hfile, (void *)pbBuffer, (DWORD)cb, (DWORD *)pcb, NULL))
  176. return HRESULT_FROM_WIN32(GetLastError());
  177. return (DWORD)(*pcb ? NOERROR : E_FAIL);
  178. }
  179. //-----------------CTxtEdit IUnknown methods: see textserv.cpp -----------------------------
  180. //------------------------ CTxtEdit IDispatch methods -------------------------
  181. /*
  182. * CTxtEdit::GetTypeInfoCount(pcTypeInfo)
  183. *
  184. * @mfunc
  185. * Get the number of TYPEINFO elements (1)
  186. *
  187. * @rdesc
  188. * HRESULT = (pcTypeInfo) ? NOERROR : E_INVALIDARG;
  189. */
  190. STDMETHODIMP CTxtEdit::GetTypeInfoCount(
  191. UINT *pcTypeInfo) //@parm Out parm to receive count
  192. {
  193. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetTypeInfoCount");
  194. if(!pcTypeInfo)
  195. return E_INVALIDARG;
  196. *pcTypeInfo = 1;
  197. return NOERROR;
  198. }
  199. /*
  200. * CTxtEdit::GetTypeInfo(iTypeInfo, lcid, ppTypeInfo)
  201. *
  202. * @mfunc
  203. * Return ptr to type information object for ITextDocument interface
  204. *
  205. * @rdesc
  206. * HRESULT
  207. */
  208. STDMETHODIMP CTxtEdit::GetTypeInfo(
  209. UINT iTypeInfo, //@parm Index of type info to return
  210. LCID lcid, //@parm Local ID of type info
  211. ITypeInfo **ppTypeInfo) //@parm Out parm to receive type info
  212. {
  213. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetTypeInfo");
  214. return ::GetTypeInfo(iTypeInfo, g_pTypeInfoDoc, ppTypeInfo);
  215. }
  216. /*
  217. * CTxtEdit::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid)
  218. *
  219. * @mfunc
  220. * Get DISPIDs for all TOM methods and properties
  221. *
  222. * @rdesc
  223. * HRESULT
  224. *
  225. * @devnote
  226. * This routine tries to find DISPIDs using the type information for
  227. * ITextDocument. If that fails, it asks the selection to find the
  228. * DISPIDs.
  229. */
  230. STDMETHODIMP CTxtEdit::GetIDsOfNames(
  231. REFIID riid, //@parm Interface ID to interpret names for
  232. OLECHAR ** rgszNames, //@parm Array of names to be mapped
  233. UINT cNames, //@parm Count of names to be mapped
  234. LCID lcid, //@parm Local ID to use for interpretation
  235. DISPID * rgdispid) //@parm Out parm to receive name mappings
  236. {
  237. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetIDsOfNames");
  238. HRESULT hr = GetTypeInfoPtrs(); // Ensure TypeInfo ptrs are OK
  239. if(hr != NOERROR)
  240. return hr;
  241. hr = g_pTypeInfoDoc->GetIDsOfNames(rgszNames, cNames, rgdispid);
  242. if(hr == NOERROR) // Succeeded in finding an
  243. return NOERROR; // ITextDocument method
  244. IDispatch *pSel = (IDispatch *)GetSel(); // See if the selection knows
  245. // the desired method
  246. if(!pSel)
  247. return hr; // No selection
  248. return pSel->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  249. }
  250. /*
  251. * CTxtEdit::Invoke(dispidMember, riid, lcid, wFlags, pdispparams,
  252. * pvarResult, pexcepinfo, puArgError)
  253. * @mfunc
  254. * Invoke members for all TOM DISPIDs, i.e., for ITextDocument,
  255. * ITextSelection, ITextRange, ITextFont, and ITextPara. TOM DISPIDs
  256. * for all but ITextDocument are delegated to the selection object.
  257. *
  258. * @rdesc
  259. * HRESULT
  260. *
  261. * @devnote
  262. * This routine trys to invoke ITextDocument members if the DISPID is
  263. * in the range 0 thru 0xff. It trys to invoke ITextSelection members if
  264. * the DISPID is in the range 0x100 thru 0x4ff (this includes
  265. * ITextSelection, ITextRange, ITextFont, and ITextPara). It returns
  266. * E_MEMBERNOTFOUND for DISPIDs outside these ranges.
  267. */
  268. STDMETHODIMP CTxtEdit::Invoke(
  269. DISPID dispidMember, //@parm Identifies member function
  270. REFIID riid, //@parm Pointer to interface ID
  271. LCID lcid, //@parm Locale ID for interpretation
  272. USHORT wFlags, //@parm Flags describing context of call
  273. DISPPARAMS *pdispparams, //@parm Ptr to method arguments
  274. VARIANT * pvarResult, //@parm Out parm for result (if not NULL)
  275. EXCEPINFO * pexcepinfo, //@parm Out parm for exception info
  276. UINT * puArgError) //@parm Out parm for error
  277. {
  278. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Invoke");
  279. HRESULT hr = GetTypeInfoPtrs(); // Ensure TypeInfo ptrs are OK
  280. if(hr != NOERROR)
  281. return hr;
  282. if((DWORD)dispidMember < 0x100) // ITextDocment method
  283. return g_pTypeInfoDoc->Invoke((IDispatch *)this, dispidMember, wFlags,
  284. pdispparams, pvarResult, pexcepinfo, puArgError);
  285. IDispatch *pSel = (IDispatch *)GetSel(); // See if the selection has
  286. // the desired method
  287. if(pSel && (DWORD)dispidMember <= 0x4ff)
  288. return pSel->Invoke(dispidMember, riid, lcid, wFlags,
  289. pdispparams, pvarResult, pexcepinfo, puArgError);
  290. return DISP_E_MEMBERNOTFOUND;
  291. }
  292. //--------------------- ITextDocument Methods/Properties -----------------------
  293. /*
  294. * ITextDocument::BeginEditCollection()
  295. *
  296. * @mfunc
  297. * Method that turns on undo grouping
  298. *
  299. * @rdesc
  300. * HRESULT = (undo enabled) ? NOERROR : S_FALSE
  301. */
  302. STDMETHODIMP CTxtEdit::BeginEditCollection ()
  303. {
  304. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::BeginEditCollection");
  305. return E_NOTIMPL;
  306. }
  307. /*
  308. * ITextDocument::EndEditCollection()
  309. *
  310. * @mfunc
  311. * Method that turns off undo grouping
  312. *
  313. * @rdesc
  314. * HRESULT = NOERROR
  315. */
  316. STDMETHODIMP CTxtEdit::EndEditCollection ()
  317. {
  318. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::EndEditCollection");
  319. return E_NOTIMPL;
  320. }
  321. /*
  322. * ITextDocument::Freeze(long *pValue)
  323. *
  324. * @mfunc
  325. * Method to increment the freeze count. If this count is nonzero,
  326. * screen updating is disabled. This allows a sequence of editing
  327. * operations to be performed without the performance loss and
  328. * flicker of screen updating. See Unfreeze() to decrement the
  329. * freeze count.
  330. *
  331. * @rdesc
  332. * HRESULT = (screen updating disabled) ? NOERROR : S_FALSE
  333. *
  334. * @todo
  335. * What about APIs like EM_LINEFROMCHAR that don't yet know how to
  336. * react to a frozen display?
  337. */
  338. STDMETHODIMP CTxtEdit::Freeze (
  339. long *pCount) //@parm Out parm to receive updated freeze count
  340. {
  341. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Freeze");
  342. CCallMgr callmgr(this);
  343. if(_pdp)
  344. {
  345. CCallMgr callmgr(this);
  346. _pdp->Freeze();
  347. if(_pdp->IsFrozen())
  348. _cFreeze++;
  349. else
  350. _cFreeze = 0;
  351. }
  352. if(pCount)
  353. *pCount = _cFreeze;
  354. return _cFreeze ? NOERROR : S_FALSE;
  355. }
  356. /*
  357. * ITextDocument::GetDefaultTabStop (pValue)
  358. *
  359. * @mfunc
  360. * Property get method that gets the default tab stop to be
  361. * used whenever the explicit tabs don't extend far enough.
  362. *
  363. * @rdesc
  364. * HRESULT = (!pValue) ? E_INVALIDARG : NOERROR
  365. */
  366. STDMETHODIMP CTxtEdit::GetDefaultTabStop (
  367. float * pValue) //@parm Out parm to receive default tab stop
  368. {
  369. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetDefaultTabStop");
  370. if(!pValue)
  371. return E_INVALIDARG;
  372. const LONG lTab = GetDefaultTab();
  373. *pValue = TWIPS_TO_FPPTS(lTab);
  374. return NOERROR;
  375. }
  376. /*
  377. * CTxtEdit::GetName (pName)
  378. *
  379. * @mfunc
  380. * Retrieve ITextDocument filename
  381. *
  382. * @rdesc
  383. * HRESULT = (!<p pName>) ? E_INVALIDARG :
  384. * (no name) ? S_FALSE :
  385. * (if not enough RAM) ? E_OUTOFMEMORY : NOERROR
  386. */
  387. STDMETHODIMP CTxtEdit::GetName (
  388. BSTR * pName) //@parm Out parm to receive filename
  389. {
  390. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetName");
  391. if(!pName)
  392. return E_INVALIDARG;
  393. *pName = NULL;
  394. if(!_pDocInfo || !_pDocInfo->_pName)
  395. return S_FALSE;
  396. *pName = SysAllocString(_pDocInfo->_pName);
  397. return *pName ? NOERROR : E_OUTOFMEMORY;
  398. }
  399. /*
  400. * ITextDocument::GetSaved (pValue)
  401. *
  402. * @mfunc
  403. * Property get method that gets whether this instance has been
  404. * saved, i.e., no changes since last save
  405. *
  406. * @rdesc
  407. * HRESULT = (!pValue) ? E_INVALIDARG : NOERROR
  408. *
  409. * @comm
  410. * Next time to aid C/C++ clients, we ought to make pValue optional
  411. * and return S_FALSE if doc isn't saved, i.e., like our other
  412. * boolean properties (see, e.g., ITextRange::IsEqual())
  413. */
  414. STDMETHODIMP CTxtEdit::GetSaved (
  415. long * pValue) //@parm Out parm to receive Saved property
  416. {
  417. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetSaved");
  418. if(!pValue)
  419. return E_INVALIDARG;
  420. *pValue = _fSaved ? tomTrue : tomFalse;
  421. return NOERROR;
  422. }
  423. /*
  424. * ITextDocument::GetSelection (ITextSelection **ppSel)
  425. *
  426. * @mfunc
  427. * Property get method that gets the active selection.
  428. *
  429. * @rdesc
  430. * HRESULT = (!ppSel) ? E_INVALIDARG :
  431. * (if active selection exists) ? NOERROR : S_FALSE
  432. */
  433. STDMETHODIMP CTxtEdit::GetSelection (
  434. ITextSelection **ppSel) //@parm Out parm to receive selection pointer
  435. {
  436. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetSelection");
  437. if(!ppSel)
  438. return E_INVALIDARG;
  439. CTxtSelection *psel = GetSel();
  440. *ppSel = (ITextSelection *)psel;
  441. if( psel )
  442. {
  443. (*ppSel)->AddRef();
  444. return NOERROR;
  445. }
  446. return S_FALSE;
  447. }
  448. /*
  449. * CTxtEdit::GetStoryCount(pCount)
  450. *
  451. * @mfunc
  452. * Get count of stories in this document.
  453. *
  454. * @rdesc
  455. * HRESULT = (!<p pCount>) ? E_INVALIDARG : NOERROR
  456. */
  457. STDMETHODIMP CTxtEdit::GetStoryCount (
  458. LONG *pCount) //@parm Out parm to receive count of stories
  459. {
  460. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetStoryCount");
  461. if(!pCount)
  462. return E_INVALIDARG;
  463. *pCount = 1;
  464. return NOERROR;
  465. }
  466. /*
  467. * ITextDocument::GetStoryRanges(ITextStoryRanges **ppStories)
  468. *
  469. * @mfunc
  470. * Property get method that gets the story collection object
  471. * used to enumerate the stories in a document. Only invoke this
  472. * method if GetStoryCount() returns a value greater than one.
  473. *
  474. * @rdesc
  475. * HRESULT = (if Stories collection exists) ? NOERROR : E_NOTIMPL
  476. */
  477. STDMETHODIMP CTxtEdit::GetStoryRanges (
  478. ITextStoryRanges **ppStories) //@parm Out parm to receive stories ptr
  479. {
  480. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetStoryRanges");
  481. return E_NOTIMPL;
  482. }
  483. /*
  484. * ITextDocument::New()
  485. *
  486. * @mfunc
  487. * Method that closes the current document and opens a document
  488. * with a default name. If changes have been made in the current
  489. * document since the last save and document file information exists,
  490. * the current document is saved.
  491. *
  492. * @rdesc
  493. * HRESULT = NOERROR
  494. */
  495. STDMETHODIMP CTxtEdit::New ()
  496. {
  497. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::New");
  498. CloseFile(TRUE); // Save and close file
  499. return SetText(NULL, 0, CP_ULE);
  500. }
  501. /*
  502. * ITextDocument::Open(pVar, Flags, CodePage)
  503. *
  504. * @mfunc
  505. * Method that opens the document specified by pVar.
  506. *
  507. * @rdesc
  508. * HRESULT = (if success) ? NOERROR : E_OUTOFMEMORY
  509. *
  510. * @future
  511. * Handle IStream
  512. */
  513. STDMETHODIMP CTxtEdit::Open (
  514. VARIANT * pVar, //@parm Filename or IStream
  515. long Flags, //@parm Read/write, create, and share flags
  516. long CodePage) //@parm Code page to use
  517. {
  518. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Open");
  519. LONG cb; // Byte count for RTF check
  520. EDITSTREAM es = {0, NOERROR, MyRead};
  521. BOOL fReplaceSel = Flags & tomPasteFile;
  522. HCURSOR hcur;
  523. LRESULT lres;
  524. TCHAR szType[10];
  525. if(!pVar || CodePage && !IsUnicodeCP(CodePage) && !IsValidCodePage(CodePage))
  526. return E_INVALIDARG; // IsValidCodePage(0) fails
  527. // even tho CP_ACP = 0 (!)
  528. if((Flags & 0xF) >= tomHTML) // RichEdit only handles auto,
  529. return E_NOTIMPL; // plain text, & RTF formats
  530. if(!fReplaceSel) // If not replacing selection,
  531. New(); // save current file and
  532. // delete current text
  533. CDocInfo * pDocInfo = GetDocInfo();
  534. if(!pDocInfo)
  535. return E_OUTOFMEMORY;
  536. pDocInfo->_wFlags = (WORD)(Flags & ~0xf0); // Save flags (w/o creation)
  537. // Process access, share, and create flags
  538. DWORD dwAccess = (Flags & tomReadOnly)
  539. ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
  540. DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
  541. if(Flags & tomShareDenyRead)
  542. dwShare &= ~FILE_SHARE_READ;
  543. if(Flags & tomShareDenyWrite)
  544. dwShare &= ~FILE_SHARE_WRITE;
  545. DWORD dwCreate = (Flags >> 4) & 0xf;
  546. if(!dwCreate) // Flags nibble 2 must contain
  547. dwCreate = OPEN_ALWAYS; // CreateFile's dwCreate
  548. if(pVar->vt == VT_BSTR && SysStringLen(pVar->bstrVal))
  549. {
  550. es.dwCookie = (DWORD_PTR)CreateFile(pVar->bstrVal, dwAccess, dwShare,
  551. NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
  552. if((HANDLE)es.dwCookie == INVALID_HANDLE_VALUE)
  553. return HRESULT_FROM_WIN32(GetLastError());
  554. if(!fReplaceSel) // If not replacing selection,
  555. { // allocate new pName
  556. pDocInfo->_pName = SysAllocString(pVar->bstrVal);
  557. if (!pDocInfo->_pName)
  558. return E_OUTOFMEMORY;
  559. pDocInfo->_hFile = (HANDLE)es.dwCookie;
  560. pDocInfo->_wFlags |= tomTruncateExisting; // Setup Saves
  561. }
  562. }
  563. else
  564. {
  565. // FUTURE: check for IStream; if not, then fail
  566. return E_INVALIDARG;
  567. }
  568. Flags &= 0xf; // Isolate conversion flags
  569. // Get first few bytes of file to check for RTF and Unicode BOM
  570. (*es.pfnCallback)(es.dwCookie, (LPBYTE)szType, 10, &cb);
  571. Flags = (!Flags || Flags == tomRTF) && IsRTF((char *)szType, cb)
  572. ? tomRTF : tomText;
  573. LONG j = 0; // Default rewind to 0
  574. if (Flags == tomRTF) // RTF
  575. Flags = SF_RTF; // Setup EM_STREAMIN for RTF
  576. else
  577. { // If it starts with
  578. Flags = SF_TEXT; // Setup EM_STREAMIN for text
  579. if(cb > 1 && *(WORD *)szType == BOM) // Unicode byte-order mark
  580. { // (BOM) file is Unicode, so
  581. Flags = SF_TEXT | SF_UNICODE; // use Unicode code page and
  582. j = 2; // bypass the BOM
  583. }
  584. else if(cb > 1 && *(WORD *)szType == RBOM)// Big Endian BOM
  585. { // BOM
  586. Flags = SF_TEXT | SF_USECODEPAGE | (CP_UBE << 16);
  587. j = 2; // Bypass the BOM
  588. }
  589. else if(cb > 2 && W32->IsUTF8BOM((BYTE *)szType))
  590. {
  591. Flags = SF_TEXT | SF_USECODEPAGE | (CP_UTF8 << 16);
  592. j = 3;
  593. }
  594. else if(CodePage == CP_ULE)
  595. Flags = SF_TEXT | SF_UNICODE;
  596. else if(CodePage)
  597. Flags = SF_TEXT | SF_USECODEPAGE | (CodePage << 16);
  598. }
  599. SetFilePointer((HANDLE)es.dwCookie, j, NULL, FILE_BEGIN); // Rewind
  600. if(fReplaceSel)
  601. Flags |= SFF_SELECTION;
  602. Flags |= SFF_KEEPDOCINFO;
  603. hcur = TxSetCursor(LoadCursor(NULL, IDC_WAIT));
  604. TxSendMessage(EM_STREAMIN, Flags, (LPARAM)&es, &lres);
  605. TxSetCursor(hcur);
  606. if(dwShare == (FILE_SHARE_READ | FILE_SHARE_WRITE) || fReplaceSel)
  607. { // Full sharing or replaced
  608. CloseHandle((HANDLE)es.dwCookie); // selection, so close file
  609. if(!fReplaceSel) // If replacing selection,
  610. pDocInfo->_hFile = NULL; // leave _pDocInfo->_hFile
  611. }
  612. _fSaved = fReplaceSel ? FALSE : TRUE; // No changes yet unless
  613. return (HRESULT)es.dwError;
  614. }
  615. /*
  616. * ITextDocument::Range(long cpFirst, long cpLim, ITextRange **ppRange)
  617. *
  618. * @mfunc
  619. * Method that gets a text range on the active story of the document
  620. *
  621. * @rdesc
  622. * HRESULT = (!ppRange) ? E_INVALIDARG :
  623. * (if success) ? NOERROR : E_OUTOFMEMORY
  624. */
  625. STDMETHODIMP CTxtEdit::Range (
  626. long cpFirst, //@parm Non active end of new range
  627. long cpLim, //@parm Active end of new range
  628. ITextRange ** ppRange) //@parm Out parm to receive range
  629. {
  630. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Range");
  631. if(!ppRange)
  632. return E_INVALIDARG;
  633. *ppRange = new CTxtRange(this, cpFirst, cpFirst - cpLim);
  634. if( *ppRange )
  635. {
  636. (*ppRange)->AddRef(); // CTxtRange() doesn't AddRef() because
  637. return NOERROR; // it's used internally for things
  638. } // besides TOM
  639. return E_OUTOFMEMORY;
  640. }
  641. /*
  642. * ITextDocument::RangeFromPoint(long x, long y, ITextRange **ppRange)
  643. *
  644. * @mfunc
  645. * Method that gets the degenerate range corresponding (at or nearest)
  646. * to the point with the screen coordinates x and y.
  647. *
  648. * @rdesc
  649. * HRESULT = (!ppRange) ? E_INVALIDARG :
  650. * (if out of RAM) ? E_OUTOFMEMORY :
  651. * (if range exists) ? NOERROR : S_FALSE
  652. */
  653. STDMETHODIMP CTxtEdit::RangeFromPoint (
  654. long x, //@parm Horizontal coord of point to use
  655. long y, //@parm Vertical coord of point to use
  656. ITextRange **ppRange) //@parm Out parm to receive range
  657. {
  658. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::RangeFromPoint");
  659. if(!ppRange)
  660. return E_INVALIDARG;
  661. *ppRange = (ITextRange *) new CTxtRange(this, 0, 0);
  662. if(!*ppRange)
  663. return E_OUTOFMEMORY;
  664. (*ppRange)->AddRef(); // CTxtRange() doesn't AddRef()
  665. return (*ppRange)->SetPoint(x, y, 0, 0);
  666. }
  667. /*
  668. * ITextDocument::Redo(long Count, long *pCount)
  669. *
  670. * @mfunc
  671. * Method to perform the redo operation Count times
  672. *
  673. * @rdesc
  674. * HRESULT = (if Count redos performed) ? NOERROR : S_FALSE
  675. */
  676. STDMETHODIMP CTxtEdit::Redo (
  677. long Count, //@parm Number of redo operations to perform
  678. long * pCount) //@parm Number of redo operations performed
  679. {
  680. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Redo");
  681. CCallMgr callmgr(this);
  682. LONG i = 0;
  683. // Freeze the display during the execution of the anti-events
  684. CFreezeDisplay fd(_pdp);
  685. HRESULT hr = NOERROR;
  686. for ( ; i < Count; i++) // loop does nothing
  687. {
  688. hr = PopAndExecuteAntiEvent(_predo, 0);
  689. if(hr != NOERROR)
  690. break;
  691. }
  692. if(pCount)
  693. *pCount = i;
  694. return hr == NOERROR && i != Count ? S_FALSE : hr;
  695. }
  696. /*
  697. * ITextDocument::Save(pVar, Flags, CodePage)
  698. *
  699. * @mfunc
  700. * Method that saves this ITextDocument to the target pVar,
  701. * which is a VARIANT that can be a filename, an IStream, or NULL. If
  702. * NULL, the filename given by this document's name is used. It that,
  703. * in turn, is NULL, the method fails. If pVar specifies a filename,
  704. * that name should replace the current Name property.
  705. *
  706. * @rdesc
  707. * HRESULT = (!pVar) ? E_INVALIDARG :
  708. * (if success) ? NOERROR : E_FAIL
  709. *
  710. * @devnote
  711. * This routine can be called with NULL arguments
  712. */
  713. STDMETHODIMP CTxtEdit::Save (
  714. VARIANT * pVar, //@parm Save target (filename or IStream)
  715. long Flags, //@parm Read/write, create, and share flags
  716. long CodePage) //@parm Code page to use
  717. {
  718. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Save");
  719. LONG cb; // Byte count for writing Unicode BOM
  720. EDITSTREAM es = {0, NOERROR, MyWrite};
  721. BOOL fChange = FALSE; // No doc info change yet
  722. HCURSOR hcur;
  723. CDocInfo * pDocInfo = GetDocInfo();
  724. if(CodePage && !IsUnicodeCP(CodePage) && !IsValidCodePage(CodePage) ||
  725. (DWORD)Flags > 0x1fff || Flags & tomReadOnly)
  726. {
  727. return E_INVALIDARG;
  728. }
  729. if((Flags & 0xf) >= tomHTML) // RichEdit only handles auto,
  730. return E_NOTIMPL; // plain text, & RTF formats
  731. if(!pDocInfo) // Doc info doesn't exist
  732. return E_OUTOFMEMORY;
  733. if (pVar && pVar->vt == VT_BSTR && // Filename string
  734. pVar->bstrVal &&
  735. SysStringLen(pVar->bstrVal) && // NonNULL filename specified
  736. (!pDocInfo->_pName ||
  737. OLEstrcmp(pVar->bstrVal, pDocInfo->_pName)))
  738. { // Filename differs
  739. fChange = TRUE; // Force write to new file
  740. CloseFile(FALSE); // Close current file; no save
  741. pDocInfo->_pName = SysAllocString(pVar->bstrVal);
  742. if(!pDocInfo->_pName)
  743. return E_OUTOFMEMORY;
  744. pDocInfo->_wFlags &= ~0xf0; // Kill previous create mode
  745. }
  746. DWORD flags = pDocInfo->_wFlags;
  747. if(!(Flags & 0xF)) // If convert flags are 0,
  748. Flags |= flags & 0xF; // use values in doc info
  749. if(!(Flags & 0xF0)) // If create flags are 0,
  750. Flags |= flags & 0xF0; // use values in doc info
  751. if(!(Flags & 0xF00)) // If share flags are 0,
  752. Flags |= flags & 0xF00; // use values in doc info
  753. if(!CodePage) // If code page is 0,
  754. CodePage = pDocInfo->_wCpg; // use code page in doc info
  755. if((DWORD)Flags != flags || // If flags or code page
  756. (WORD)CodePage != pDocInfo->_wCpg) // changed, force write
  757. {
  758. fChange = TRUE;
  759. }
  760. pDocInfo->_wFlags = (WORD)Flags; // Save flags
  761. // Yikes, nowhere to save. bail-out now
  762. if(!_pDocInfo->_pName)
  763. return E_FAIL;
  764. if(_fSaved && !fChange) // No changes, so assume
  765. return NOERROR; // saved file is up to date
  766. DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
  767. if(Flags & tomShareDenyRead)
  768. dwShare &= ~FILE_SHARE_READ;
  769. if(Flags & tomShareDenyWrite)
  770. dwShare &= ~FILE_SHARE_WRITE;
  771. DWORD dwCreate = (Flags >> 4) & 0xF;
  772. if(!dwCreate)
  773. dwCreate = CREATE_NEW;
  774. if(pDocInfo->_hFile)
  775. {
  776. CloseHandle(pDocInfo->_hFile); // Close current file handle
  777. pDocInfo->_hFile = NULL;
  778. }
  779. es.dwCookie = (DWORD_PTR)CreateFile(pDocInfo->_pName, GENERIC_READ | GENERIC_WRITE, dwShare, NULL,
  780. dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
  781. if((HANDLE)es.dwCookie == INVALID_HANDLE_VALUE)
  782. return HRESULT_FROM_WIN32(GetLastError());
  783. pDocInfo->_hFile = (HANDLE)es.dwCookie;
  784. Flags &= 0xF; // Isolate conversion flags
  785. if(Flags == tomRTF) // RTF
  786. Flags = SF_RTF; // Setup EM_STREAMOUT for RTF
  787. else
  788. {
  789. Flags = SF_TEXT; // Setup EM_STREAMOUT for text
  790. if(IsUnicodeCP(CodePage) || CodePage == CP_UTF8)
  791. { // If Unicode, start file with
  792. LONG j = 2; // Unicode byte order mark
  793. WORD wBOM = BOM;
  794. WORD wRBOM = RBOM;
  795. BYTE *pb = (BYTE *)&wRBOM; // Default Big Endian Unicode
  796. if(CodePage == CP_UTF8)
  797. {
  798. j = 3;
  799. pb = szUTF8BOM;
  800. }
  801. else if(CodePage == CP_ULE) // Little Endian Unicode
  802. {
  803. Flags = SF_TEXT | SF_UNICODE;
  804. pb = (BYTE *)&wBOM;
  805. }
  806. (*es.pfnCallback)(es.dwCookie, pb, j, &cb);
  807. }
  808. }
  809. if(CodePage && CodePage != CP_ULE)
  810. Flags |= SF_USECODEPAGE | (CodePage << 16);
  811. hcur = TxSetCursor(LoadCursor(NULL, IDC_WAIT));
  812. TxSendMessage(EM_STREAMOUT, Flags, (LPARAM)&es, NULL);
  813. TxSetCursor(hcur);
  814. if(dwShare == (FILE_SHARE_READ | FILE_SHARE_WRITE))
  815. { // Full sharing, so close
  816. CloseHandle(pDocInfo->_hFile); // current file handle
  817. pDocInfo->_hFile = NULL;
  818. }
  819. _fSaved = TRUE; // File is saved
  820. return (HRESULT)es.dwError;
  821. }
  822. /*
  823. * ITextDocument::SetDefaultTabStop (Value)
  824. *
  825. * @mfunc
  826. * Property set method that sets the default tab stop to be
  827. * used whenever the explicit tabs don't extend far enough.
  828. *
  829. * @rdesc
  830. * HRESULT = (Value < 0) ? E_INVALIDARG : NOERROR
  831. */
  832. STDMETHODIMP CTxtEdit::SetDefaultTabStop (
  833. float Value) //@parm Out parm to receive default tab stop
  834. {
  835. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetDefaultTabStop");
  836. if(Value <= 0)
  837. return E_INVALIDARG;
  838. CDocInfo *pDocInfo = GetDocInfo();
  839. if(!pDocInfo) // Doc info doesn't exist
  840. return E_OUTOFMEMORY;
  841. pDocInfo->_dwDefaultTabStop = FPPTS_TO_TWIPS(Value);
  842. _pdp->UpdateView();
  843. return NOERROR;
  844. }
  845. /*
  846. * ITextDocument::SetSaved (Value)
  847. *
  848. * @mfunc
  849. * Property set method that sets whether this instance has been
  850. * saved, i.e., no changes since last save
  851. *
  852. * @rdesc
  853. * HRESULT = NOERROR
  854. */
  855. STDMETHODIMP CTxtEdit::SetSaved (
  856. long Value) //@parm New value of Saved property
  857. {
  858. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetSaved");
  859. _fSaved = Value ? TRUE : FALSE;
  860. return NOERROR;
  861. }
  862. /*
  863. * ITextDocument::Undo(Count, *pCount)
  864. *
  865. * @mfunc
  866. * Method to perform the undo operation Count times or to control
  867. * the nature of undo processing. Count = 0 stops undo processing
  868. * and discards any saved undo states. Count = -1 turns on undo
  869. * processing with the default undo limit. Count = tomSuspend
  870. * suspends undo processing, but doesn't discard saved undo states,
  871. * and Count = tomResume resumes undo processing with the undo states
  872. * active when Count = tomSuspend was given.
  873. *
  874. * @rdesc
  875. * HRESULT = (if Count undos performed) ? NOERROR : S_FALSE
  876. */
  877. STDMETHODIMP CTxtEdit::Undo (
  878. long Count, //@parm Count of undo operations to perform
  879. // 0 stops undo processing
  880. // -1 turns restores it
  881. long * pCount) //@parm Number of undo operations performed
  882. {
  883. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Undo");
  884. CCallMgr callmgr(this);
  885. LONG i = 0;
  886. // Freeze display during execution of anti-events
  887. CFreezeDisplay fd(_pdp);
  888. HRESULT hr = NOERROR;
  889. // Note: for Count <= 0,
  890. for ( ; i < Count; i++) // loop does nothing
  891. {
  892. hr = PopAndExecuteAntiEvent(_pundo, 0);
  893. if(hr != NOERROR)
  894. break;
  895. }
  896. if(pCount)
  897. *pCount = i;
  898. if(Count <= 0)
  899. i = HandleSetUndoLimit(Count);
  900. return hr == NOERROR && i != Count ? S_FALSE : hr;
  901. }
  902. /*
  903. * ITextDocument::Unfreeze(pCount)
  904. *
  905. * @mfunc
  906. * Method to decrement freeze count. If this count goes to zero,
  907. * screen updating is enabled. This method cannot decrement the
  908. * count below zero.
  909. *
  910. * @rdesc
  911. * HRESULT = (screen updating enabled) ? NOERROR : S_FALSE
  912. *
  913. * @devnote
  914. * The display maintains its own private reference count which may
  915. * temporarily exceed the reference count of this method. So even
  916. * if this method indicates that the display is unfrozen, it may be
  917. * for a while longer.
  918. */
  919. STDMETHODIMP CTxtEdit::Unfreeze (
  920. long *pCount) //@parm Out parm to receive updated freeze count
  921. {
  922. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Unfreeze");
  923. CCallMgr callmgr(this);
  924. if(_cFreeze)
  925. {
  926. CCallMgr callmgr(this);
  927. AssertSz(_pdp && _pdp->IsFrozen(),
  928. "CTxtEdit::Unfreeze: screen not frozen but expected to be");
  929. _cFreeze--;
  930. _pdp->Thaw();
  931. }
  932. if(pCount)
  933. *pCount = _cFreeze;
  934. return _cFreeze ? S_FALSE : NOERROR;
  935. }
  936. //----------------------- ITextDocument2 Methods -----------------------
  937. /*
  938. * ITextDocument2::AttachMsgFilter(pFilter)
  939. *
  940. * @mfunc
  941. * Method to attach a new message filter to the edit instance.
  942. * All window messages received by the edit instance will be forwarded
  943. * to the message filter. The message filter must be bound to the document
  944. * before it can be used (Refer to the ITextMessageFilter API).
  945. *
  946. * @rdesc
  947. * HRESULT = filter succesfully attached ? NOERROR : QI failure.
  948. */
  949. STDMETHODIMP CTxtEdit::AttachMsgFilter (
  950. IUnknown *pFilter) //@parm the IUnknown for the new message filter
  951. {
  952. ITextMsgFilter *pMsgFilter = NULL;
  953. HRESULT hr = pFilter->QueryInterface(IID_ITextMsgFilter, (void **)&pMsgFilter);
  954. if (SUCCEEDED(hr))
  955. {
  956. if (_pMsgFilter)
  957. _pMsgFilter->AttachMsgFilter(pMsgFilter);
  958. else
  959. _pMsgFilter = pMsgFilter;
  960. }
  961. return hr;
  962. }
  963. /*
  964. * ITextDocument2::GetEffectColor(Index, pcr)
  965. *
  966. * @mfunc
  967. * Method to retrieve the COLORREF color used in special attribute
  968. * displays. The first 15 values are for special underline colors 1 - 15.
  969. * Later we may define indices for other effects, e.g., URLs, strikeout.
  970. * If an index between 1 and 15 hasn't been defined by an appropriate
  971. * call to ITextDocument2:SetEffectColor(), the corresponding WORD
  972. * default color value given by g_Colors[] is returned.
  973. *
  974. * @rdesc
  975. * HRESULT = (valid active color index)
  976. * ? NOERROR : E_INVALIDARG
  977. */
  978. STDMETHODIMP CTxtEdit::GetEffectColor(
  979. long Index, //@parm Which special color to get
  980. COLORREF *pcr) //@parm Out parm for color
  981. {
  982. if(!pcr)
  983. return E_INVALIDARG;
  984. if(!IN_RANGE(1, Index, 15))
  985. {
  986. *pcr = (COLORREF)tomUndefined;
  987. return E_INVALIDARG;
  988. }
  989. *pcr = g_Colors[Index];
  990. CDocInfo *pDocInfo = GetDocInfo();
  991. if(!pDocInfo)
  992. return E_OUTOFMEMORY;
  993. Index--;
  994. if (Index < pDocInfo->_cColor &&
  995. pDocInfo->_prgColor[Index] != (COLORREF)tomUndefined)
  996. {
  997. *pcr = pDocInfo->_prgColor[Index];
  998. }
  999. return NOERROR;
  1000. }
  1001. /*
  1002. * ITextDocument2::SetEffectColor(Index, cr)
  1003. *
  1004. * @mfunc
  1005. * Method to save the Index'th special document color. Indices
  1006. * 1 - 15 are defined for underlining. Later we may define
  1007. * indices for other effects, e.g., URLs, strikeout.
  1008. *
  1009. * @rdesc
  1010. * HRESULT = (valid index)
  1011. * ? NOERROR : E_INVALIDARG
  1012. */
  1013. STDMETHODIMP CTxtEdit::SetEffectColor(
  1014. long Index, //@parm Which special color to set
  1015. COLORREF cr) //@parm Color to use
  1016. {
  1017. CDocInfo *pDocInfo = GetDocInfo();
  1018. if(!pDocInfo)
  1019. return E_OUTOFMEMORY;
  1020. Index--;
  1021. if(!IN_RANGE(0, Index, 14))
  1022. return E_INVALIDARG;
  1023. if(Index >= pDocInfo->_cColor)
  1024. {
  1025. LONG cColor = (Index + 4) & ~3; // Round up to 4
  1026. COLORREF *prgColor = (COLORREF *)PvReAlloc(pDocInfo->_prgColor,
  1027. cColor*sizeof(COLORREF));
  1028. if(!prgColor)
  1029. return E_OUTOFMEMORY;
  1030. for(LONG i = pDocInfo->_cColor; i < cColor; i++)
  1031. prgColor[i] = (COLORREF)tomUndefined;
  1032. pDocInfo->_cColor = (char)cColor;
  1033. pDocInfo->_prgColor = prgColor;
  1034. }
  1035. pDocInfo->_prgColor[Index] = cr;
  1036. return NOERROR;
  1037. }
  1038. /*
  1039. * ITextDocument2::SetCaretType(CaretType)
  1040. *
  1041. * @mfunc
  1042. * Method to sllow programmatic control over the caret type.
  1043. * The form of the control is TBD as is its interaction with
  1044. * existing formatting (e.g. font size and italics).
  1045. *
  1046. * @rdesc
  1047. * HRESULT = caret type is one we understand ? NOERROR : E_INVALIDARG
  1048. */
  1049. STDMETHODIMP CTxtEdit::SetCaretType(
  1050. long CaretType) //@parm specification of caret type to use
  1051. {
  1052. // For now, just care about Korean block craet.
  1053. if (CaretType == tomKoreanBlockCaret)
  1054. _fKoreanBlockCaret = TRUE;
  1055. else if (CaretType == tomNormalCaret)
  1056. _fKoreanBlockCaret = FALSE;
  1057. else
  1058. return E_INVALIDARG;
  1059. if (_psel && _psel->IsCaretShown() && _fFocus)
  1060. {
  1061. _psel->CreateCaret();
  1062. TxShowCaret(TRUE);
  1063. }
  1064. return NOERROR;
  1065. }
  1066. /*
  1067. * ITextDocument2::GetCaretType(pCaretType)
  1068. *
  1069. * @mfunc
  1070. * Method to retrieve the previously set caret type.
  1071. * TBD. Can one get it without setting it?
  1072. *
  1073. * @rdesc
  1074. * HRESULT = caret info OK ? NOERROR : E_INVALIDARG
  1075. */
  1076. STDMETHODIMP CTxtEdit::GetCaretType(
  1077. long *pCaretType) //@parm current caret type specification
  1078. {
  1079. if (!pCaretType)
  1080. return E_INVALIDARG;
  1081. *pCaretType = _fKoreanBlockCaret ? tomKoreanBlockCaret : tomNormalCaret;
  1082. return NOERROR;
  1083. }
  1084. /*
  1085. * ITextDocument2::GetImmContext(pContext)
  1086. *
  1087. * @mfunc
  1088. * Method to retrieve the IMM context from our host.
  1089. *
  1090. * @rdesc
  1091. * HRESULT = ImmContext available ? NOERROR : E_INVALIDARG
  1092. */
  1093. STDMETHODIMP CTxtEdit::GetImmContext(
  1094. long *pContext) //@parm Imm context
  1095. {
  1096. if (!pContext)
  1097. return E_INVALIDARG;
  1098. *pContext = 0;
  1099. if (!_fInOurHost)
  1100. {
  1101. // ask host for Imm Context
  1102. HIMC hIMC = TxImmGetContext();
  1103. *pContext = (long) hIMC;
  1104. }
  1105. return *pContext ? NOERROR : S_FALSE;
  1106. }
  1107. /*
  1108. * ITextDocument2::ReleaseImmContext(Context)
  1109. *
  1110. * @mfunc
  1111. * Method to release the IMM context.
  1112. *
  1113. * @rdesc
  1114. * HRESULT = ImmContext available ? NOERROR : E_INVALIDARG
  1115. */
  1116. STDMETHODIMP CTxtEdit::ReleaseImmContext(
  1117. long Context) //@parm Imm context to be release
  1118. {
  1119. if (!_fInOurHost)
  1120. {
  1121. // ask host to release Imm Context
  1122. TxImmReleaseContext((HIMC)Context);
  1123. return NOERROR;
  1124. }
  1125. return S_FALSE;
  1126. }
  1127. /*
  1128. * ITextDocument2::GetPreferredFont(cp, lCodePage, lOption, lCurCodePage, lCurFontSize,
  1129. * ,pFontName, pPitchAndFamily, pNewFontSize)
  1130. *
  1131. * @mfunc
  1132. * Method to retrieve the preferred font name and pitch and family at a
  1133. * given cp and codepage.
  1134. *
  1135. * @rdesc
  1136. * HRESULT = FontName available ? NOERROR : E_INVALIDARG
  1137. */
  1138. STDMETHODIMP CTxtEdit::GetPreferredFont(
  1139. long cp, //@parm cp
  1140. long lCodepage, //@parm codepage preferred
  1141. long lOption, //@parm option for matching current font
  1142. long lCurCodePage, //@parm current codepage
  1143. long lCurFontSize, //@parm current font size
  1144. BSTR *pFontName, //@parm preferred fontname
  1145. long *pPitchAndFamily, //@parm pitch and family
  1146. long *plNewFontSize) //@parm new font size preferred
  1147. {
  1148. if (!pFontName || !IN_RANGE(IGNORE_CURRENT_FONT, lOption, MATCH_FONT_SIG))
  1149. return E_INVALIDARG;
  1150. if (!IsAutoFont()) // EXIT if auto font is turned off
  1151. return S_FALSE;
  1152. CRchTxtPtr rtp(this, 0);
  1153. CCFRunPtr rp(rtp);
  1154. short iFont;
  1155. short yHeight;
  1156. BYTE bPitchAndFamily;
  1157. BYTE iCharRep = CharRepFromCodePage(lCodepage);
  1158. rp.Move(cp);
  1159. if (rp.GetPreferredFontInfo(
  1160. iCharRep,
  1161. iCharRep,
  1162. iFont,
  1163. yHeight,
  1164. bPitchAndFamily,
  1165. -1,
  1166. lOption))
  1167. {
  1168. if (*pFontName)
  1169. wcscpy(*pFontName, GetFontName((LONG)iFont));
  1170. else
  1171. {
  1172. *pFontName = SysAllocString(GetFontName((LONG)iFont));
  1173. if (!*pFontName)
  1174. return E_OUTOFMEMORY;
  1175. }
  1176. if (pPitchAndFamily)
  1177. *pPitchAndFamily = bPitchAndFamily;
  1178. // Calc the new font size if needed
  1179. if (plNewFontSize)
  1180. {
  1181. *plNewFontSize = lCurFontSize;
  1182. if (_fAutoFontSizeAdjust && lCodepage != lCurCodePage)
  1183. *plNewFontSize = yHeight / TWIPS_PER_POINT; // Set the preferred size
  1184. }
  1185. return S_OK;
  1186. }
  1187. return E_FAIL;
  1188. }
  1189. /*
  1190. * ITextDocument2::GetNotificationMode( long *plMode )
  1191. *
  1192. * @mfunc
  1193. * Method to retrieve the current notification mode.
  1194. *
  1195. * @rdesc
  1196. * HRESULT = notification mode available ? NOERROR : E_INVALIDARG
  1197. */
  1198. STDMETHODIMP CTxtEdit::GetNotificationMode(
  1199. long *plMode) //@parm current notification mode
  1200. {
  1201. if (!plMode)
  1202. return E_INVALIDARG;
  1203. *plMode = _fSuppressNotify ? tomFalse : tomTrue;
  1204. return NOERROR;
  1205. }
  1206. /*
  1207. * ITextDocument2::SetNotificationMode(lMode)
  1208. *
  1209. * @mfunc
  1210. * Method to set the current notification mode.
  1211. *
  1212. * @rdesc
  1213. * HRESULT = notification mode set ? NOERROR : E_INVALIDARG
  1214. */
  1215. STDMETHODIMP CTxtEdit::SetNotificationMode(
  1216. long lMode) //@parm new notification mode
  1217. {
  1218. if (lMode == tomFalse)
  1219. _fSuppressNotify = 1;
  1220. else if (lMode == tomTrue)
  1221. _fSuppressNotify = 0;
  1222. else
  1223. return E_INVALIDARG;
  1224. return NOERROR;
  1225. }
  1226. /*
  1227. * ITextDocument2::GetClientRect(Type, pLeft, pTop,pRight, pBottom )
  1228. *
  1229. * @mfunc
  1230. * Method to retrieve the client rect and inset adjustment.
  1231. *
  1232. * @rdesc
  1233. * HRESULT = notification mode set ? NOERROR : E_INVALIDARG
  1234. */
  1235. STDMETHODIMP CTxtEdit::GetClientRect(
  1236. long Type, //@parm option
  1237. long *pLeft, //@parm left
  1238. long *pTop, //@parm top
  1239. long *pRight, //@parm right
  1240. long *pBottom) //@parm bottom
  1241. {
  1242. if (!pLeft || !pTop || !pRight || !pBottom)
  1243. return E_INVALIDARG;
  1244. RECT rcArea;
  1245. TxGetClientRect(&rcArea);
  1246. if ( Type & tomIncludeInset )
  1247. {
  1248. // Ajdust veiw inset
  1249. RECTUV rcInset;
  1250. TxGetViewInset( &rcInset, NULL );
  1251. rcArea.right -= rcInset.right;
  1252. rcArea.bottom -= rcInset.bottom;
  1253. rcArea.left += rcInset.left;
  1254. rcArea.top += rcInset.top;
  1255. }
  1256. // Caller wants screen coordinates?
  1257. if ( !(Type & tomClientCoord) )
  1258. {
  1259. POINT ptTopLeft = {rcArea.left, rcArea.top};
  1260. POINT ptBottomRight = {rcArea.right, rcArea.bottom};
  1261. if (!TxClientToScreen(&ptTopLeft) ||
  1262. !TxClientToScreen(&ptBottomRight))
  1263. return E_FAIL; // It is unexpected for this to happen
  1264. *pLeft = ptTopLeft.x;
  1265. *pTop = ptTopLeft.y;
  1266. *pRight = ptBottomRight.x;
  1267. *pBottom = ptBottomRight.y;
  1268. }
  1269. else
  1270. {
  1271. *pLeft = rcArea.left;
  1272. *pTop = rcArea.top;
  1273. *pRight = rcArea.right;
  1274. *pBottom = rcArea.bottom;
  1275. }
  1276. return NOERROR;
  1277. }
  1278. /*
  1279. * ITextDocument2::GetSelectionEx(ppSel)
  1280. *
  1281. * @mfunc
  1282. * Method to retrieve selection.
  1283. *
  1284. * @rdesc
  1285. * HRESULT = selection ? NOERROR : S_FALSE
  1286. */
  1287. STDMETHODIMP CTxtEdit::GetSelectionEx(
  1288. ITextSelection **ppSel) //@parm Get Selection object
  1289. {
  1290. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetSelectionEx");
  1291. if (_fInPlaceActive)
  1292. return GetSelection (ppSel);
  1293. Assert("Getting selection while not active");
  1294. if(!ppSel)
  1295. return E_INVALIDARG;
  1296. *ppSel = NULL;
  1297. return S_FALSE;
  1298. }
  1299. /*
  1300. * ITextDocument2::GetWindow(phWnd)
  1301. *
  1302. * @mfunc
  1303. * Method to get the host window
  1304. *
  1305. * @rdesc
  1306. * HRESULT = NOERROR if host return hWnd
  1307. */
  1308. STDMETHODIMP CTxtEdit::GetWindow(
  1309. long *phWnd) //@parm hWnd
  1310. {
  1311. if (!phWnd)
  1312. return E_INVALIDARG;
  1313. return TxGetWindow((HWND *)phWnd);
  1314. }
  1315. /*
  1316. * ITextDocument2::GetFEFlags(pFEFlags)
  1317. *
  1318. * @mfunc
  1319. * Method to get Host FE flags
  1320. *
  1321. * @rdesc
  1322. * HRESULT = NOERROR if host returns FE Flags
  1323. */
  1324. STDMETHODIMP CTxtEdit::GetFEFlags(
  1325. long *pFEFlags) //@parm FE Flags
  1326. {
  1327. return TxGetFEFlags(pFEFlags);
  1328. }
  1329. /*
  1330. * ITextDocument2::UpdateWindow(void)
  1331. *
  1332. * @mfunc
  1333. * Method to update the RE window
  1334. *
  1335. * @rdesc
  1336. * HRESULT = NOERROR
  1337. */
  1338. STDMETHODIMP CTxtEdit::UpdateWindow(void)
  1339. {
  1340. TxUpdateWindow();
  1341. return NOERROR;
  1342. }
  1343. /*
  1344. * ITextDocument2::CheckTextLimit(long cch, long *pcch)
  1345. *
  1346. * @mfunc
  1347. * Method to check if the count of characters to be added would
  1348. * exceed max. text limit. The number of characters exced is returned
  1349. * in pcch
  1350. *
  1351. * @rdesc
  1352. * HRESULT = NOERROR
  1353. */
  1354. STDMETHODIMP CTxtEdit::CheckTextLimit(
  1355. long cch, //@parm count of characters to be added
  1356. long *pcch) //@parm return the number of characters exced text limit
  1357. {
  1358. if(!pcch)
  1359. return E_INVALIDARG;
  1360. *pcch = 0;
  1361. if (cch > 0)
  1362. {
  1363. DWORD cchNew = (DWORD)(GetAdjustedTextLength() + cch);
  1364. if(cchNew > TxGetMaxLength())
  1365. *pcch = cchNew - TxGetMaxLength();
  1366. }
  1367. return NOERROR;
  1368. }
  1369. /*
  1370. * ITextDocument2::IMEInProgress(lMode)
  1371. *
  1372. * @mfunc
  1373. * Method for IME message filter to inform client that IME composition
  1374. * is in progress.
  1375. *
  1376. * @rdesc
  1377. * HRESULT = NOERROR
  1378. */
  1379. STDMETHODIMP CTxtEdit::IMEInProgress(
  1380. long lMode) //@parm current IME composition status
  1381. {
  1382. if (lMode == tomFalse)
  1383. _fIMEInProgress = 0;
  1384. else if (lMode == tomTrue)
  1385. _fIMEInProgress = 1;
  1386. return NOERROR;
  1387. }
  1388. /*
  1389. * ITextDocument2::SysBeep(void)
  1390. *
  1391. * @mfunc
  1392. * Method to generate system beep.
  1393. *
  1394. * @rdesc
  1395. * HRESULT = NOERROR
  1396. */
  1397. STDMETHODIMP CTxtEdit::SysBeep(void)
  1398. {
  1399. Beep();
  1400. return NOERROR;
  1401. }
  1402. /*
  1403. * ITextDocument2::Update(lMode)
  1404. *
  1405. * @mfunc
  1406. * Method for update the selection or caret. If lMode is tomTrue, then
  1407. * scroll the caret into view.
  1408. *
  1409. * @rdesc
  1410. * HRESULT = NOERROR
  1411. */
  1412. STDMETHODIMP CTxtEdit::Update(
  1413. long lMode) //@parm current IME composition status
  1414. {
  1415. if (!_psel)
  1416. return S_FALSE;
  1417. _psel->Update(lMode == tomTrue ? TRUE : FALSE);
  1418. return NOERROR;
  1419. }
  1420. /*
  1421. * ITextDocument2::Notify(lNotify)
  1422. *
  1423. * @mfunc
  1424. * Method for notifying the host for certain IME events
  1425. *
  1426. * @rdesc
  1427. * HRESULT = NOERROR
  1428. */
  1429. STDMETHODIMP CTxtEdit::Notify(
  1430. long lNotify) //@parm Notification code
  1431. {
  1432. TxNotify(lNotify, NULL);
  1433. return NOERROR;
  1434. }
  1435. /*
  1436. * ITextDocument2::GetDocumentFont(ppITextFont)
  1437. *
  1438. * @mfunc
  1439. * Method for getting the default document font
  1440. *
  1441. * @rdesc
  1442. * HRESULT = NOERROR
  1443. */
  1444. STDMETHODIMP CTxtEdit::GetDocumentFont(
  1445. ITextFont **ppFont) //@parm get ITextFont object
  1446. {
  1447. CTxtFont *pTxtFont;
  1448. if(!ppFont)
  1449. return E_INVALIDARG;
  1450. pTxtFont = new CTxtFont(NULL);
  1451. if (pTxtFont)
  1452. {
  1453. pTxtFont->_CF = *GetCharFormat(-1);
  1454. pTxtFont->_dwMask = CFM_ALL2;
  1455. }
  1456. *ppFont = (ITextFont *) pTxtFont;
  1457. return *ppFont ? NOERROR : E_OUTOFMEMORY;
  1458. }
  1459. /*
  1460. * ITextDocument2::GetDocumentPara(ppITextPara)
  1461. *
  1462. * @mfunc
  1463. * Method for getting the default document para
  1464. *
  1465. * @rdesc
  1466. * HRESULT = NOERROR
  1467. */
  1468. STDMETHODIMP CTxtEdit::GetDocumentPara(
  1469. ITextPara **ppPara) //@parm get ITextPara object
  1470. {
  1471. CTxtPara *pTxtPara;
  1472. if(!ppPara)
  1473. return E_INVALIDARG;
  1474. pTxtPara = new CTxtPara(NULL);
  1475. if (pTxtPara)
  1476. {
  1477. pTxtPara->_PF = *GetParaFormat(-1);
  1478. pTxtPara->_dwMask = PFM_ALL2;
  1479. pTxtPara->_PF._bTabCount = 0;
  1480. pTxtPara->_PF._iTabs = -1;
  1481. }
  1482. *ppPara = (ITextPara *) pTxtPara;
  1483. return *ppPara ? NOERROR : E_OUTOFMEMORY;
  1484. }
  1485. /*
  1486. * ITextDocument2::GetCallManager(ppVoid)
  1487. *
  1488. * @mfunc
  1489. * Method for getting the call manager
  1490. *
  1491. * @rdesc
  1492. * HRESULT = NOERROR
  1493. */
  1494. STDMETHODIMP CTxtEdit::GetCallManager(
  1495. IUnknown **ppVoid) //@parm get CallMgr object
  1496. {
  1497. CCallMgr *pCallMgr;
  1498. if(!ppVoid)
  1499. return E_INVALIDARG;
  1500. pCallMgr = new CCallMgr(this);
  1501. *ppVoid = (IUnknown *) pCallMgr;
  1502. return *ppVoid ? NOERROR : E_OUTOFMEMORY;
  1503. }
  1504. /*
  1505. * ITextDocument2::ReleaseCallManager(ppITextPara)
  1506. *
  1507. * @mfunc
  1508. * Method for getting the default document para
  1509. *
  1510. * @rdesc
  1511. * HRESULT = NOERROR
  1512. */
  1513. STDMETHODIMP CTxtEdit::ReleaseCallManager(
  1514. IUnknown *pVoid) //@parm Call Manager object
  1515. {
  1516. CCallMgr *pCallMgr;
  1517. if(!pVoid)
  1518. return E_INVALIDARG;
  1519. pCallMgr = (CCallMgr *)pVoid;
  1520. delete pCallMgr;
  1521. return NOERROR;
  1522. }
  1523. //----------------------- ITextDocument Helper Functions -----------------------
  1524. /*
  1525. * CTxtEdit::CloseFile (bSave)
  1526. *
  1527. * @mfunc
  1528. * Method that closes the current document. If changes have been made
  1529. * in the current document since the last save and document file
  1530. * information exists, the current document is saved.
  1531. *
  1532. * @rdesc
  1533. * HRESULT = NOERROR
  1534. */
  1535. HRESULT CTxtEdit::CloseFile (
  1536. BOOL bSave)
  1537. {
  1538. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Close");
  1539. CDocInfo *pDocInfo = _pDocInfo;
  1540. if(pDocInfo)
  1541. {
  1542. if(bSave) // Save current file if
  1543. Save(NULL, 0, 0); // any changes made
  1544. // FUTURE(BradO): This code is very similar to the destructor code.
  1545. // We have a problem here in that some of the CDocInfo information
  1546. // should persist from Open to Close to Open (ex. default tab stop)
  1547. // mixed with other per-Open/Close info. A better job of abstracting
  1548. // these two types of info would really clean up this code.
  1549. if(pDocInfo->_pName)
  1550. {
  1551. SysFreeString(pDocInfo->_pName); // Free filename BSTR
  1552. pDocInfo->_pName = NULL;
  1553. }
  1554. if(pDocInfo->_hFile)
  1555. {
  1556. CloseHandle(pDocInfo->_hFile); // Close file if open
  1557. pDocInfo->_hFile = NULL;
  1558. }
  1559. pDocInfo->_wFlags = 0;
  1560. pDocInfo->_wCpg = 0;
  1561. pDocInfo->_lcid = 0;
  1562. pDocInfo->_lcidfe = 0;
  1563. if(pDocInfo->_lpstrLeadingPunct)
  1564. {
  1565. FreePv(pDocInfo->_lpstrLeadingPunct);
  1566. pDocInfo->_lpstrLeadingPunct = NULL;
  1567. }
  1568. if(pDocInfo->_lpstrFollowingPunct)
  1569. {
  1570. FreePv(pDocInfo->_lpstrFollowingPunct);
  1571. pDocInfo->_lpstrFollowingPunct = NULL;
  1572. }
  1573. }
  1574. return NOERROR;
  1575. }
  1576. /*
  1577. * CTxtEdit::SetDefaultLCID (lcid)
  1578. *
  1579. * @mfunc
  1580. * Property set method that sets the default LCID
  1581. *
  1582. * @rdesc
  1583. * HRESULT = NOERROR
  1584. *
  1585. * @comm
  1586. * This property should be part of TOM
  1587. */
  1588. HRESULT CTxtEdit::SetDefaultLCID (
  1589. LCID lcid) //@parm New default LCID value
  1590. {
  1591. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetDefaultLCID");
  1592. CDocInfo *pDocInfo = GetDocInfo();
  1593. if(!pDocInfo) // Doc info doesn't exist
  1594. return E_OUTOFMEMORY;
  1595. pDocInfo->_lcid = lcid;
  1596. return NOERROR;
  1597. }
  1598. /*
  1599. * CTxtEdit::GetDefaultLCID (pLCID)
  1600. *
  1601. * @mfunc
  1602. * Property get method that gets the default LCID
  1603. *
  1604. * @rdesc
  1605. * HRESULT = (!pLCID) ? E_INVALIDARG : NOERROR
  1606. */
  1607. HRESULT CTxtEdit::GetDefaultLCID (
  1608. LCID *pLCID) //@parm Out parm with default LCID value
  1609. {
  1610. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetDefaultLCID");
  1611. if(!pLCID)
  1612. return E_INVALIDARG;
  1613. CDocInfo *pDocInfo = GetDocInfo();
  1614. if(!pDocInfo) // Doc info doesn't exist
  1615. return E_OUTOFMEMORY;
  1616. *pLCID = _pDocInfo->_lcid;
  1617. return NOERROR;
  1618. }
  1619. /*
  1620. * CTxtEdit::SetDefaultLCIDFE (lcid)
  1621. *
  1622. * @mfunc
  1623. * Property set method that sets the default FE LCID
  1624. *
  1625. * @rdesc
  1626. * HRESULT = NOERROR
  1627. *
  1628. * @comm
  1629. * This property should be part of TOM
  1630. */
  1631. HRESULT CTxtEdit::SetDefaultLCIDFE (
  1632. LCID lcid) //@parm New default LCID value
  1633. {
  1634. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetDefaultLCIDFE");
  1635. CDocInfo *pDocInfo = GetDocInfo();
  1636. if(!pDocInfo) // Doc info doesn't exist
  1637. return E_OUTOFMEMORY;
  1638. pDocInfo->_lcidfe = lcid;
  1639. return NOERROR;
  1640. }
  1641. /*
  1642. * CTxtEdit::GetDefaultLCIDFE (pLCID)
  1643. *
  1644. * @mfunc
  1645. * Property get method that gets the default FE LCID
  1646. *
  1647. * @rdesc
  1648. * HRESULT = (!pLCID) ? E_INVALIDARG : NOERROR
  1649. */
  1650. HRESULT CTxtEdit::GetDefaultLCIDFE (
  1651. LCID *pLCID) //@parm Out parm with default LCID value
  1652. {
  1653. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetDefaultLCID");
  1654. if(!pLCID)
  1655. return E_INVALIDARG;
  1656. CDocInfo *pDocInfo = GetDocInfo();
  1657. if(!pDocInfo) // Doc info doesn't exist
  1658. return E_OUTOFMEMORY;
  1659. *pLCID = _pDocInfo->_lcidfe;
  1660. return NOERROR;
  1661. }
  1662. /*
  1663. * CTxtEdit::SetDocumentType(bDocType)
  1664. *
  1665. * @mfunc
  1666. * Property set method that sets the document's type (none-\ltrdoc-\rtldoc)
  1667. *
  1668. * @rdesc
  1669. * HRESULT = NOERROR
  1670. */
  1671. HRESULT CTxtEdit::SetDocumentType (
  1672. LONG DocType) //@parm New document-type value
  1673. {
  1674. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetDocumentType");
  1675. CDocInfo *pDocInfo = GetDocInfo();
  1676. if(!pDocInfo) // Doc info doesn't exist
  1677. return E_OUTOFMEMORY;
  1678. pDocInfo->_bDocType = (BYTE)DocType;
  1679. return NOERROR;
  1680. }
  1681. /*
  1682. * CTxtEdit::GetDocumentType (pDocType)
  1683. *
  1684. * @mfunc
  1685. * Property get method that gets the document type
  1686. *
  1687. * @rdesc
  1688. * HRESULT = (!pDocType) ? E_INVALIDARG : NOERROR
  1689. */
  1690. HRESULT CTxtEdit::GetDocumentType (
  1691. LONG *pDocType) //@parm Out parm with document type value
  1692. {
  1693. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetDocumentType");
  1694. if(!pDocType)
  1695. return E_INVALIDARG;
  1696. CDocInfo *pDocInfo = GetDocInfo();
  1697. if(!pDocInfo) // Doc info doesn't exist
  1698. return E_OUTOFMEMORY;
  1699. *pDocType = _pDocInfo->_bDocType;
  1700. return NOERROR;
  1701. }
  1702. /*
  1703. * CTxtEdit::GetLeadingPunct (plpstrLeadingPunct)
  1704. *
  1705. * @mfunc
  1706. * Retrieve leading kinsoku punctuation for document
  1707. *
  1708. * @rdesc
  1709. * HRESULT = (!<p plpstrLeadingPunct>) ? E_INVALIDARG :
  1710. * (no leading punct) ? S_FALSE :
  1711. * (if not enough RAM) ? E_OUTOFMEMORY : NOERROR
  1712. */
  1713. HRESULT CTxtEdit::GetLeadingPunct (
  1714. LPSTR * plpstrLeadingPunct) //@parm Out parm to receive leading
  1715. // kinsoku punctuation
  1716. {
  1717. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetLeadingPunct");
  1718. if(!plpstrLeadingPunct)
  1719. return E_INVALIDARG;
  1720. *plpstrLeadingPunct = NULL;
  1721. if(!_pDocInfo || !_pDocInfo->_lpstrLeadingPunct)
  1722. return S_FALSE;
  1723. *plpstrLeadingPunct = _pDocInfo->_lpstrLeadingPunct;
  1724. return NOERROR;
  1725. }
  1726. /*
  1727. * CTxtEdit::SetLeadingPunct (lpstrLeadingPunct)
  1728. *
  1729. * @mfunc
  1730. * Set leading kinsoku punctuation for document
  1731. *
  1732. * @rdesc
  1733. * HRESULT = (if not enough RAM) ? E_OUTOFMEMORY : NOERROR
  1734. */
  1735. HRESULT CTxtEdit::SetLeadingPunct (
  1736. LPSTR lpstrLeadingPunct) //@parm In parm containing leading
  1737. // kinsoku punctuation
  1738. {
  1739. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetLeadingPunct");
  1740. CDocInfo *pDocInfo = GetDocInfo();
  1741. if(!pDocInfo)
  1742. return E_OUTOFMEMORY;
  1743. if(pDocInfo->_lpstrLeadingPunct)
  1744. FreePv(pDocInfo->_lpstrLeadingPunct);
  1745. if(lpstrLeadingPunct && *lpstrLeadingPunct)
  1746. pDocInfo->_lpstrLeadingPunct = lpstrLeadingPunct;
  1747. else
  1748. {
  1749. pDocInfo->_lpstrLeadingPunct = NULL;
  1750. return E_INVALIDARG;
  1751. }
  1752. return NOERROR;
  1753. }
  1754. /*
  1755. * CTxtEdit::GetFollowingPunct (plpstrFollowingPunct)
  1756. *
  1757. * @mfunc
  1758. * Retrieve following kinsoku punctuation for document
  1759. *
  1760. * @rdesc
  1761. * HRESULT = (!<p plpstrFollowingPunct>) ? E_INVALIDARG :
  1762. * (no following punct) ? S_FALSE :
  1763. * (if not enough RAM) ? E_OUTOFMEMORY : NOERROR
  1764. */
  1765. HRESULT CTxtEdit::GetFollowingPunct (
  1766. LPSTR * plpstrFollowingPunct) //@parm Out parm to receive following
  1767. // kinsoku punctuation
  1768. {
  1769. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetFollowingPunct");
  1770. if(!plpstrFollowingPunct)
  1771. return E_INVALIDARG;
  1772. *plpstrFollowingPunct = NULL;
  1773. if(!_pDocInfo || !_pDocInfo->_lpstrFollowingPunct)
  1774. return S_FALSE;
  1775. *plpstrFollowingPunct = _pDocInfo->_lpstrFollowingPunct;
  1776. return NOERROR;
  1777. }
  1778. /*
  1779. * CTxtEdit::SetFollowingPunct (lpstrFollowingPunct)
  1780. *
  1781. * @mfunc
  1782. * Set following kinsoku punctuation for document
  1783. *
  1784. * @rdesc
  1785. * HRESULT = (if not enough RAM) ? E_OUTOFMEMORY : NOERROR
  1786. */
  1787. HRESULT CTxtEdit::SetFollowingPunct (
  1788. LPSTR lpstrFollowingPunct) //@parm In parm containing following
  1789. // kinsoku punctuation
  1790. {
  1791. TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetFollowingPunct");
  1792. CDocInfo *pDocInfo = GetDocInfo();
  1793. if(!pDocInfo)
  1794. return E_OUTOFMEMORY;
  1795. if(pDocInfo->_lpstrFollowingPunct)
  1796. FreePv(pDocInfo->_lpstrFollowingPunct);
  1797. if(lpstrFollowingPunct && *lpstrFollowingPunct)
  1798. pDocInfo->_lpstrFollowingPunct = lpstrFollowingPunct;
  1799. else
  1800. {
  1801. pDocInfo->_lpstrFollowingPunct = NULL;
  1802. return E_INVALIDARG;
  1803. }
  1804. return NOERROR;
  1805. }
  1806. /*
  1807. * CTxtEdit::InitDocInfo()
  1808. *
  1809. * @mfunc initialize doc info structure
  1810. *
  1811. * @rdesc
  1812. * HRESULT
  1813. */
  1814. HRESULT CTxtEdit::InitDocInfo()
  1815. {
  1816. _wZoomNumerator = _wZoomDenominator = 0;// Turn off zoom
  1817. // Reset Vertical style
  1818. DWORD dwBits = 0;
  1819. _phost->TxGetPropertyBits(TXTBIT_VERTICAL, &dwBits);
  1820. if (dwBits & TXTBIT_VERTICAL)
  1821. {
  1822. _fUseAtFont = TRUE;
  1823. HandleSetTextFlow(tflowSW);
  1824. }
  1825. else
  1826. {
  1827. _fUseAtFont = FALSE;
  1828. HandleSetTextFlow(tflowES);
  1829. }
  1830. if(_pDocInfo)
  1831. {
  1832. _pDocInfo->Init();
  1833. return NOERROR;
  1834. }
  1835. return GetDocInfo() ? NOERROR : E_OUTOFMEMORY;
  1836. }
  1837. /*
  1838. * CTxtEdit::GetBackgroundType()
  1839. *
  1840. * @mfunc
  1841. * Get background type
  1842. *
  1843. * @rdesc
  1844. * Background type (only for main display)
  1845. */
  1846. LONG CTxtEdit::GetBackgroundType()
  1847. {
  1848. return _pDocInfo ? _pDocInfo->_nFillType : -1;
  1849. }
  1850. /*
  1851. * CTxtEdit::TxGetBackColor()
  1852. *
  1853. * @mfunc
  1854. * Get background color
  1855. *
  1856. * @rdesc
  1857. * Background color (only for main display)
  1858. */
  1859. COLORREF CTxtEdit::TxGetBackColor() const
  1860. {
  1861. return (_pDocInfo && _pDocInfo->_nFillType == 0)
  1862. ? _pDocInfo->_crColor : _phost->TxGetSysColor(COLOR_WINDOW);
  1863. }
  1864. //----------------------- CDocInfo related Functions -----------------------
  1865. /*
  1866. * CDocInfo::Init()
  1867. *
  1868. * @mfunc
  1869. * Initializer for CDocInfo
  1870. *
  1871. * @comment
  1872. * It is assumed that CDocInfo created by a new operator that zeroes
  1873. * the structure. This initializer is called by the constructor and
  1874. * by CTxtEdit::InitDocInfo().
  1875. */
  1876. void CDocInfo::Init()
  1877. {
  1878. _wCpg = (WORD)GetACP();
  1879. _lcid = GetSystemDefaultLCID();
  1880. if(IsFELCID(_lcid))
  1881. {
  1882. _lcidfe = _lcid;
  1883. _lcid = MAKELCID(sLanguageEnglishUS, SORT_DEFAULT);
  1884. }
  1885. _dwDefaultTabStop = lDefaultTab;
  1886. _bDocType = 0;
  1887. InitBackground();
  1888. }
  1889. /*
  1890. * CDocInfo::InitBackground()
  1891. *
  1892. * @mfunc
  1893. * Background initializer for CDocInfo
  1894. */
  1895. void CDocInfo::InitBackground()
  1896. {
  1897. _nFillType = -1;
  1898. _sFillAngle = 0;
  1899. if(_hBitmapBack)
  1900. DeleteObject(_hBitmapBack);
  1901. GlobalFree(_hdata);
  1902. _hdata = NULL;
  1903. _hBitmapBack = NULL;
  1904. }
  1905. /*
  1906. * CDocInfo::~CDocInfo
  1907. *
  1908. * @mfunc destructor for the docinfo class
  1909. */
  1910. CDocInfo::~CDocInfo()
  1911. {
  1912. if(_pName)
  1913. SysFreeString(_pName);
  1914. if(_hFile)
  1915. CloseHandle(_hFile);
  1916. FreePv(_lpstrLeadingPunct);
  1917. FreePv(_lpstrFollowingPunct);
  1918. FreePv(_prgColor);
  1919. if(_hBitmapBack)
  1920. DeleteObject(_hBitmapBack);
  1921. GlobalFree(_hdata);
  1922. }
  1923. /*
  1924. * CTxtEdit::GetDocInfo ()
  1925. *
  1926. * @mfunc
  1927. * If _pDocInfo is NULL, equate it to a new CDocInfo. In either case
  1928. * return _pDocInfo
  1929. *
  1930. * @rdesc
  1931. * CTxtEdit::_pDocInfo, the ptr to the CDocInfo object
  1932. */
  1933. CDocInfo * CTxtEdit::GetDocInfo()
  1934. {
  1935. TRACEBEGIN(TRCSUBSYSEDIT, TRCSCOPEINTERN, "CTxtEdit::GetDocInfo");
  1936. if (!_pDocInfo)
  1937. _pDocInfo = new CDocInfo();
  1938. // It is the caller's responsiblity to notice that an error occurred
  1939. // in the allocation of the CDocInfo object.
  1940. return _pDocInfo;
  1941. }