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.

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