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.

10611 lines
410 KiB

  1. // HtmParse.cpp : Implementation of CHtmParse
  2. // Copyright (c)1997-1999 Microsoft Corporation, All Rights Reserved
  3. #include "stdafx.h"
  4. #include <designer.h>
  5. #include <time.h> // for random number generation
  6. #include "triedit.h"
  7. #include "HtmParse.h"
  8. #include "table.h"
  9. #include "lexer.h"
  10. #include "guids.h"
  11. #include "util.h"
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CTriEditParse
  14. #undef ASSERT
  15. #define ASSERT(b) _ASSERTE(b)
  16. #ifdef NEEDED
  17. inline int
  18. indexPrevtokTagStart(int index, TOKSTRUCT *pTokArray)
  19. {
  20. while ( (index >= 0)
  21. && (pTokArray[index].token.tokClass != tokTag)
  22. && (pTokArray[index].token.tok != TokTag_START)
  23. )
  24. {
  25. index--;
  26. }
  27. return(index);
  28. }
  29. inline int
  30. indexPrevTokElem(int index, TOKSTRUCT *pTokArray)
  31. {
  32. while ( (index >= 0)
  33. && (pTokArray[index].token.tokClass != tokElem)
  34. )
  35. {
  36. index--;
  37. }
  38. return(index);
  39. }
  40. #endif //NEEDED
  41. BOOL
  42. FIsWhiteSpaceToken(WCHAR *pwOld, int indexStart, int indexEnd)
  43. {
  44. BOOL fWhiteSpace = TRUE;
  45. int index;
  46. for (index = indexStart; index < indexEnd; index++)
  47. {
  48. if ( pwOld[index] != ' '
  49. && pwOld[index] != '\t'
  50. && pwOld[index] != '\r'
  51. && pwOld[index] != '\n'
  52. )
  53. {
  54. fWhiteSpace = FALSE;
  55. break;
  56. }
  57. }
  58. return (fWhiteSpace);
  59. } /* FIsWhiteSpaceToken() */
  60. inline void GlobalUnlockFreeNull(HGLOBAL *phg)
  61. {
  62. GlobalUnlock(*phg); // do we need to check if this was already Unlocked?
  63. GlobalFree(*phg);
  64. *phg = NULL;
  65. }
  66. BOOL
  67. FIsAbsURL(LPOLESTR pstr)
  68. {
  69. LPCWSTR szHttp[] = {L"http:"};
  70. LPCWSTR szFile[] = {L"file:"};
  71. BOOL fRet = FALSE;
  72. if (pstr == NULL)
  73. goto LRet;
  74. if ( 0 == _wcsnicmp(szHttp[0], pstr, wcslen(szHttp[0]))
  75. || 0 == _wcsnicmp(szFile[0], pstr, wcslen(szFile[0]))
  76. )
  77. {
  78. fRet = TRUE;
  79. goto LRet;
  80. }
  81. LRet:
  82. return(fRet);
  83. }
  84. BOOL
  85. FURLNeedSpecialHandling(TOKSTRUCT *pTokArray, int iArray, LPWSTR pwOld, int cMaxToken, int *pichURL, int *pcchURL)
  86. {
  87. int index = iArray+1;
  88. int iHref = -1;
  89. int iURL = -1;
  90. BOOL fRet = FALSE;
  91. BOOL fCodeBase = FALSE;
  92. while ( index < cMaxToken
  93. && pTokArray[index].token.tok != TokTag_CLOSE
  94. && pTokArray[index].token.tokClass != tokTag
  95. ) // look for TokAttrib_HREF
  96. {
  97. if ( iHref == -1
  98. && ( pTokArray[index].token.tok == TokAttrib_HREF
  99. || pTokArray[index].token.tok == TokAttrib_SRC
  100. || pTokArray[index].token.tok == TokAttrib_CODEBASE
  101. )
  102. && pTokArray[index].token.tokClass == tokAttr
  103. )
  104. {
  105. iHref = index;
  106. // special case - if we have CODEBASE attribute, we always want special processing
  107. if (pTokArray[index].token.tok == TokAttrib_CODEBASE)
  108. fCodeBase = TRUE;
  109. }
  110. if ( iHref != -1
  111. && pTokArray[index].token.tok == 0
  112. && (pTokArray[index].token.tokClass == tokString || pTokArray[index].token.tokClass == tokValue)
  113. )
  114. {
  115. iURL = index;
  116. break;
  117. }
  118. index++;
  119. }
  120. if (iURL != -1) // its set properly
  121. {
  122. int cchURL;
  123. WCHAR *pszURL;
  124. BOOL fQuote = (pwOld[pTokArray[iURL].token.ibTokMin] == '"');
  125. cchURL = (fQuote)
  126. ? pTokArray[iURL].token.ibTokMac-pTokArray[iURL].token.ibTokMin-2
  127. : pTokArray[iURL].token.ibTokMac-pTokArray[iURL].token.ibTokMin;
  128. *pichURL = (fQuote)
  129. ? pTokArray[iURL].token.ibTokMin+1
  130. : pTokArray[iURL].token.ibTokMin;
  131. // special case - if the quoted value happens to be a serverside script,
  132. // we can ignore it here and decalre that we don't need to do any special
  133. // processing.
  134. if ( ((pTokArray[iURL].token.ibTokMac-pTokArray[iURL].token.ibTokMin) == 1)
  135. || (cchURL < 0)
  136. )
  137. {
  138. *pcchURL = 0;
  139. goto LRet;
  140. }
  141. *pcchURL = cchURL;
  142. // special case - if we have CODEBASE attribute, we always want special processing
  143. // we don't need to see if its URL is absolute or not...
  144. if (fCodeBase)
  145. {
  146. fRet = TRUE;
  147. goto LRet;
  148. }
  149. pszURL = new WCHAR [cchURL+1];
  150. ASSERT(pszURL != NULL);
  151. memcpy( (BYTE *)pszURL,
  152. (BYTE *)&pwOld[pTokArray[iURL].token.ibTokMin + ((fQuote)? 1 : 0)],
  153. (cchURL)*sizeof(WCHAR));
  154. pszURL[cchURL] = '\0';
  155. if (!FIsAbsURL((LPOLESTR)pszURL))
  156. fRet = TRUE;
  157. delete pszURL;
  158. } // if (iURL != -1)
  159. LRet:
  160. return(fRet);
  161. }
  162. // Copied from hu_url.cpp
  163. //-----------------------------------------------------------------------------
  164. // Useful directory separator check
  165. //-----------------------------------------------------------------------------
  166. inline BOOL IsDirSep(CHAR ch)
  167. {
  168. return ('\\' == ch || '/' == ch);
  169. }
  170. inline BOOL IsDirSep(WCHAR ch)
  171. {
  172. return (L'\\' == ch || L'/' == ch);
  173. }
  174. //-----------------------------------------------------------------------------
  175. // UtilConvertToRelativeURL
  176. //
  177. // Returns an item-relative URL.
  178. // The URL is returned identical if
  179. // the projects don't match
  180. // the protocols don't match
  181. //
  182. // Assumes that protocol-less URLs are "http:". Must specify "file:" explicitly
  183. // to play with file URLs.
  184. //-----------------------------------------------------------------------------
  185. static LPOLESTR
  186. SkipServer(LPOLESTR pstr)
  187. {
  188. pstr = wcschr(pstr, L'/');
  189. if (pstr == NULL)
  190. return NULL;
  191. pstr = wcschr(pstr+1, L'/');
  192. if (pstr == NULL)
  193. return NULL;
  194. pstr = wcschr(pstr+1, L'/');
  195. return pstr; // positioned on the slash if there was one.
  196. }
  197. static LPOLESTR
  198. SkipFile(LPOLESTR pstr)
  199. {
  200. LPOLESTR pstrT;
  201. pstrT = wcspbrk(pstr, L":\\/");
  202. if (pstr == NULL || pstrT == NULL)
  203. return pstr;
  204. // Guard against the case "//\\".
  205. if (pstrT == pstr &&
  206. IsDirSep(pstr[0]) &&
  207. IsDirSep(pstr[1]))
  208. {
  209. if (IsDirSep(pstr[2]) && IsDirSep(pstr[3]))
  210. {
  211. pstrT = pstr + 2; // saw a "//\\"
  212. }
  213. else if (pstr[2] != L'\0' && pstr[3] == L':')
  214. {
  215. pstrT = pstr + 3; // saw a "//c:"
  216. }
  217. }
  218. ASSERT(!wcschr(pstrT + 1, ':')); // better not be more colons!
  219. if (*pstrT == ':') // drive letter possibility
  220. {
  221. return pstrT + 1; // point at the character after the colon
  222. }
  223. if (pstrT[0] == pstrT[1]) // double slash?
  224. {
  225. // Skip server part.
  226. pstrT = wcspbrk(pstrT + 2, L"\\/");
  227. if (pstrT == NULL)
  228. return pstr; // malformed!
  229. // Skip share part.
  230. pstrT = wcspbrk(pstrT + 1, L"\\/");
  231. if (pstrT == NULL)
  232. return pstr; // malformed!
  233. return pstrT;
  234. }
  235. return pstr;
  236. }
  237. static LPOLESTR
  238. FindLastSlash(LPOLESTR pstr)
  239. {
  240. LPOLESTR pstrSlash; // '/'
  241. LPOLESTR pstrWhack; // '\'
  242. pstrSlash = wcsrchr(pstr, L'/');
  243. pstrWhack = wcsrchr(pstr, L'\\');
  244. return pstrSlash > pstrWhack
  245. ? pstrSlash
  246. : pstrWhack;
  247. }
  248. HRESULT
  249. UtilConvertToRelativeURL(
  250. LPOLESTR pstrDestURL, // URL to 'relativize'
  251. LPOLESTR pstrDestFolder, // URL to be relative to.
  252. LPOLESTR pstrDestProject, // Project to be relative to.
  253. BSTR * pbstrRelativeURL)
  254. {
  255. HRESULT hr = S_OK;
  256. LPOLESTR pstrFolder;
  257. LPOLESTR pstrURL;
  258. LPOLESTR pchLastSlash;
  259. CComBSTR strWork;
  260. int cch;
  261. int cchFolder;
  262. int i;
  263. int ichLastSlash;
  264. bool fAbsoluteURL = false;
  265. bool fAbsoluteFolder = false;
  266. bool fFileURL = false;
  267. // If there's a ':' in the URL we're relativizing, it's assumed
  268. // to contain a protocol. If the protocol isn't "http:".
  269. if (!FIsAbsURL(pstrDestURL)) // VID6 - bug 22895
  270. goto Copy;
  271. pstrURL = pstrDestURL;
  272. if (wcschr(pstrDestURL, L':'))
  273. {
  274. // Check the protocol against the two we understand. If it is some other thing,
  275. // we punt.
  276. if (wcsncmp(pstrDestURL, L"http:", 5) != 0)
  277. {
  278. if (wcsncmp(pstrDestURL, L"file:", 5) != 0)
  279. goto Copy;
  280. // File URLs are normalized by skipping any '\\server\share' part.
  281. fFileURL = true;
  282. pstrURL = SkipFile(pstrDestURL + 5); // 5 skips the 'file:' prefix
  283. }
  284. else if (pstrDestProject != NULL)
  285. {
  286. // Project-relative URLs had better match the project prefix.
  287. cch = wcslen(pstrDestProject);
  288. if (_wcsnicmp(pstrDestURL, pstrDestProject, cch) != 0)
  289. goto Copy;
  290. // Project-relative URLs are normalized by skipping the project prefix.
  291. pstrURL = pstrDestURL + cch - 1;
  292. ASSERT(*pstrURL == '/');
  293. }
  294. else
  295. {
  296. // Generic 'http:' URLs skip the server part only.
  297. pstrURL = SkipServer(pstrDestURL);
  298. ASSERT(*pstrURL == '/');
  299. }
  300. if (!pstrURL)
  301. goto Copy;
  302. fAbsoluteURL = true;
  303. }
  304. // If the folder contains an 'http:' prefix, then find the server and skip that part.
  305. // otherwise it's assumed the folder is already in a project-relative format.
  306. pstrFolder = pstrDestFolder;
  307. if (NULL == pstrFolder)
  308. goto Copy;
  309. if (wcsncmp(pstrDestFolder, L"file://", 7) == 0)
  310. {
  311. if (!fFileURL)
  312. goto Copy;
  313. pstrFolder = SkipFile(pstrDestFolder + 5);
  314. fAbsoluteFolder = true;
  315. }
  316. else if (wcsncmp(pstrDestFolder, L"http://", 7) == 0)
  317. {
  318. if (pstrDestProject != NULL)
  319. {
  320. // If a project was passed in, make sure the place we're relativizing to has the same path.
  321. // If they don't match, we're in trouble.
  322. cch = wcslen(pstrDestProject);
  323. if (_wcsnicmp(pstrDestFolder, pstrDestProject, cch) != 0)
  324. goto Copy;
  325. pstrFolder = pstrDestFolder + cch - 1;
  326. }
  327. else
  328. {
  329. pstrFolder = SkipServer(pstrDestFolder);
  330. }
  331. ASSERT(pstrFolder);
  332. ASSERT(*pstrFolder == '/');
  333. fAbsoluteFolder = true;
  334. }
  335. // If both the URL and the folder had absolute paths, we need to ensure
  336. // that the servers are the same.
  337. if (fAbsoluteFolder && fAbsoluteURL)
  338. {
  339. if (pstrURL - pstrDestURL != pstrFolder - pstrDestFolder ||
  340. _wcsnicmp(pstrDestURL, pstrDestFolder, SAFE_PTR_DIFF_TO_INT(pstrURL - pstrDestURL)) != 0)
  341. goto Copy;
  342. }
  343. // From now on, ignore the item at the end of pstrFolder
  344. pchLastSlash = FindLastSlash(pstrFolder);
  345. ASSERT(pchLastSlash);
  346. cchFolder = 1 + SAFE_PTR_DIFF_TO_INT(pchLastSlash - pstrFolder);
  347. // Both folder and item are now relative to the server root.
  348. // Locate the last slash in the URL.
  349. pchLastSlash = FindLastSlash(pstrURL);
  350. if (pchLastSlash == NULL)
  351. ichLastSlash = 0;
  352. else
  353. ichLastSlash = 1 + SAFE_PTR_DIFF_TO_INT(pchLastSlash - pstrURL);
  354. // Find any common directories.
  355. cch = min(cchFolder, ichLastSlash);
  356. ichLastSlash = -1;
  357. for (i = 0; i < cch && pstrFolder[i] == pstrURL[i]; ++i)
  358. {
  359. if (IsDirSep(pstrFolder[i]))
  360. ichLastSlash = i;
  361. }
  362. // ichLastSlash should point beyond at last slash of the last common folder.
  363. // For each remaining slash, append a ../ to the path.
  364. for (; i < cchFolder; ++i)
  365. {
  366. if (IsDirSep(pstrFolder[i]))
  367. {
  368. strWork += (fFileURL ? L"..\\" : L"../");
  369. }
  370. }
  371. if (-1 == ichLastSlash)
  372. { // no common parts, append all of the destination
  373. strWork += pstrURL;
  374. }
  375. else
  376. { // append only the non-match part of the destination
  377. strWork += (pstrURL + ichLastSlash + 1);
  378. }
  379. Cleanup:
  380. *pbstrRelativeURL = strWork.Copy();
  381. if (!*pbstrRelativeURL && ::wcslen(strWork) > 0)
  382. hr = E_OUTOFMEMORY;
  383. return hr;
  384. Copy:
  385. strWork = pstrDestURL;
  386. goto Cleanup;
  387. }
  388. long CTriEditParse::m_bInit = 0;
  389. CTriEditParse::CTriEditParse()
  390. {
  391. m_rgSublang = 0;
  392. m_fHasTitleIn = FALSE;
  393. m_hgPTDTC = NULL;
  394. m_cchPTDTC = 0;
  395. m_ichBeginHeadTagIn = -1;
  396. m_ispInfoBase = 0;
  397. if(0 == m_bInit++)
  398. InitSublanguages();
  399. }
  400. CTriEditParse::~CTriEditParse()
  401. {
  402. // save last variant as default if it's not ASP
  403. if (NULL != m_rgSublang)
  404. {
  405. for( int i= 0; NULL != m_rgSublang[i].szSubLang; i++)
  406. {
  407. delete [] (LPTSTR)(m_rgSublang[i].szSubLang);
  408. }
  409. delete [] m_rgSublang;
  410. }
  411. ASSERT(0 != m_bInit);
  412. if(0 == --m_bInit)
  413. {
  414. ATLTRACE(_T("Releasing tables\n"));
  415. // delete dynamically allocated tables
  416. for (int i = 0; NULL != g_arpTables[i]; i++)
  417. delete g_arpTables[i];
  418. delete g_pTabDefault;
  419. m_bInit = 0;
  420. }
  421. }
  422. // copied from CColorHtml::NextToken
  423. STDMETHODIMP CTriEditParse::NextToken
  424. (
  425. LPCWSTR pszText,
  426. UINT cbText,
  427. UINT* pcbCur,
  428. DWORD* pLXS,
  429. TXTB* pToken
  430. )
  431. {
  432. ASSERT(pszText != NULL);
  433. ASSERT(pcbCur != NULL);
  434. ASSERT(pLXS != NULL);
  435. ASSERT(pToken != NULL);
  436. USES_CONVERSION;
  437. if(pszText == NULL || pcbCur == NULL || pLXS == NULL || pToken == NULL)
  438. return E_INVALIDARG;
  439. if(0 == cbText)
  440. return S_FALSE;
  441. SetTable(*pLXS); // set g_pTable according to state
  442. #ifdef _UNICODE
  443. *pcbCur = GetToken(pszText, cbText, *pcbCur, pLXS, *pToken);
  444. #else // _UNICODE
  445. int cch;
  446. LPTSTR pszTemp;
  447. // get the converted length
  448. cch = WideCharToMultiByte(CP_ACP, 0, pszText, cbText,
  449. NULL, 0, NULL, NULL);
  450. pszTemp = new char[cch + 1];
  451. ZeroMemory(pszTemp, cch + 1);
  452. // copy the wide char to multibyte
  453. WideCharToMultiByte(CP_ACP, 0, pszText, cbText, pszTemp, cch,
  454. NULL, NULL);
  455. *pcbCur = GetToken(pszTemp, cch, *pcbCur, pLXS, *pToken);
  456. delete [] pszTemp;
  457. #endif // _UNICODE
  458. return (*pcbCur < cbText) ? NOERROR : S_FALSE;
  459. }
  460. // set g_pTable according to state
  461. void CTriEditParse::SetTable(DWORD lxs)
  462. {
  463. ASSERT(SubLangIndexFromLxs(lxs) < sizeof g_arpTables/sizeof g_arpTables[0]);
  464. g_pTable = g_arpTables[SubLangIndexFromLxs(lxs)];
  465. ASSERT(g_pTable != NULL);
  466. }
  467. void CTriEditParse::InitSublanguages()
  468. {
  469. #define cHTML2Len 2048
  470. g_pTabDefault = new CStaticTableSet(ALL, IDS_HTML);
  471. int cl = CV_FIXED;
  472. CTableSet * rgpts[CV_MAX +1];
  473. memset(rgpts, 0, sizeof rgpts);
  474. CTableSet* ptabset; // current
  475. CTableSet* ptabBackup; // backup default
  476. memset(g_arpTables, 0, sizeof g_arpTables);
  477. m_rgSublang = new SUBLANG[cl+2]; // 0th + list + empty terminator
  478. ASSERT(NULL != m_rgSublang);
  479. if (NULL != m_rgSublang)
  480. memset(m_rgSublang, 0, (cl+2)*sizeof SUBLANG);
  481. UINT iLang = 1;
  482. TCHAR strDefault[cHTML2Len];
  483. // Microsoft browsers
  484. // Internet Explorer 3
  485. ptabset = MakeTableSet(rgpts, IEXP3, IDS_IEXP3);
  486. SetLanguage( strDefault, m_rgSublang, ptabset, iLang, IDR_HTML, CLSID_NULL );
  487. // Set backup default as IE 3
  488. ptabBackup = ptabset;
  489. if (lstrlen(strDefault) == 0)
  490. {
  491. ASSERT(lstrlen(ptabBackup->Name()) != 0);
  492. lstrcpy(strDefault, ptabBackup->Name());
  493. }
  494. // User's additions
  495. for (int n = 0; rgpts[n]; n++)
  496. {
  497. ptabset = rgpts[n];
  498. SetLanguage( strDefault, m_rgSublang, ptabset, iLang, 0, CLSID_NULL );
  499. ptabBackup = ptabset;
  500. }
  501. // HTML 2.0 base (if not overridden)
  502. {
  503. TCHAR strHTML2[cHTML2Len];
  504. ::LoadString( _Module.GetModuleInstance(),
  505. IDS_RFC1866,
  506. strHTML2,
  507. cHTML2Len
  508. );
  509. if (!FindTable(rgpts,strHTML2))
  510. {
  511. ptabset = new CStaticTableSet(HTML2, IDS_RFC1866);
  512. SetLanguage( strDefault, m_rgSublang, ptabset, iLang, 0, CLSID_NULL);
  513. }
  514. }
  515. if (NULL == g_arpTables[0])
  516. {
  517. ASSERT(NULL != ptabBackup); // error: didn't get a default!
  518. //Find the backup in the tables
  519. int i;
  520. for (i = 1; NULL != g_arpTables[i]; i++)
  521. {
  522. if (g_arpTables[i] == ptabBackup)
  523. break;
  524. }
  525. ASSERT(NULL != g_arpTables[i]); // must be in table
  526. // Set default
  527. g_arpTables[0] = g_pTable = g_arpTables[i];
  528. m_rgSublang[0] = m_rgSublang[i];
  529. m_rgSublang[0].lxsInitial = LxsFromSubLangIndex(0);
  530. // Move the rest down to fill the hole
  531. for (; g_arpTables[i]; i++)
  532. {
  533. g_arpTables[i] = g_arpTables[i+1];
  534. m_rgSublang[i] = m_rgSublang[i+1];
  535. m_rgSublang[i].lxsInitial = LxsFromSubLangIndex(i);
  536. }
  537. }
  538. ASSERT(NULL != g_arpTables[0]);
  539. // set global ASP sublang ptr
  540. // start at 1, since the default is at 0, and should never be ASP
  541. for (int i = 1; NULL != m_rgSublang[i].szSubLang; i++)
  542. {
  543. if (m_rgSublang[i].nIdTemplate == IDR_ASP)
  544. {
  545. g_psublangASP = &m_rgSublang[i];
  546. break;
  547. }
  548. }
  549. }
  550. // Reallocs are expensive, so when we Realloc, should we add some more pad so that
  551. // we wont have to call Realloc very often?
  552. HRESULT
  553. ReallocBuffer(HGLOBAL *phg, DWORD cbNew, UINT uFlags)
  554. {
  555. HRESULT hr = S_OK;
  556. HGLOBAL hg;
  557. ASSERT(*phg != NULL);
  558. ASSERT(cbNew != 0); // will we ever get this?
  559. GlobalUnlock(*phg);
  560. hg = *phg;
  561. #pragma prefast(suppress:308, "noise")
  562. *phg = GlobalReAlloc(*phg, cbNew, uFlags);
  563. if (*phg == NULL)
  564. {
  565. #ifdef DEBUG
  566. hr = GetLastError();
  567. #endif // DEBUG
  568. GlobalFree(hg);
  569. hr = E_OUTOFMEMORY;
  570. }
  571. return(hr);
  572. } /* ReallocBuffer() */
  573. HRESULT
  574. ReallocIfNeeded(HGLOBAL *phg, WCHAR **ppwNew, UINT cbNeed, UINT uFlags)
  575. {
  576. HRESULT hr = S_OK;
  577. ASSERT(*phg != NULL);
  578. if (GlobalSize(*phg) < cbNeed)
  579. {
  580. hr = ReallocBuffer(phg, cbNeed, uFlags);
  581. if (hr == E_OUTOFMEMORY)
  582. goto LRet;
  583. ASSERT(*phg != NULL);
  584. *ppwNew = (WCHAR *)GlobalLock(*phg);
  585. }
  586. LRet:
  587. return(hr);
  588. } /* ReallocIfNeeded() */
  589. void
  590. CTriEditParse::fnRestoreSSS(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  591. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  592. INT *pcSSSOut, UINT *pichNewCur, UINT *pichBeginCopy,
  593. DWORD /*dwFlags*/)
  594. {
  595. // Server Side Script case
  596. // This occurs inside <% %>. we assume simple SSS
  597. // remove the added <SCRIPT LANGUAGE=SERVERASP> & </SCRIPT> text around it
  598. UINT iArray = *piArrayStart;
  599. INT i;
  600. UINT ichScrStart, ichScrEnd, indexScrStart, indexScrEnd;
  601. UINT ichSSSStart, ichSSSEnd;
  602. UINT ichNewCur = *pichNewCur;
  603. UINT ichBeginCopy = *pichBeginCopy;
  604. INT cSSSOut = *pcSSSOut;
  605. LPCWSTR szSSS[] = {L"SERVERASP", L"\"SERVERASP\""};
  606. LPCWSTR szSSSSp[] = {L"SERVERASPSP"};
  607. BOOL fSpecialSSS = FALSE;
  608. LPWSTR pwNew = *ppwNew;
  609. INT iMatchMax;
  610. UINT cbNeed;
  611. UINT ichScrWspBegin, ichScrWspEnd, ichSp;
  612. ASSERT(cSSSOut >= 0); // make sure that this was initilized
  613. if (cSSSOut == 0)
  614. goto LRetOnly;
  615. //{TokTag_START, TokElem_SCRIPT, TokTag_CLOSE, TokElem_SCRIPT, fnRestoreSSS}
  616. ichScrStart = ichScrEnd = indexScrStart = indexScrEnd = ichSSSStart = ichSSSEnd = 0;
  617. ichScrWspBegin = ichScrWspEnd = 0;
  618. while (cSSSOut > 0)
  619. {
  620. // start at iArray of pTokArray and look for TokElem_SCRIPT
  621. //while (pTokArray[iArray].token.tok != ft.tokBegin2)
  622. // iArray++;
  623. ASSERT(iArray < ptep->m_cMaxToken);
  624. if (pTokArray[iArray].token.tok != TokElem_SCRIPT)
  625. goto LRet;
  626. // Here's the deal - we have to ignore all SSS that appear
  627. // as values inside client scripts or insize objects/dtcs
  628. // so, we need to skip this TokElem_SCRIPT tag if we found '</' before TokElem_SCRIPT
  629. if ( pTokArray[iArray].token.tok == TokElem_SCRIPT
  630. && pTokArray[iArray-1].token.tok != TokTag_START
  631. )
  632. {
  633. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  634. iArray++; // so that we don't come here again with the same iArray
  635. ptep->m_fDontDeccItem = TRUE; // we can do things differently here next time around
  636. ptep->m_cSSSOut++;
  637. goto LRet;
  638. }
  639. //ASSERT(pTokArray[iArray].token.tok == TokElem_SCRIPT);
  640. i = iArray; // the position at which we found ft.tokBegin2
  641. // look for the special LANGUAGE arrtibute that we had set.
  642. // if that doesn't exist, this is not the SSS we want
  643. // we don't really need to look for this till ptep->m_cMaxToken,
  644. // but this will cover boundary cases
  645. iMatchMax = (pTokArray[iArray].iNextprev == -1)? ptep->m_cMaxToken : pTokArray[iArray].iNextprev;
  646. while (i < iMatchMax)
  647. {
  648. if (pTokArray[i].token.tok == TokAttrib_LANGUAGE)
  649. {
  650. ASSERT(pTokArray[i].token.tokClass == tokAttr);
  651. break;
  652. }
  653. i++;
  654. }
  655. if (i < iMatchMax)
  656. {
  657. // make sure that the next one is tokOpEqual
  658. ASSERT(pTokArray[i+1].token.tokClass == tokOp);
  659. //ASSERT(((pwOld+pTokArray[i+1].token.ibTokMin)*sizeof(WCHAR)) == '=');
  660. // get the next value and compare it with szSSS[]
  661. // note that this may also match with szSSSSp[]
  662. if ( 0 != _wcsnicmp(szSSS[0], &pwOld[pTokArray[i+2].token.ibTokMin], wcslen(szSSS[0]))
  663. && 0 != _wcsnicmp(szSSS[1], &pwOld[pTokArray[i+2].token.ibTokMin], wcslen(szSSS[1]))
  664. )
  665. {
  666. iArray = i;
  667. goto LNextSSS; // not this one
  668. }
  669. }
  670. else // error case
  671. {
  672. iArray++;
  673. goto LRet;
  674. }
  675. // compare with szSSSSp[] and set fSpecialSSS
  676. if (0 == _wcsnicmp(szSSSSp[0], &pwOld[pTokArray[i+2].token.ibTokMin], wcslen(szSSSSp[0])))
  677. fSpecialSSS = TRUE;
  678. i = iArray; // we are OK, so lets look for < before SCRIPT tag
  679. while (i >= 0)
  680. {
  681. // do we need to do anything else here?
  682. if (pTokArray[i].token.tok == ft.tokBegin)
  683. {
  684. ASSERT(pTokArray[i].token.tok == TokTag_START);
  685. ASSERT(pTokArray[i].token.tokClass == tokTag);
  686. break;
  687. }
  688. i--;
  689. }
  690. if (i >= 0) // found TokTag_START token
  691. {
  692. ichScrStart = pTokArray[i].token.ibTokMin;
  693. indexScrStart = i;
  694. }
  695. else // error case
  696. {
  697. // we found SCRIPT, but didn't find < of <SCRIPT
  698. // we can't process this SSS, so quit
  699. goto LRet;
  700. }
  701. // now lets look for <! that would be after <SCRIPT LANGUAGE = SERVERASP>
  702. while (i < (int)ptep->m_cMaxToken)
  703. {
  704. if ( pTokArray[i].token.tok == TokTag_CLOSE
  705. && pTokArray[i].token.tokClass == tokTag
  706. )
  707. ichScrWspBegin = pTokArray[i].token.ibTokMac; // if we had saved white space, it would begin here
  708. if (pTokArray[i].token.tok == TokTag_BANG)
  709. {
  710. ASSERT(pTokArray[i].token.tokClass == tokTag);
  711. ASSERT(pTokArray[i+1].token.tokClass == tokComment);
  712. //we can assert for next 2 chars as --
  713. ichSSSStart = pTokArray[i].token.ibTokMin;
  714. break;
  715. }
  716. i++;
  717. }
  718. if (i >= (int)ptep->m_cMaxToken) // didn't find <!
  719. {
  720. goto LRet;
  721. }
  722. // look for ending -->
  723. while (i < (int)ptep->m_cMaxToken)
  724. {
  725. if (pTokArray[i].token.tok == TokTag_CLOSE && pTokArray[i].token.tokClass == tokTag)
  726. {
  727. //we can assert for next 2 chars as --
  728. ASSERT(*(pwOld+pTokArray[i].token.ibTokMin-1) == '-');
  729. ASSERT(*(pwOld+pTokArray[i].token.ibTokMin-2) == '-');
  730. ichSSSEnd = pTokArray[i].token.ibTokMac;
  731. break;
  732. }
  733. i++;
  734. }
  735. if (i >= (int)ptep->m_cMaxToken) // didn't find >
  736. {
  737. goto LRet;
  738. }
  739. // now look for ft.tokEnd2 & ft.tokEnd (i.e. TokElem_SCRIPT & >)
  740. while (pTokArray[i].token.tok != ft.tokEnd2)
  741. {
  742. if (pTokArray[i].token.tok == TokTag_END && pTokArray[i].token.tokClass == tokTag)
  743. ichScrWspEnd = pTokArray[i].token.ibTokMin; // past the last white space
  744. i++;
  745. }
  746. ASSERT(i < (int)ptep->m_cMaxToken);
  747. ASSERT(pTokArray[i].token.tok == TokElem_SCRIPT);
  748. ASSERT(pTokArray[i].token.tokClass == tokElem);
  749. // go forward and look for > of SCRIPT>
  750. // as additional check, we can also check that previous token is </
  751. while (i < (int)ptep->m_cMaxToken)
  752. {
  753. if (pTokArray[i].token.tok == ft.tokEnd)
  754. {
  755. ASSERT(pTokArray[i].token.tok == TokTag_CLOSE);
  756. ASSERT(pTokArray[i].token.tokClass == tokTag);
  757. break;
  758. }
  759. i++;
  760. }
  761. if (i < (int)ptep->m_cMaxToken) // found TokTag_CLOSE
  762. {
  763. ichScrEnd = pTokArray[i].token.ibTokMac;
  764. indexScrEnd = i;
  765. }
  766. else // error case
  767. {
  768. // we found SCRIPT, but didn't find > of SCRIPT>
  769. // we can't process this SSS, so quit
  770. goto LRet;
  771. }
  772. iArray = i+1; // set it for next run
  773. cbNeed = (ichNewCur+(ichScrStart-ichBeginCopy)+(ichSSSEnd-ichSSSStart))*sizeof(WCHAR)+cbBufPadding;
  774. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  775. goto LRet;
  776. // do the Blts
  777. // ichBeginCopy is a position in pwOld and
  778. // ichNewCur is a position in pwNew
  779. // copy from ichBeginCopy to begining of SSS
  780. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  781. (BYTE *)(&pwOld[ichBeginCopy]),
  782. (ichScrStart-ichBeginCopy)*sizeof(WCHAR));
  783. ichNewCur += (ichScrStart-ichBeginCopy);
  784. ichBeginCopy = ichScrEnd; // make it ready for next copy
  785. if (fSpecialSSS)
  786. {
  787. // in special case, we need to make space for the <%@...%> at the begining of pwNew
  788. // so, we move all the above stuff (ichNewCur chars) by (ichSSSEnd-ichSSSStart-3).
  789. memmove((BYTE *)(&pwNew[ichSSSEnd-ichSSSStart-3]),
  790. (BYTE *)pwNew,
  791. (ichNewCur)*sizeof(WCHAR)
  792. );
  793. // we now copy <%@...%> at the begining of the doc instead of at ichNewCur
  794. // now skip <SCRIPT LANGUAGE=SERVERASP> & only copy <% ....%>
  795. // note that we have to get rid of 3 extra chars we had added when we converted going in Trident
  796. memcpy( (BYTE *)(pwNew),
  797. (BYTE *)&pwOld[ichSSSStart+2],/*get rid of 2 extra chars we had added at the begining*/
  798. (ichSSSEnd-ichSSSStart-3)*sizeof(WCHAR));
  799. pwNew[0] = '<'; pwNew[1] = '%'; // note that we have moved the SSS to the begining of the doc
  800. ichNewCur += ichSSSEnd-ichSSSStart-3; // here we got rid of 1 extra char that was added
  801. pwNew[(ichSSSEnd-ichSSSStart-3)-2] = '%';
  802. pwNew[(ichSSSEnd-ichSSSStart-3)-1] = '>';
  803. // change <!-- to <% and --> to %>
  804. }
  805. else
  806. {
  807. // in pwNew get rid of white space characters from ichNewCur backwards
  808. ichSp = ichNewCur-1;
  809. while ( ( pwNew[ichSp] == ' ' || pwNew[ichSp] == '\r'
  810. || pwNew[ichSp] == '\n' || pwNew[ichSp] == '\t'
  811. )
  812. )
  813. {
  814. ichSp--;
  815. }
  816. ichSp++; // compensate for the last decrement, ichSp points to the 1st white-space character
  817. ichNewCur = ichSp;
  818. // copy pre-script white space
  819. if (ichScrWspBegin > 0 && ichSSSStart > ichScrWspBegin) // has been set
  820. {
  821. memcpy( (BYTE *)&pwNew[ichNewCur],
  822. (BYTE *)&pwOld[ichScrWspBegin],
  823. (ichSSSStart-ichScrWspBegin)*sizeof(WCHAR));
  824. ichNewCur += ichSSSStart-ichScrWspBegin;
  825. }
  826. // now skip <SCRIPT LANGUAGE=SERVERASP> & only copy <% ....%>
  827. // note that we have to get rid of 3 extra chars we had added when we converted going in Trident
  828. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  829. (BYTE *)(&pwOld[ichSSSStart+2]),/*get rid of 2 extra chars we had added at the begining*/
  830. (ichSSSEnd-ichSSSStart-3)*sizeof(WCHAR));
  831. pwNew[ichNewCur] = '<';
  832. pwNew[ichNewCur+1] = '%';
  833. ichNewCur += ichSSSEnd-ichSSSStart-3; // here we got rid of 1 extra char that was added
  834. pwNew[ichNewCur-2] = '%';
  835. pwNew[ichNewCur-1] = '>';
  836. // copy post-script white space
  837. if (ichScrWspEnd > 0 && ichScrWspEnd > ichSSSEnd) // has been set
  838. {
  839. memcpy( (BYTE *)&pwNew[ichNewCur],
  840. (BYTE *)&pwOld[ichSSSEnd],
  841. (ichScrWspEnd-ichSSSEnd)*sizeof(WCHAR));
  842. ichNewCur += ichScrWspEnd-ichSSSEnd;
  843. }
  844. // increment iArray & ichBeginCopy till the next non-whitespace token
  845. while (iArray < (int)ptep->m_cMaxToken)
  846. {
  847. UINT ich;
  848. BOOL fNonWspToken = FALSE; // assume the next token to be whitespace
  849. // scan entire token and see if it has all white-space characters
  850. for (ich = pTokArray[iArray].token.ibTokMin; ich < pTokArray[iArray].token.ibTokMac; ich++)
  851. {
  852. if ( pwOld[ich] != ' ' && pwOld[ich] != '\t'
  853. && pwOld[ich] != '\r' && pwOld[ich] != '\n'
  854. )
  855. {
  856. fNonWspToken = TRUE;
  857. break;
  858. }
  859. }
  860. if (fNonWspToken)
  861. {
  862. ichBeginCopy = pTokArray[iArray].token.ibTokMin;
  863. break;
  864. }
  865. iArray++;
  866. }
  867. }
  868. cSSSOut--;
  869. } // while (cSSSOut > 0)
  870. LNextSSS:
  871. LRet:
  872. *pcchNew = ichNewCur;
  873. *ppwNew = pwNew;
  874. *pichNewCur = ichNewCur;
  875. *pichBeginCopy = ichBeginCopy;
  876. *piArrayStart = iArray;
  877. LRetOnly:
  878. return;
  879. } /* fnRestoreSSS() */
  880. void
  881. CTriEditParse::fnSaveSSS(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  882. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  883. INT *pcSSSIn, UINT *pichNewCur, UINT *pichBeginCopy,
  884. DWORD /*dwFlags*/)
  885. {
  886. // Server Side Script case
  887. // This occur inside <% %>. We assume simple SSS
  888. // add <SCRIPT LANGUAGE=SERVERASP> & </SCRIPT> around it
  889. // tag used for saving the SSS.
  890. /* 2 spaces at the end of 1st element are important */
  891. LPCWSTR rgSSSTags[] =
  892. {
  893. L"\r\n<SCRIPT LANGUAGE=\"SERVERASP\">",
  894. L"\r\n<SCRIPT LANGUAGE=\"SERVERASPSP\">",
  895. L"</SCRIPT>\r\n"
  896. };
  897. UINT iArray = *piArrayStart;
  898. UINT i;
  899. UINT ichSSSStart, ichSSSEnd, indexSSSStart, indexSSSEnd;
  900. HGLOBAL hgSSS = NULL;
  901. WCHAR *pSSS;
  902. UINT ichNewCur = *pichNewCur;
  903. UINT ichBeginCopy = *pichBeginCopy;
  904. INT cSSSIn = *pcSSSIn;
  905. LPWSTR pwNew = *ppwNew;
  906. int indexSSSTag;
  907. UINT cbNeed;
  908. UINT ichSp;
  909. ASSERT(cSSSIn >= 0); // make sure that this was initilized
  910. if (cSSSIn == 0)
  911. goto LRetOnly;
  912. ichSSSStart = ichSSSEnd = indexSSSStart = indexSSSEnd = 0;
  913. while (cSSSIn > 0)
  914. {
  915. INT cbMin = 0x4fff; // init & increment size of hgSSS
  916. INT cchCurSSS = 0;
  917. int index;
  918. // handle special case here - if the script is inside <xmp> tag, we shouldn't convert the script
  919. // NOTE that we are only handling <xmp> <%...%> </xmp> case here
  920. // we don't have to worry about nested xmp's because its not valid html.
  921. // such invalid cases are <xmp>...<xmp> </xmp> <% %> </xmp> OR <xmp>...<xmp> <% %> </xmp> </xmp>
  922. // handle TokElem_PLAINTEXT as well
  923. index = iArray;
  924. while (index >= 0)
  925. {
  926. if ( (pTokArray[index].token.tok == TokElem_XMP || pTokArray[index].token.tok == TokElem_PLAINTEXT)
  927. && pTokArray[index].token.tokClass == tokElem
  928. && pTokArray[index].iNextprev > iArray
  929. )
  930. {
  931. iArray++;
  932. goto LRet;
  933. }
  934. index--;
  935. }
  936. // start at the begining of pTokArray and look for first <%
  937. ASSERT(ft.tokBegin2 == -1);
  938. ASSERT(ft.tokEnd2 == -1);
  939. // Here both supporting tokens are -1, so we simply look for main tokens.
  940. i = iArray;
  941. while (i < ptep->m_cMaxToken)
  942. {
  943. // do we need to do anything else here?
  944. if (pTokArray[i].token.tok == ft.tokBegin)
  945. {
  946. ASSERT(pTokArray[i].token.tok == TokTag_SSSOPEN);
  947. ASSERT(pTokArray[i].token.tokClass == tokSSS);
  948. break;
  949. }
  950. i++;
  951. }
  952. if (i < ptep->m_cMaxToken) // found TokTag_SSSOPEN token
  953. {
  954. ichSSSStart = pTokArray[i].token.ibTokMin;
  955. indexSSSStart = i;
  956. }
  957. // look for ft.tokEnd
  958. if (pTokArray[i].iNextprev != -1)
  959. {
  960. // NOTE that this will give us topmost nested level of the SSS
  961. indexSSSEnd = pTokArray[i].iNextprev;
  962. ichSSSEnd = pTokArray[indexSSSEnd].token.ibTokMac;
  963. ASSERT(indexSSSEnd < ptep->m_cMaxToken);
  964. // this will be a wierd case where the iNextprev is incorrectly pointing to another token
  965. // but lets handle that case.
  966. if (pTokArray[indexSSSEnd].token.tok != TokTag_SSSCLOSE)
  967. goto LFindSSSClose; // find it by looking at each token
  968. }
  969. else // actually, this is an error case, but rather than just giving assert, try to find the token
  970. {
  971. LFindSSSClose:
  972. while (i < ptep->m_cMaxToken)
  973. {
  974. if (pTokArray[i].token.tok == ft.tokEnd)
  975. {
  976. ASSERT(pTokArray[i].token.tok == TokTag_SSSCLOSE);
  977. ASSERT(pTokArray[i].token.tokClass == tokSSS);
  978. break;
  979. }
  980. i++;
  981. }
  982. if (i < ptep->m_cMaxToken) // found TokTag_SSSCLOSE token
  983. {
  984. ichSSSEnd = pTokArray[i].token.ibTokMac;
  985. indexSSSEnd = i;
  986. }
  987. else // error case
  988. {
  989. goto LRet; // didn't find %>, but exhausted the token array
  990. }
  991. }
  992. iArray = indexSSSEnd; // set for for next SSS
  993. // now insert text from rgSSSTags[] into the source
  994. // 0. Allocate a local buffer
  995. cbNeed = wcslen(rgSSSTags[0]) + wcslen(rgSSSTags[0]) + wcslen(rgSSSTags[2])
  996. + (ichSSSEnd-ichSSSStart) + cbMin;
  997. hgSSS = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cbNeed*sizeof(WCHAR));
  998. if (hgSSS == NULL)
  999. goto LErrorRet;
  1000. pSSS = (WCHAR *) GlobalLock(hgSSS);
  1001. ASSERT(pSSS != NULL);
  1002. // NOTE - This flag would have been set to TRUE only if,
  1003. // we have found <%@ as the 1st SSS in the document
  1004. indexSSSTag = 0;
  1005. if (ptep->m_fSpecialSSS)
  1006. {
  1007. ptep->m_fSpecialSSS = FALSE;
  1008. indexSSSTag = 1;
  1009. }
  1010. //-------------------------------------------------------------------------------
  1011. // ASSUMPTION - The big assumption we are making is that IE5 doesn't change
  1012. // anything inside the client sctipt. So far we have seen that.
  1013. // In the worst case, if they start mucking with the contents of client script,
  1014. // we will loose the spacing, but there will be NO DATA LOSS.
  1015. //
  1016. // Based on this assumption, we simply save the pre-post script spacing as is
  1017. // and expect to restore it on the way out.
  1018. //-------------------------------------------------------------------------------
  1019. // 1. Insert <SCRIPT> from rgSSSTags[indexSSSTag]
  1020. wcscpy(&pSSS[cchCurSSS], rgSSSTags[indexSSSTag]);
  1021. cchCurSSS += wcslen(rgSSSTags[indexSSSTag]);
  1022. // insert the white space as it occurs in pwOld, ichSSSStart is '<' of '<%', walk backwards
  1023. ichSp = ichSSSStart-1;
  1024. while ( ( pwOld[ichSp] == ' ' || pwOld[ichSp] == '\r'
  1025. || pwOld[ichSp] == '\n' || pwOld[ichSp] == '\t'
  1026. )
  1027. )
  1028. {
  1029. ichSp--;
  1030. }
  1031. ichSp++; // compensate for the last decrement
  1032. if ((int)(ichSSSStart-ichSp) > 0)
  1033. {
  1034. wcsncpy(&pSSS[cchCurSSS], &pwOld[ichSp], ichSSSStart-ichSp);
  1035. cchCurSSS += ichSSSStart-ichSp;
  1036. }
  1037. // now add TokTag_BANG '<!'
  1038. pSSS[cchCurSSS++] = '<';
  1039. pSSS[cchCurSSS++] = '!';
  1040. // 2. copy the script from pwOld
  1041. wcsncpy(&pSSS[cchCurSSS], &pwOld[ichSSSStart], ichSSSEnd-ichSSSStart);
  1042. pSSS[cchCurSSS] = '-';
  1043. pSSS[cchCurSSS+1] = '-';
  1044. cchCurSSS += (ichSSSEnd-ichSSSStart);
  1045. pSSS[cchCurSSS] = pSSS[cchCurSSS-1]; //note : -1 is '>'
  1046. pSSS[cchCurSSS-2] = '-';
  1047. pSSS[cchCurSSS-1] = '-';
  1048. cchCurSSS++; // we are adding one extra character
  1049. // insert the white space as it occurs in pwOld, ichSSSEnd is past '%>', walk forward
  1050. ichSp = ichSSSEnd;
  1051. while ( (ichSp < pTokArray[ptep->m_cMaxToken-1].token.ibTokMac-1)
  1052. && ( pwOld[ichSp] == ' ' || pwOld[ichSp] == '\r'
  1053. || pwOld[ichSp] == '\n' || pwOld[ichSp] == '\t'
  1054. )
  1055. )
  1056. {
  1057. ichSp++;
  1058. }
  1059. if ((int)(ichSp-ichSSSEnd) > 0)
  1060. {
  1061. wcsncpy(&pSSS[cchCurSSS], &pwOld[ichSSSEnd], ichSp-ichSSSEnd);
  1062. cchCurSSS += ichSp-ichSSSEnd;
  1063. }
  1064. // 3. Insert </SCRIPT> from rgSSSTags[2]
  1065. wcscpy(&pSSS[cchCurSSS], rgSSSTags[2]);
  1066. cchCurSSS += wcslen(rgSSSTags[2]);
  1067. /* REALLOCATE pwNew IF NEEDED here, use cache value for GlobalSize(*phgNew) and don't forget to update it too */
  1068. cbNeed = (ichNewCur+(ichSSSStart-ichBeginCopy)+(cchCurSSS))*sizeof(WCHAR)+cbBufPadding;
  1069. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  1070. goto LErrorRet;
  1071. // ichBeginCopy is a position in pwOld and
  1072. // ichNewCur is a position in pwNew
  1073. if ((int)(ichSSSStart-ichBeginCopy) >= 0)
  1074. {
  1075. // copy till begining of the <%
  1076. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1077. (BYTE *)(&pwOld[ichBeginCopy]),
  1078. (ichSSSStart-ichBeginCopy)*sizeof(WCHAR));
  1079. ichNewCur += ichSSSStart-ichBeginCopy;
  1080. ichBeginCopy = ichSSSEnd; // set it for next script
  1081. // copy the converted SSS
  1082. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1083. (BYTE *)(pSSS),
  1084. cchCurSSS*sizeof(WCHAR));
  1085. ichNewCur += cchCurSSS;
  1086. }
  1087. if (hgSSS != NULL)
  1088. GlobalUnlockFreeNull(&hgSSS);
  1089. cSSSIn--;
  1090. } // while(cSSSIn > 0)
  1091. LErrorRet:
  1092. if (hgSSS != NULL)
  1093. GlobalUnlockFreeNull(&hgSSS);
  1094. LRet:
  1095. *pcchNew = ichNewCur;
  1096. *ppwNew = pwNew;
  1097. *pichNewCur = ichNewCur;
  1098. *pichBeginCopy = ichBeginCopy;
  1099. *piArrayStart = iArray;
  1100. LRetOnly:
  1101. return;
  1102. } /* fnSaveSSS() */
  1103. void
  1104. CTriEditParse::fnRestoreDTC(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  1105. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  1106. INT *piObj, UINT *pichNewCur, UINT *pichBeginCopy,
  1107. DWORD dwFlags)
  1108. {
  1109. // OBJECTS case - (These were converted from DTCs in modeInput
  1110. // if we get OBJECT, search backwards (carefully) for tokTag/TokTag_START (<) in pTokArray
  1111. // once we find that, remember the ibTokMin for Object conversion
  1112. // look for the /OBJECT (i.e. look for OBJECT and look for previous /) and
  1113. // once we get those two next to each other, wait for upcoming toktag_CLOSE which will end that Object
  1114. // remember ibTokMac at that position. This is the OBJECT range.
  1115. // First, insert the startspan text
  1116. // Then generate and insert the endspan text (note that we may have to extend our
  1117. // buffer becausethe generated text mey not fit.
  1118. // Do the appropriate Blts to adjust the buffer.
  1119. UINT cchObjStart, indexObjStart, cchObjEnd, indexObjEnd;
  1120. HGLOBAL hgDTC = NULL;
  1121. WCHAR *pDTC;
  1122. UINT iArray = *piArrayStart;
  1123. INT i;
  1124. UINT ichNewCur = *pichNewCur;
  1125. UINT ichBeginCopy = *pichBeginCopy;
  1126. HRESULT hr;
  1127. LPWSTR pwNew = *ppwNew;
  1128. UINT cbNeed;
  1129. long iControlMac;
  1130. CComPtr<IHTMLDocument2> pHTMLDoc;
  1131. CComPtr<IHTMLElementCollection> pHTMLColl;
  1132. CComPtr<IDispatch> pDispControl;
  1133. CComPtr<IActiveDesigner> pActiveDesigner;
  1134. VARIANT vaName, vaIndex;
  1135. // DTC tag used for saving the DTC.
  1136. LPCWSTR rgDTCTags[] =
  1137. {
  1138. L"<!--METADATA TYPE=\"DesignerControl\" startspan\r\n",
  1139. L"\r\n-->\r\n",
  1140. L"\r\n<!--METADATA TYPE=\"DesignerControl\" endspan-->"
  1141. };
  1142. LPCWSTR rgCommentRT[] =
  1143. {
  1144. L"DTCRUNTIME",
  1145. L"--DTCRUNTIME ",
  1146. L" DTCRUNTIME--",
  1147. };
  1148. int ichRT, cchRT, ichRTComment, cchRTComment, indexRTComment;
  1149. ichRTComment = ichRT = -1;
  1150. indexRTComment = -1;
  1151. cchRT = cchRTComment = 0;
  1152. cchObjStart = indexObjStart = cchObjEnd = indexObjEnd = 0;
  1153. // start at the begining of pTokArray and look for first OBJECT
  1154. //while (pTokArray[iArray].token.tok != ft.tokBegin2)
  1155. // iArray++;
  1156. ASSERT(iArray < ptep->m_cMaxToken);
  1157. if (pTokArray[iArray].token.tok != TokElem_OBJECT)
  1158. goto LRet;
  1159. //ASSERT(pTokArray[iArray].token.tok == TokElem_OBJECT);
  1160. i = iArray; // the position at which we found ft.tokBegin2
  1161. while (i >=0)
  1162. {
  1163. // do we need to do anything else here?
  1164. if (pTokArray[i].token.tok == ft.tokBegin)
  1165. {
  1166. ASSERT(pTokArray[i].token.tok == TokTag_START);
  1167. ASSERT(pTokArray[i].token.tokClass == tokTag);
  1168. break;
  1169. }
  1170. i--;
  1171. }
  1172. if (i >= 0) // found TokTag_START token
  1173. {
  1174. cchObjStart = pTokArray[i].token.ibTokMin;
  1175. indexObjStart = i;
  1176. }
  1177. i = pTokArray[iArray].iNextprev;
  1178. if (i == -1) // no matching end, skip this <OBJECT>
  1179. goto LRet;
  1180. ASSERT(pTokArray[pTokArray[iArray].iNextprev].token.tok == TokElem_OBJECT);
  1181. ASSERT(pTokArray[pTokArray[iArray].iNextprev].token.tokClass == tokElem);
  1182. ASSERT(pTokArray[i-1].token.tok == TokTag_END);
  1183. // from this ith position, look for ft.tokEnd
  1184. while (i < (int)ptep->m_cMaxToken)
  1185. {
  1186. if (pTokArray[i].token.tok == ft.tokEnd)
  1187. {
  1188. ASSERT(pTokArray[i].token.tok == TokTag_CLOSE);
  1189. ASSERT(pTokArray[i].token.tokClass == tokTag);
  1190. break;
  1191. }
  1192. i++;
  1193. }
  1194. if (i < (int)ptep->m_cMaxToken) // found TokTag_CLOSE token
  1195. {
  1196. cchObjEnd = pTokArray[i].token.ibTokMac;
  1197. indexObjEnd = i;
  1198. }
  1199. // look for the special comment that has the runtime text saved
  1200. // we will need it if SaveRuntimeText() failed
  1201. i = indexObjStart;
  1202. while (i < (int)indexObjEnd)
  1203. {
  1204. if ( pTokArray[i].token.tok == TokTag_BANG
  1205. && pTokArray[i].token.tokClass == tokTag)
  1206. {
  1207. // found the comment, now make sure that this is the comment with DTCRUNTIME
  1208. if ( (pwOld[pTokArray[i+1].token.ibTokMin] == '-')
  1209. && (pwOld[pTokArray[i+1].token.ibTokMin+1] == '-')
  1210. && (0 == _wcsnicmp(rgCommentRT[0], &pwOld[pTokArray[i+1].token.ibTokMin+2], wcslen(rgCommentRT[0])))
  1211. && (pwOld[pTokArray[i+1].token.ibTokMac-1] == '-')
  1212. && (pwOld[pTokArray[i+1].token.ibTokMac-2] == '-')
  1213. && (0 == _wcsnicmp(rgCommentRT[0], &pwOld[pTokArray[i+1].token.ibTokMac-2-wcslen(rgCommentRT[0])], wcslen(rgCommentRT[0])))
  1214. )
  1215. {
  1216. ichRT = pTokArray[i+1].token.ibTokMin + wcslen(rgCommentRT[1]);
  1217. cchRT = pTokArray[i+1].token.ibTokMac-pTokArray[i+1].token.ibTokMin - wcslen(rgCommentRT[2]) - wcslen(rgCommentRT[1]);
  1218. indexRTComment = i;
  1219. ichRTComment = pTokArray[i].token.ibTokMin;
  1220. cchRTComment = pTokArray[i+2].token.ibTokMac-pTokArray[i].token.ibTokMin;
  1221. break;
  1222. }
  1223. }
  1224. i++;
  1225. }
  1226. iArray = indexObjEnd; // set it for the next Object
  1227. // now, replace the OBJECT - Insert startspan and endspan stuff
  1228. pHTMLDoc = NULL;
  1229. hr = ptep->m_pUnkTrident->QueryInterface(IID_IHTMLDocument2, (void **) &pHTMLDoc);
  1230. if (hr != S_OK)
  1231. goto LErrorRet;
  1232. pHTMLColl = NULL;
  1233. hr = pHTMLDoc->get_applets(&pHTMLColl);
  1234. if (hr != S_OK)
  1235. {
  1236. goto LErrorRet;
  1237. }
  1238. pHTMLColl->get_length(&iControlMac);
  1239. ASSERT(*piObj <= iControlMac);
  1240. hr = S_FALSE;
  1241. VariantInit(&vaName);
  1242. VariantInit(&vaIndex);
  1243. V_VT(&vaName) = VT_ERROR;
  1244. V_ERROR(&vaName) = DISP_E_PARAMNOTFOUND;
  1245. V_VT(&vaIndex) = VT_I4;
  1246. V_I4(&vaIndex) = *piObj;
  1247. *piObj += 1; // get it ready for the next control
  1248. ptep->m_iControl = *piObj; // get it ready for the next control
  1249. pDispControl = NULL;
  1250. hr = pHTMLColl->item(vaIndex, vaName, &pDispControl);
  1251. // Trident has a bug that if the object was nested inside <scripts> tags,
  1252. // it returns S_OK with pDispControl as NULL. (See VID BUG 11303)
  1253. if (hr != S_OK || pDispControl == NULL)
  1254. {
  1255. goto LErrorRet;
  1256. }
  1257. pActiveDesigner = NULL;
  1258. hr = pDispControl->QueryInterface(IID_IActiveDesigner, (void **) &pActiveDesigner);
  1259. if (hr != S_OK) // release pActiveDesigner
  1260. {
  1261. pActiveDesigner.Release();
  1262. pDispControl.Release();
  1263. }
  1264. if (hr == S_OK) // Found the control!
  1265. {
  1266. // This is a DTC
  1267. IStream *pStm;
  1268. HGLOBAL hg = NULL;
  1269. INT cbMin = 0x8fff; // init & increment size of hgDTC
  1270. INT cchCurDTC = 0;
  1271. #ifdef DEBUG
  1272. CComPtr<IHTMLElement> pHTMLElem = NULL;
  1273. hr = pDispControl->QueryInterface(IID_IHTMLElement, (void **) &pHTMLElem);
  1274. if (hr != S_OK)
  1275. {
  1276. goto LErrorRet;
  1277. }
  1278. // get the index for TokAttrib_ID from pTokArray
  1279. // from here get the actual value for future comparison
  1280. i = indexObjStart;
  1281. // actually, this has to exist before TokElem_PARAM,
  1282. // but this takes care of boundary cases
  1283. while (i < (int)indexObjEnd)
  1284. {
  1285. if (pTokArray[i].token.tok == TokAttrib_CLASSID)
  1286. {
  1287. ASSERT(pTokArray[i].token.tokClass == tokAttr);
  1288. break;
  1289. }
  1290. i++;
  1291. }
  1292. if (i < (int)indexObjEnd -1) // found TokAttrib_CLASSID
  1293. {
  1294. CComPtr<IPersistPropertyBag> pPersistPropBag;
  1295. INT ichClsid;
  1296. // make sure that the next one is tokOpEqual
  1297. ASSERT(pTokArray[i+1].token.tokClass == tokOp);
  1298. // make sure that the next one is the id and get that value
  1299. //ASSERT(pTokArray[i].token.tok == );
  1300. // Is there any other way to skip "clsid:" string that appears before the clsid?
  1301. ichClsid = pTokArray[i+2].token.ibTokMin + strlen("clsid:");
  1302. pPersistPropBag = NULL;
  1303. hr = pDispControl->QueryInterface(IID_IPersistPropertyBag, (void **) &pPersistPropBag);
  1304. if (hr == S_OK)
  1305. {
  1306. CLSID clsid;
  1307. LPOLESTR szClsid;
  1308. if (S_OK == pPersistPropBag->GetClassID(&clsid))
  1309. {
  1310. if (S_OK == StringFromCLSID(clsid, &szClsid))
  1311. ASSERT(0 == _wcsnicmp(szClsid+1/* for {*/, &pwOld[ichClsid], sizeof(CLSID)));
  1312. ::CoTaskMemFree(szClsid);
  1313. }
  1314. }
  1315. }
  1316. #endif // DEBUG
  1317. ASSERT(*piObj <= iControlMac);
  1318. // Do the Blts.
  1319. // 0. Allocate a local buffer
  1320. hgDTC = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, ((cchObjEnd-cchObjStart)+cbMin)*sizeof(WCHAR)); // stack
  1321. if (hgDTC == NULL)
  1322. goto LErrorRet;
  1323. pDTC= (WCHAR *) GlobalLock(hgDTC);
  1324. ASSERT(pDTC != NULL);
  1325. if (!(dwFlags & dwFilterDTCsWithoutMetaTags))
  1326. {
  1327. INT indexTokOp = -1;
  1328. INT indexClsId = -1;
  1329. // 1. Insert MetaData1 tag from rgDTCTags[0]
  1330. wcscpy(&pDTC[cchCurDTC], rgDTCTags[0]);
  1331. cchCurDTC += wcslen(rgDTCTags[0]);
  1332. // 2. copy the <OBJECT> </OBJECT> from pwOld
  1333. // Split the copy into 3 parts...
  1334. // part 1 - copy from cchObjStart till = following the ClassId
  1335. // part 2 - add a quote around the classId value (if needed) and copy the value
  1336. // part 3 - copy rest of the object till cchObjEnd
  1337. // VID98-BUG 5649 - Fix DaVinci bug by adding quote around classId's.
  1338. // NOTE - we want to make sure that the classId value is inside quotes,
  1339. // if there is one for this <OBJECT> tag,
  1340. // we actually don't need to go this far, but thats the indexObjEnd is the
  1341. // only index know
  1342. for (i = indexObjStart; i < (INT)indexObjEnd; i++)
  1343. {
  1344. if ( pTokArray[i].token.tok == TokAttrib_CLASSID
  1345. && pTokArray[i].token.tokClass == tokAttr)
  1346. {
  1347. indexClsId = i;
  1348. }
  1349. if ( pwOld[pTokArray[i].token.ibTokMin] == '='
  1350. && pTokArray[i].token.tokClass == tokOp
  1351. && indexTokOp == -1)
  1352. {
  1353. indexTokOp = i;
  1354. }
  1355. } // for ()
  1356. // following are simply error cases, we won't run into them unless we have
  1357. // incomplete HTML
  1358. if ( indexClsId == -1 /* we didn't have clsid for this <OBJECT> */
  1359. || indexTokOp == -1 /* rare but possible error case of incomplete HTML */
  1360. )
  1361. {
  1362. if (ichRTComment == -1)
  1363. {
  1364. wcsncpy(&pDTC[cchCurDTC], &pwOld[cchObjStart], cchObjEnd - cchObjStart);
  1365. cchCurDTC += cchObjEnd - cchObjStart;
  1366. }
  1367. else
  1368. {
  1369. wcsncpy(&pDTC[cchCurDTC], &pwOld[cchObjStart], ichRTComment - cchObjStart);
  1370. cchCurDTC += ichRTComment - cchObjStart;
  1371. wcsncpy(&pDTC[cchCurDTC], &pwOld[ichRTComment+cchRTComment], cchObjEnd - (ichRTComment+cchRTComment));
  1372. cchCurDTC += cchObjEnd - (ichRTComment+cchRTComment);
  1373. }
  1374. }
  1375. else
  1376. {
  1377. LPCWSTR szClsId[] =
  1378. {
  1379. L"clsid:",
  1380. };
  1381. ASSERT(indexTokOp != -1);
  1382. // copy till '=' of 'classid=clsid:XXXX'
  1383. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1384. (BYTE *)(&pwOld[cchObjStart]),
  1385. (pTokArray[indexTokOp].token.ibTokMac-cchObjStart)*sizeof(WCHAR));
  1386. cchCurDTC += (pTokArray[indexTokOp].token.ibTokMac-cchObjStart);
  1387. if (0 == _wcsnicmp(szClsId[0], &pwOld[pTokArray[indexTokOp+1].token.ibTokMin], wcslen(szClsId[0])))
  1388. {
  1389. ASSERT(pwOld[pTokArray[indexTokOp+1].token.ibTokMin] != '"');
  1390. pDTC[cchCurDTC] = '"';
  1391. cchCurDTC++;
  1392. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1393. (BYTE *)(&pwOld[pTokArray[indexTokOp+1].token.ibTokMin]),
  1394. (pTokArray[indexTokOp+1].token.ibTokMac - pTokArray[indexTokOp+1].token.ibTokMin)*sizeof(WCHAR));
  1395. cchCurDTC += pTokArray[indexTokOp+1].token.ibTokMac - pTokArray[indexTokOp+1].token.ibTokMin;
  1396. pDTC[cchCurDTC] = '"';
  1397. cchCurDTC++;
  1398. if (ichRTComment == -1)
  1399. {
  1400. ASSERT((int)(cchObjEnd-pTokArray[indexTokOp+1].token.ibTokMac) >= 0);
  1401. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1402. (BYTE *)(&pwOld[pTokArray[indexTokOp+1].token.ibTokMac]),
  1403. (cchObjEnd-pTokArray[indexTokOp+1].token.ibTokMac)*sizeof(WCHAR));
  1404. cchCurDTC += (cchObjEnd-pTokArray[indexTokOp+1].token.ibTokMac);
  1405. }
  1406. else
  1407. {
  1408. if (indexRTComment == -1)
  1409. {
  1410. ASSERT((int)(ichRTComment-pTokArray[indexTokOp+1].token.ibTokMac) >= 0);
  1411. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1412. (BYTE *)(&pwOld[pTokArray[indexTokOp+1].token.ibTokMac]),
  1413. (ichRTComment-pTokArray[indexTokOp+1].token.ibTokMac)*sizeof(WCHAR));
  1414. cchCurDTC += (ichRTComment-pTokArray[indexTokOp+1].token.ibTokMac);
  1415. ASSERT((int)(cchObjEnd-(ichRTComment+cchRTComment)) >= 0);
  1416. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1417. (BYTE *)(&pwOld[ichRTComment+cchRTComment]),
  1418. (cchObjEnd-(ichRTComment+cchRTComment))*sizeof(WCHAR));
  1419. cchCurDTC += (cchObjEnd-(ichRTComment+cchRTComment));
  1420. }
  1421. else
  1422. {
  1423. // format and copy from indexTokOp+2 till indexRTComment
  1424. for (i = indexTokOp+2; i < indexRTComment; i++)
  1425. {
  1426. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1427. (BYTE *)(&pwOld[pTokArray[i].token.ibTokMin]),
  1428. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  1429. cchCurDTC += pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin;
  1430. if (pTokArray[i].token.tok == TokTag_CLOSE && pTokArray[i].token.tokClass == tokTag)
  1431. {
  1432. // Don't bother checking for existing EOLs...
  1433. // add \r\n
  1434. pDTC[cchCurDTC++] = '\r';
  1435. pDTC[cchCurDTC++] = '\n';
  1436. pDTC[cchCurDTC++] = '\t';
  1437. }
  1438. }
  1439. // copy from end of the comment till </object>
  1440. ASSERT((int)(cchObjEnd-(ichRTComment+cchRTComment)) >= 0);
  1441. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1442. (BYTE *)(&pwOld[ichRTComment+cchRTComment]),
  1443. (cchObjEnd-(ichRTComment+cchRTComment))*sizeof(WCHAR));
  1444. cchCurDTC += (cchObjEnd-(ichRTComment+cchRTComment));
  1445. }
  1446. }
  1447. }
  1448. else
  1449. {
  1450. if (ichRTComment == -1)
  1451. {
  1452. ASSERT((int)(cchObjEnd-pTokArray[indexTokOp+1].token.ibTokMin) >= 0);
  1453. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1454. (BYTE *)(&pwOld[pTokArray[indexTokOp+1].token.ibTokMin]),
  1455. (cchObjEnd-pTokArray[indexTokOp+1].token.ibTokMin)*sizeof(WCHAR));
  1456. cchCurDTC += (cchObjEnd-pTokArray[indexTokOp+1].token.ibTokMin);
  1457. }
  1458. else
  1459. {
  1460. ASSERT((int)(ichRTComment-pTokArray[indexTokOp+1].token.ibTokMin) >= 0);
  1461. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1462. (BYTE *)(&pwOld[pTokArray[indexTokOp+1].token.ibTokMin]),
  1463. (ichRTComment-pTokArray[indexTokOp+1].token.ibTokMin)*sizeof(WCHAR));
  1464. cchCurDTC += (ichRTComment-pTokArray[indexTokOp+1].token.ibTokMin);
  1465. ASSERT((int)(cchObjEnd-(ichRTComment+cchRTComment)) >= 0);
  1466. memcpy( (BYTE *)(&pDTC[cchCurDTC]),
  1467. (BYTE *)(&pwOld[ichRTComment+cchRTComment]),
  1468. (cchObjEnd-(ichRTComment+cchRTComment))*sizeof(WCHAR));
  1469. cchCurDTC += (cchObjEnd-(ichRTComment+cchRTComment));
  1470. }
  1471. }
  1472. }
  1473. // 3. Insert MetaData2 tag from rgDTCtags[1]
  1474. wcscpy(&pDTC[cchCurDTC], rgDTCTags[1]);
  1475. cchCurDTC += wcslen(rgDTCTags[1]);
  1476. }
  1477. // 4. Add runtime text (copy code from old stuff)
  1478. if ((hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm)) != S_OK)
  1479. goto LErrorRet;
  1480. ASSERT(pActiveDesigner != NULL);
  1481. if ((hr = pActiveDesigner->SaveRuntimeState(IID_IPersistTextStream, IID_IStream, pStm)) == S_OK)
  1482. {
  1483. if ((hr = GetHGlobalFromStream(pStm, &hg)) != S_OK)
  1484. goto LErrorRet;
  1485. STATSTG stat;
  1486. if ((hr = pStm->Stat(&stat, STATFLAG_NONAME)) != S_OK)
  1487. goto LErrorRet;
  1488. int cch = stat.cbSize.LowPart / sizeof(WCHAR);
  1489. // before we put stuff from hg into pDTC,
  1490. // lets make sure that its big enough
  1491. cbNeed = (cchCurDTC+cch)*sizeof(WCHAR)+cbBufPadding;
  1492. if (GlobalSize(hgDTC) < cbNeed)
  1493. {
  1494. hr = ReallocBuffer( &hgDTC, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT);
  1495. if (hr == E_OUTOFMEMORY)
  1496. goto LErrorRet;
  1497. ASSERT(hgDTC != NULL);
  1498. pDTC = (WCHAR *)GlobalLock(hgDTC);
  1499. }
  1500. wcsncpy(&pDTC[cchCurDTC], (LPCWSTR) GlobalLock(hg), cch);
  1501. cchCurDTC += cch;
  1502. // HACK - BUG fix 9844
  1503. // Some DTCs add a NULL at the end of their runtime text
  1504. if (pDTC[cchCurDTC-1] == '\0')
  1505. cchCurDTC--;
  1506. GlobalUnlock(hg);
  1507. }
  1508. else if (hr == S_FALSE)
  1509. {
  1510. // copy the commented runtime text into pDTC & incremtn cchCurDTC
  1511. if (ichRTComment != -1 && ichRT != -1) // we have the runtime text
  1512. {
  1513. ASSERT(cchRT >= 0);
  1514. cbNeed = (cchCurDTC+cchRT)*sizeof(WCHAR)+cbBufPadding;
  1515. if (GlobalSize(hgDTC) < cbNeed)
  1516. {
  1517. hr = ReallocBuffer( &hgDTC, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT);
  1518. if (hr == E_OUTOFMEMORY)
  1519. goto LErrorRet;
  1520. ASSERT(hgDTC != NULL);
  1521. pDTC = (WCHAR *)GlobalLock(hgDTC);
  1522. }
  1523. wcsncpy(&pDTC[cchCurDTC], &pwOld[ichRT], cchRT);
  1524. cchCurDTC += cchRT;
  1525. }
  1526. }
  1527. if (!(dwFlags & dwFilterDTCsWithoutMetaTags))
  1528. {
  1529. // 5. Insert MetaData2 tag from rgDTCtags[2]
  1530. wcscpy(&pDTC[cchCurDTC], rgDTCTags[2]);
  1531. cchCurDTC += wcslen(rgDTCTags[2]);
  1532. }
  1533. // now insert/replace contents of pDTC into pwNew
  1534. // we are insert/replacing (cchObjEnd-cchObjStart) wchars
  1535. // by cchCurDTC wchars, so realloc pwNew first
  1536. /* Reallocate pwNew IF NEEDED here use cache value for GlobalSize(*phgNew) and don't forget to update it too */
  1537. cbNeed = (ichNewCur+(cchObjStart-ichBeginCopy)+(cchCurDTC))*sizeof(WCHAR)+cbBufPadding;
  1538. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  1539. goto LErrorRet;
  1540. // cchObjStart/End are actually ich's
  1541. // ichBeginCopy is a position in pwOld and
  1542. // ichNewCur is a position in pwNew
  1543. // copy till begining of the <OBJECT>
  1544. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1545. (BYTE *)(&pwOld[ichBeginCopy]),
  1546. (cchObjStart-ichBeginCopy)*sizeof(WCHAR));
  1547. ichNewCur += cchObjStart-ichBeginCopy;
  1548. ichBeginCopy = cchObjEnd; // set it for next object
  1549. CComPtr<IPersistPropertyBag> pPersistPropBag = NULL;
  1550. hr = pDispControl->QueryInterface(IID_IPersistPropertyBag, (void **) &pPersistPropBag);
  1551. if (hr == S_OK)
  1552. {
  1553. CLSID clsid;
  1554. if (S_OK == pPersistPropBag->GetClassID(&clsid))
  1555. {
  1556. if (IsEqualCLSID(clsid, CLSID_PageTr))
  1557. {
  1558. if (ptep->m_cchPTDTC != 0)
  1559. {
  1560. // Note that there is no need to realloc here since our buffer will already be bigger than we need it to be.
  1561. if (cchCurDTC != ptep->m_cchPTDTC)
  1562. {
  1563. memmove((BYTE *)(pwNew+ptep->m_ichPTDTC+cchCurDTC),
  1564. (BYTE *)(pwNew+ptep->m_ichPTDTC+ptep->m_cchPTDTC),
  1565. (ichNewCur-ptep->m_ichPTDTC-ptep->m_cchPTDTC)*sizeof(WCHAR));
  1566. ichNewCur += cchCurDTC-ptep->m_cchPTDTC;
  1567. }
  1568. memcpy( (BYTE *)(pwNew+ptep->m_ichPTDTC),
  1569. (BYTE *)(pDTC),
  1570. cchCurDTC*sizeof(WCHAR));
  1571. ptep->m_cchPTDTC = 0;
  1572. ptep->m_ichBeginHeadTagIn = 0; // reset, so that if we had multiple PTDTCs,
  1573. //we won't try to stuff them inside HEAD
  1574. goto LSkipDTC;
  1575. }
  1576. else // this is the case where the PTDTC didn't exist before going to Trident
  1577. {
  1578. // we need to move this between <head> </head> tags if they exist
  1579. if (ptep->m_ichBeginHeadTagIn > 0) // we had HEAD tag in Source view
  1580. {
  1581. int ichInsertPTDTC = ptep->m_ichBeginHeadTagIn;
  1582. // insert the control immediately after the <HEAD> tag
  1583. //in pwNew look for '>' after ichInsertPTDTC
  1584. while (pwNew[ichInsertPTDTC] != '>')
  1585. ichInsertPTDTC++;
  1586. ichInsertPTDTC++; // skip '>'
  1587. ASSERT(ichInsertPTDTC < (INT)ichNewCur);
  1588. memmove((BYTE *)(pwNew+ichInsertPTDTC+cchCurDTC),
  1589. (BYTE *)(pwNew+ichInsertPTDTC),
  1590. (ichNewCur-ichInsertPTDTC)*sizeof(WCHAR));
  1591. ichNewCur += cchCurDTC;
  1592. memcpy( (BYTE *)(pwNew+ichInsertPTDTC),
  1593. (BYTE *)(pDTC),
  1594. cchCurDTC*sizeof(WCHAR));
  1595. ptep->m_ichBeginHeadTagIn = 0;
  1596. goto LSkipDTC;
  1597. }
  1598. }
  1599. } // else if (IsEqualCLSID(clsid, CLSID_PageTr))
  1600. } // if (S_OK == pPersistPropBag->GetClassID(&clsid))
  1601. } // if (hr == S_OK)
  1602. // copy the converted DTC
  1603. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1604. (BYTE *)(pDTC),
  1605. cchCurDTC*sizeof(WCHAR));
  1606. ichNewCur += cchCurDTC;
  1607. LSkipDTC:
  1608. if (hgDTC != NULL)
  1609. GlobalUnlockFreeNull(&hgDTC);
  1610. } // if (hr == S_OK)
  1611. else // this object was not a DTC
  1612. {
  1613. // we don't need to do the same for DTC's, but lets visit this in next release
  1614. LPCWSTR rgComment[] =
  1615. {
  1616. L"ERRORPARAM",
  1617. L"--ERRORPARAM ",
  1618. L" ERRORPARAM--",
  1619. };
  1620. BOOL fFoundParam = FALSE;
  1621. INT iParam = -1;
  1622. INT ichObjStartEnd, iCommentStart, iCommentEnd;
  1623. UINT iObjTagEnd;
  1624. INT cComment, iFirstComment, iComment;
  1625. iCommentStart = iCommentEnd = iComment = -1;
  1626. // loop through indexObjStart till indexObjEnd to see if we have any <PARAM> tags
  1627. for (i = indexObjStart; i < (INT)indexObjEnd; i++)
  1628. {
  1629. if ( pTokArray[i].token.tok == TokElem_PARAM
  1630. && pTokArray[i].token.tokClass == tokElem)
  1631. {
  1632. fFoundParam = TRUE;
  1633. iParam = i;
  1634. break;
  1635. }
  1636. } // for ()
  1637. if (fFoundParam)
  1638. ASSERT(iParam != -1);
  1639. // We need to copy till end of <OBJECT...> irrespective of if we find <PARAM>s or not.
  1640. // copy till end of <OBJECT...> tag and set ichBeginCopy to be after the commented <PARAM> tags
  1641. // calculate ichObjStartEnd
  1642. iObjTagEnd = indexObjStart;
  1643. while (iObjTagEnd < indexObjEnd)
  1644. {
  1645. if ( pTokArray[iObjTagEnd].token.tok == TokTag_CLOSE
  1646. && pTokArray[iObjTagEnd].token.tokClass == tokTag)
  1647. break;
  1648. iObjTagEnd++;
  1649. }
  1650. if (iObjTagEnd >= indexObjEnd) // error case
  1651. goto LErrorRet;
  1652. ichObjStartEnd = pTokArray[iObjTagEnd].token.ibTokMac;
  1653. cbNeed = (ichNewCur+ichObjStartEnd-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  1654. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  1655. goto LRet;
  1656. ASSERT((INT)(ichObjStartEnd-ichBeginCopy) >= 0);
  1657. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1658. (BYTE *)(&pwOld[ichBeginCopy]),
  1659. (ichObjStartEnd-ichBeginCopy)*sizeof(WCHAR));
  1660. ichNewCur += (ichObjStartEnd-ichBeginCopy);
  1661. ichBeginCopy = ichObjStartEnd;
  1662. iArray = iObjTagEnd + 1;
  1663. // generally, we don't expect Trident to move the comment from where it was put
  1664. // but if it does, be prepared.
  1665. // NOTE - Lets not worry about the following case for this release becasue prior assumption
  1666. // Also, should we look for more comments if the first one wasn't the magic one?
  1667. // Would Trident move it form where it originally inserted?
  1668. // ASSUMPTION - that Trident doesn't muck with the contents inside a comment block
  1669. // if rgComment[0] matches and rgComment[1] does not, Trident may have mucked with the
  1670. // comment contents. This invalidates our original assumption.
  1671. // NOTE - We can get away with ignoring this case for thie release
  1672. i = iObjTagEnd;
  1673. cComment = 0;
  1674. iFirstComment = -1;
  1675. while ((UINT)i < indexObjEnd)
  1676. {
  1677. if ( pTokArray[i].token.tok == TokTag_BANG
  1678. && pTokArray[i].token.tokClass == tokTag)
  1679. {
  1680. cComment++;
  1681. if (iFirstComment == -1)
  1682. iFirstComment = i;
  1683. }
  1684. i++;
  1685. }
  1686. if (cComment == 0) // error, didn't find the comment
  1687. goto LErrorRet;
  1688. // early return cases
  1689. // 1. see if these are comments or not.They could be anything that start with '<!'
  1690. // e.g. <!DOCTYPE
  1691. i = iFirstComment;
  1692. while (i < (INT)indexObjEnd)
  1693. {
  1694. if ( (i < (INT)ptep->m_cMaxToken)
  1695. && (pwOld[pTokArray[i].token.ibTokMin] == '-')
  1696. && (pwOld[pTokArray[i].token.ibTokMin+1] == '-')
  1697. && (0 == _wcsnicmp(rgComment[0], &pwOld[pTokArray[i].token.ibTokMin+2], wcslen(rgComment[0])))
  1698. )
  1699. {
  1700. ASSERT(i-1 >= 0);
  1701. iCommentStart = i-1; // this is a comment we are interested in
  1702. }
  1703. else
  1704. goto LNextComment;
  1705. // The first part matched, look at the end of the comment
  1706. if ( (pwOld[pTokArray[i].token.ibTokMac-1] == '-')
  1707. && (pwOld[pTokArray[i].token.ibTokMac-2] == '-')
  1708. && (0 == _wcsnicmp( rgComment[0],
  1709. &pwOld[pTokArray[i].token.ibTokMac-(wcslen(rgComment[0])+2)],
  1710. wcslen(rgComment[0])
  1711. )
  1712. )
  1713. )
  1714. {
  1715. iCommentEnd = i + 1;
  1716. iComment = i;
  1717. ASSERT(iCommentEnd < (INT)ptep->m_cMaxToken);
  1718. break;
  1719. }
  1720. else // error case (our assumption was not valid). ignore and return with iArraySav+1
  1721. goto LNextComment;
  1722. LNextComment:
  1723. i++;
  1724. } // while ()
  1725. // HANDLE THIS CASE - WHAT IF WE DIDN'T FIND A SINGLE COMMENT????
  1726. if (fFoundParam)
  1727. {
  1728. if (iCommentStart != -1 && iCommentEnd != -1)
  1729. {
  1730. cbNeed = (ichNewCur+(pTokArray[iCommentEnd].token.ibTokMac-pTokArray[iObjTagEnd].token.ibTokMin)+(iCommentStart-iObjTagEnd)*3/*for eol,tab*/+(pTokArray[iObjTagEnd].token.ibTokMac-ichBeginCopy))*sizeof(WCHAR)+cbBufPadding;
  1731. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  1732. goto LErrorRet;
  1733. // we need to format the param tags because trident puts them on one line
  1734. // copy till the first param tag
  1735. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1736. (BYTE *)(&pwOld[ichBeginCopy]),
  1737. (pTokArray[iObjTagEnd].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  1738. ichNewCur += (pTokArray[iObjTagEnd].token.ibTokMac-ichBeginCopy);
  1739. // From here, copy each param tag and insert an EOL after each.
  1740. // Stop at iCommentStart
  1741. for (i = iObjTagEnd+1; i < iCommentStart; i++)
  1742. {
  1743. // if its TokTag_START, insert EOL
  1744. if ( pTokArray[i].token.tok == TokTag_START
  1745. && pTokArray[i].token.tokClass == tokTag
  1746. )
  1747. {
  1748. pwNew[ichNewCur] = '\r';
  1749. ichNewCur++;
  1750. pwNew[ichNewCur] = '\n';
  1751. ichNewCur++;
  1752. pwNew[ichNewCur] = '\t'; // replace this with appropriate alignment
  1753. ichNewCur++;
  1754. }
  1755. // copy the tag
  1756. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1757. (BYTE *)(&pwOld[pTokArray[i].token.ibTokMin]),
  1758. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  1759. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  1760. } // for ()
  1761. // from here, look for extra spaces/tabs/eols that trident has accumulated
  1762. // at the end of the PARAM tags and remove them.
  1763. for (i = iCommentEnd+1; i <= (int)indexObjEnd; i++)
  1764. {
  1765. if ( (pTokArray[i].token.tokClass == tokIDENTIFIER && pTokArray[i].token.tok == 0)
  1766. || ( pTokArray[i].token.tokClass == tokOp
  1767. && pTokArray[i].token.tok == 0
  1768. && pwOld[pTokArray[i].token.ibTokMin] == 0x0a
  1769. && pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin == 1
  1770. )
  1771. )
  1772. {
  1773. int iChar;
  1774. BOOL fCopy = FALSE;
  1775. // see if all the characters in this token are spaces/tabs/eols
  1776. for (iChar = pTokArray[i].token.ibTokMin; iChar < (int)pTokArray[i].token.ibTokMac; iChar++)
  1777. {
  1778. if ( pwOld[iChar] != ' '
  1779. && pwOld[iChar] != '\r'
  1780. && pwOld[iChar] != '\n'
  1781. && pwOld[iChar] != '\t'
  1782. )
  1783. {
  1784. // we need to copy this token
  1785. fCopy = TRUE;
  1786. break;
  1787. }
  1788. } // for (iChar)
  1789. if (fCopy)
  1790. {
  1791. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1792. (BYTE *)(&pwOld[pTokArray[i].token.ibTokMin]),
  1793. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  1794. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  1795. }
  1796. }
  1797. else
  1798. {
  1799. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1800. (BYTE *)(&pwOld[pTokArray[i].token.ibTokMin]),
  1801. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  1802. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  1803. if (pTokArray[i].token.tok == TokTag_CLOSE && pTokArray[i].token.tokClass == tokTag)
  1804. {
  1805. pwNew[ichNewCur++] = '\r';
  1806. pwNew[ichNewCur++] = '\n';
  1807. }
  1808. }
  1809. } // for ()
  1810. ichBeginCopy = pTokArray[indexObjEnd].token.ibTokMac;
  1811. iArray = indexObjEnd + 1;
  1812. }
  1813. }
  1814. else
  1815. {
  1816. if (iCommentStart != -1 && iCommentEnd != -1 && iComment != -1)
  1817. {
  1818. INT cchComment1, cchComment2;
  1819. INT ichCommentStart, ichParamStart, cchCommentToken;
  1820. // We didn't have any <PARAM> for this object. It means one of the following
  1821. // (a)Trident deleted those or (b)it didn't have any before going to Trident
  1822. // If Trident deleted those, we should have them in form of a comment.
  1823. // If we didn't have those before doing to Trident, we won't have that magic comment
  1824. // BUT by the time we come here, we are sure that we have found the magic comment
  1825. // ASSUME that trident won't move the comment from its original place
  1826. // NOTE - In this release, we don't need to handle the case of Trident moving the comment location
  1827. // which was originally placed just after <OBJECT ...>
  1828. // remove the comment tokens surrounding the <PARAM>s.
  1829. cchComment1 = wcslen(rgComment[1]);
  1830. cchComment2 = wcslen(rgComment[2]);
  1831. // remove cchComment1 chars from begining of pwOld[pTokArray[i+1].token.ibTokMin
  1832. // remove cchComment2 chars from the end of pwOld[pTokArray[i+1].token.ibTokMac
  1833. // and copy the rest into pwNew
  1834. ichCommentStart = pTokArray[iCommentStart].token.ibTokMin;
  1835. ichParamStart = pTokArray[iCommentStart+1].token.ibTokMin+cchComment1;
  1836. ASSERT((INT)(ichCommentStart-ichBeginCopy) >= 0);
  1837. cbNeed = (ichNewCur+ichCommentStart-ichBeginCopy+pTokArray[iComment].token.ibTokMac-pTokArray[iComment].token.ibTokMin)*sizeof(WCHAR)+cbBufPadding;
  1838. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  1839. goto LRet;
  1840. // copy till begining of the comment
  1841. memcpy( (BYTE *)(pwNew+ichNewCur),
  1842. (BYTE *)(pwOld+ichBeginCopy),
  1843. (ichCommentStart-ichBeginCopy)*sizeof(WCHAR));
  1844. ichNewCur += ichCommentStart-ichBeginCopy;
  1845. ichBeginCopy = pTokArray[iCommentEnd].token.ibTokMac;
  1846. cchCommentToken = pTokArray[iComment].token.ibTokMac-pTokArray[iComment].token.ibTokMin;
  1847. ASSERT((INT)(cchCommentToken-cchComment1-cchComment2) >= 0);
  1848. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  1849. (BYTE *)&(pwOld[ichParamStart]),
  1850. (cchCommentToken-cchComment1-cchComment2)*sizeof(WCHAR));
  1851. ichNewCur += pTokArray[iComment].token.ibTokMac-pTokArray[iComment].token.ibTokMin-cchComment1-cchComment2;
  1852. iArray = iCommentEnd + 1;
  1853. }
  1854. } // if (!fFoundParam)
  1855. } // else of if (hr == S_OK)
  1856. LErrorRet:
  1857. //free hgDTC if its not NULL
  1858. if (hgDTC != NULL)
  1859. GlobalUnlockFreeNull(&hgDTC);
  1860. LRet:
  1861. *pcchNew = ichNewCur;
  1862. *ppwNew = pwNew;
  1863. *pichNewCur = ichNewCur;
  1864. *pichBeginCopy = ichBeginCopy;
  1865. *piArrayStart = iArray;
  1866. //LRetOnly:
  1867. return;
  1868. } /* fnRestoreDTC() */
  1869. void
  1870. CTriEditParse::fnSaveDTC(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  1871. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  1872. INT *pcDTC, UINT *pichNewCur, UINT *pichBeginCopy,
  1873. DWORD /*dwFlags*/)
  1874. {
  1875. // DTC case -
  1876. // if we get STARTSPAN, search backwords (carefully) for tokTag_BANG in pTokArray
  1877. // once we find that, remember the ibTokMin for DTC replacement
  1878. // once we get a ENDSPAN tagID, wait for upcoming toktag_CLOSE which will end DTC
  1879. // remember ibTokMac at that position. This is the DTC range.
  1880. // In pTokArray, start at METADATA and look for matching OBJECT & /OBJECT tokIDs
  1881. // Blt the OBJECT block over to ibTokMin and NULL remaining area in DEBUG build
  1882. UINT indexDTCStart, indexDTCEnd, cchDTCStart, cchDTCEnd;
  1883. UINT indexObjectStart, indexObjectEnd, cchObjectStart, cchObjectEnd;
  1884. BOOL fFindFirstObj;
  1885. UINT ichNewCur = *pichNewCur;
  1886. UINT ichBeginCopy = *pichBeginCopy;
  1887. UINT iArray = *piArrayStart;
  1888. INT cDTC = *pcDTC;
  1889. INT i;
  1890. INT ichClsid = 0; // init
  1891. LPOLESTR szClsid;
  1892. UINT iStartSpan;
  1893. LPWSTR pwNew = *ppwNew;
  1894. LPCWSTR rgCommentRT[] =
  1895. {
  1896. L" <!--DTCRUNTIME ",
  1897. L" DTCRUNTIME--> ",
  1898. L"-->",
  1899. };
  1900. LPCWSTR szDesignerControl[] =
  1901. {
  1902. L"\"DesignerControl\"",
  1903. L"DesignerControl",
  1904. };
  1905. BOOL fDesignerControlFound;
  1906. UINT iArraySav = iArray;
  1907. UINT ichObjectEndBegin, indexRTMac, indexRTStart;
  1908. BOOL fFirstDash;
  1909. UINT cbNeed;
  1910. indexDTCStart = indexDTCEnd = cchDTCStart = cchDTCEnd = 0;
  1911. indexObjectStart = indexObjectEnd = cchObjectStart = cchObjectEnd = 0;
  1912. ASSERT(cDTC >= 0); // make sure that this was initilized
  1913. if (cDTC == 0)
  1914. goto LRetOnly;
  1915. while (cDTC > 0)
  1916. {
  1917. // start at iArray of pTokArray and look for STARTSPAN
  1918. //while (pTokArray[iArray].token.tok != ft.tokBegin2)
  1919. // iArray++;
  1920. ASSERT(iArray < ptep->m_cMaxToken);
  1921. if (pTokArray[iArray].token.tok != TokAttrib_STARTSPAN)
  1922. goto LRet; // something is wrong
  1923. iStartSpan = iArray;
  1924. ASSERT(pTokArray[iArray].token.tok == TokAttrib_STARTSPAN);
  1925. ASSERT(pTokArray[iArray].token.tokClass == tokAttr);
  1926. i = iArray; // the position at which we found ft.tokBegin2
  1927. fDesignerControlFound = FALSE;
  1928. while (i >= 0)
  1929. {
  1930. // do we need to do anything else here?
  1931. if (pTokArray[i].token.tok == ft.tokBegin)
  1932. {
  1933. ASSERT(pTokArray[i].token.tok == TokTag_BANG);
  1934. ASSERT(pTokArray[i].token.tokClass == tokTag);
  1935. break;
  1936. }
  1937. if ( ( pTokArray[i].token.tokClass == tokString
  1938. && 0 == _wcsnicmp(szDesignerControl[0], &pwOld[pTokArray[i].token.ibTokMin], wcslen(szDesignerControl[0]))
  1939. )
  1940. || ( pTokArray[i].token.tokClass == tokValue
  1941. && 0 == _wcsnicmp(szDesignerControl[1], &pwOld[pTokArray[i].token.ibTokMin], wcslen(szDesignerControl[1]))
  1942. )
  1943. )
  1944. {
  1945. fDesignerControlFound = TRUE;
  1946. }
  1947. i--;
  1948. }
  1949. if (i >= 0) // found TokTag_BANG token
  1950. {
  1951. cchDTCStart = pTokArray[i].token.ibTokMin;
  1952. indexDTCStart = i;
  1953. }
  1954. else // error case
  1955. {
  1956. // we found STARTSPAN, but didn't find <! of <!--METADATA
  1957. // we can't process this DTC, so quit
  1958. goto LRet;
  1959. }
  1960. if (!fDesignerControlFound)
  1961. {
  1962. // we didn't find DesignerControl for the DTC, which means this is not the DTC we care about
  1963. // we can't process this DTC, so quit
  1964. iArray = iArraySav + 1;
  1965. goto LRet;
  1966. }
  1967. // now, look for ft.tokEnd2 i.e. TokAttrib_ENDSPAN
  1968. if ( pTokArray[iStartSpan].iNextprev != -1 /* validate */
  1969. && pTokArray[pTokArray[iStartSpan].iNextprev].token.tok == ft.tokEnd2)
  1970. {
  1971. ASSERT(pTokArray[pTokArray[iStartSpan].iNextprev].token.tokClass == tokAttr);
  1972. i = iStartSpan;
  1973. while (i < (int)ptep->m_cMaxToken && pTokArray[i].token.tok != TokElem_OBJECT)
  1974. i++;
  1975. if (i < (int)ptep->m_cMaxToken) // found the first <OBJECT> tag
  1976. indexObjectStart = i;
  1977. i = pTokArray[iStartSpan].iNextprev;
  1978. }
  1979. else // actually, we should have found ft.tokEnd2 in the if case, but if stack unwinding didn't happen correctly...
  1980. {
  1981. // on the way, look for 1st <OBJECT> tag
  1982. fFindFirstObj = TRUE;
  1983. i = iArray;
  1984. while (pTokArray[i].token.tok != ft.tokEnd2)
  1985. {
  1986. if (fFindFirstObj && pTokArray[i].token.tok == TokElem_OBJECT)
  1987. {
  1988. ASSERT(pTokArray[i].token.tokClass == tokElem);
  1989. indexObjectStart = i;
  1990. fFindFirstObj = FALSE;
  1991. }
  1992. i++;
  1993. if (i >= (int)ptep->m_cMaxToken)
  1994. break;
  1995. }
  1996. if (i >= (int)ptep->m_cMaxToken)
  1997. {
  1998. // we didn't find ENDSPAN before hitting ptep->m_cMaxToken
  1999. // we can't process this DTC, so quit
  2000. goto LRet;
  2001. }
  2002. }
  2003. ASSERT(pTokArray[i].token.tok == TokAttrib_ENDSPAN);
  2004. ASSERT(pTokArray[i].token.tokClass == tokAttr);
  2005. // from this i'th position, look backwards to find '<!' of '<!--METADATA ...endspan...'
  2006. indexRTMac = i;
  2007. while (indexRTMac > indexObjectStart)
  2008. {
  2009. if ( pTokArray[indexRTMac].token.tok == TokTag_BANG
  2010. && pTokArray[indexRTMac].token.tokClass == tokTag
  2011. )
  2012. {
  2013. break;
  2014. }
  2015. indexRTMac--;
  2016. }
  2017. if (indexRTMac <= indexObjectStart) // error case
  2018. goto LRet;
  2019. // save this ith position to find last </OBJECT> tag
  2020. indexObjectEnd = indexObjectStart;
  2021. // from this ith poistion, look for ft.tokEnd
  2022. while (i < (int)ptep->m_cMaxToken)
  2023. {
  2024. if (pTokArray[i].token.tok == ft.tokEnd)
  2025. {
  2026. ASSERT(pTokArray[i].token.tok == TokTag_CLOSE);
  2027. ASSERT(pTokArray[i].token.tokClass == tokTag);
  2028. break;
  2029. }
  2030. i++;
  2031. }
  2032. if (i < (int)ptep->m_cMaxToken) // found TokTag_CLOSE token
  2033. {
  2034. cchDTCEnd = pTokArray[i].token.ibTokMac;
  2035. indexDTCEnd = i;
  2036. }
  2037. else
  2038. {
  2039. // we didn't find TokTag_CLOSE after ENDSPAN,
  2040. // we can't process this DTC, so quit
  2041. goto LRet;
  2042. }
  2043. // look forward from indexObjectEnd for the </OBJECT> tag
  2044. while (indexObjectEnd < ptep->m_cMaxToken)
  2045. {
  2046. if ( pTokArray[indexObjectEnd].token.tok == TokElem_OBJECT
  2047. && pTokArray[indexObjectEnd].token.tokClass == tokElem
  2048. && pTokArray[indexObjectEnd-1].token.tok == TokTag_END /* </ */
  2049. )
  2050. break;
  2051. indexObjectEnd++;
  2052. }
  2053. if (indexObjectEnd >= ptep->m_cMaxToken) // didn't find </OBJECT>, error case
  2054. {
  2055. goto LRet;
  2056. }
  2057. if (indexObjectEnd > indexObjectStart) // </OBJECT> found
  2058. {
  2059. // get ibTokMin of the previous < tag for indexObjectStart
  2060. i = indexObjectStart;
  2061. // generally, the previous tag should be the one we want,
  2062. // but this covers the boundary cases
  2063. while (i > (int)indexDTCStart)
  2064. {
  2065. if (pTokArray[i].token.tok == TokTag_START)
  2066. {
  2067. ASSERT(pTokArray[i].token.tokClass == tokTag);
  2068. break;
  2069. }
  2070. i--;
  2071. }
  2072. //ASSERT(i > (int)indexDTCStart+1); // atleast
  2073. cchObjectStart = pTokArray[i].token.ibTokMin;
  2074. // get ibTokMac of the next > tag for indexObjectEnd
  2075. i = indexObjectEnd;
  2076. // generally, the next tag should be the one we want,
  2077. // but this covers the boundary cases
  2078. while (i < (int)indexDTCEnd)
  2079. {
  2080. if (pTokArray[i].token.tok == TokTag_CLOSE)
  2081. {
  2082. ASSERT(pTokArray[i].token.tokClass == tokTag);
  2083. break;
  2084. }
  2085. i++;
  2086. }
  2087. ASSERT(i < (int)indexDTCEnd -1); // atleast
  2088. cchObjectEnd = pTokArray[i].token.ibTokMac; // do we need -1 here?
  2089. }
  2090. else
  2091. goto LRet;
  2092. // from indexObjectEnd look backwards to get tokTag_END
  2093. indexRTStart = i+1;
  2094. i = indexObjectEnd;
  2095. while (i > (int)indexObjectStart) // we don't have to go this far
  2096. {
  2097. if ( pTokArray[i].token.tok == TokTag_END
  2098. && pTokArray[i].token.tokClass == tokTag
  2099. )
  2100. {
  2101. break;
  2102. }
  2103. i--;
  2104. }
  2105. if (i <= (int)indexObjectStart) // error case, do we care?
  2106. goto LRet;
  2107. ichObjectEndBegin = pTokArray[i].token.ibTokMin;
  2108. iArray = indexDTCEnd; // set it for next DTC entry
  2109. // now Replace the DTC
  2110. // ichBeginCopy is a position in pwOld and
  2111. // ichNewCur is a position in pwNew
  2112. // copy from ichBeginCopy to begining of DTC
  2113. if ((int)(cchDTCStart-ichBeginCopy) >= 0)
  2114. {
  2115. cbNeed = (ichNewCur+cchDTCStart-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  2116. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2117. goto LSkipCopy;
  2118. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2119. (BYTE *)(&pwOld[ichBeginCopy]),
  2120. (cchDTCStart-ichBeginCopy)*sizeof(WCHAR));
  2121. ichNewCur += (cchDTCStart-ichBeginCopy);
  2122. ichBeginCopy = cchDTCEnd; // make it ready for next copy
  2123. }
  2124. i = indexObjectStart;
  2125. while (i < (int)indexObjectEnd)
  2126. {
  2127. if (pTokArray[i].token.tok == TokAttrib_CLASSID)
  2128. {
  2129. ASSERT(pTokArray[i].token.tokClass == tokAttr);
  2130. break;
  2131. }
  2132. i++;
  2133. }
  2134. if (i < (int)indexObjectEnd -1) // found TokAttrib_CLASSID
  2135. {
  2136. // make sure that the next one is tokOpEqual
  2137. ASSERT(pTokArray[i+1].token.tokClass == tokOp);
  2138. // make sure that the next one is the id and get that value
  2139. //ASSERT(pTokArray[i].token.tok == );
  2140. // Is there any other way to skip "clsid:" string that appears before the clsid?
  2141. ichClsid = pTokArray[i+2].token.ibTokMin + strlen("clsid:");
  2142. // This is a HACK to fix DaVinci's bug, where they can't handle non-quoted
  2143. // classId
  2144. if (pwOld[pTokArray[i+2].token.ibTokMin] == '"')
  2145. ichClsid++;
  2146. }
  2147. if (ptep->m_fInHdrIn)
  2148. {
  2149. if ( (S_OK == StringFromCLSID(CLSID_PageTr, &szClsid))
  2150. && (0 == _wcsnicmp(szClsid+1/* for {*/, &pwOld[ichClsid], sizeof(CLSID)))
  2151. )
  2152. {
  2153. // copy the object part of the DTC into m_pPTDTC
  2154. if (ptep->m_pPTDTC != NULL) // means that we have more than one PTDTC on the page
  2155. goto LMultPTDTC;
  2156. ptep->m_hgPTDTC = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, (cchObjectEnd-cchObjectStart)*sizeof(WCHAR));
  2157. // if the allocation failed, just don't copy into ptep->m_hgPTDTC
  2158. if (ptep->m_hgPTDTC != NULL)
  2159. {
  2160. ptep->m_pPTDTC = (WORD *) GlobalLock(ptep->m_hgPTDTC);
  2161. ASSERT(ptep->m_pPTDTC != NULL);
  2162. memcpy( (BYTE *)(ptep->m_pPTDTC),
  2163. (BYTE *)(&pwOld[cchObjectStart]),
  2164. (cchObjectEnd-cchObjectStart)*sizeof(WCHAR));
  2165. ptep->m_cchPTDTCObj = cchObjectEnd-cchObjectStart;
  2166. ptep->m_ichPTDTC = cchDTCStart; // with respect to the saved header
  2167. ptep->m_cchPTDTC = cchDTCEnd - cchDTCStart;
  2168. ::CoTaskMemFree(szClsid);
  2169. goto LSkipCopy;
  2170. }
  2171. }
  2172. LMultPTDTC:
  2173. ::CoTaskMemFree(szClsid);
  2174. }
  2175. cbNeed = (ichNewCur+(cchObjectEnd-cchObjectStart)+(pTokArray[indexRTMac].token.ibTokMin-cchObjectEnd)+wcslen(rgCommentRT[0])+wcslen(rgCommentRT[1]))*sizeof(WCHAR)+cbBufPadding;
  2176. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2177. goto LSkipCopy;
  2178. // STEP 1 - copy till the begining of </OBJECT>
  2179. ASSERT((int)(ichObjectEndBegin-cchObjectStart) >= 0);
  2180. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2181. (BYTE *)(&pwOld[cchObjectStart]),
  2182. (ichObjectEndBegin-cchObjectStart)*sizeof(WCHAR));
  2183. ichNewCur += ichObjectEndBegin-cchObjectStart;
  2184. // STEP 2 - Insert the runtime text as a comment
  2185. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2186. (BYTE *)(rgCommentRT[0]),
  2187. wcslen(rgCommentRT[0])*sizeof(WCHAR));
  2188. ichNewCur += wcslen(rgCommentRT[0]);
  2189. // we need to loop thr indexRTStart & indexRTMac and copy token by token
  2190. // and modify TokTag_BANG on the way
  2191. fFirstDash = TRUE;
  2192. while (indexRTStart < indexRTMac)
  2193. {
  2194. // (4/14/98)
  2195. // VID-BUG 17453 Fotm Manager DTC puts in 0x0d (\r) as an end of line instead of
  2196. // putting 0x0d 0xa (\r\n) as an end of line.
  2197. // In this case, the token thats generated is tokIdentifier => "0x0d - - >"
  2198. // instead of getting 3 separate tokens for the normal case as "0x0d 0x0a"
  2199. // & "- -" & ">".
  2200. // Two ways to fix this problem ...
  2201. // 1. Handle this would be in our tokenizer that treats "0x0d" as an
  2202. // end of line as well. But at this time, its not a safe change to do.
  2203. // 2. In the below if condition, add the fact that we may have "0x0d" followed
  2204. // by "-->" for end of metadata comment.
  2205. if ( fFirstDash
  2206. && ( (0 == _wcsnicmp(rgCommentRT[2], &pwOld[pTokArray[indexRTStart].token.ibTokMin], wcslen(rgCommentRT[2])))
  2207. || ( (0 == _wcsnicmp(rgCommentRT[2], &pwOld[pTokArray[indexRTStart].token.ibTokMin+1], wcslen(rgCommentRT[2])))
  2208. && (pwOld[pTokArray[indexRTStart].token.ibTokMin] == 0x0d)
  2209. )
  2210. )
  2211. )
  2212. {
  2213. indexRTStart++;
  2214. fFirstDash = FALSE;
  2215. continue;
  2216. }
  2217. memcpy( (BYTE *)&pwNew[ichNewCur],
  2218. (BYTE *)&pwOld[pTokArray[indexRTStart].token.ibTokMin],
  2219. (pTokArray[indexRTStart].token.ibTokMac-pTokArray[indexRTStart].token.ibTokMin)*sizeof(WCHAR)
  2220. );
  2221. ichNewCur += pTokArray[indexRTStart].token.ibTokMac-pTokArray[indexRTStart].token.ibTokMin;
  2222. if ( pTokArray[indexRTStart].token.tok == TokTag_BANG
  2223. && pTokArray[indexRTStart].token.tokClass == tokTag
  2224. )
  2225. {
  2226. pwNew[ichNewCur-2] = '?';
  2227. }
  2228. if ( pTokArray[indexRTStart].token.tok == TokTag_CLOSE
  2229. && pTokArray[indexRTStart].token.tokClass == tokTag
  2230. && pwOld[pTokArray[indexRTStart-1].token.ibTokMac-1] == '-'
  2231. && pwOld[pTokArray[indexRTStart-1].token.ibTokMac-2] == '-'
  2232. )
  2233. {
  2234. pwNew[ichNewCur-1] = '?';
  2235. }
  2236. // following is a hack for the NavBar DTC
  2237. if ( pTokArray[indexRTStart].token.tok == TokElem_METADATA
  2238. && pTokArray[indexRTStart].token.tokClass == tokElem
  2239. )
  2240. {
  2241. pwNew[ichNewCur-1] = '?';
  2242. }
  2243. indexRTStart++;
  2244. } // while ()
  2245. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2246. (BYTE *)(rgCommentRT[1]),
  2247. wcslen(rgCommentRT[1])*sizeof(WCHAR));
  2248. ichNewCur += wcslen(rgCommentRT[1]);
  2249. // STEP 3 - copy the rest of the object, i.e. the </OBJECT> tag
  2250. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2251. (BYTE *)(&pwOld[ichObjectEndBegin]),
  2252. (cchObjectEnd-ichObjectEndBegin)*sizeof(WCHAR));
  2253. ichNewCur += cchObjectEnd-ichObjectEndBegin;
  2254. LSkipCopy:
  2255. cDTC--;
  2256. } // while (cDTC > 0)
  2257. LRet:
  2258. *pcchNew = ichNewCur;
  2259. *ppwNew = pwNew;
  2260. *pichNewCur = ichNewCur;
  2261. *pichBeginCopy = ichBeginCopy;
  2262. *piArrayStart = iArray;
  2263. LRetOnly:
  2264. return;
  2265. } /* fnSaveDTC() */
  2266. void
  2267. CTriEditParse::fnSaveHtmlTag(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  2268. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  2269. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  2270. DWORD /*dwFlags*/)
  2271. {
  2272. BOOL fFoundTag, fFoundHtmlBegin;
  2273. INT i;
  2274. UINT cchHtml, iHtmlBegin, iHtmlEnd;
  2275. UINT ichNewCur = *pichNewCur;
  2276. UINT ichBeginCopy = *pichBeginCopy;
  2277. UINT iArray = *piArrayStart;
  2278. LPWSTR pwNew = *ppwNew;
  2279. UINT cbNeed;
  2280. // assert that iArray'th element in pTokArry is TokTag_HTML
  2281. // Look for any non -1 tags before iArray
  2282. // if we find any, it indicates that we have some stuff before <HTML> that trident doesn't like
  2283. // in pwNew, move all ichNewCur bytes (copied so far) to make space for <HTML> at the begining
  2284. // copy from pwOld <HTML location=> tag
  2285. // adjust ichNewCur and ichBeginCopy
  2286. // **** don't bother about maintaning info about <HTML> tag's location for Restore
  2287. ASSERT(pTokArray[iArray].token.tok == TokElem_HTML);
  2288. iHtmlBegin = i = iArray-1; // init
  2289. fFoundTag = fFoundHtmlBegin = FALSE;
  2290. while (i >= 0)
  2291. {
  2292. if (pTokArray[i].token.tokClass == tokElem || pTokArray[i].token.tokClass == tokSSS)
  2293. {
  2294. fFoundTag = TRUE;
  2295. break;
  2296. }
  2297. if (!fFoundHtmlBegin && pTokArray[i].token.tok == ft.tokBegin) // look for < of <HTML>
  2298. {
  2299. fFoundHtmlBegin = TRUE;
  2300. iHtmlBegin = i; // generally, this should be the right before TokElem_HTML
  2301. }
  2302. i--;
  2303. }
  2304. if (!fFoundHtmlBegin) // we didn't find < for <HTML>, so we are in deep trouble, lets quit here
  2305. {
  2306. goto LRet;
  2307. }
  2308. if (!fFoundTag) // we didn't find any tag before TokElem_HTML, so we don't need to do anything, quit
  2309. {
  2310. goto LRet;
  2311. }
  2312. // move <HTML> tag at the begining of pwNew
  2313. i = iHtmlBegin; // iArray;
  2314. ASSERT(pTokArray[i].token.tok == TokTag_START);
  2315. ASSERT(pTokArray[i].token.tokClass == tokTag);
  2316. // look for > of <HTML>
  2317. while (i < (int)ptep->m_cMaxToken) // generally, this will be the very next tag, but this covers boundary cases
  2318. {
  2319. if (pTokArray[i].token.tok == ft.tokEnd)
  2320. break;
  2321. i++;
  2322. }
  2323. if (i >= (int)ptep->m_cMaxToken) // error case, didn't find > of <HTML>, so quit
  2324. {
  2325. iArray++; // so that we won't come back here for the same token
  2326. goto LRet;
  2327. }
  2328. iHtmlEnd = i; // found > of <HTML>
  2329. iArray = i; // set it after > of <HTML>
  2330. cbNeed = (ichNewCur+pTokArray[iHtmlBegin].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  2331. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2332. goto LRet;
  2333. // copy till begining of the <HTML>
  2334. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2335. (BYTE *)(&pwOld[ichBeginCopy]),
  2336. (pTokArray[iHtmlBegin].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  2337. ichNewCur += pTokArray[iHtmlBegin].token.ibTokMin-ichBeginCopy;
  2338. ichBeginCopy = pTokArray[iHtmlEnd].token.ibTokMac; // set it for next thing
  2339. // move all the stuff from pwNew+0 till pwNew+ichNewCur by cchHtml (make space for <HTML>)
  2340. cchHtml = pTokArray[iHtmlEnd].token.ibTokMac-pTokArray[iHtmlBegin].token.ibTokMin;
  2341. memmove((BYTE *)(&pwNew[cchHtml]),
  2342. (BYTE *)pwNew,
  2343. ichNewCur*sizeof(WCHAR));
  2344. ichNewCur += cchHtml;
  2345. // copy <HTML>
  2346. memcpy( (BYTE *)pwNew,
  2347. (BYTE *)(&pwOld[pTokArray[iHtmlBegin].token.ibTokMin]),
  2348. cchHtml*sizeof(WCHAR));
  2349. LRet:
  2350. *pcchNew = ichNewCur;
  2351. *ppwNew = pwNew;
  2352. *pichNewCur = ichNewCur;
  2353. *pichBeginCopy = ichBeginCopy;
  2354. *piArrayStart = iArray;
  2355. } /* fnSaveHtmlTag() */
  2356. void
  2357. CTriEditParse::fnRestoreHtmlTag(CTriEditParse* /*ptep*/, LPWSTR /*pwOld*/,
  2358. LPWSTR* /*ppwNew*/, UINT* /*pcchNew*/, HGLOBAL* /*phgNew*/,
  2359. TOKSTRUCT* /*pTokArray*/, UINT* /*piArrayStart*/, FilterTok /*ft*/,
  2360. INT* /*pcHtml*/, UINT* /*pichNewCur*/, UINT* /*pichBeginCopy*/,
  2361. DWORD /*dwFlags*/)
  2362. {
  2363. // ****
  2364. // because we didn't save any info about <HTML> tag's location for Restore, we just return
  2365. return;
  2366. } /* fnRestoreHtmlTag() */
  2367. void
  2368. CTriEditParse::fnSaveNBSP(CTriEditParse* /*ptep*/, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  2369. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  2370. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  2371. DWORD /*dwFlags*/)
  2372. {
  2373. UINT ichNewCur = *pichNewCur;
  2374. UINT ichBeginCopy = *pichBeginCopy;
  2375. UINT iArray = *piArrayStart;
  2376. LPWSTR pwNew = *ppwNew;
  2377. LPCWSTR szNBSP[] = {L"&NBSP"};
  2378. LPCWSTR szNBSPlower[] = {L"&nbsp;"};
  2379. INT ichNbspStart, ichNbspEnd;
  2380. UINT cbNeed;
  2381. // see if pwOld[pTokArray->token.ibtokMin] matches with "&nbsp",
  2382. // and convert it to lower case
  2383. ASSERT(pTokArray[iArray].token.tokClass == tokEntity);
  2384. if (0 == _wcsnicmp(szNBSP[0], &pwOld[pTokArray[iArray].token.ibTokMin], wcslen(szNBSP[0])))
  2385. {
  2386. // ichBeginCopy is a position in pwOld and
  2387. // ichNewCur is a position in pwNew
  2388. // copy from ichBeginCopy to begining of &nbsp
  2389. // check if we have enough memory - If not, realloc
  2390. ichNbspStart = pTokArray[iArray].token.ibTokMin;
  2391. ichNbspEnd = pTokArray[iArray].token.ibTokMac;
  2392. cbNeed = (ichNewCur+ichNbspStart-ichBeginCopy+wcslen(szNBSPlower[0]))*sizeof(WCHAR)+cbBufPadding;
  2393. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2394. goto LErrorRet;
  2395. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2396. (BYTE *)(&pwOld[ichBeginCopy]),
  2397. (ichNbspStart-ichBeginCopy)*sizeof(WCHAR));
  2398. ichNewCur += (ichNbspStart-ichBeginCopy);
  2399. ichBeginCopy = ichNbspEnd; // make it ready for next copy
  2400. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2401. (BYTE *)(szNBSPlower[0]),
  2402. (wcslen(szNBSPlower[0]))*sizeof(WCHAR));
  2403. ichNewCur += wcslen(szNBSPlower[0]);
  2404. }
  2405. LErrorRet:
  2406. iArray++; // so that we won't look at the same token again
  2407. //LRet:
  2408. *pcchNew = ichNewCur;
  2409. *ppwNew = pwNew;
  2410. *pichNewCur = ichNewCur;
  2411. *pichBeginCopy = ichBeginCopy;
  2412. *piArrayStart = iArray;
  2413. } /* fnSaveNBSP() */
  2414. void
  2415. CTriEditParse::fnRestoreNBSP(CTriEditParse* /*ptep*/, LPWSTR /*pwOld*/,
  2416. LPWSTR* /*ppwNew*/, UINT* /*pcchNew*/, HGLOBAL* /*phgNew*/,
  2417. TOKSTRUCT* /*pTokArray*/, UINT* /*piArrayStart*/, FilterTok /*ft*/,
  2418. INT* /*pcHtml*/, UINT* /*pichNewCur*/, UINT* /*pichBeginCopy*/,
  2419. DWORD /*dwFlags*/)
  2420. {
  2421. return;
  2422. } /* fnRestoreNBSP() */
  2423. BOOL
  2424. FIsSpecialTag(TOKSTRUCT *pTokArray, int iTag, WCHAR* /*pwOld*/)
  2425. {
  2426. BOOL fRet = FALSE;
  2427. if ( ( pTokArray[iTag].token.tokClass == tokSpace
  2428. || pTokArray[iTag].token.tokClass == tokComment)
  2429. && pTokArray[iTag].token.tok == 0
  2430. && iTag > 0
  2431. && ( pTokArray[iTag-1].token.tok == TokTag_START
  2432. || pTokArray[iTag-1].token.tok == TokTag_PI
  2433. || ( pTokArray[iTag-1].token.tok == TokTag_BANG
  2434. && pTokArray[iTag+1].token.tok == TokTag_CLOSE
  2435. && pTokArray[iTag+1].token.tokClass == tokTag
  2436. )
  2437. )
  2438. && pTokArray[iTag-1].token.tokClass == tokTag
  2439. )
  2440. {
  2441. fRet = TRUE;
  2442. #ifdef WFC_FIX
  2443. int cch = pTokArray[iTag].token.ibTokMac-pTokArray[iTag].token.ibTokMin;
  2444. WCHAR *pStr = new WCHAR[cch+1];
  2445. WCHAR *pFound = NULL;
  2446. // see if this is xml tag
  2447. // for now we will check tags that have a ':' in them.
  2448. // NOTE - This will get changed when parser change to recognise xml tags is made
  2449. if (pStr != NULL)
  2450. {
  2451. memcpy( (BYTE *)pStr,
  2452. (BYTE *)&pwOld[pTokArray[iTag].token.ibTokMin],
  2453. cch*sizeof(WCHAR));
  2454. pStr[cch] = '\0';
  2455. pFound = wcschr(pStr, ':');
  2456. if (pFound)
  2457. fRet = TRUE;
  2458. delete pStr;
  2459. }
  2460. #endif //WFC_FIX
  2461. }
  2462. return(fRet);
  2463. }
  2464. void
  2465. GetTagRange(TOKSTRUCT *pTokArray, int iArrayLast, int *piTag, int *pichTokTagClose, BOOL fMatch)
  2466. {
  2467. int index = *piTag;
  2468. int iTokTagClose = -1;
  2469. if (fMatch) // we should look fot pTokArray[iTag].iNextprev
  2470. {
  2471. if (pTokArray[*piTag].iNextprev == -1)
  2472. goto LRet;
  2473. index = pTokArray[*piTag].iNextprev; // that way, we will look for '>' after matching end
  2474. }
  2475. // look for TokTag_CLOSE, from iTag onwards
  2476. while (index < iArrayLast)
  2477. {
  2478. if ( pTokArray[index].token.tokClass == tokTag
  2479. && pTokArray[index].token.tok == TokTag_CLOSE)
  2480. {
  2481. iTokTagClose = index;
  2482. break;
  2483. }
  2484. index++;
  2485. }
  2486. if (iTokTagClose != -1) // we found it
  2487. {
  2488. *pichTokTagClose = pTokArray[iTokTagClose].token.ibTokMac;
  2489. *piTag = iTokTagClose + 1;
  2490. }
  2491. LRet:
  2492. return;
  2493. } /* GetTagRange() */
  2494. void CTriEditParse::fnSaveHdr(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  2495. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  2496. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD dwFlags)
  2497. {
  2498. UINT ichNewCur = *pichNewCur;
  2499. UINT ichBeginCopy = *pichBeginCopy;
  2500. UINT iArray = *piArrayStart;
  2501. LPWSTR pwNew = *ppwNew;
  2502. INT cchBeforeBody = 0;
  2503. UINT i, iFound;
  2504. WCHAR *pHdr;
  2505. UINT cbNeed;
  2506. if (ptep->m_hgDocRestore == NULL)
  2507. goto LRetOnly;
  2508. // lock
  2509. pHdr = (WCHAR *)GlobalLock(ptep->m_hgDocRestore);
  2510. ASSERT(pHdr != NULL);
  2511. // look forward to make sure that we don't have multiple <BODY> tags
  2512. // this may be a result of a typo in user's document or trident inserting it
  2513. i = iArray+1;
  2514. iFound = iArray;
  2515. while (i < ptep->m_cMaxToken)
  2516. {
  2517. if ( (pTokArray[i].token.tok == TokElem_BODY)
  2518. && (pTokArray[i].token.tokClass == tokElem)
  2519. && (pTokArray[i-1].token.tok == TokTag_START)
  2520. && (pTokArray[i-1].token.tokClass == tokTag)
  2521. )
  2522. {
  2523. iFound = i;
  2524. break;
  2525. }
  2526. i++;
  2527. }
  2528. if (iFound > iArray) // this means that we found the last <BODY> tag Trident inserted
  2529. iArray = iFound;
  2530. ASSERT(pTokArray[iArray].token.tok == TokElem_BODY);
  2531. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  2532. // what if we DON'T have a <BODY> tag at all. We would have found </BODY> here.
  2533. // If thats the case, we just don't save anything
  2534. ASSERT(iArray-1 >= 0);
  2535. if (pTokArray[iArray-1].token.tok != TokTag_START)
  2536. cchBeforeBody = 0;
  2537. else
  2538. cchBeforeBody = pTokArray[iArray].token.ibTokMin;
  2539. // realloc if needed
  2540. if (cchBeforeBody*sizeof(WCHAR)+sizeof(int) > GlobalSize(ptep->m_hgDocRestore))
  2541. {
  2542. HGLOBAL hgDocRestore;
  2543. GlobalUnlock(ptep->m_hgDocRestore);
  2544. hgDocRestore = ptep->m_hgDocRestore;
  2545. #pragma prefast(suppress:308, "noise")
  2546. ptep->m_hgDocRestore = GlobalReAlloc(ptep->m_hgDocRestore, cchBeforeBody*sizeof(WCHAR)+sizeof(int), GMEM_MOVEABLE|GMEM_ZEROINIT);
  2547. // if this alloc failed, we may still want to continue
  2548. if (ptep->m_hgDocRestore == NULL)
  2549. {
  2550. GlobalFree(hgDocRestore);
  2551. goto LRet;
  2552. }
  2553. else
  2554. {
  2555. pHdr = (WCHAR *)GlobalLock(ptep->m_hgDocRestore); // do we need to unlock this first?
  2556. ASSERT(pHdr != NULL);
  2557. }
  2558. }
  2559. // copy from pwOld
  2560. memcpy( (BYTE *)pHdr,
  2561. (BYTE *)&cchBeforeBody,
  2562. sizeof(INT));
  2563. memcpy( (BYTE *)(pHdr)+sizeof(INT),
  2564. (BYTE *)pwOld,
  2565. cchBeforeBody*sizeof(WCHAR));
  2566. // reconstruct the pre_BODY part of the document
  2567. // NOTE - for next time around ...
  2568. // If we get the title & body tags from pwNew instead of pwOld, we won't
  2569. // loose the DESIGNTIMESPs for those 2 tags
  2570. if (cchBeforeBody > 0)
  2571. {
  2572. int iTag = 0;
  2573. int ichTokTagClose = -1;
  2574. BOOL fMatch = FALSE;
  2575. LPCWSTR rgSpaceTags[] =
  2576. {
  2577. L" DESIGNTIMESP=",
  2578. L" designtimesp=",
  2579. };
  2580. WCHAR szIndex[cchspBlockMax]; // will we have more than 20 digit numbers as number of DESIGNTIMESPx?
  2581. int index = iArray;
  2582. int ichBodyTokenStart, ichBodyTokenEnd;
  2583. LPCWSTR rgPreBody[] = {L"<BODY",};
  2584. memset((BYTE *)pwNew, 0, ichNewCur*sizeof(WCHAR));
  2585. // if we have a unicode stream, we should preserve 0xff,0xfe that occurs at the
  2586. // beginning of the file
  2587. ichNewCur = 0;
  2588. if (ptep->m_fUnicodeFile)
  2589. {
  2590. memcpy((BYTE *)pwNew, (BYTE *)pwOld, sizeof(WCHAR));
  2591. ichNewCur = 1;
  2592. }
  2593. // loop through all tags starting from index of '<' of <html> till iArray
  2594. // if the tag we see is one of the following, then copy that tag into pwNew
  2595. // ------------------------------------------------------------------------
  2596. // <HTML>, <HEAD>..</HEAD>, <TITLE>..</TITLE>, <STYLE>..</STYLE>,
  2597. // <LINK>, <BASE>, <BASEFONT>
  2598. // ------------------------------------------------------------------------
  2599. iTag = 0;
  2600. ichTokTagClose = -1;
  2601. while (iTag < (int)iArray)
  2602. {
  2603. if ( pTokArray[iTag].token.tokClass == tokAttr
  2604. && pTokArray[iTag].token.tok == TokAttrib_STARTSPAN)
  2605. {
  2606. GetTagRange(pTokArray, iArray, &iTag, &ichTokTagClose, TRUE);
  2607. }
  2608. else if ( ( (pTokArray[iTag].token.tokClass == tokElem)
  2609. && ( pTokArray[iTag].token.tok == TokElem_HTML
  2610. || pTokArray[iTag].token.tok == TokElem_HEAD
  2611. || pTokArray[iTag].token.tok == TokElem_META
  2612. || pTokArray[iTag].token.tok == TokElem_LINK
  2613. || pTokArray[iTag].token.tok == TokElem_BASE
  2614. || pTokArray[iTag].token.tok == TokElem_BASEFONT
  2615. || pTokArray[iTag].token.tok == TokElem_TITLE
  2616. || pTokArray[iTag].token.tok == TokElem_STYLE
  2617. || pTokArray[iTag].token.tok == TokElem_OBJECT
  2618. )
  2619. )
  2620. || (FIsSpecialTag(pTokArray, iTag, pwOld))
  2621. )
  2622. {
  2623. int iTagSav = iTag;
  2624. fMatch = FALSE;
  2625. ichTokTagClose = -1;
  2626. if ( pTokArray[iTag].token.tok == TokElem_TITLE
  2627. || pTokArray[iTag].token.tok == TokElem_STYLE
  2628. || pTokArray[iTag].token.tok == TokElem_OBJECT
  2629. )
  2630. fMatch = TRUE;
  2631. GetTagRange(pTokArray, iArray, &iTag, &ichTokTagClose, fMatch);
  2632. if (ichTokTagClose != -1)
  2633. {
  2634. // copy the stuff into pwNew
  2635. pwNew[ichNewCur++] = '<';
  2636. if ( pTokArray[iTagSav-1].token.tok == TokTag_END
  2637. && pTokArray[iTagSav-1].token.tokClass == tokTag)
  2638. {
  2639. pwNew[ichNewCur++] = '/';
  2640. }
  2641. else if ( pTokArray[iTagSav-1].token.tok == TokTag_PI
  2642. && pTokArray[iTagSav-1].token.tokClass == tokTag)
  2643. {
  2644. pwNew[ichNewCur++] = '?';
  2645. }
  2646. else if ( pTokArray[iTagSav-1].token.tok == TokTag_BANG
  2647. && pTokArray[iTagSav-1].token.tokClass == tokTag)
  2648. {
  2649. pwNew[ichNewCur++] = '!';
  2650. }
  2651. memcpy( (BYTE *)&pwNew[ichNewCur],
  2652. (BYTE *)&pwOld[pTokArray[iTagSav].token.ibTokMin],
  2653. (ichTokTagClose-pTokArray[iTagSav].token.ibTokMin)*sizeof(WCHAR));
  2654. ichNewCur += ichTokTagClose-pTokArray[iTagSav].token.ibTokMin;
  2655. // do we want to add \r\n after each tag we copy?
  2656. }
  2657. else
  2658. goto LNext;
  2659. }
  2660. else
  2661. {
  2662. LNext:
  2663. iTag++;
  2664. }
  2665. } // while (iTag < (int)iArray)
  2666. // we know that iArray is currently pointing to tokElem_BODY
  2667. // go backwards and look for '<', so that we can copy from that point
  2668. ASSERT(pTokArray[iArray].token.tok == TokElem_BODY);
  2669. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  2670. index = iArray;
  2671. while (index >= 0)
  2672. {
  2673. if ( pTokArray[index].token.tok == TokTag_START
  2674. && pTokArray[index].token.tokClass == tokTag)
  2675. {
  2676. break;
  2677. }
  2678. index--;
  2679. }
  2680. if (index < 0) // error case, we didn't find '<' before BODY
  2681. goto LSkipBody;
  2682. ichBodyTokenStart = pTokArray[index].token.ibTokMin;
  2683. // now go forward till we get the '>' of <BODY>, we don't have to go this far,
  2684. // but this covers boundary cases
  2685. index = iArray;
  2686. while (index < (int)ptep->m_cMaxToken)
  2687. {
  2688. if ( pTokArray[index].token.tok == TokTag_CLOSE
  2689. && pTokArray[index].token.tokClass == tokTag)
  2690. {
  2691. break;
  2692. }
  2693. index++;
  2694. }
  2695. if (index > (int)ptep->m_cMaxToken) // error case, we didn't find '>' before BODY
  2696. goto LSkipBody;
  2697. ichBodyTokenEnd = pTokArray[index-1].token.ibTokMac; // BUG 15391 - don't copy TokTag_CLOSE here, it gets added later
  2698. // blt part of the <BODY> tag into pwNew. (BUG 15391 - excluding the ending >)
  2699. ASSERT(ichBodyTokenEnd-ichBodyTokenStart >= 0);
  2700. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)&pwOld[ichBodyTokenStart], (ichBodyTokenEnd-ichBodyTokenStart)*sizeof(WCHAR));
  2701. ichNewCur += (ichBodyTokenEnd-ichBodyTokenStart);
  2702. // only if spacing flag is set
  2703. if (dwFlags & dwPreserveSourceCode)
  2704. {
  2705. // BUG 15391 - insert DESIGNTIMESP with (ptep->m_ispInfoBlock+ptep->m_ispInfoBase-1) & add '>' at the end
  2706. ASSERT(wcslen(rgSpaceTags[1]) == wcslen(rgSpaceTags[0]));
  2707. if (iswupper(pwOld[pTokArray[iArray].token.ibTokMin]) != 0) // upper case - BUG 15389
  2708. {
  2709. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)rgSpaceTags[0], wcslen(rgSpaceTags[0])*sizeof(WCHAR));
  2710. ichNewCur += wcslen(rgSpaceTags[0]);
  2711. }
  2712. else
  2713. {
  2714. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)rgSpaceTags[1], wcslen(rgSpaceTags[1])*sizeof(WCHAR));
  2715. ichNewCur += wcslen(rgSpaceTags[1]);
  2716. }
  2717. (WCHAR)_itow(ptep->m_ispInfoBlock+ptep->m_ispInfoBase-1, szIndex, 10);
  2718. ASSERT(wcslen(szIndex) < sizeof(szIndex));
  2719. memcpy( (BYTE *)(pwNew+ichNewCur),
  2720. (BYTE *)(szIndex),
  2721. wcslen(szIndex)*sizeof(WCHAR));
  2722. ichNewCur += wcslen(szIndex);
  2723. }
  2724. goto LBodyCopyDone;
  2725. LSkipBody:
  2726. // if we skipped copying <BODY> tag, we must put in a dummy <BODY> at ichNewCur
  2727. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)rgPreBody[0], wcslen(rgPreBody[0])*sizeof(WCHAR));
  2728. ichNewCur = wcslen(rgPreBody[0]);
  2729. LBodyCopyDone:
  2730. pwNew[ichNewCur++] = '>'; //ending '>' that we skipped copying before
  2731. // set ichBeginCopy and iArray appropriately
  2732. iArray = index+1;
  2733. ichBeginCopy = pTokArray[iArray].token.ibTokMin;
  2734. }
  2735. // Copy everything upto and including <BODY>
  2736. //LSkipCopy:
  2737. if (ptep->m_pPTDTC != NULL) // we had saved PageTransitionDTC in a temporary
  2738. {
  2739. ASSERT(ptep->m_cchPTDTCObj >= 0);
  2740. cbNeed = (ichNewCur+ptep->m_cchPTDTCObj)*sizeof(WCHAR)+cbBufPadding;
  2741. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2742. goto LRet;
  2743. memcpy( (BYTE *)&pwNew[ichNewCur],
  2744. (BYTE *)ptep->m_pPTDTC,
  2745. ptep->m_cchPTDTCObj*sizeof(WCHAR));
  2746. ichNewCur += ptep->m_cchPTDTCObj;
  2747. GlobalUnlockFreeNull(&(ptep->m_hgPTDTC));
  2748. }
  2749. ptep->m_fInHdrIn = FALSE;
  2750. LRet:
  2751. // unlock
  2752. GlobalUnlock(ptep->m_hgDocRestore);
  2753. *pcchNew = ichNewCur;
  2754. *ppwNew = pwNew;
  2755. *pichNewCur = ichNewCur;
  2756. *pichBeginCopy = ichBeginCopy;
  2757. *piArrayStart = iArray;
  2758. LRetOnly:
  2759. return;
  2760. } /* fnSaveHdr() */
  2761. void
  2762. CTriEditParse::fnRestoreHdr(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  2763. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  2764. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD dwFlags)
  2765. {
  2766. UINT ichNewCur = *pichNewCur;
  2767. UINT ichBeginCopy = *pichBeginCopy;
  2768. UINT iArray = *piArrayStart;
  2769. LPWSTR pwNew = *ppwNew;
  2770. INT cchBeforeBody = 0;
  2771. WCHAR *pHdr;
  2772. INT ichBodyStart, ichBodyEnd;
  2773. UINT i, iFound;
  2774. UINT cbNeed;
  2775. if (ptep->m_hgDocRestore == NULL)
  2776. goto LRetOnly;
  2777. // lock, copy, unlock
  2778. pHdr = (WCHAR *)GlobalLock(ptep->m_hgDocRestore);
  2779. ASSERT(pHdr != NULL);
  2780. ASSERT(pTokArray[iArray].token.tok == TokElem_BODY);
  2781. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  2782. // HACK to fix a TRIDENT misbehaviour
  2783. // If we had any text before <BODY> tag going into Trident, it will add 2nd <BODY>
  2784. // tag before this text comming out of Trident without looking forward and
  2785. // recognizing that a <BODY> tag already exists. Ideally, Trident should move teh
  2786. // <BODY> tag at appropriate place rather than inserting a 2nd one.
  2787. // Lets assume that Trident will insert only one extra <BODY> tag.
  2788. i = iArray + 1; // we know iArray is the 1st <BODY> tag
  2789. iFound = iArray;
  2790. while (i < ptep->m_cMaxToken)
  2791. {
  2792. if ( (pTokArray[i].token.tok == ft.tokBegin2) /*TokElem_BODY*/
  2793. && (pTokArray[i-1].token.tok == TokTag_START)
  2794. )
  2795. {
  2796. iFound = i;
  2797. break;
  2798. }
  2799. i++;
  2800. }
  2801. if (iFound > iArray) // this means that we found the last <BODY> tag Trident inserted
  2802. iArray = iFound;
  2803. memcpy((BYTE *)&cchBeforeBody, (BYTE *)pHdr, sizeof(INT));
  2804. // realloc if needed
  2805. ichBodyStart = pTokArray[iArray].token.ibTokMin;
  2806. ichBodyEnd = pTokArray[iArray].token.ibTokMac;
  2807. cbNeed = (ichNewCur+cchBeforeBody+ichBodyEnd-ichBodyStart)*sizeof(WCHAR)+cbBufPadding;
  2808. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2809. goto LErrorRet;
  2810. if (cchBeforeBody > 0)
  2811. {
  2812. // ichBeginCopy is a position in pwOld and
  2813. // ichNewCur is a position in pwNew
  2814. // copy from ichBeginCopy to begining of &nbsp
  2815. memcpy( (BYTE *)(pwNew),
  2816. (BYTE *)(pHdr)+sizeof(INT),
  2817. cchBeforeBody*sizeof(WCHAR));
  2818. // fill 0s from pwNew+cchBeforeBody till pwNew+ichNewCur-1 (inclusive)
  2819. if ((int)ichNewCur-cchBeforeBody > 0)
  2820. memset((BYTE *)(pwNew+cchBeforeBody), 0, (ichNewCur-cchBeforeBody)*sizeof(WCHAR));
  2821. ichNewCur = cchBeforeBody; // note that we are initializing ichNewCur here ***
  2822. ichBeginCopy = ichBodyEnd; // make it ready for next copy
  2823. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  2824. (BYTE *)(&pwOld[ichBodyStart]),
  2825. (ichBodyEnd-ichBodyStart)*sizeof(WCHAR));
  2826. ichNewCur += (ichBodyEnd-ichBodyStart);
  2827. }
  2828. else // if we didn't save anything, it means that we had no pre-BODY stuff in the doc (bug 15393)
  2829. {
  2830. if (ptep->m_fUnicodeFile && ichNewCur == 0)
  2831. {
  2832. memcpy((BYTE *)pwNew, (BYTE *)pwOld, sizeof(WCHAR));
  2833. ichNewCur = ichBeginCopy = 1;
  2834. }
  2835. // actually, we should get the '>' of <body> tag instead of using iArray+1
  2836. if (dwFlags & dwFilterSourceCode)
  2837. ichBeginCopy = pTokArray[iArray+1].token.ibTokMac; // '>' of <BODY> tag
  2838. else
  2839. {
  2840. #ifdef NEEDED // VID6 - bug 22781 (This is going to generate some debate, so #ifdef instead of removing.
  2841. LPCWSTR rgPreBody[] =
  2842. {
  2843. L"<HTML>\r\n<HEAD><TITLE></TITLE></HEAD>\r\n",
  2844. };
  2845. ASSERT(ichNewCur >= 0); // make sure its not invalid
  2846. memcpy( (BYTE *)&pwNew[ichNewCur], (BYTE *)rgPreBody[0], wcslen(rgPreBody[0])*sizeof(WCHAR));
  2847. ichNewCur += wcslen(rgPreBody[0]);
  2848. #endif //NEEDED
  2849. // Note that we had not saved any thing before going to design view because there was
  2850. // no <BODY> tag. we should now copy from current pwOld[ichBeginCopy] till
  2851. // the new pwOld[ichBeginCopy] into pwNew[ichNewCur] and then set ichBeginCopy.
  2852. if (pTokArray[iArray-1].token.ibTokMin > ichBeginCopy)
  2853. {
  2854. memcpy( (BYTE *)&pwNew[ichNewCur],
  2855. (BYTE *)&pwOld[ichBeginCopy],
  2856. (pTokArray[iArray-1].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  2857. ichNewCur += pTokArray[iArray-1].token.ibTokMin-ichBeginCopy;
  2858. }
  2859. ichBeginCopy = pTokArray[iArray-1].token.ibTokMin; // '<' of <BODY> tag
  2860. }
  2861. }
  2862. LErrorRet:
  2863. // unlock
  2864. GlobalUnlock(ptep->m_hgDocRestore);
  2865. *pcchNew = ichNewCur;
  2866. *ppwNew = pwNew;
  2867. *pichNewCur = ichNewCur;
  2868. *pichBeginCopy = ichBeginCopy;
  2869. *piArrayStart = iArray;
  2870. LRetOnly:
  2871. return;
  2872. } /* fnRestoreHdr() */
  2873. void CTriEditParse::fnSaveFtr(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  2874. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  2875. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD /*dwFlags*/)
  2876. {
  2877. UINT ichNewCur = *pichNewCur;
  2878. UINT ichBeginCopy = *pichBeginCopy;
  2879. UINT iArray = *piArrayStart;
  2880. LPWSTR pwNew = *ppwNew;
  2881. INT cchAfterBody = 0;
  2882. INT cchBeforeBody = 0;
  2883. INT cchPreEndBody = 0;
  2884. WCHAR *pFtr;
  2885. INT ichStart, ichEnd;
  2886. UINT iArraySav = iArray;
  2887. UINT cbNeed;
  2888. if (ptep->m_hgDocRestore == NULL)
  2889. goto LRetOnly;
  2890. // lock
  2891. pFtr = (WCHAR *)GlobalLock(ptep->m_hgDocRestore);
  2892. ASSERT(pFtr != NULL);
  2893. ichStart = pTokArray[iArray-1].token.ibTokMin; // init
  2894. ASSERT(pTokArray[iArray].token.tok == TokElem_BODY);
  2895. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  2896. ASSERT(pTokArray[iArray-1].token.tok == TokTag_END);
  2897. // what if we DON'T have a </BODY> tag at all. Lets handle the error case here
  2898. // If thats the case, we just don't save anything
  2899. ASSERT(iArray-1 >= 0);
  2900. if (pTokArray[iArray-1].token.tok != TokTag_END)
  2901. {
  2902. cchAfterBody = 0;
  2903. cchPreEndBody = 0;
  2904. }
  2905. else
  2906. {
  2907. // following was added for Bug fix for 7542
  2908. cchAfterBody = pTokArray[ptep->m_cMaxToken-1].token.ibTokMac-pTokArray[iArray].token.ibTokMac;
  2909. // now calculate the space required to save stuff from before </BODY>
  2910. // till the previous meaningful token
  2911. ichStart = ichEnd = pTokArray[iArray-1].token.ibTokMin;
  2912. ichStart--; // now ichStart is pointing to a character before </BODY>
  2913. while ( (ichStart >= 0)
  2914. && ( pwOld[ichStart] == ' '
  2915. || pwOld[ichStart] == '\r'
  2916. || pwOld[ichStart] == '\n'
  2917. || pwOld[ichStart] == '\t'
  2918. )
  2919. )
  2920. {
  2921. ichStart--;
  2922. }
  2923. ichStart++; // the current char is not one of the above, so increment
  2924. if (ichStart == ichEnd) // we didn't have anyspace, eol, tab between </BODY> & previous token
  2925. {
  2926. cchPreEndBody = 0;
  2927. }
  2928. else
  2929. {
  2930. ASSERT(ichEnd - ichStart > 0);
  2931. cchPreEndBody = ichEnd - ichStart;
  2932. }
  2933. }
  2934. // get cchBeforeBody if pre-BODY part was saved, and adjust pFtr for saving
  2935. memcpy((BYTE *)&cchBeforeBody, (BYTE *)pFtr, sizeof(INT));
  2936. pFtr += cchBeforeBody + sizeof(INT)/sizeof(WCHAR);
  2937. // realloc if needed
  2938. if ((cchPreEndBody+cchAfterBody+cchBeforeBody)*sizeof(WCHAR)+3*sizeof(int) > GlobalSize(ptep->m_hgDocRestore))
  2939. {
  2940. HGLOBAL hgDocRestore;
  2941. GlobalUnlock(ptep->m_hgDocRestore);
  2942. hgDocRestore = ptep->m_hgDocRestore;
  2943. #pragma prefast(suppress:308, "noise")
  2944. ptep->m_hgDocRestore = GlobalReAlloc(ptep->m_hgDocRestore, (cchPreEndBody+cchAfterBody+cchBeforeBody)*sizeof(WCHAR)+3*sizeof(int), GMEM_MOVEABLE|GMEM_ZEROINIT);
  2945. // if this alloc failed, we may still want to continue
  2946. if (ptep->m_hgDocRestore == NULL)
  2947. {
  2948. GlobalFree(hgDocRestore);
  2949. goto LRet;
  2950. }
  2951. else
  2952. {
  2953. pFtr = (WCHAR *)GlobalLock(ptep->m_hgDocRestore); // do we need to unlock this first?
  2954. ASSERT(pFtr != NULL);
  2955. // remember to set pFtr to be after cchBeforeBody
  2956. pFtr += cchBeforeBody + sizeof(INT)/sizeof(WCHAR);
  2957. }
  2958. }
  2959. // copy from pwOld
  2960. memcpy( (BYTE *)pFtr,
  2961. (BYTE *)&cchAfterBody,
  2962. sizeof(INT));
  2963. memcpy( (BYTE *)(pFtr)+sizeof(INT),
  2964. (BYTE *)(pwOld+pTokArray[iArray].token.ibTokMac),
  2965. cchAfterBody*sizeof(WCHAR));
  2966. pFtr += cchAfterBody + sizeof(INT)/sizeof(WCHAR);
  2967. memcpy( (BYTE *)pFtr,
  2968. (BYTE *)&cchPreEndBody,
  2969. sizeof(INT));
  2970. memcpy( (BYTE *)(pFtr)+sizeof(INT),
  2971. (BYTE *)&(pwOld[ichStart]),
  2972. cchPreEndBody*sizeof(WCHAR));
  2973. // the very next token from TokElem_BODY will be TokTag_CLOSE in most cases, but just in case...
  2974. while (iArray < ptep->m_cMaxToken)
  2975. {
  2976. if (pTokArray[iArray].token.tok == TokTag_CLOSE && pTokArray[iArray].token.tokClass == tokTag)
  2977. break;
  2978. iArray++;
  2979. }
  2980. if (iArray >= ptep->m_cMaxToken)
  2981. {
  2982. iArray = iArraySav+1; // atleast copy till that point
  2983. goto LRet;
  2984. }
  2985. // copy till '>' of </BODY> from pwOld into pwNew
  2986. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  2987. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  2988. cbNeed = (ichNewCur+pTokArray[iArray].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  2989. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  2990. goto LRet;
  2991. memcpy( (BYTE *)&(pwNew[ichNewCur]),
  2992. (BYTE *)&(pwOld[ichBeginCopy]),
  2993. (pTokArray[iArray].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  2994. ichNewCur += pTokArray[iArray].token.ibTokMac-ichBeginCopy;
  2995. ichBeginCopy = pTokArray[iArray].token.ibTokMac;
  2996. iArray = ptep->m_cMaxToken - 1;
  2997. ichBeginCopy = pTokArray[ptep->m_cMaxToken-1].token.ibTokMac; // we don't want to copy anything after this
  2998. LRet:
  2999. // unlock
  3000. GlobalUnlock(ptep->m_hgDocRestore);
  3001. *pcchNew = ichNewCur;
  3002. *ppwNew = pwNew;
  3003. *pichNewCur = ichNewCur;
  3004. *pichBeginCopy = ichBeginCopy;
  3005. *piArrayStart = iArray;
  3006. LRetOnly:
  3007. return;
  3008. } /* fnSaveFtr() */
  3009. void CTriEditParse::fnRestoreFtr(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  3010. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  3011. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD dwFlags)
  3012. {
  3013. UINT ichNewCur = *pichNewCur;
  3014. UINT ichBeginCopy = *pichBeginCopy;
  3015. UINT iArray = *piArrayStart;
  3016. LPWSTR pwNew = *ppwNew;
  3017. INT cchAfterBody = 0;
  3018. INT cchBeforeBody = 0;
  3019. WCHAR *pFtr;
  3020. INT ichBodyEnd;
  3021. UINT i, iFound;
  3022. INT ichInsEOL = -1; // initilize
  3023. UINT cbNeed;
  3024. if (ptep->m_hgDocRestore == NULL)
  3025. goto LRetOnly;
  3026. // lock, copy, unlock
  3027. pFtr = (WCHAR *)GlobalLock(ptep->m_hgDocRestore);
  3028. ASSERT(pFtr != NULL);
  3029. ASSERT(pTokArray[iArray].token.tok == TokElem_BODY);
  3030. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  3031. // HACK to fix a TRIDENT misbehaviour
  3032. // If we had any text before <BODY> tag going into Trident, it will add 2nd <BODY>
  3033. // tag before this text comming out of Trident without looking forward and
  3034. // recognizing that a <BODY> tag already exists. Ideally, Trident should move teh
  3035. // <BODY> tag at appropriate place rather than inserting a 2nd one.
  3036. // Lets assume that Trident will insert only one extra <\BODY> tag.
  3037. i = iArray + 1; // we know iArray is the 1st <\BODY> tag
  3038. iFound = iArray;
  3039. while (i < ptep->m_cMaxToken)
  3040. {
  3041. if ( (pTokArray[i].token.tok == ft.tokBegin2) /*TokElem_BODY*/
  3042. && (pTokArray[i-1].token.tok == TokTag_END)
  3043. )
  3044. {
  3045. iFound = i;
  3046. break;
  3047. }
  3048. i++;
  3049. }
  3050. if (iFound > iArray) // this means that we found the last <BODY> tag Trident inserted
  3051. iArray = iFound;
  3052. memcpy((BYTE *)&cchBeforeBody, (BYTE *)pFtr, sizeof(INT));
  3053. pFtr += cchBeforeBody + sizeof(INT)/sizeof(WCHAR);
  3054. memcpy((BYTE *)&cchAfterBody, (BYTE *)pFtr, sizeof(INT));
  3055. pFtr += sizeof(INT)/sizeof(WCHAR);
  3056. ichBodyEnd = pTokArray[iArray].token.ibTokMac;
  3057. // if (cchAfterBody == 0) // get the size of our own header
  3058. // realloc if needed
  3059. cbNeed = (ichNewCur+cchAfterBody+(ichBodyEnd-ichBeginCopy)+2/* for EOL*/)*sizeof(WCHAR)+cbBufPadding;
  3060. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3061. goto LErrorRet;
  3062. if (cchAfterBody > 0)
  3063. {
  3064. LPCWSTR rgSpaceTags[] = {L"DESIGNTIMESP"};
  3065. int cchTag, index, indexDSP;
  3066. // ichBeginCopy is a position in pwOld and
  3067. // ichNewCur is a position in pwNew
  3068. // copy from ichBeginCopy to end of HTML document
  3069. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3070. (BYTE *)(&pwOld[ichBeginCopy]),
  3071. (ichBodyEnd-ichBeginCopy)*sizeof(WCHAR));
  3072. ichNewCur += (ichBodyEnd-ichBeginCopy);
  3073. ichBeginCopy = ichBodyEnd;
  3074. // now that we have copied 'BODY' of </BODY> tag, lets make sure its of correct case (bug 18248)
  3075. indexDSP = -1;
  3076. index = pTokArray[iArray].iNextprev;
  3077. cchTag = wcslen(rgSpaceTags[0]);
  3078. if (index != -1 && index < (int)iArray) // we have matching <BODY> tag prior to this one
  3079. {
  3080. // get the designtimesp attribute
  3081. while (index < (int)iArray) // we will never come this far, but thats the only known position at this point
  3082. {
  3083. if (pTokArray[index].token.tok == TokTag_CLOSE)
  3084. break;
  3085. if ( (pTokArray[index].token.tok == 0)
  3086. && (pTokArray[index].token.tokClass == tokSpace)
  3087. && (0 == _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[index].token.ibTokMin], cchTag))
  3088. )
  3089. {
  3090. indexDSP = index;
  3091. break;
  3092. }
  3093. index++;
  3094. } // while
  3095. if (indexDSP != -1) // we found DESIGNTIMESP attribute
  3096. {
  3097. // look for the case of designtimesp
  3098. if (iswupper(pwOld[pTokArray[indexDSP].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  3099. _wcsupr(&pwNew[ichNewCur-4]); // length of BODY tag name
  3100. else
  3101. _wcslwr(&pwNew[ichNewCur-4]); // length of BODY tag name
  3102. }
  3103. }
  3104. // we know that the following condition will be met most of the times, but just to cover
  3105. // incomplete HTML cases...
  3106. if ( (pTokArray[iArray].token.tok == ft.tokBegin2) /*TokElem_BODY*/
  3107. && (pTokArray[iArray-1].token.tok == TokTag_END)
  3108. )
  3109. {
  3110. ichInsEOL = ichNewCur - (pTokArray[iArray].token.ibTokMac - pTokArray[iArray-1].token.ibTokMin);
  3111. }
  3112. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3113. (BYTE *)pFtr,
  3114. (cchAfterBody)*sizeof(WCHAR));
  3115. ichNewCur += (cchAfterBody);
  3116. // we had saved spacing info before </BODY>
  3117. if (ichInsEOL != -1)
  3118. {
  3119. INT cchPreEndBody = 0;
  3120. pFtr += cchAfterBody;
  3121. cchPreEndBody = *(int *)pFtr;
  3122. if (cchPreEndBody > 0)
  3123. {
  3124. INT ichT = ichInsEOL-1;
  3125. WCHAR *pw = NULL;
  3126. INT cchSubStr = 0;
  3127. WCHAR *pwStr = NULL;
  3128. WCHAR *pwSubStr = NULL;
  3129. pFtr += sizeof(INT)/sizeof(WCHAR); // pFtr now points to Pre </BODY> stuff
  3130. // This is kind of hacky - but I don't see a way out, atleast
  3131. // If the contents in pFtr at cchPreEndBody are subset of the
  3132. // contents before </BODY> and after any previous text/tokens,
  3133. // then we shouldn't do the following memcpy()
  3134. while ( ichT >= 0 /* validation */
  3135. && ( pwNew[ichT] == ' '
  3136. || pwNew[ichT] == '\n'
  3137. || pwNew[ichT] == '\r'
  3138. || pwNew[ichT] == '\t'
  3139. )
  3140. )
  3141. {
  3142. ichT--;
  3143. cchSubStr++;
  3144. }
  3145. ichT++; // compensate the last decrement
  3146. if (cchSubStr > 0)
  3147. {
  3148. ASSERT(ichT >= 0);
  3149. pwStr = new WCHAR [cchSubStr+1];
  3150. memcpy((BYTE *)pwStr, (BYTE *)(&pwNew[ichT]), cchSubStr*sizeof(WCHAR));
  3151. pwStr[cchSubStr] = '\0';
  3152. pwSubStr = new WCHAR [cchPreEndBody+1];
  3153. memcpy((BYTE *)pwSubStr, (BYTE *)pFtr, cchPreEndBody*sizeof(WCHAR));
  3154. pwSubStr[cchPreEndBody] = '\0';
  3155. pw = wcsstr(pwStr, pwSubStr);
  3156. }
  3157. if (pw == NULL) // means that the substring wasn't found
  3158. {
  3159. // allocate more memory if needed
  3160. cbNeed = (ichNewCur+cchPreEndBody)*sizeof(WCHAR)+cbBufPadding;
  3161. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3162. goto LErrorRet;
  3163. memmove((BYTE *)(&pwNew[ichInsEOL+cchPreEndBody]),
  3164. (BYTE *)(&pwNew[ichInsEOL]),
  3165. (ichNewCur-ichInsEOL)*sizeof(WCHAR));
  3166. memcpy( (BYTE *)(&pwNew[ichInsEOL]),
  3167. (BYTE *)(pFtr),
  3168. (cchPreEndBody)*sizeof(WCHAR));
  3169. ichNewCur += cchPreEndBody;
  3170. }
  3171. if (pwStr != NULL)
  3172. delete pwStr;
  3173. if (pwSubStr != NULL)
  3174. delete pwSubStr;
  3175. } // if (cchPreEndBody > 0)
  3176. } // if (ichInsEOL != -1)
  3177. ichBeginCopy = pTokArray[ptep->m_cMaxToken-1].token.ibTokMac; // we don't want to copy anything after this
  3178. iArray = ptep->m_cMaxToken - 1;
  3179. // WISH LIST Item for space preservation
  3180. // we know that ptep->m_ispInfoBlock was the last spacing block that was recovered.
  3181. // This block (like all others) has 4 parts (1)pre '<' (2)between '<>' & order info
  3182. // (3)post '>' (4)pre matching '</'
  3183. // At this point we care about (3) & (4)
  3184. // first of all, get ichBeginNext (ich past '>') & ichBeginMatch (ich before '</')
  3185. // apply the saved spacing info to the contents of pwNew
  3186. // The difficult part is to get these ich's without parsing pwNew.
  3187. }
  3188. else
  3189. {
  3190. // copy our own Footer
  3191. if (dwFlags & dwFilterSourceCode)
  3192. {
  3193. int ichBodyStart, index, ichBodyTagEnd;
  3194. // get the '</' of </body>
  3195. index = iArray;
  3196. while (index >= 0) // we won't go this far, but just in case we have invalid html
  3197. {
  3198. if ( pTokArray[index].token.tok == TokTag_END
  3199. && pTokArray[index].token.tokClass == tokTag
  3200. )
  3201. {
  3202. break;
  3203. }
  3204. index--;
  3205. }
  3206. if (index >= 0)
  3207. {
  3208. ichBodyStart = pTokArray[index].token.ibTokMin;
  3209. // copy till the current token's begining, see if we have enough space
  3210. if (ichBodyStart > (int)ichBeginCopy)
  3211. {
  3212. cbNeed = (ichNewCur+ichBodyStart-ichBeginCopy+1/*for null at the end*/)*sizeof(WCHAR)+cbBufPadding;
  3213. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3214. goto LErrorRet;
  3215. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3216. (BYTE *)(&pwOld[ichBeginCopy]),
  3217. (ichBodyStart-ichBeginCopy)*sizeof(WCHAR));
  3218. ichNewCur += (ichBodyStart-ichBeginCopy);
  3219. ichBeginCopy = ichBodyStart; // setting this is redundant, but it makes the code readable.
  3220. }
  3221. else if (ichBodyEnd > (int)ichBeginCopy)
  3222. {
  3223. index = iArray;
  3224. while (index <= (int)ptep->m_cMaxToken) // we won't go this far, but just in case we have invalid html
  3225. {
  3226. if ( pTokArray[index].token.tok == TokTag_CLOSE
  3227. && pTokArray[index].token.tokClass == tokTag
  3228. )
  3229. {
  3230. break;
  3231. }
  3232. index++;
  3233. }
  3234. if (index < (int)ptep->m_cMaxToken)
  3235. {
  3236. ichBodyTagEnd = pTokArray[index].token.ibTokMac;
  3237. cbNeed = (ichNewCur+ichBodyTagEnd-ichBeginCopy+1/*for null at the end*/)*sizeof(WCHAR)+cbBufPadding;
  3238. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3239. goto LErrorRet;
  3240. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3241. (BYTE *)(&pwOld[ichBeginCopy]),
  3242. (ichBodyTagEnd-ichBeginCopy)*sizeof(WCHAR));
  3243. ichNewCur += (ichBodyTagEnd-ichBeginCopy);
  3244. ichBeginCopy = ichBodyTagEnd; // setting this is redundant, but it makes the code readable.
  3245. }
  3246. }
  3247. // add a null at the end
  3248. // to keep the code in ssync with the if (cchAfterBody > 0) case
  3249. pwNew[ichNewCur++] = '\0';
  3250. ichBeginCopy = pTokArray[ptep->m_cMaxToken-1].token.ibTokMac; // we don't want to copy anything after this
  3251. iArray = ptep->m_cMaxToken - 1;
  3252. } // if (index >= 0)
  3253. } // if (dwFlags & dwFilterSourceCode)
  3254. }
  3255. if (ptep->m_cchPTDTC != 0)
  3256. {
  3257. // this means that we didn't encounter the DTC on way out from Trident
  3258. // but they were there when we went to Trident. The user must have deleted
  3259. // the DTCs while in Design view
  3260. ASSERT(ptep->m_ichPTDTC != 0);
  3261. // remove m_cchPTDTC WCHARS from m_ichPTDTC
  3262. memset( (BYTE *)&pwNew[ptep->m_ichPTDTC],
  3263. 0,
  3264. ptep->m_cchPTDTC*sizeof(WCHAR)
  3265. );
  3266. memmove((BYTE *)&pwNew[ptep->m_ichPTDTC],
  3267. (BYTE *)&pwNew[ptep->m_ichPTDTC+ptep->m_cchPTDTC],
  3268. (ichNewCur-(ptep->m_ichPTDTC+ptep->m_cchPTDTC))*sizeof(WCHAR)
  3269. );
  3270. ichNewCur -= ptep->m_cchPTDTC;
  3271. ptep->m_cchPTDTC = 0;
  3272. }
  3273. LErrorRet:
  3274. // unlock
  3275. GlobalUnlock(ptep->m_hgDocRestore);
  3276. *pcchNew = ichNewCur;
  3277. *ppwNew = pwNew;
  3278. *pichNewCur = ichNewCur;
  3279. *pichBeginCopy = ichBeginCopy;
  3280. *piArrayStart = iArray;
  3281. LRetOnly:
  3282. return;
  3283. } /* fnRestoreFtr() */
  3284. void CTriEditParse::fnSaveObject(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  3285. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  3286. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD /*dwFlags*/)
  3287. {
  3288. // scan till the end of the object.
  3289. // If we find '<% %>' blocks inside, put a comment with a special tag around it,
  3290. // else simply copy that object as is and exit
  3291. UINT ichNewCur = *pichNewCur;
  3292. UINT ichBeginCopy = *pichBeginCopy;
  3293. UINT iArray = *piArrayStart;
  3294. LPWSTR pwNew = *ppwNew;
  3295. INT ichObjectStart, ichObjectEnd, iObjectStart, iObjectEnd, i;
  3296. BOOL fSSSFound = FALSE;
  3297. UINT iArraySav = iArray;
  3298. UINT cbNeed;
  3299. ichObjectStart = ichObjectEnd = iObjectStart = iObjectEnd = 0;
  3300. if ( pTokArray[iArray-1].token.tok == TokTag_END
  3301. && pTokArray[iArray-1].token.tokClass == tokTag
  3302. )
  3303. {
  3304. iArray++;
  3305. goto LRet;
  3306. }
  3307. ASSERT(pTokArray[iArray].token.tok == TokElem_OBJECT); // we should be at the object tag
  3308. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  3309. iObjectStart = iArray;
  3310. if (pTokArray[iArray].iNextprev != -1)
  3311. {
  3312. // NOTE that this will give us topmost nested level of the OBJECT, if we had nested objects
  3313. iObjectEnd = pTokArray[iArray].iNextprev;
  3314. ASSERT(iObjectEnd < (INT)ptep->m_cMaxToken);
  3315. ASSERT((iObjectEnd-1 >= 0) && pTokArray[iObjectEnd-1].token.tok == TokTag_END);
  3316. // this will be a wierd case where the iNextprev is incorrectly pointing to another token
  3317. // but lets handle that case.
  3318. if (pTokArray[iObjectEnd].token.tok != TokElem_OBJECT)
  3319. goto LFindObjectClose; // find it by looking at each token
  3320. }
  3321. else // actually, this is an error case, but rather than just giving assert, try to find the token
  3322. {
  3323. LFindObjectClose:
  3324. i = iObjectStart+1;
  3325. while (i < (INT)ptep->m_cMaxToken)
  3326. {
  3327. // this may not give us the correct matching </OBJECT> if we had nested objects.
  3328. // but we don't have that knowledge at this point any way.
  3329. if ( pTokArray[i].token.tok == TokElem_OBJECT
  3330. && pTokArray[i].token.tokClass == tokElem
  3331. && (i-1 >= 0) /* validation */
  3332. && pTokArray[i-1].token.tok == TokTag_END
  3333. )
  3334. {
  3335. break;
  3336. }
  3337. i++;
  3338. }
  3339. if (i < (INT)ptep->m_cMaxToken) // found TokElem_OBJECT token
  3340. iObjectEnd = i;
  3341. else // error case
  3342. goto LRet; // didn't find OBJECT, but exhausted the token array
  3343. }
  3344. // at this point iObjectStart & iObjectEnd point to OBJECT of <OBJECT> and iObjectEnd respectively
  3345. // look for '<' in <OBJECT> & and '>' in </OBJECT>
  3346. i = iObjectStart;
  3347. while (i >= 0)
  3348. {
  3349. if ( pTokArray[i].token.tok == TokTag_START
  3350. && pTokArray[i].token.tokClass == tokTag
  3351. )
  3352. break;
  3353. i--;
  3354. }
  3355. if (i < 0) // error case
  3356. goto LRet;
  3357. iObjectStart = i;
  3358. ichObjectStart = pTokArray[iObjectStart].token.ibTokMin;
  3359. i = iObjectEnd;
  3360. while (i <= (INT)ptep->m_cMaxToken)
  3361. {
  3362. if ( pTokArray[i].token.tok == TokTag_CLOSE
  3363. && pTokArray[i].token.tokClass == tokTag
  3364. )
  3365. break;
  3366. i++;
  3367. }
  3368. if (i >= (INT)ptep->m_cMaxToken) // error case
  3369. goto LRet;
  3370. iObjectEnd = i;
  3371. ichObjectEnd = pTokArray[iObjectEnd].token.ibTokMac;
  3372. ASSERT(ichObjectEnd > ichObjectStart);
  3373. // look for <% %> between iObjectStart & iObjectEnd
  3374. for (i = iObjectStart; i <= iObjectEnd; i++)
  3375. {
  3376. if ( pTokArray[i].token.tok == TokTag_SSSOPEN
  3377. && pTokArray[i].token.tokClass == tokSSS
  3378. )
  3379. {
  3380. fSSSFound = TRUE;
  3381. break;
  3382. }
  3383. }
  3384. if (fSSSFound) // this object can't be displayed in Trident, so convert it
  3385. {
  3386. LPCWSTR rgComment[] =
  3387. {
  3388. L"<!--ERROROBJECT ",
  3389. L" ERROROBJECT-->",
  3390. };
  3391. //if (dwFlags & dwPreserveSourceCode)
  3392. //{
  3393. // in this case, we would have already copied <OBJECT ... DESIGNTIMESP=x>
  3394. // and ichNewCur is adjusted accordingly
  3395. // get ich that points after <OBJECT> in pwOld
  3396. // I don't like this, but don't see a way out...
  3397. // look back in pwNew and get ich that points to '<' of <OBJECT ... DESIGNTIMESP=x>
  3398. // insert the comment there
  3399. //}
  3400. //else
  3401. //{
  3402. ASSERT((INT)(ichObjectStart-ichBeginCopy) > 0);
  3403. cbNeed = (ichNewCur+ichObjectEnd-ichBeginCopy+wcslen(rgComment[0])+wcslen(rgComment[1]))*sizeof(WCHAR)+cbBufPadding;
  3404. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3405. goto LNoCopy;
  3406. // copy till begining of <OBJECT>
  3407. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3408. (BYTE *)(&pwOld[ichBeginCopy]),
  3409. (ichObjectStart-ichBeginCopy)*sizeof(WCHAR));
  3410. ichNewCur += ichObjectStart-ichBeginCopy;
  3411. // copy the comment begining
  3412. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3413. (BYTE *)(rgComment[0]),
  3414. wcslen(rgComment[0])*sizeof(WCHAR));
  3415. ichNewCur += wcslen(rgComment[0]);
  3416. // copy from <OBJECT> to </OBJECT>
  3417. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3418. (BYTE *)(&pwOld[ichObjectStart]),
  3419. (ichObjectEnd-ichObjectStart)*sizeof(WCHAR));
  3420. ichNewCur += ichObjectEnd-ichObjectStart;
  3421. // copy the comment end
  3422. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3423. (BYTE *)(rgComment[1]),
  3424. wcslen(rgComment[1])*sizeof(WCHAR));
  3425. ichNewCur += wcslen(rgComment[1]);
  3426. //}
  3427. }
  3428. else
  3429. {
  3430. // We always save its contents into our buffer and replace it on the way back if need be
  3431. // save cchClsId, clsId, cchParam, PARAM_Tags
  3432. INT cchParam, ichParam, iParamStart, iParamEnd;
  3433. INT ichObjStartEnd; // ich at the end of <OBJECT .....>
  3434. LPCWSTR rgComment[] =
  3435. {
  3436. L"<!--ERRORPARAM ",
  3437. L" ERRORPARAM-->",
  3438. };
  3439. INT iObjTagEnd = -1;
  3440. iParamStart = iObjectStart;
  3441. while (iParamStart < iObjectEnd)
  3442. {
  3443. //if ( pTokArray[iParamStart].token.tok == TokAttrib_CLASSID
  3444. // && pTokArray[iParamStart].token.tokClass == tokAttr)
  3445. // iClsId = iParamStart;
  3446. if ( pTokArray[iParamStart].token.tok == TokElem_PARAM
  3447. && pTokArray[iParamStart].token.tokClass == tokElem)
  3448. break;
  3449. iParamStart++;
  3450. }
  3451. if (iParamStart >= iObjectEnd) // don't see any <PARAM> tags, so don't save
  3452. goto LSkipSave;
  3453. while (iParamStart > iObjectStart) // generally this will the previous token, but cover all cases
  3454. {
  3455. if ( pTokArray[iParamStart].token.tok == TokTag_START
  3456. && pTokArray[iParamStart].token.tokClass == tokTag)
  3457. break;
  3458. iParamStart--;
  3459. }
  3460. if (iParamStart <= iObjectStart) // error
  3461. goto LSkipSave;
  3462. ichParam = pTokArray[iParamStart].token.ibTokMin;
  3463. iParamEnd = iObjectEnd;
  3464. while (iParamEnd > iObjectStart)
  3465. {
  3466. if ( pTokArray[iParamEnd].token.tok == TokElem_PARAM
  3467. && pTokArray[iParamEnd].token.tokClass == tokElem)
  3468. break;
  3469. iParamEnd--;
  3470. }
  3471. while (iParamEnd < iObjectEnd) // generally this will the previous token, but cover all cases
  3472. {
  3473. if ( pTokArray[iParamEnd].token.tok == TokTag_CLOSE
  3474. && pTokArray[iParamEnd].token.tokClass == tokTag)
  3475. break;
  3476. iParamEnd++;
  3477. }
  3478. if (iParamEnd >= iObjectEnd) // error
  3479. goto LSkipSave;
  3480. cchParam = pTokArray[iParamEnd].token.ibTokMac - ichParam;
  3481. ASSERT(cchParam > 0);
  3482. // calculate ichObjStartEnd
  3483. iObjTagEnd = iObjectStart;
  3484. while (iObjTagEnd < iParamStart)
  3485. {
  3486. if ( pTokArray[iObjTagEnd].token.tok == TokTag_CLOSE
  3487. && pTokArray[iObjTagEnd].token.tokClass == tokTag)
  3488. break;
  3489. iObjTagEnd++;
  3490. }
  3491. if (iObjTagEnd >= iParamStart) // error case
  3492. goto LSkipSave;
  3493. ichObjStartEnd = pTokArray[iObjTagEnd].token.ibTokMac;
  3494. // realloc if needed
  3495. cbNeed = (ichNewCur+cchParam+(ichObjStartEnd-ichBeginCopy)+wcslen(rgComment[0])+wcslen(rgComment[1]))*sizeof(WCHAR)+cbBufPadding;
  3496. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3497. goto LSkipSave;
  3498. // 1. copy <OBJECT ...> tag into pwNew
  3499. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3500. (BYTE *)(&pwOld[ichBeginCopy]),
  3501. (ichObjStartEnd-ichBeginCopy)*sizeof(WCHAR));
  3502. ichNewCur += (ichObjStartEnd-ichBeginCopy);
  3503. ichBeginCopy = ichObjStartEnd;
  3504. #ifdef ERROR_PARAM
  3505. // 2. now insert the <PARAM> tags as a comment at pwNew[ichNewCur]
  3506. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3507. (BYTE *)(rgComment[0]),
  3508. wcslen(rgComment[0])*sizeof(WCHAR));
  3509. ichNewCur += wcslen(rgComment[0]);
  3510. // we should copy <PARAM> tags ONLY. We may have things other than the tags
  3511. // in between. e.g. comments
  3512. // Look for TokElem_PARAM between iParamStart & iParamEnd
  3513. ASSERT(pTokArray[iParamStart].token.tok == TokTag_START);
  3514. ASSERT(pTokArray[iParamEnd].token.tok == TokTag_CLOSE);
  3515. // Find PARAM tag, get the '<' & '>' for that PARAM and copy that to pwNew
  3516. // repeat
  3517. index = iParamStart;
  3518. iPrev = iParamStart;
  3519. while (index <= iParamEnd)
  3520. {
  3521. INT iStart, iEnd;
  3522. iStart = iEnd = -1; // that way, its easy to make sure that this is initilized
  3523. // get PARAM
  3524. while ( ( pTokArray[index].token.tok != TokElem_PARAM
  3525. || pTokArray[index].token.tokClass != tokElem)
  3526. && (index <= iParamEnd)
  3527. )
  3528. index++;
  3529. if (index > iParamEnd)
  3530. goto LDoneCopy;
  3531. // get '<' before the PARAM
  3532. while ( ( pTokArray[index].token.tok != TokTag_START
  3533. || pTokArray[index].token.tokClass != tokTag)
  3534. && (index >= iPrev)
  3535. )
  3536. index--;
  3537. if (index < iPrev)
  3538. goto LDoneCopy;
  3539. iStart = index;
  3540. // get matching '>'
  3541. while ( ( pTokArray[index].token.tok != TokTag_CLOSE
  3542. || pTokArray[index].token.tokClass != tokTag)
  3543. && (index <= iParamEnd)
  3544. )
  3545. index++;
  3546. if (index > iParamEnd)
  3547. goto LDoneCopy;
  3548. iEnd = index;
  3549. ASSERT(iEnd > iStart);
  3550. ASSERT(iStart != -1);
  3551. ASSERT(iEnd != -1);
  3552. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3553. (BYTE *)(&pwOld[pTokArray[iStart].token.ibTokMin]),
  3554. (pTokArray[iEnd].token.ibTokMac-pTokArray[iStart].token.ibTokMin)*sizeof(WCHAR));
  3555. ichNewCur += (pTokArray[iEnd].token.ibTokMac-pTokArray[iStart].token.ibTokMin);
  3556. iPrev = iEnd + 1;
  3557. }
  3558. LDoneCopy:
  3559. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  3560. (BYTE *)(rgComment[1]),
  3561. wcslen(rgComment[1])*sizeof(WCHAR));
  3562. ichNewCur += wcslen(rgComment[1]);
  3563. #endif //ERROR_PARAM
  3564. // fake iArraySav to be iObjTagEnd, that way we will st iArray correctly before we leave
  3565. ASSERT(iObjTagEnd != -1);
  3566. iArraySav = (UINT)iObjTagEnd;
  3567. LSkipSave:
  3568. iArray = iArraySav + 1;
  3569. goto LRet;
  3570. }
  3571. LNoCopy:
  3572. ichBeginCopy = ichObjectEnd; // set it for next copy
  3573. iArray = iObjectEnd+1; // set it after </OBJECT>
  3574. LRet:
  3575. *pcchNew = ichNewCur;
  3576. *ppwNew = pwNew;
  3577. *pichNewCur = ichNewCur;
  3578. *pichBeginCopy = ichBeginCopy;
  3579. *piArrayStart = iArray;
  3580. //LRetOnly:
  3581. return;
  3582. } /* fnSaveObject() */
  3583. void
  3584. CTriEditParse::fnRestoreObject(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  3585. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  3586. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD /*dwFlags*/)
  3587. {
  3588. // look for the special tag after the '<!--'
  3589. // if we find it, this was an object, remove the comments around it
  3590. // else simply copy the comment and return
  3591. UINT ichNewCur = *pichNewCur;
  3592. UINT ichBeginCopy = *pichBeginCopy;
  3593. UINT iArray = *piArrayStart;
  3594. LPWSTR pwNew = *ppwNew;
  3595. INT iArraySav = iArray;
  3596. INT ichCommentStart, ichCommentEnd, iCommentStart, iCommentEnd, cchComment1, cchComment2;
  3597. INT ichObjectStart;
  3598. LPCWSTR rgComment[] =
  3599. {
  3600. L"ERROROBJECT",
  3601. L"--ERROROBJECT ",
  3602. L" ERROROBJECT--",
  3603. L"TRIEDITCOMMENT-",
  3604. L"TRIEDITCOMMENTEND-",
  3605. L"TRIEDITPRECOMMENT-",
  3606. };
  3607. BOOL fSimpleComment = FALSE;
  3608. UINT cbNeed;
  3609. ichCommentStart = ichCommentEnd = iCommentStart = iCommentEnd = 0;
  3610. ASSERT(pTokArray[iArray].token.tok == TokTag_BANG); // we should be at the comment
  3611. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  3612. // ASSUMPTION - that Trident doesn't muck with the contents inside a comment block
  3613. // if rgComment[0] matches and rgComment[1] does not, Trident may have mucked with the
  3614. // comment contents. This invalidates our original assumption.
  3615. // NOTE - In this version, we can get away by assuming that trident doesn't muck with the comments
  3616. // early return cases
  3617. // 1. see if this is a comment or not. It could be anything that starts with '<!'
  3618. // e.g. <!DOCTYPE
  3619. if ( (iArray+1 < (INT)ptep->m_cMaxToken)
  3620. && (pwOld[pTokArray[iArray+1].token.ibTokMin] == '-')
  3621. && (pwOld[pTokArray[iArray+1].token.ibTokMin+1] == '-')
  3622. && (0 == _wcsnicmp(rgComment[0], &pwOld[pTokArray[iArray+1].token.ibTokMin+2], wcslen(rgComment[0])))
  3623. )
  3624. {
  3625. iCommentStart = iArray; // this is a comment we are interested in
  3626. }
  3627. else if ( (iArray+1 < (INT)ptep->m_cMaxToken)
  3628. && (pwOld[pTokArray[iArray+1].token.ibTokMin] == '-')
  3629. && (pwOld[pTokArray[iArray+1].token.ibTokMin+1] == '-')
  3630. && (0 == _wcsnicmp(rgComment[3], &pwOld[pTokArray[iArray+1].token.ibTokMin+2], wcslen(rgComment[3])))
  3631. )
  3632. {
  3633. fSimpleComment = TRUE; // BUG 14056 - Instead of going to LRet, process the comment for space preservation. We will save 3 strings that look similar to text run
  3634. }
  3635. else
  3636. {
  3637. iArray = iArraySav + 1; // not this one
  3638. goto LRet;
  3639. }
  3640. // The first part matched, look at the end of the comment
  3641. if ( (pwOld[pTokArray[iArray+1].token.ibTokMac-1] == '-')
  3642. && (pwOld[pTokArray[iArray+1].token.ibTokMac-2] == '-')
  3643. && (0 == _wcsnicmp( rgComment[0],
  3644. &pwOld[pTokArray[iArray+1].token.ibTokMac-(wcslen(rgComment[0])+2)],
  3645. wcslen(rgComment[0])
  3646. )
  3647. )
  3648. )
  3649. {
  3650. iCommentEnd = iArray + 2;
  3651. ASSERT(iCommentEnd < (INT)ptep->m_cMaxToken);
  3652. }
  3653. else // error case (our assumption was not valid). ignore and return with iArraySav+1
  3654. {
  3655. if (!fSimpleComment)
  3656. {
  3657. iArray = iArraySav + 1; // not this one
  3658. goto LRet;
  3659. }
  3660. }
  3661. if (!fSimpleComment)
  3662. {
  3663. // found the correct one
  3664. cchComment1 = wcslen(rgComment[1]);
  3665. cchComment2 = wcslen(rgComment[2]);
  3666. // remove cchComment1 chars from begining of pwOld[pTokArray[iArray+1].token.ibTokMin
  3667. // remove cchComment2 chars from the end of pwOld[pTokArray[iArray+1].token.ibTokMac
  3668. // and copy the rest into pwNew
  3669. // copy till begining of the comment
  3670. ichCommentStart = pTokArray[iCommentStart].token.ibTokMin;
  3671. ichObjectStart = pTokArray[iCommentStart+1].token.ibTokMin+cchComment1;
  3672. ASSERT((INT)ichCommentStart-ichBeginCopy >= 0);
  3673. cbNeed = (ichNewCur+(ichCommentStart-ichBeginCopy)+(pTokArray[iArray+1].token.ibTokMac-pTokArray[iArray+1].token.ibTokMin))*sizeof(WCHAR)+cbBufPadding;
  3674. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3675. goto LRet;
  3676. memcpy( (BYTE *)(pwNew+ichNewCur),
  3677. (BYTE *)(pwOld+ichBeginCopy),
  3678. (ichCommentStart-ichBeginCopy)*sizeof(WCHAR));
  3679. ichNewCur += ichCommentStart-ichBeginCopy;
  3680. ichBeginCopy = pTokArray[iCommentEnd].token.ibTokMac;
  3681. ASSERT((INT)(pTokArray[iArray+1].token.ibTokMac-pTokArray[iArray+1].token.ibTokMin-cchComment1-cchComment2) >= 0);
  3682. memcpy( (BYTE *)(pwNew+ichNewCur),
  3683. (BYTE *)&(pwOld[ichObjectStart]),
  3684. (pTokArray[iArray+1].token.ibTokMac-pTokArray[iArray+1].token.ibTokMin-cchComment1-cchComment2)*sizeof(WCHAR));
  3685. ichNewCur += pTokArray[iArray+1].token.ibTokMac-pTokArray[iArray+1].token.ibTokMin-cchComment1-cchComment2;
  3686. iArray = iCommentEnd + 1;
  3687. }
  3688. else
  3689. {
  3690. int ichspBegin, ichspEnd, ichCopy;
  3691. WCHAR *pwstr = NULL;
  3692. // part 1 - copy till begining of the comment & apply spacing
  3693. iCommentStart = iArraySav;
  3694. ASSERT(pTokArray[iArraySav].token.tok == TokTag_BANG);
  3695. ASSERT(pTokArray[iArraySav].token.tokClass == tokTag);
  3696. iCommentEnd = iCommentStart + 2;
  3697. ASSERT(pTokArray[iCommentEnd].token.tok == TokTag_CLOSE);
  3698. ASSERT(pTokArray[iCommentEnd].token.tokClass == tokTag);
  3699. ichCommentStart = pTokArray[iCommentStart].token.ibTokMin;
  3700. ASSERT((INT)ichCommentStart-ichBeginCopy >= 0);
  3701. cbNeed = (ichNewCur+ichCommentStart-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  3702. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3703. goto LRet;
  3704. memcpy( (BYTE *)&pwNew[ichNewCur],
  3705. (BYTE *)&pwOld[ichBeginCopy],
  3706. (ichCommentStart-ichBeginCopy)*sizeof(WCHAR));
  3707. ichNewCur += ichCommentStart-ichBeginCopy;
  3708. // make sure that we have enough space
  3709. // to make this calculation simple, we assume the extreme case where every
  3710. // character in the comment had end of line after it. i.e. we will insert
  3711. // 2 characters ('\r\n') after each character in the comment when we restore
  3712. // the spacing. That means, as long as we have enough space for
  3713. // (pTokArray[iCommentEnd].token.ibTokMac-pTokArray[iCommentStart].token.ibTokMin)*3
  3714. // we are fine
  3715. cbNeed = (ichNewCur+3*(pTokArray[iCommentEnd].token.ibTokMac-pTokArray[iCommentStart].token.ibTokMin))*sizeof(WCHAR)+cbBufPadding;
  3716. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  3717. goto LRet;
  3718. // apply spacing for pre comment part
  3719. // remove extsting spacing before the comment & add the saved spacing
  3720. // note that we already have copied till the begining of the comment
  3721. ichNewCur--;
  3722. while ( ( pwNew[ichNewCur] == ' ' || pwNew[ichNewCur] == '\t'
  3723. || pwNew[ichNewCur] == '\r' || pwNew[ichNewCur] == '\n'
  3724. )
  3725. )
  3726. {
  3727. ichNewCur--;
  3728. }
  3729. ichNewCur++; // compensate, ichNewCur points to non-white space characher
  3730. // now, start writing out the saved spacing
  3731. // look for rgComment[4] & rgComment[5]
  3732. ichspBegin = pTokArray[iCommentStart+1].token.ibTokMin + 2/*for --*/ + wcslen(rgComment[3]);
  3733. pwstr = wcsstr(&pwOld[ichspBegin], rgComment[4]);// pwstr points just after the spacing info block
  3734. if (pwstr == NULL) // didn't find the substring
  3735. {
  3736. // copy the entire comment as is
  3737. memcpy( (BYTE *)&pwNew[ichNewCur],
  3738. (BYTE *)&pwOld[pTokArray[iCommentStart+1].token.ibTokMin],
  3739. (pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2)*sizeof(WCHAR));
  3740. ichNewCur += pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2;
  3741. goto LCommentEnd;
  3742. }
  3743. ichspBegin = SAFE_PTR_DIFF_TO_INT(pwstr+wcslen(rgComment[4])-pwOld);
  3744. pwstr = wcsstr(&pwOld[ichspBegin], rgComment[5]);// pwstr points just after the spacing info block
  3745. if (pwstr == NULL) // didn't find the substring
  3746. {
  3747. // copy the entire comment as is
  3748. memcpy( (BYTE *)&pwNew[ichNewCur],
  3749. (BYTE *)&pwOld[pTokArray[iCommentStart+1].token.ibTokMin],
  3750. (pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2)*sizeof(WCHAR));
  3751. ichNewCur += pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2;
  3752. goto LCommentEnd;
  3753. }
  3754. ichCopy = SAFE_PTR_DIFF_TO_INT(pwstr-pwOld) + wcslen(rgComment[5]); // actual comment begins at ichCopy
  3755. ichspEnd = SAFE_PTR_DIFF_TO_INT(pwstr-pwOld);
  3756. ASSERT(ichspEnd >= ichspBegin);
  3757. while (ichspBegin < ichspEnd)
  3758. {
  3759. switch(pwOld[ichspBegin])
  3760. {
  3761. case chCommentSp:
  3762. pwNew[ichNewCur++] = ' ';
  3763. break;
  3764. case chCommentTab:
  3765. pwNew[ichNewCur++] = '\t';
  3766. break;
  3767. case chCommentEOL:
  3768. pwNew[ichNewCur++] = '\r';
  3769. pwNew[ichNewCur++] = '\n';
  3770. break;
  3771. case ',':
  3772. ASSERT(FALSE);
  3773. break;
  3774. }
  3775. ichspBegin++;
  3776. }
  3777. // now pre comment spacing is restored
  3778. pwNew[ichNewCur++] = '<';
  3779. pwNew[ichNewCur++] = '!';
  3780. pwNew[ichNewCur++] = '-';
  3781. pwNew[ichNewCur++] = '-';
  3782. // part 2 - copy the comment and apply spacing
  3783. // from pTokArray[iCommentStart+1].token,ibTokMIn, look for rgComment[4]
  3784. // thats where we keep our spacing info. Exclude this stuff while copying the comment
  3785. ichspBegin = pTokArray[iCommentStart+1].token.ibTokMin + 2/*for --*/ + wcslen(rgComment[3]);
  3786. // locate rgComment[4] that will be somewhere in iCommentStart'th token
  3787. pwstr = wcsstr(&pwOld[ichspBegin], rgComment[4]);// pwstr points just after the spacing info block
  3788. if (pwstr == NULL) // didn't find the substring
  3789. {
  3790. // copy the entire comment as is
  3791. memcpy( (BYTE *)&pwNew[ichNewCur],
  3792. (BYTE *)&pwOld[pTokArray[iCommentStart+1].token.ibTokMin],
  3793. (pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2)*sizeof(WCHAR));
  3794. ichNewCur += pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2;
  3795. goto LCommentEnd;
  3796. }
  3797. ichspEnd = SAFE_PTR_DIFF_TO_INT(pwstr - pwOld);
  3798. ASSERT(ichspEnd >= ichspBegin);
  3799. while (ichspBegin < ichspEnd)
  3800. {
  3801. switch(pwOld[ichspBegin])
  3802. {
  3803. case chCommentSp:
  3804. pwNew[ichNewCur++] = ' ';
  3805. break;
  3806. case chCommentTab:
  3807. pwNew[ichNewCur++] = '\t';
  3808. break;
  3809. case chCommentEOL:
  3810. pwNew[ichNewCur++] = '\r';
  3811. pwNew[ichNewCur++] = '\n';
  3812. break;
  3813. case ',':
  3814. while ( pwOld[ichCopy] == ' ' || pwOld[ichCopy] == '\t'
  3815. || pwOld[ichCopy] == '\r' || pwOld[ichCopy] == '\n'
  3816. )
  3817. {
  3818. if (ichCopy >= (int)(pTokArray[iCommentStart+1].token.ibTokMac-2)) // we are done with copying
  3819. goto LCommentEnd;
  3820. ichCopy++;
  3821. }
  3822. while ( pwOld[ichCopy] != ' ' && pwOld[ichCopy] != '\t'
  3823. && pwOld[ichCopy] != '\r' && pwOld[ichCopy] != '\n'
  3824. )
  3825. {
  3826. if (ichCopy >= (int)(pTokArray[iCommentStart+1].token.ibTokMac-2)) // we are done with copying
  3827. goto LCommentEnd;
  3828. pwNew[ichNewCur++] = pwOld[ichCopy++];
  3829. }
  3830. break;
  3831. }
  3832. ichspBegin++;
  3833. }
  3834. LCommentEnd:
  3835. // part 3 - copy the end of comment
  3836. pwNew[ichNewCur++] = '-';
  3837. pwNew[ichNewCur++] = '-';
  3838. pwNew[ichNewCur++] = '>';
  3839. // set iArray & ichBeginCopy for next run
  3840. ichBeginCopy = pTokArray[iCommentEnd].token.ibTokMac;
  3841. iArray = iCommentEnd + 1;
  3842. }
  3843. LRet:
  3844. *pcchNew = ichNewCur;
  3845. *ppwNew = pwNew;
  3846. *pichNewCur = ichNewCur;
  3847. *pichBeginCopy = ichBeginCopy;
  3848. *piArrayStart = iArray;
  3849. //LRetOnly:
  3850. return;
  3851. } /* fnRestoreObject()*/
  3852. void
  3853. CTriEditParse::fnSaveSpace(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  3854. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  3855. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD /*dwFlags*/)
  3856. {
  3857. UINT ichNewCur = *pichNewCur;
  3858. UINT ichBeginCopy = *pichBeginCopy;
  3859. INT iArray = (INT)*piArrayStart;
  3860. INT ichEnd, ichBegin;
  3861. LPWSTR pwNew = *ppwNew;
  3862. INT iArraySav = iArray;
  3863. LPCWSTR rgSpaceTags[] =
  3864. {
  3865. L" DESIGNTIMESP=",
  3866. L" DESIGNTIMESP1=",
  3867. L" designtimesp=",
  3868. };
  3869. INT iArrayElem = -1;
  3870. INT iArrayMatch, iArrayPrevTag;
  3871. INT ichEndMatch, ichBeginMatch, ichEndPrev, ichBeginPrev, ichEndNext, ichBeginNext, ichEndTag, ichBeginTag;
  3872. WCHAR szIndex[cchspBlockMax]; // will we have more than 20 digit numbers as number of DESIGNTIMESPx?
  3873. UINT cbNeed;
  3874. int cchURL = 0;
  3875. int ichURL = 0;
  3876. // {-1, TokTag_START, tokTag, TokTag_CLOSE, -1, tokClsIgnore, fnSaveSpace},
  3877. ASSERT(dwFlags &dwPreserveSourceCode);
  3878. // special cases where we don't need to save spacing, because Trident doesn't muck with
  3879. // the spacing in these cases. If this changes in future, remove these cases.
  3880. // If this case is removed, then make sure that fnSaveObject() changes accordingly
  3881. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /* validation */
  3882. && (pTokArray[iArray+1].token.tok == TokElem_OBJECT)
  3883. && (pTokArray[iArray+1].token.tokClass == tokElem)
  3884. )
  3885. {
  3886. // (iArray+1)th token is an OBJECT tag
  3887. iArray = iArraySav + 1;
  3888. goto LRet;
  3889. }
  3890. // trident munges custom attributes inside STYLE tag, so DESIGNTIMESP gets out of place
  3891. // so lets not save any spacing info for TokElem_STYLE
  3892. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /* validation */
  3893. && (pTokArray[iArray+1].token.tok == TokElem_STYLE)
  3894. && (pTokArray[iArray+1].token.tokClass == tokElem)
  3895. )
  3896. {
  3897. // (iArray+1)th token is an STYLE tag
  3898. iArray = iArraySav + 1;
  3899. goto LRet;
  3900. }
  3901. // trident overwrites PARAM tags, so we can skip saving spacing info
  3902. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /* validation */
  3903. && (pTokArray[iArray+1].token.tok == TokElem_PARAM)
  3904. && (pTokArray[iArray+1].token.tokClass == tokElem)
  3905. )
  3906. {
  3907. // (iArray+1)th token is an PARAM tag
  3908. iArray = iArraySav + 1;
  3909. goto LRet;
  3910. }
  3911. // we should skip saving for <applet>
  3912. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /* validation */
  3913. && ( pTokArray[iArray+1].token.tok == TokElem_APPLET
  3914. )
  3915. && (pTokArray[iArray+1].token.tokClass == tokElem)
  3916. )
  3917. {
  3918. // (iArray+1)th token is an APPLET tag
  3919. iArray = iArraySav + 1;
  3920. goto LRet;
  3921. }
  3922. // we special case textarea tags, so we should skip saving spacing info
  3923. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /* validation */
  3924. && (pTokArray[iArray+1].token.tok == TokElem_TEXTAREA)
  3925. && (pTokArray[iArray+1].token.tokClass == tokElem)
  3926. )
  3927. {
  3928. // (iArray+1)th token is TEXTAREA tag
  3929. iArray = iArraySav + 1;
  3930. goto LRet;
  3931. }
  3932. // we special case A/IMG/LINK tags with Relative URLs ONLY, so we should skip saving spacing info
  3933. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /* validation */
  3934. && ( pTokArray[iArray+1].token.tok == TokElem_A
  3935. || pTokArray[iArray+1].token.tok == TokElem_IMG
  3936. || pTokArray[iArray+1].token.tok == TokElem_LINK
  3937. )
  3938. && (pTokArray[iArray+1].token.tokClass == tokElem)
  3939. && (FURLNeedSpecialHandling(pTokArray, iArray, pwOld, (int)ptep->m_cMaxToken, &ichURL, &cchURL))
  3940. )
  3941. {
  3942. iArray = iArraySav + 1;
  3943. goto LRet;
  3944. }
  3945. // step 1
  3946. // look for > that matches with <. we already are at ft.tokBegin2 i.e. <
  3947. ASSERT(pTokArray[iArray].token.tok == TokTag_START);
  3948. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  3949. ichBeginTag = pTokArray[iArray].token.ibTokMac;
  3950. while (iArray < (int)ptep->m_cMaxToken)
  3951. {
  3952. if (pTokArray[iArray].token.tok == ft.tokEnd && pTokArray[iArray].token.tokClass == tokTag) // ft.tokEnd2 is -1
  3953. break;
  3954. if (pTokArray[iArray].token.tokClass == tokElem)
  3955. iArrayElem = iArray;
  3956. iArray++;
  3957. }
  3958. if (iArray >= (int)ptep->m_cMaxToken) // didn't find >
  3959. {
  3960. goto LRet;
  3961. }
  3962. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE); // found >
  3963. ASSERT(pTokArray[iArray].token.tokClass == tokTag); // found >
  3964. ichEndTag = ichBegin = pTokArray[iArray].token.ibTokMin;
  3965. ichEnd = pTokArray[iArray].token.ibTokMac;
  3966. // step 2
  3967. // look for > before iArraySav. Boundary case will be for the first < in the document
  3968. // save the spacing info
  3969. ASSERT(pTokArray[iArraySav].token.tok == TokTag_START);
  3970. ASSERT(pTokArray[iArraySav].token.tokClass == tokTag);
  3971. ichEndPrev = pTokArray[iArraySav].token.ibTokMin;
  3972. ichBeginPrev = ichEndPrev-1;
  3973. // look for previous TokTag_CLOSE
  3974. // if the tag ending tag, ichBeginPrev becomes ibTokMac of '>' tag
  3975. // if the tag is starting tag, ichBeginPrev becomes ibTokMac+(white space just after that tag)
  3976. iArrayPrevTag = iArraySav; // this is TokTag_START
  3977. while (iArrayPrevTag >= 0)
  3978. {
  3979. if ( ( pTokArray[iArrayPrevTag].token.tokClass == tokTag
  3980. && pTokArray[iArrayPrevTag].token.tok == TokTag_CLOSE
  3981. )
  3982. || ( pTokArray[iArrayPrevTag].token.tokClass == tokSSS
  3983. && pTokArray[iArrayPrevTag].token.tok == TokTag_SSSCLOSE
  3984. )/* VID6 - bug 22787 */
  3985. )
  3986. {
  3987. break;
  3988. }
  3989. iArrayPrevTag--;
  3990. }
  3991. if (iArrayPrevTag < 0) // handle error case
  3992. {
  3993. // leave the old behaviour as is for V1
  3994. while (ichBeginPrev >= 0)
  3995. {
  3996. if ( pwOld[ichBeginPrev] != ' '
  3997. && pwOld[ichBeginPrev] != '\r'
  3998. && pwOld[ichBeginPrev] != '\n'
  3999. && pwOld[ichBeginPrev] != '\t'
  4000. )
  4001. break;
  4002. ichBeginPrev--;
  4003. }
  4004. goto LGotEndNext;
  4005. }
  4006. ichBeginPrev = pTokArray[iArrayPrevTag].token.ibTokMac - 1;
  4007. LGotEndNext:
  4008. if (ichBeginPrev < 0)
  4009. ichBeginPrev = 0;
  4010. else
  4011. ichBeginPrev++;
  4012. // step 3
  4013. // look for TokTag_START after iArray(which currently is TokTag_CLOSE)
  4014. // save spacing info
  4015. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  4016. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  4017. //iArrayNextStart = iArray;
  4018. ichBeginNext = pTokArray[iArray].token.ibTokMac;
  4019. ASSERT(ichBeginNext == ichEnd);
  4020. ichEndNext = ichBeginNext;
  4021. while (ichEndNext < (INT)pTokArray[ptep->m_cMaxToken-1].token.ibTokMac)
  4022. {
  4023. if ( pwOld[ichEndNext] != ' '
  4024. && pwOld[ichEndNext] != '\r'
  4025. && pwOld[ichEndNext] != '\n'
  4026. && pwOld[ichEndNext] != '\t'
  4027. )
  4028. break;
  4029. ichEndNext++;
  4030. }
  4031. if (ichEndNext >= (INT)pTokArray[ptep->m_cMaxToken-1].token.ibTokMac)
  4032. ichEndNext = pTokArray[ptep->m_cMaxToken-1].token.ibTokMac;
  4033. // step 4
  4034. // if iArrayElem != -1, look for pTokArray[iArrayElem].iNextprev. If its not -1, set iArrayMatch
  4035. // look for previous TokTag_START/TokTag_END. look for previous TokTag_CLOSE
  4036. // save spacing info
  4037. if (iArrayElem == -1) // this can happen if we have incomplete HTML
  4038. {
  4039. ichEndMatch = ichBeginMatch = 0;
  4040. goto LSkipMatchCalc;
  4041. }
  4042. iArrayMatch = pTokArray[iArrayElem].iNextprev;
  4043. if (iArrayMatch != -1) // match was set while tokenizing
  4044. {
  4045. ichBeginMatch = ichEndMatch = 0; //init
  4046. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  4047. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  4048. while (iArrayMatch >= iArray) // iArray is TokTag_CLOSE of the current tag (i.e. '>')
  4049. {
  4050. if ( pTokArray[iArrayMatch].token.tokClass == tokTag
  4051. && ( pTokArray[iArrayMatch].token.tok == TokTag_START
  4052. || pTokArray[iArrayMatch].token.tok == TokTag_END
  4053. )
  4054. )
  4055. break;
  4056. iArrayMatch--;
  4057. }
  4058. if (iArrayMatch > iArray) // did find '</' or '<' after the current tag
  4059. {
  4060. ichEndMatch = pTokArray[iArrayMatch].token.ibTokMin;
  4061. ichBeginMatch = ichEndMatch; // init
  4062. // look for '>' and set ichBeginMatch
  4063. while (iArrayMatch >= iArray) // iArray is TokTag_CLOSE of the current tag (i.e. '>')
  4064. {
  4065. if ( ( pTokArray[iArrayMatch].token.tokClass == tokTag
  4066. && pTokArray[iArrayMatch].token.tok == TokTag_CLOSE
  4067. )
  4068. || ( pTokArray[iArrayMatch].token.tokClass == tokSSS
  4069. && pTokArray[iArrayMatch].token.tok == TokTag_SSSCLOSE
  4070. )/* VID6 - bug 22787 */
  4071. )
  4072. break;
  4073. iArrayMatch--;
  4074. }
  4075. if (iArrayMatch >= iArray) // they may very well be the same
  4076. {
  4077. ichBeginMatch = pTokArray[iArrayMatch].token.ibTokMac;
  4078. ASSERT(ichBeginMatch <= ichEndMatch);
  4079. ASSERT(ichBeginMatch >= ichEnd);
  4080. }
  4081. }
  4082. }
  4083. else
  4084. {
  4085. // don't bother saving any info from here
  4086. ichEndMatch = ichBeginMatch = 0;
  4087. }
  4088. LSkipMatchCalc:
  4089. if (ichEndPrev > ichBeginPrev)
  4090. ptep->hrMarkSpacing(pwOld, ichEndPrev, &ichBeginPrev);
  4091. else
  4092. ptep->hrMarkSpacing(pwOld, ichEndPrev, &ichEndPrev);
  4093. if (ichEndTag > ichBeginTag)
  4094. {
  4095. INT ichBeginTagSav = ichBeginTag;
  4096. ptep->hrMarkSpacing(pwOld, ichEndTag, &ichBeginTag);
  4097. // iArray'th token is TokTag_CLOSE & iArraySav is TokTag_START
  4098. ptep->hrMarkOrdering(pwOld, pTokArray, iArraySav, iArray, ichEndTag, &ichBeginTagSav);
  4099. }
  4100. else
  4101. {
  4102. INT ichEndTagSav = ichEndTag;
  4103. ptep->hrMarkSpacing(pwOld, ichEndTag, &ichEndTag);
  4104. // iArray'th token is TokTag_CLOSE & iArraySav is TokTag_START
  4105. ptep->hrMarkOrdering(pwOld, pTokArray, iArraySav, iArray, ichEndTagSav, &ichEndTagSav);
  4106. }
  4107. if (ichEndNext > ichBeginNext)
  4108. ptep->hrMarkSpacing(pwOld, ichEndNext, &ichBeginNext);
  4109. else
  4110. ptep->hrMarkSpacing(pwOld, ichEndNext, &ichEndNext);
  4111. if (ichEndMatch > ichBeginMatch)
  4112. ptep->hrMarkSpacing(pwOld, ichEndMatch, &ichBeginMatch);
  4113. else
  4114. ptep->hrMarkSpacing(pwOld, ichEndMatch, &ichEndMatch);
  4115. // realloc if needed
  4116. cbNeed = (ichNewCur+ichBegin-ichBeginCopy+3*wcslen(rgSpaceTags[0])+(ichEnd-ichBegin))*sizeof(WCHAR);
  4117. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  4118. goto LErrorRet;
  4119. // ichBeginCopy is a position in pwOld and
  4120. // ichNewCur is a position in pwNew
  4121. // copy from ichBeginCopy to >
  4122. ASSERT((INT)(ichBegin-ichBeginCopy) >= 0);
  4123. if ((INT)(ichBegin-ichBeginCopy) > 0)
  4124. {
  4125. memcpy( (BYTE *)(pwNew+ichNewCur),
  4126. (BYTE *)(pwOld+ichBeginCopy),
  4127. (ichBegin-ichBeginCopy)*sizeof(WCHAR));
  4128. ichNewCur += (ichBegin-ichBeginCopy);
  4129. }
  4130. ichBeginCopy = ichEnd; // make it ready for next copy
  4131. // BUG 15389 - Ideal fix will be to save the exact tag and restore it when we switch back,
  4132. // but it will be a bigger change at this point, So we simply look at first character of the tag.
  4133. // If it is uppercase, write DESIGNTIMESP, else write designtimesp
  4134. // ASSUMPTION is that Trident doesn't change the case of unknown attribute & so far its TRUE.
  4135. // ASSUMPTION is that we don't have extra spaces between '<' & the tag name.
  4136. ASSERT(wcslen(rgSpaceTags[0]) == wcslen(rgSpaceTags[2]));
  4137. if (iswupper(pwOld[pTokArray[iArraySav+1].token.ibTokMin]) != 0) // upper case
  4138. {
  4139. memcpy( (BYTE *)(pwNew+ichNewCur),
  4140. (BYTE *)(rgSpaceTags[0]),
  4141. (wcslen(rgSpaceTags[0]))*sizeof(WCHAR));
  4142. ichNewCur += wcslen(rgSpaceTags[0]);
  4143. }
  4144. else
  4145. {
  4146. memcpy( (BYTE *)(pwNew+ichNewCur),
  4147. (BYTE *)(rgSpaceTags[2]),
  4148. (wcslen(rgSpaceTags[2]))*sizeof(WCHAR));
  4149. ichNewCur += wcslen(rgSpaceTags[2]);
  4150. }
  4151. (WCHAR)_itow(ptep->m_ispInfoBlock+ptep->m_ispInfoBase, szIndex, 10);
  4152. ptep->m_ispInfoBlock++;
  4153. ASSERT(wcslen(szIndex) < sizeof(szIndex));
  4154. ASSERT(sizeof(szIndex) == cchspBlockMax*sizeof(WCHAR));
  4155. memcpy( (BYTE *)(pwNew+ichNewCur),
  4156. (BYTE *)(szIndex),
  4157. wcslen(szIndex)*sizeof(WCHAR));
  4158. ichNewCur += wcslen(szIndex);
  4159. // if (m_ispInfoIn == 0), then we have the last block of SPINFO, lets save it here
  4160. if (ptep->m_ispInfoIn == 0)
  4161. {
  4162. ASSERT(FALSE);
  4163. // realloc if needed
  4164. cbNeed = (ichNewCur+ichBegin-ichBeginCopy+2*wcslen(rgSpaceTags[1]))*sizeof(WCHAR);
  4165. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  4166. goto LErrorRet;
  4167. memcpy( (BYTE *)(pwNew+ichNewCur),
  4168. (BYTE *)(rgSpaceTags[1]),
  4169. (wcslen(rgSpaceTags[1]))*sizeof(WCHAR));
  4170. ichNewCur += wcslen(rgSpaceTags[1]);
  4171. *(WCHAR *)(pwNew+ichNewCur) = 'Z'; // ptep->m_ispInfoIn;
  4172. ichNewCur++;
  4173. }
  4174. ASSERT((INT)(ichEnd-ichBegin) > 0);
  4175. memcpy( (BYTE *)(pwNew+ichNewCur),
  4176. (BYTE *)(pwOld+ichBegin),
  4177. (ichEnd-ichBegin)*sizeof(WCHAR));
  4178. ichNewCur += (ichEnd-ichBegin);
  4179. // restore iArray
  4180. iArray = iArraySav+1;
  4181. LErrorRet:
  4182. LRet:
  4183. *pcchNew = ichNewCur;
  4184. *ppwNew = pwNew;
  4185. *pichNewCur = ichNewCur;
  4186. *pichBeginCopy = ichBeginCopy;
  4187. *piArrayStart = (UINT)iArray;
  4188. } /* fnSaveSpace() */
  4189. void
  4190. CTriEditParse::fnRestoreSpace(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  4191. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  4192. INT *pcHtml, UINT *pichNewCur, UINT *pichBeginCopy, DWORD dwFlags)
  4193. {
  4194. UINT ichNewCur = *pichNewCur;
  4195. UINT ichBeginCopy = *pichBeginCopy;
  4196. INT iArray = (INT)*piArrayStart;
  4197. UINT ichBegin, ichspInfoEndtagEnd;
  4198. LPWSTR pwNew = *ppwNew;
  4199. LPCWSTR rgSpaceTags[] =
  4200. {
  4201. L"DESIGNTIMESP",
  4202. L"DESIGNTIMESP1",
  4203. };
  4204. INT iArraySav = iArray;
  4205. WORD *pspInfoEnd, *pspInfoOrder;
  4206. INT cchwspInfo; // spInfo block size in wide chars
  4207. INT cchRange; // number of char for which this spInfo was saved
  4208. BOOL fMatch = FALSE;
  4209. BOOL fMatchLast = FALSE;
  4210. INT cchtok, cchtag, itoktagStart, ichtoktagStart, iArrayValue, index;
  4211. WCHAR szIndex[cchspBlockMax];
  4212. INT cwOrderInfo = 0;
  4213. UINT cbNeed;
  4214. INT ichNewCurSav = -1; // init to -1 so that we will know when its set.
  4215. int ichNewCurAtIndex0 = -1; // we need to adjust the saved ichNewCur because it gets invalidated
  4216. // as soon as the tag moves as a result of restoring pre-tag spaces.
  4217. ASSERT(dwFlags & dwPreserveSourceCode);
  4218. // take care of the matching end token's spacing
  4219. if ( pTokArray[iArray].token.tok == ft.tokBegin2
  4220. && pTokArray[iArray].token.tokClass == tokTag
  4221. )
  4222. {
  4223. ASSERT(ft.tokBegin2 == TokTag_END);
  4224. fnRestoreSpaceEnd( ptep, pwOld, ppwNew, pcchNew, phgNew, pTokArray, piArrayStart,
  4225. ft, pcHtml, pichNewCur, pichBeginCopy, dwFlags);
  4226. goto LRetOnly;
  4227. }
  4228. // we already are at (token.tok == tokSpace), which may be DESIGNTIMESPx
  4229. ASSERT(pTokArray[iArray].token.tok == 0);
  4230. ASSERT(pTokArray[iArray].token.tokClass == tokSpace);
  4231. cchtok = pTokArray[iArray].token.ibTokMac - pTokArray[iArray].token.ibTokMin;
  4232. cchtag = wcslen(rgSpaceTags[0]);
  4233. if (cchtag == cchtok)
  4234. {
  4235. if (0 == _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[iArray].token.ibTokMin], cchtag))
  4236. {
  4237. fMatch = TRUE;// match
  4238. }
  4239. else
  4240. goto LNoMatch;
  4241. }
  4242. else if (cchtag+1 == cchtok)
  4243. {
  4244. if (0 == _wcsnicmp(rgSpaceTags[1], &pwOld[pTokArray[iArray].token.ibTokMin], cchtag+1))
  4245. {
  4246. fMatchLast = TRUE;// match
  4247. }
  4248. else
  4249. goto LNoMatch;
  4250. }
  4251. else
  4252. {
  4253. LNoMatch:
  4254. iArray = iArraySav + 1;
  4255. goto LRet;
  4256. }
  4257. ASSERT(fMatch || fMatchLast); // one of them has to be TRUE
  4258. // found DESIGNTIMESPx. Now, go backwords and look for ft.tokBegin
  4259. itoktagStart = iArray;
  4260. ASSERT(ft.tokBegin == TokTag_START);
  4261. while (itoktagStart >= 0)
  4262. {
  4263. if ( pTokArray[itoktagStart].token.tok == ft.tokBegin
  4264. && pTokArray[itoktagStart].token.tokClass == tokTag
  4265. )
  4266. {
  4267. break;
  4268. }
  4269. itoktagStart--;
  4270. }
  4271. if (itoktagStart < 0) // didn't find '<' before DESIGNTIMESPx
  4272. {
  4273. iArray = iArraySav + 1;
  4274. goto LRet;
  4275. }
  4276. // found '<' before DESIGNTIMESPx
  4277. // the spacing info saved was for the portion of the document before the '<'
  4278. ASSERT(pTokArray[itoktagStart].token.tok == TokTag_START);
  4279. ASSERT(pTokArray[itoktagStart].token.tokClass == tokTag);
  4280. // we already know that iArray'th token is DESIGNTIMESPx, so get past the '=' that follows it
  4281. // ASSUMPTION - the value of attribute DESIGNTIMESPx will NOT get munged by Trident.
  4282. // NOTE - the above assumption is correct for this release of Trident
  4283. while (iArray < (int)ptep->m_cMaxToken)
  4284. {
  4285. if (*(WORD *)(pwOld+pTokArray[iArray].token.ibTokMin) == '=')
  4286. {
  4287. ASSERT(pTokArray[iArray].token.tokClass == tokOp);
  4288. break;
  4289. }
  4290. else if (*(WORD *)(pwOld+pTokArray[iArray].token.ibTokMin) == '>') // gone too far
  4291. goto LSkip1;
  4292. iArray++;
  4293. }
  4294. if (iArray >= (int)ptep->m_cMaxToken) // didn't find = after DESIGNTIMESPx
  4295. {
  4296. LSkip1:
  4297. iArray = iArraySav + 1;
  4298. goto LRet;
  4299. }
  4300. iArrayValue = -1;
  4301. while (iArray < (int)ptep->m_cMaxToken)
  4302. {
  4303. if ( (iArrayValue == -1)
  4304. && ( (pTokArray[iArray].token.tokClass == tokValue)
  4305. || (pTokArray[iArray].token.tokClass == tokString)
  4306. )
  4307. )
  4308. iArrayValue = iArray;
  4309. else if ( pTokArray[iArray].token.tok == TokTag_CLOSE
  4310. && pTokArray[iArray].token.tokClass == tokTag
  4311. )
  4312. {
  4313. ASSERT(*(WORD *)(pwOld+pTokArray[iArray].token.ibTokMin) == '>');
  4314. break;
  4315. }
  4316. iArray++;
  4317. }
  4318. if (iArrayValue == -1 || iArray >= (int)ptep->m_cMaxToken) // didn't find tokValue after DESIGNTIMESPx
  4319. {
  4320. // BUG 9040
  4321. //if (iArray >= (int)ptep->m_cMaxToken && iArrayValue != -1)
  4322. //{
  4323. // SOLUTION 1
  4324. // overwrite the stuff from pwOld[pTokArray[iArraySav].token.ibTokMin]
  4325. // to pwOld[pTokArray[iArrayValue].token.ibTokMac - 1]
  4326. // SOLUTION 2
  4327. // look for DESIGNTIMESP from pwOld[pTokArray[itokTagStart].token.ibTokMac - 1]
  4328. // to pwOld[pTokArray[iArray].token.ibTokMac - 1] and overwrite all of those
  4329. // strings with spaces. We could NULL those and do the blts, but why bother
  4330. // when the html isn't valid!
  4331. // make sure that all DESIGNTIMESPs are stripped off if we encountered this error case
  4332. //}
  4333. iArray = iArraySav + 1;
  4334. goto LRet;
  4335. }
  4336. // we know that 4 blocks of info was saved for each DESIGNTIMESPx attribute
  4337. // before tag, within tag, after tag, before matching end-tag
  4338. // even if no info was saved, the block will still exist with 2 words (size,# of char)
  4339. ichspInfoEndtagEnd = pTokArray[iArray].token.ibTokMac;
  4340. // first copy the document till DESIGNTIMESPx
  4341. // skip DESIGNTIMESPx and its value and set ichBeginCopy to be after that
  4342. // NOTE - token before iArraySav'th one should be tokSpace with lenght 1
  4343. // and with a value of chSpace (unless Trident has modified it). If thats TRUE,
  4344. // we should skip that too, because we added it when we put in DESIGNTIMESPx.
  4345. // fix Trident's behaviour - If Trident sees unknown tag(s) it puts it(them) at the end
  4346. // and inserts EOL before those. In this case, we would have inserted a space before DESIGNTIMESP
  4347. // and Trident would have inserted EOL. If thats not the case, we will ignore it.
  4348. if ( (iArraySav-1 > 0) /* validation */
  4349. && ( ( (pTokArray[iArraySav-1].token.ibTokMac - pTokArray[iArraySav-1].token.ibTokMin == 1)
  4350. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin] == ' ')
  4351. )
  4352. || ( (pTokArray[iArraySav-1].token.ibTokMac - pTokArray[iArraySav-1].token.ibTokMin == 3)
  4353. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin] == ' ')
  4354. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin+1] == '\r')
  4355. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin+2] == '\n')
  4356. )
  4357. )
  4358. )
  4359. {
  4360. ichBegin = pTokArray[iArraySav-1].token.ibTokMin;
  4361. }
  4362. else
  4363. ichBegin = pTokArray[iArraySav].token.ibTokMin;
  4364. ASSERT(ichBegin >= ichBeginCopy);
  4365. cbNeed = (ichNewCur+(ichBegin-ichBeginCopy))*sizeof(WCHAR) + cbBufPadding;
  4366. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  4367. {
  4368. iArray = iArraySav + 1;
  4369. goto LRet;
  4370. }
  4371. // BUG 15389 - look at the case of DESIGNTIMESP & convert the tag into upper/lower case...
  4372. //memcpy( (BYTE *)(pwNew+ichNewCur),
  4373. // (BYTE *)(pwOld+ichBeginCopy),
  4374. // (ichBegin-ichBeginCopy)*sizeof(WCHAR));
  4375. //ichNewCur += (ichBegin-ichBeginCopy);
  4376. if (ichBegin >= ichBeginCopy )
  4377. {
  4378. // step 1 - copy from ichBeginCopy to '<' of the current tag
  4379. if ((int)(pTokArray[itoktagStart].token.ibTokMac-ichBeginCopy) > 0)
  4380. {
  4381. memcpy( (BYTE *)(pwNew+ichNewCur),
  4382. (BYTE *)(pwOld+ichBeginCopy),
  4383. (pTokArray[itoktagStart].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  4384. ichNewCur += (pTokArray[itoktagStart].token.ibTokMac-ichBeginCopy);
  4385. ichNewCurSav = ichNewCur+1; // used as a peg to get preceding tokTag_START i.e. '<'
  4386. }
  4387. // step 2 - convert current tag into upper/lower case & copy it
  4388. if (ichBeginCopy < pTokArray[itoktagStart+1].token.ibTokMin)
  4389. {
  4390. ASSERT((int)(pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin) > 0);
  4391. memcpy( (BYTE *)(pwNew+ichNewCur),
  4392. (BYTE *)(pwOld+pTokArray[itoktagStart+1].token.ibTokMin),
  4393. (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin)*sizeof(WCHAR));
  4394. if (iswupper(pwOld[pTokArray[iArraySav].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  4395. {
  4396. // convert the tag into upper case. ASSUME that the tag is at itoktagStart+1
  4397. _wcsupr(&pwNew[ichNewCur]);
  4398. }
  4399. else
  4400. {
  4401. // convert the tag into lower case. ASSUME that the tag is at itoktagStart+1
  4402. _wcslwr(&pwNew[ichNewCur]);
  4403. }
  4404. ichNewCur += (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin);
  4405. }
  4406. else // this tag is alreay been copied
  4407. {
  4408. // hack
  4409. if (pTokArray[itoktagStart+1].token.ibTokMac == ichBeginCopy) // means we are just past the current tag
  4410. {
  4411. if (iswupper(pwOld[pTokArray[iArraySav].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  4412. {
  4413. ASSERT(ichNewCur >= (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin));
  4414. // convert the tag into upper case. ASSUME that the tag is at itoktagStart+1
  4415. _wcsupr(&pwNew[ichNewCur-(pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin)]);
  4416. }
  4417. else
  4418. {
  4419. ASSERT(ichNewCur >= (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin));
  4420. // convert the tag into lower case. ASSUME that the tag is at itoktagStart+1
  4421. _wcslwr(&pwNew[ichNewCur-(pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin)]);
  4422. }
  4423. }
  4424. }
  4425. // step 3 - copy from after the tag (which is at ichtoktagStart+1) to ichBegin
  4426. if ((int)(ichBegin-pTokArray[itoktagStart+1].token.ibTokMac) > 0)
  4427. {
  4428. memcpy( (BYTE *)(pwNew+ichNewCur),
  4429. (BYTE *)(pwOld+pTokArray[itoktagStart+1].token.ibTokMac),
  4430. (ichBegin-pTokArray[itoktagStart+1].token.ibTokMac)*sizeof(WCHAR));
  4431. ichNewCur += (ichBegin-pTokArray[itoktagStart+1].token.ibTokMac);
  4432. }
  4433. }
  4434. // set ichBeginCopy
  4435. ichBeginCopy = ichspInfoEndtagEnd; // make it ready for next copy
  4436. // copy the rest of the tag (skipping DESIGNTIMESPx = value)
  4437. ASSERT((INT)(ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac) >= 0);
  4438. memcpy( (BYTE *)(pwNew+ichNewCur),
  4439. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMac),
  4440. (ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac)*sizeof(WCHAR));
  4441. ichNewCur += (ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac);
  4442. memset((BYTE *)szIndex, 0, sizeof(szIndex));
  4443. // check if the value has quotes around it and don't copy them to szIndex
  4444. if ( pwOld[pTokArray[iArrayValue].token.ibTokMin] == '"'
  4445. && pwOld[pTokArray[iArrayValue].token.ibTokMac-1] == '"'
  4446. )
  4447. {
  4448. memcpy( (BYTE *)szIndex,
  4449. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMin+1),
  4450. (pTokArray[iArrayValue].token.ibTokMac-pTokArray[iArrayValue].token.ibTokMin-2)*sizeof(WCHAR));
  4451. }
  4452. else
  4453. {
  4454. memcpy( (BYTE *)szIndex,
  4455. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMin),
  4456. (pTokArray[iArrayValue].token.ibTokMac-pTokArray[iArrayValue].token.ibTokMin)*sizeof(WCHAR));
  4457. }
  4458. ptep->m_ispInfoBlock = _wtoi(szIndex);
  4459. ptep->m_ispInfoBlock -= ptep->m_ispInfoBase;
  4460. if (ptep->m_ispInfoBlock < 0)
  4461. {
  4462. iArray = iArraySav + 1;
  4463. goto LRet;
  4464. }
  4465. // NOTE - we can cache this info in a link list at the begining
  4466. // get to the ptep->m_ispInfoBlock'th block from ptep->m_pspInfoOutStart
  4467. ASSERT(ptep->m_cchspInfoTotal >= 0);
  4468. pspInfoEnd = ptep->m_pspInfoOutStart + ptep->m_cchspInfoTotal;
  4469. ptep->m_pspInfoOut = ptep->m_pspInfoOutStart;
  4470. for (index = 0; index < ptep->m_ispInfoBlock; index++)
  4471. {
  4472. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // before <
  4473. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // between <>
  4474. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // Order Info
  4475. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // after >
  4476. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // before matching </
  4477. // we somehow have gone beyond the data that was saved for spacing
  4478. if (ptep->m_pspInfoOut >= pspInfoEnd)
  4479. {
  4480. iArray = iArraySav + 1;
  4481. goto LRet;
  4482. }
  4483. }
  4484. // get the Order Info
  4485. pspInfoOrder = ptep->m_pspInfoOut;
  4486. pspInfoOrder += *(WORD *)pspInfoOrder; // skip info saved for spacing before '<'
  4487. pspInfoOrder += *(WORD *)pspInfoOrder; // skip info saved for spacing between '<>'
  4488. // now pspInfoOrder is at correct place
  4489. cwOrderInfo = *(WORD *)pspInfoOrder++;
  4490. ASSERT(cwOrderInfo >= 1);
  4491. // process this info
  4492. if (cwOrderInfo > 1) // means that we saved some info
  4493. {
  4494. INT cchNewCopy;
  4495. cchNewCopy = (ichBegin-pTokArray[itoktagStart].token.ibTokMin) + (ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac);
  4496. ptep->FRestoreOrder(pwNew, pwOld, pspInfoOrder, &ichNewCur, cwOrderInfo, pTokArray, itoktagStart, iArray, iArraySav, iArrayValue, cchNewCopy, phgNew);
  4497. }
  4498. ichtoktagStart = ichNewCur; // init
  4499. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  4500. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  4501. for (index = 0; index < 4; index++)
  4502. {
  4503. BOOL fLookback = FALSE;
  4504. cchwspInfo = *(WORD *)ptep->m_pspInfoOut++;
  4505. cchRange = *(WORD *)ptep->m_pspInfoOut++;
  4506. if (cchwspInfo == 2) // we didn't save any spacing info
  4507. {
  4508. if (index == 0) // special case BUG 8741
  4509. {
  4510. // Note that we didn't save anything before this tag. which means that
  4511. // we had '>' or some text immediately before the < tag.
  4512. ichtoktagStart = ichNewCur;
  4513. while (ichtoktagStart >= 0)
  4514. {
  4515. if (pwNew[ichtoktagStart] == '<')
  4516. {
  4517. ichtoktagStart--;
  4518. break;
  4519. }
  4520. ichtoktagStart--;
  4521. }
  4522. if (ichtoktagStart >= 0)
  4523. {
  4524. int cws = 0;
  4525. int ichtagStart = ichtoktagStart;
  4526. // remove any such white space trident inserts.
  4527. while ( pwNew[ichtoktagStart] == ' '
  4528. || pwNew[ichtoktagStart] == '\r'
  4529. || pwNew[ichtoktagStart] == '\n'
  4530. || pwNew[ichtoktagStart] == '\t')
  4531. {
  4532. cws++;
  4533. ichtoktagStart--;
  4534. }
  4535. if (cws > 0)
  4536. {
  4537. ASSERT((int)(ichNewCur-ichtagStart-1) >= 0);
  4538. //ichtokTagStart now points to either '>' or a non-whitespace char
  4539. memmove((BYTE*)&pwNew[ichtoktagStart+1],
  4540. (BYTE*)&pwNew[ichtoktagStart+1+cws],
  4541. (ichNewCur-ichtagStart-1)*sizeof(WCHAR));
  4542. ichNewCur -= cws;
  4543. }
  4544. } // if (ichtoktagStart >= 0)
  4545. } // if (index == 0)
  4546. goto LNext;
  4547. }
  4548. // note that ichtoktagStart is a position in pwNew
  4549. switch (index)
  4550. {
  4551. case 0: // before < of the tag
  4552. fLookback = TRUE;
  4553. ichtoktagStart = (ichNewCurSav == -1)?ichNewCur:ichNewCurSav;// handle < ... <%..%>...> case correctly
  4554. ichNewCurAtIndex0 = ichNewCur; // lets save the ichNewCur before we restore pre-tag spacing
  4555. while (ichtoktagStart >= 0)
  4556. {
  4557. if (pwNew[ichtoktagStart] == '<' && pwNew[ichtoktagStart+1] != '%')
  4558. {
  4559. ichtoktagStart--;
  4560. break;
  4561. }
  4562. ichtoktagStart--;
  4563. }
  4564. if (ichtoktagStart < 0) // looks to be an error, don't try to restore the spacing
  4565. {
  4566. ptep->m_pspInfoOut += cchwspInfo-2;
  4567. continue;
  4568. }
  4569. break;
  4570. case 1: // between <> of the tag
  4571. fLookback = FALSE;
  4572. // NOTE - we can assume that in 'case 0' we had put ichtoktagStart is just before '<'
  4573. // so that we can avoid this while loop. but what if we skipped case '0'?
  4574. // adjust ichNewCurSav to reflect the pre-tag spacing so that it doesn't become invalid
  4575. // we may need to adjust it in ichNewCur-ichNewCurAtIndex0 < 0 case as well, but lets not
  4576. // add code at this stage that we don't have to. (4/30/98)
  4577. if (ichNewCurAtIndex0 != -1 && ichNewCurSav != -1 && ichNewCur-ichNewCurAtIndex0 > 0)
  4578. ichNewCurSav = ichNewCurSav + (ichNewCur-ichNewCurAtIndex0);
  4579. ichtoktagStart = (ichNewCurSav == -1)?ichNewCur:ichNewCurSav;// handle < ... <%..%>...> case correctly
  4580. while (ichtoktagStart >= 0)
  4581. {
  4582. if (pwNew[ichtoktagStart] == '<' && pwNew[ichtoktagStart+1] != '%')
  4583. {
  4584. ichtoktagStart++;
  4585. break;
  4586. }
  4587. ichtoktagStart--;
  4588. }
  4589. if (ichtoktagStart < 0) // looks to be an error, don't try to restore the spacing
  4590. {
  4591. ptep->m_pspInfoOut += cchwspInfo-2; // for spacing info
  4592. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // for Order Info
  4593. continue;
  4594. }
  4595. break;
  4596. case 2: // after > of the tag
  4597. // Observation - Trident messes up the document in following way -
  4598. // If we had an EOL after '>' which is followed by HTML text,
  4599. // trident eats that EOL
  4600. // BUT
  4601. // If we had a space/tab before that EOL trident doesn't eat it!!!
  4602. // so I have added the conditions
  4603. // && (pwOld[pTokArray[iArray+1].token.ibTokMin] != ' ')
  4604. // && (pwOld[pTokArray[iArray+1].token.ibTokMin] != '\t')
  4605. // here is the deal - If the next tone happens to be plain text, there is no danger
  4606. // of applying the same format twice.( i.e. once for after '>' and the next time for
  4607. // before the next '<')
  4608. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /*validation*/
  4609. && pTokArray[iArray+1].token.tok == 0
  4610. && pTokArray[iArray+1].token.tokClass == tokIDENTIFIER
  4611. && (pwOld[pTokArray[iArray+1].token.ibTokMin] != '\r')
  4612. && (pwOld[pTokArray[iArray+1].token.ibTokMin] != ' ')
  4613. && (pwOld[pTokArray[iArray+1].token.ibTokMin] != '\t')
  4614. )
  4615. {
  4616. fLookback = FALSE;
  4617. ichtoktagStart = ichNewCur;
  4618. while (ichtoktagStart >= 0)
  4619. {
  4620. if (pwNew[ichtoktagStart] == '>')
  4621. {
  4622. ichtoktagStart++;
  4623. break;
  4624. }
  4625. ichtoktagStart--;
  4626. }
  4627. if (ichtoktagStart < 0) // looks to be an error, don't try to restore the spacing
  4628. {
  4629. ptep->m_pspInfoOut += cchwspInfo-2;
  4630. continue;
  4631. }
  4632. }
  4633. else
  4634. {
  4635. ptep->m_pspInfoOut += cchwspInfo-2; // we ignore this info
  4636. continue;
  4637. }
  4638. break;
  4639. case 3: // before matching end tag
  4640. ptep->m_pspInfoOut += cchwspInfo-2; // we ignore this info
  4641. continue;
  4642. //fLookback = TRUE;
  4643. //ichtoktagStart = 0; // we ignore this info
  4644. break;
  4645. }
  4646. if (index == 3) // skip this info, because we have not reached matching end tag yet
  4647. ptep->m_pspInfoOut += cchwspInfo-2;
  4648. //else if (index == 0)
  4649. // ptep->FRestoreSpacingInHTML(pwNew, pwOld, &ichNewCur, &cchwspInfo, cchRange, ichtoktagStart, fLookback, index);
  4650. else
  4651. ptep->FRestoreSpacing(pwNew, pwOld, &ichNewCur, &cchwspInfo, cchRange, ichtoktagStart, fLookback, index);
  4652. LNext:
  4653. if (index == 1) // we have already processed this info, just move the pointer ahead
  4654. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut;
  4655. } // for ()
  4656. iArray++; // go part > of this tag for the next round
  4657. LRet:
  4658. *pcchNew = ichNewCur;
  4659. *ppwNew = pwNew;
  4660. *pichNewCur = ichNewCur;
  4661. *pichBeginCopy = ichBeginCopy;
  4662. *piArrayStart = (UINT)iArray;
  4663. LRetOnly:
  4664. return;
  4665. } /* fnRestoreSpace() */
  4666. void
  4667. CTriEditParse::fnRestoreSpaceEnd(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  4668. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok ft,
  4669. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy, DWORD /*dwFlags*/)
  4670. {
  4671. UINT ichNewCur = *pichNewCur;
  4672. UINT ichBeginCopy = *pichBeginCopy;
  4673. INT iArray = (INT)*piArrayStart;
  4674. LPWSTR pwNew = *ppwNew;
  4675. LPCWSTR rgSpaceTags[] =
  4676. {
  4677. L"DESIGNTIMESP",
  4678. };
  4679. INT iArraySav = iArray;
  4680. INT iArrayMatch, i, itoktagStart;
  4681. BOOL fMatch = FALSE;
  4682. INT cchtag;
  4683. WORD *pspInfoEnd;
  4684. INT cchwspInfo; // spInfo block size in wide chars
  4685. INT cchRange; // number of char for which this spInfo was saved
  4686. INT ichtoktagStart, iArrayValue, index;
  4687. WCHAR szIndex[cchspBlockMax];
  4688. int iDSP = -1;
  4689. UINT cbNeed;
  4690. ASSERT(dwFlags & dwPreserveSourceCode);
  4691. // take care of the matching end token's spacing
  4692. ASSERT(pTokArray[iArray].token.tok == ft.tokBegin2);
  4693. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  4694. ASSERT(ft.tokBegin2 == TokTag_END);
  4695. // We already are at (token.tok == TokTag_END)
  4696. // Get the tokElem after the current token and find its matching begin token
  4697. // If we don't find the begin token, we don't have spacing for this end token, return
  4698. while (iArray < (int)ptep->m_cMaxToken)
  4699. {
  4700. if (pTokArray[iArray].token.tokClass == tokElem) // generally this will be the next token
  4701. break;
  4702. iArray++;
  4703. }
  4704. if (iArray >= (int)ptep->m_cMaxToken) // error case
  4705. {
  4706. iArray = iArraySav + 1;
  4707. goto LRet;
  4708. }
  4709. if (pTokArray[iArray].iNextprev == -1)
  4710. {
  4711. iArray = iArraySav + 1;
  4712. goto LRet;
  4713. }
  4714. iArrayMatch = pTokArray[iArray].iNextprev;
  4715. // look for 'DESIGNTIMESP' from iArrayMatch till the next '>'
  4716. // If we don't find 'DESIGNTIMESP', this is an error case, return.
  4717. i = iArrayMatch;
  4718. cchtag = wcslen(rgSpaceTags[0]);
  4719. while ( i < iArraySav /* boundary case */
  4720. && ( pTokArray[i].token.tokClass != tokTag
  4721. || pTokArray[i].token.tok != TokTag_CLOSE
  4722. )
  4723. )
  4724. {
  4725. if ( pTokArray[i].token.tokClass == tokSpace
  4726. && cchtag == (int)(pTokArray[i].token.ibTokMac - pTokArray[i].token.ibTokMin)
  4727. && (0 == _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[i].token.ibTokMin], cchtag))
  4728. )
  4729. {
  4730. fMatch = TRUE;
  4731. break;
  4732. }
  4733. i++;
  4734. }
  4735. if (!fMatch)
  4736. {
  4737. iArray = iArraySav + 1;
  4738. goto LRet;
  4739. }
  4740. // at this point pTokArray[i] is 'DESIGNTIMESP'
  4741. iDSP = i; // save for later use when we convert the tokElem to upper/lower case
  4742. itoktagStart = i;
  4743. while (itoktagStart >= 0)
  4744. {
  4745. if ( pTokArray[itoktagStart].token.tok == ft.tokBegin
  4746. && pTokArray[itoktagStart].token.tokClass == tokTag
  4747. )
  4748. {
  4749. break;
  4750. }
  4751. itoktagStart--;
  4752. }
  4753. if (itoktagStart < 0) // didn't find '<' before DESIGNTIMESPx
  4754. {
  4755. iArray = iArraySav + 1;
  4756. goto LRet;
  4757. }
  4758. // found '<' before DESIGNTIMESPx
  4759. ASSERT(pTokArray[itoktagStart].token.tok == TokTag_START);
  4760. ASSERT(pTokArray[itoktagStart].token.tokClass == tokTag);
  4761. // we already know that i'th token is DESIGNTIMESPx, so get past the '=' that follows it
  4762. // ASSUMPTION - the value of attribute DESIGNTIMESPx will NOT get munged by Trident.
  4763. // NOTE - The above assumption is correct for this Trident release.
  4764. while (i < iArraySav)
  4765. {
  4766. if (*(WORD *)(pwOld+pTokArray[i].token.ibTokMin) == '=')
  4767. {
  4768. ASSERT(pTokArray[i].token.tokClass == tokOp);
  4769. break;
  4770. }
  4771. else if (*(WORD *)(pwOld+pTokArray[i].token.ibTokMin) == '>') // gone too far
  4772. goto LSkip1;
  4773. i++;
  4774. }
  4775. if (i >= iArraySav) // didn't find = after DESIGNTIMESPx
  4776. {
  4777. LSkip1:
  4778. iArray = iArraySav + 1;
  4779. goto LRet;
  4780. }
  4781. iArrayValue = -1;
  4782. while (i < iArraySav)
  4783. {
  4784. if ( (iArrayValue == -1)
  4785. && ( pTokArray[i].token.tokClass == tokValue
  4786. || pTokArray[i].token.tokClass == tokString)
  4787. )
  4788. iArrayValue = i;
  4789. else if ( pTokArray[i].token.tok == TokTag_CLOSE
  4790. && pTokArray[i].token.tokClass == tokTag
  4791. )
  4792. {
  4793. ASSERT(*(WORD *)(pwOld+pTokArray[i].token.ibTokMin) == '>');
  4794. break;
  4795. }
  4796. i++;
  4797. }
  4798. if (iArrayValue == -1)/*BUG 7951 || i >= iArraySav)*/ // didn't find tokValue after DESIGNTIMESPx
  4799. {
  4800. iArray = iArraySav + 1;
  4801. goto LRet;
  4802. }
  4803. // we know that iArraySav'th token is '</', copy till that token and apply spacing
  4804. cbNeed = (ichNewCur+pTokArray[iArraySav].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  4805. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  4806. goto LRet;
  4807. ASSERT(pTokArray[iArraySav].token.ibTokMin >= ichBeginCopy);
  4808. memcpy( (BYTE *)(pwNew+ichNewCur),
  4809. (BYTE *)(pwOld+ichBeginCopy),
  4810. (pTokArray[iArraySav].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  4811. ichNewCur += (pTokArray[iArraySav].token.ibTokMin-ichBeginCopy);
  4812. ichtoktagStart = ichNewCur-1;
  4813. memcpy( (BYTE *)(pwNew+ichNewCur),
  4814. (BYTE *)(pwOld+pTokArray[iArraySav].token.ibTokMin),
  4815. (pTokArray[iArraySav].token.ibTokMac-pTokArray[iArraySav].token.ibTokMin)*sizeof(WCHAR));
  4816. ichNewCur += (pTokArray[iArraySav].token.ibTokMac-pTokArray[iArraySav].token.ibTokMin);
  4817. ichBeginCopy = pTokArray[iArraySav].token.ibTokMac; // make it ready for next copy
  4818. // we know that 4 blocks of info was saved for each DESIGNTIMESPx attribute
  4819. // before tag, within tag, after tag, before matching end-tag
  4820. // even if no info was saved, the block will still exist with 2 words (size,# of char)
  4821. memset((BYTE *)szIndex, 0, sizeof(szIndex));
  4822. // check if the value has quotes around it and don't copy them to szIndex
  4823. if ( pwOld[pTokArray[iArrayValue].token.ibTokMin] == '"'
  4824. && pwOld[pTokArray[iArrayValue].token.ibTokMac-1] == '"'
  4825. )
  4826. {
  4827. memcpy( (BYTE *)szIndex,
  4828. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMin+1),
  4829. (pTokArray[iArrayValue].token.ibTokMac-pTokArray[iArrayValue].token.ibTokMin-2)*sizeof(WCHAR));
  4830. }
  4831. else
  4832. {
  4833. memcpy( (BYTE *)szIndex,
  4834. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMin),
  4835. (pTokArray[iArrayValue].token.ibTokMac-pTokArray[iArrayValue].token.ibTokMin)*sizeof(WCHAR));
  4836. }
  4837. ptep->m_ispInfoBlock = _wtoi(szIndex);
  4838. ptep->m_ispInfoBlock -= ptep->m_ispInfoBase;
  4839. if (ptep->m_ispInfoBlock < 0)
  4840. {
  4841. iArray = iArraySav + 1;
  4842. goto LRet;
  4843. }
  4844. // NOTE - we can cache this info in a link list at the begining
  4845. // get to the ptep->m_ispInfoBlock'th block from ptep->m_pspInfoOutStart
  4846. ASSERT(ptep->m_cchspInfoTotal >= 0);
  4847. pspInfoEnd = ptep->m_pspInfoOutStart + ptep->m_cchspInfoTotal;
  4848. ptep->m_pspInfoOut = ptep->m_pspInfoOutStart;
  4849. for (index = 0; index < ptep->m_ispInfoBlock; index++)
  4850. {
  4851. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // before <
  4852. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // between <>
  4853. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // Order Info
  4854. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // after >
  4855. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // before matching </
  4856. // we somehow have gone beyond the data that was saved for spacing
  4857. if (ptep->m_pspInfoOut >= pspInfoEnd)
  4858. {
  4859. iArray = iArraySav + 1;
  4860. goto LRet;
  4861. }
  4862. }
  4863. // skip pre '<' data
  4864. cchwspInfo = *(WORD *)ptep->m_pspInfoOut++;
  4865. cchRange = *(WORD *)ptep->m_pspInfoOut++;
  4866. ptep->m_pspInfoOut += cchwspInfo - 2;
  4867. // skip '<...>' data
  4868. cchwspInfo = *(WORD *)ptep->m_pspInfoOut++;
  4869. cchRange = *(WORD *)ptep->m_pspInfoOut++;
  4870. ptep->m_pspInfoOut += cchwspInfo - 2;
  4871. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // for Order Info
  4872. // skip post '>' data
  4873. cchwspInfo = *(WORD *)ptep->m_pspInfoOut++;
  4874. cchRange = *(WORD *)ptep->m_pspInfoOut++;
  4875. ptep->m_pspInfoOut += cchwspInfo - 2;
  4876. // now we are at matching </...> of the token
  4877. cchwspInfo = *(WORD *)ptep->m_pspInfoOut++;
  4878. cchRange = *(WORD *)ptep->m_pspInfoOut++;
  4879. if (cchwspInfo == 2) // we didn't save any spacing info
  4880. {
  4881. // here is a little story. If we didn't save any spacing information for this end
  4882. // tag, that means we didn't have any white-space before it. Lets go back from
  4883. // pwNew[ichNewCur-1] and remove the white-space.
  4884. // NOTE - Ideally, this needs to get folded into FRestoreSpacing, but
  4885. // FRestorespacing gets called from other places too so this is late in
  4886. // the game to that kind of change.
  4887. // we know that pwNew[ichNewCur-1] is '/' & pwNew[ichNewCur-2] is '<'
  4888. if ((int)(ichNewCur-2) >= 0 && pwNew[ichNewCur-1] == '/' && pwNew[ichNewCur-2] == '<')
  4889. {
  4890. ichNewCur = ichNewCur - 3;
  4891. while ( ( pwNew[ichNewCur] == ' ' || pwNew[ichNewCur] == '\t'
  4892. || pwNew[ichNewCur] == '\r' || pwNew[ichNewCur] == '\n'
  4893. )
  4894. )
  4895. {
  4896. ichNewCur--;
  4897. }
  4898. ichNewCur++; // compensate, ichNewCur points to non-white space characher
  4899. pwNew[ichNewCur++] = '<';
  4900. pwNew[ichNewCur++] = '/';
  4901. }
  4902. iArray = iArraySav + 1;
  4903. goto LRestoreCaseAndRet;
  4904. }
  4905. ptep->FRestoreSpacing(pwNew, pwOld, &ichNewCur, &cchwspInfo, cchRange, ichtoktagStart, /*fLookback*/TRUE, /*index*/3);
  4906. iArray = iArraySav + 1; // go past '</', we have already copied the doc till this point
  4907. LRestoreCaseAndRet:
  4908. // BUG 15389 - we need to start copying the tokElem as well with proper upper/lower case
  4909. // we should combine this memcpy with the above ones, but I want to keep the
  4910. // code separate
  4911. if (pTokArray[iArray].token.tokClass == tokElem && iDSP != -1)
  4912. {
  4913. // except for </BODY> tag because we need to restore post-end-BODY stuff in fnRestoreFtr()
  4914. if (pTokArray[iArray].token.tok != TokElem_BODY && pTokArray[iArray].token.tok != tokElem)
  4915. {
  4916. cbNeed = (ichNewCur+pTokArray[iArray].token.ibTokMac-pTokArray[iArray].token.ibTokMin)*sizeof(WCHAR)+cbBufPadding;
  4917. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  4918. goto LRet;
  4919. memcpy( (BYTE *)(pwNew+ichNewCur),
  4920. (BYTE *)(pwOld+pTokArray[iArray].token.ibTokMin),
  4921. (pTokArray[iArray].token.ibTokMac-pTokArray[iArray].token.ibTokMin)*sizeof(WCHAR));
  4922. // convert into upper/lower case appropriately to match the opening tag's case
  4923. if (iswupper(pwOld[pTokArray[iDSP].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  4924. {
  4925. _wcsupr(&pwNew[ichNewCur]);
  4926. }
  4927. else
  4928. {
  4929. _wcslwr(&pwNew[ichNewCur]);
  4930. }
  4931. ichNewCur += (pTokArray[iArray].token.ibTokMac-pTokArray[iArray].token.ibTokMin);
  4932. // set ichBeginCopy & iArray for next run
  4933. ichBeginCopy = pTokArray[iArray].token.ibTokMac;
  4934. iArray++;
  4935. }
  4936. }
  4937. LRet:
  4938. *pcchNew = ichNewCur;
  4939. *ppwNew = pwNew;
  4940. *pichNewCur = ichNewCur;
  4941. *pichBeginCopy = ichBeginCopy;
  4942. *piArrayStart = (UINT)iArray;
  4943. //LRetOnly:
  4944. return;
  4945. } /* fnRestoreSpaceEnd() */
  4946. void
  4947. CTriEditParse::fnSaveTbody(CTriEditParse* /*ptep*/,
  4948. LPWSTR /*pwOld*/, LPWSTR* /*ppwNew*/, UINT* /*pcchNew*/, HGLOBAL* /*phgNew*/,
  4949. TOKSTRUCT* /*pTokArray*/, UINT *piArrayStart, FilterTok /*ft*/,
  4950. INT* /*pcHtml*/, UINT* /*pichNewCur*/, UINT* /*hBeginCopy*/,
  4951. DWORD /*dwFlags*/)
  4952. {
  4953. UINT iArray = *piArrayStart;
  4954. ASSERT(pTokArray[iArray].token.tok == TokElem_TBODY);
  4955. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  4956. iArray++;
  4957. *piArrayStart = iArray;
  4958. return;
  4959. } /* fnSaveTbody() */
  4960. void
  4961. CTriEditParse::fnRestoreTbody(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  4962. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  4963. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  4964. DWORD /*dwFlags*/)
  4965. {
  4966. // see if we have DESIGNTIMESP as an attribute for <TBODY>. If we do, ignore this one because
  4967. // we know it existed before going to trident. Else, remove this one because trident inserted
  4968. // it.
  4969. // NOTE - If Trident inserted it, we also have to remove the matching </TBODY>
  4970. UINT ichNewCur = *pichNewCur;
  4971. UINT ichBeginCopy = *pichBeginCopy;
  4972. INT iArray = (INT)*piArrayStart;
  4973. LPWSTR pwNew = *ppwNew;
  4974. INT ichTBodyStart, ichTBodyEnd;
  4975. BOOL fFoundDSP = FALSE;
  4976. INT iArraySav = iArray;
  4977. INT cchtag;
  4978. LPCWSTR rgSpaceTags[] =
  4979. {
  4980. L"DESIGNTIMESP",
  4981. };
  4982. BOOL fBeginTBody = FALSE;
  4983. UINT cbNeed;
  4984. ichTBodyStart = pTokArray[iArray].token.ibTokMin; // init
  4985. ASSERT(pTokArray[iArray].token.tok == TokElem_TBODY);
  4986. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  4987. // look for '<' or '</' before TBODY
  4988. while (iArray >= 0) // generally, it will be the previous token, but just in case...
  4989. {
  4990. if ( (pTokArray[iArray].token.tok == TokTag_START)
  4991. && (pTokArray[iArray].token.tokClass == tokTag)
  4992. )
  4993. {
  4994. fBeginTBody = TRUE;
  4995. ichTBodyStart = pTokArray[iArray].token.ibTokMin;
  4996. break;
  4997. }
  4998. else if ( (pTokArray[iArray].token.tok == TokTag_END)
  4999. && (pTokArray[iArray].token.tokClass == tokTag)
  5000. )
  5001. {
  5002. if (ptep->m_iTBodyMax > 0) // we have atleast one saved <TBODY>
  5003. {
  5004. ASSERT(ptep->m_pTBodyStack != NULL);
  5005. if (ptep->m_pTBodyStack[ptep->m_iTBodyMax-1] == (UINT)iArraySav) // this was the matching </TBODY>
  5006. {
  5007. // we want to remove it
  5008. ichTBodyStart = pTokArray[iArray].token.ibTokMin;
  5009. break;
  5010. }
  5011. else // this one doesn't match with the saved one, so quit
  5012. {
  5013. iArray = iArraySav + 1;
  5014. goto LRet;
  5015. }
  5016. }
  5017. else // we don't have any saved <TBODY>, so quit
  5018. {
  5019. iArray = iArraySav + 1;
  5020. goto LRet;
  5021. }
  5022. }
  5023. iArray--;
  5024. } // while ()
  5025. if (iArray < 0) // this can happen only if we have incomplete HTML. Handle error case
  5026. {
  5027. iArray = iArraySav + 1;
  5028. goto LRet;
  5029. }
  5030. ichTBodyEnd = pTokArray[iArraySav].token.ibTokMac; // init
  5031. iArray = iArraySav;
  5032. ASSERT(pTokArray[iArray].token.tok == TokElem_TBODY);
  5033. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  5034. cchtag = wcslen(rgSpaceTags[0]);
  5035. while (iArray < (int)ptep->m_cMaxToken)
  5036. {
  5037. if ( (pTokArray[iArray].token.tok == TokTag_CLOSE) /* > */
  5038. && (pTokArray[iArray].token.tokClass == tokTag)
  5039. )
  5040. {
  5041. ichTBodyEnd = pTokArray[iArray].token.ibTokMac;
  5042. break;
  5043. }
  5044. // look for DESIGNTIMESP
  5045. if ( (pTokArray[iArray].token.tok == 0)
  5046. && (pTokArray[iArray].token.tokClass == tokSpace)
  5047. && (cchtag == (INT)(pTokArray[iArray].token.ibTokMac - pTokArray[iArray].token.ibTokMin))
  5048. && (0 == _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[iArray].token.ibTokMin], cchtag))
  5049. )
  5050. {
  5051. fFoundDSP = TRUE;
  5052. break;
  5053. }
  5054. else if (pTokArray[iArray].token.tokClass == tokAttr)
  5055. {
  5056. // look for any attribute before '>'
  5057. // Even if Trident inserted this <TBODY>, the user may have set some TBODY properties
  5058. // If thats the case, we don't want to remove this <TBODY>
  5059. fFoundDSP = TRUE; // fake it to be fFoundDSP
  5060. break;
  5061. }
  5062. iArray++;
  5063. }
  5064. if (iArray >= (int)ptep->m_cMaxToken) // error case
  5065. {
  5066. iArray = iArraySav + 1;
  5067. goto LRet;
  5068. }
  5069. if (fFoundDSP)
  5070. {
  5071. iArray = iArraySav + 1;
  5072. goto LRet;
  5073. }
  5074. // we found '>', but didn't find DESIGNTIMESP
  5075. // At this point we are sure that this was added by trident
  5076. ASSERT(iArray < (int)ptep->m_cMaxToken);
  5077. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  5078. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  5079. ASSERT(!fFoundDSP);
  5080. if (fBeginTBody)
  5081. {
  5082. // copy till ichTBodyStart, skip from ichTBodyStart till ichTBodyEnd, set ichBeginCopy accordingly
  5083. // get the iArray for the matching </TBODY> and save it on stack
  5084. if (ptep->m_pTBodyStack == NULL) // first time, so allocate it
  5085. {
  5086. ASSERT(ptep->m_hgTBodyStack == NULL);
  5087. ptep->m_hgTBodyStack = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cTBodyInit*sizeof(UINT));
  5088. if (ptep->m_hgTBodyStack == NULL)
  5089. {
  5090. // not enough memory, so lets keep all <TBODY> elements
  5091. goto LRet;
  5092. }
  5093. ptep->m_pTBodyStack = (UINT *)GlobalLock(ptep->m_hgTBodyStack);
  5094. ASSERT(ptep->m_pTBodyStack != NULL);
  5095. ptep->m_iMaxTBody = cTBodyInit;
  5096. ptep->m_iTBodyMax = 0;
  5097. }
  5098. else
  5099. {
  5100. ASSERT(ptep->m_hgTBodyStack != NULL);
  5101. // see if we need to realloc it
  5102. if (ptep->m_iTBodyMax+1 >= ptep->m_iMaxTBody)
  5103. {
  5104. HRESULT hrRet;
  5105. hrRet = ReallocBuffer( &ptep->m_hgTBodyStack,
  5106. (ptep->m_iMaxTBody+cTBodyInit)*sizeof(UINT),
  5107. GMEM_MOVEABLE|GMEM_ZEROINIT);
  5108. if (hrRet == E_OUTOFMEMORY)
  5109. goto LRet;
  5110. ptep->m_iMaxTBody += cTBodyInit;
  5111. ptep->m_pTBodyStack = (UINT *)GlobalLock(ptep->m_hgTBodyStack);
  5112. ASSERT(ptep->m_pTBodyStack != NULL);
  5113. }
  5114. }
  5115. if (pTokArray[iArraySav].iNextprev != -1) // handle error case
  5116. {
  5117. ptep->m_pTBodyStack[ptep->m_iTBodyMax] = pTokArray[iArraySav].iNextprev;
  5118. ptep->m_iTBodyMax++;
  5119. }
  5120. else
  5121. {
  5122. // don't delete this <TBODY> and its matching </TBODY>
  5123. goto LRet;
  5124. }
  5125. }
  5126. else
  5127. {
  5128. // if this was a matching </TBODY> for the one trident inserted, we don't copy it to pwNew
  5129. ASSERT(ptep->m_iTBodyMax > 0);
  5130. // look in ptep->m_pTBodyStack and see if you find this iArray
  5131. ASSERT(ptep->m_pTBodyStack[ptep->m_iTBodyMax-1] == (UINT)iArraySav);
  5132. // assume that we never can have tangled TBODY's
  5133. ptep->m_pTBodyStack[ptep->m_iTBodyMax-1] = 0;
  5134. ptep->m_iTBodyMax--;
  5135. }
  5136. // now do the actual skipping
  5137. cbNeed = (ichNewCur+ichTBodyStart-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  5138. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  5139. goto LRet;
  5140. if ((INT)(ichTBodyStart-ichBeginCopy) > 0)
  5141. {
  5142. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  5143. (BYTE *)(&pwOld[ichBeginCopy]),
  5144. (ichTBodyStart-ichBeginCopy)*sizeof(WCHAR));
  5145. ichNewCur += (ichTBodyStart-ichBeginCopy);
  5146. }
  5147. ichBeginCopy = ichTBodyEnd;
  5148. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  5149. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  5150. iArray++; // iArray was at '>' of TBODY, so set it to be the next one.
  5151. LRet:
  5152. *pcchNew = ichNewCur;
  5153. *ppwNew = pwNew;
  5154. *pichNewCur = ichNewCur;
  5155. *pichBeginCopy = ichBeginCopy;
  5156. *piArrayStart = iArray;
  5157. return;
  5158. } /* fnRestoreTbody() */
  5159. void
  5160. CTriEditParse::fnSaveApplet(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  5161. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  5162. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  5163. DWORD dwFlags)
  5164. {
  5165. UINT ichNewCur = *pichNewCur;
  5166. UINT ichBeginCopy = *pichBeginCopy;
  5167. UINT iArray = *piArrayStart;
  5168. LPWSTR pwNew = *ppwNew;
  5169. UINT iArraySav = iArray;
  5170. int indexAppletEnd, ichAppletEnd, indexAppletTagClose, index;
  5171. UINT cbNeed;
  5172. int cchURL = 0;
  5173. int ichURL = 0;
  5174. LPCWSTR rgDspURL[] =
  5175. {
  5176. L" DESIGNTIMEURL=",
  5177. L" DESIGNTIMEURL2=",
  5178. };
  5179. indexAppletTagClose = -1;
  5180. ASSERT(pTokArray[iArray].token.tok == TokElem_APPLET);
  5181. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  5182. // get the ending '>' of the </applet>
  5183. indexAppletEnd = pTokArray[iArraySav].iNextprev;
  5184. if (indexAppletEnd == -1) // error case, we don't have matching </applet> tag
  5185. {
  5186. iArray = iArraySav + 1;
  5187. goto LRet;
  5188. }
  5189. // validity check - the matching tag is not '</applet>'
  5190. if (indexAppletEnd-1 >= 0 && pTokArray[indexAppletEnd-1].token.tok != TokTag_END)
  5191. {
  5192. iArray = iArraySav + 1;
  5193. goto LRet;
  5194. }
  5195. // get ending '>' of the <applet ...>
  5196. while (iArray < (int)ptep->m_cMaxToken)
  5197. {
  5198. if ( (pTokArray[iArray].token.tok == TokTag_CLOSE) /* > */
  5199. && (pTokArray[iArray].token.tokClass == tokTag)
  5200. )
  5201. {
  5202. indexAppletTagClose = iArray;
  5203. break;
  5204. }
  5205. iArray++;
  5206. }
  5207. if (iArray >= (int)ptep->m_cMaxToken) // invalid case
  5208. {
  5209. iArray = iArraySav + 1;
  5210. goto LRet;
  5211. }
  5212. iArray = indexAppletEnd;
  5213. while (iArray < (int)ptep->m_cMaxToken) // generally, it will be the next token, but just in case...
  5214. {
  5215. if ( (pTokArray[iArray].token.tok == TokTag_CLOSE) /* > */
  5216. && (pTokArray[iArray].token.tokClass == tokTag)
  5217. )
  5218. {
  5219. break;
  5220. }
  5221. iArray++;
  5222. }
  5223. indexAppletEnd = iArray;
  5224. ichAppletEnd = pTokArray[indexAppletEnd].token.ibTokMac;
  5225. // step 1 - if the applet needs special URL processing, act on it.
  5226. if (!FURLNeedSpecialHandling(pTokArray, iArraySav, pwOld, (int)ptep->m_cMaxToken, &ichURL, &cchURL))
  5227. goto LStep2;
  5228. else // save the URL as an attribute value of DESIGNTIMEURL
  5229. {
  5230. // make sure we have enough space in pwNew.
  5231. // copy from ichBeginCopy till current token's ending '>'.
  5232. // index points to APPLET
  5233. index = indexAppletTagClose;
  5234. cbNeed = (ichNewCur+pTokArray[index].token.ibTokMin-ichBeginCopy+wcslen(rgDspURL[0])+cchURL+3/*eq,quotes*/)*sizeof(WCHAR)+cbBufPadding;
  5235. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  5236. {
  5237. iArray = iArraySav + 1;
  5238. goto LRet;
  5239. }
  5240. // index points to '>'
  5241. if ((int) (pTokArray[index].token.ibTokMin-ichBeginCopy) > 0)
  5242. {
  5243. memcpy( (BYTE *)&pwNew[ichNewCur],
  5244. (BYTE *)&pwOld[ichBeginCopy],
  5245. (pTokArray[index].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  5246. ichNewCur += (pTokArray[index].token.ibTokMin-ichBeginCopy);
  5247. }
  5248. if (cchURL != 0)
  5249. {
  5250. // add 'DESIGNTIMEURL=' followed by the current URL as quoted value
  5251. memcpy( (BYTE *)&pwNew[ichNewCur],
  5252. (BYTE *)rgDspURL[0],
  5253. wcslen(rgDspURL[0])*sizeof(WCHAR));
  5254. ichNewCur += wcslen(rgDspURL[0]);
  5255. pwNew[ichNewCur++] = '"';
  5256. memcpy( (BYTE *)&pwNew[ichNewCur],
  5257. (BYTE *)&pwOld[ichURL],
  5258. cchURL*sizeof(WCHAR));
  5259. ichNewCur += cchURL;
  5260. pwNew[ichNewCur++] = '"';
  5261. }
  5262. if (dwFlags & dwPreserveSourceCode)
  5263. ptep->SaveSpacingSpecial(ptep, pwOld, &pwNew, phgNew, pTokArray, iArraySav-1, &ichNewCur);
  5264. // add ending '>' and set ichBeginCopy, iArray, ichNewCur appropriately
  5265. memcpy( (BYTE *)&pwNew[ichNewCur],
  5266. (BYTE *)&pwOld[pTokArray[index].token.ibTokMin],
  5267. (pTokArray[index].token.ibTokMac-pTokArray[index].token.ibTokMin)*sizeof(WCHAR));
  5268. ichNewCur += (pTokArray[index].token.ibTokMac-pTokArray[index].token.ibTokMin);
  5269. iArray = index+1; // redundant, but makes code more understandable
  5270. ichBeginCopy = pTokArray[index].token.ibTokMac;
  5271. }
  5272. // step2 - copy the applet
  5273. LStep2:
  5274. cbNeed = (ichNewCur+ichAppletEnd-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  5275. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  5276. goto LRet;
  5277. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  5278. (BYTE *)(&pwOld[ichBeginCopy]),
  5279. (ichAppletEnd-ichBeginCopy)*sizeof(WCHAR));
  5280. ichNewCur += (ichAppletEnd-ichBeginCopy);
  5281. ichBeginCopy = ichAppletEnd;
  5282. iArray = indexAppletEnd;
  5283. LRet:
  5284. *pcchNew = ichNewCur;
  5285. *ppwNew = pwNew;
  5286. *pichNewCur = ichNewCur;
  5287. *pichBeginCopy = ichBeginCopy;
  5288. *piArrayStart = iArray;
  5289. return;
  5290. } /* fnSaveApplet() */
  5291. void
  5292. CTriEditParse::fnRestoreApplet(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  5293. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  5294. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  5295. DWORD dwFlags)
  5296. {
  5297. UINT ichNewCur = *pichNewCur;
  5298. UINT ichBeginCopy = *pichBeginCopy;
  5299. UINT iArray = *piArrayStart;
  5300. LPWSTR pwNew = *ppwNew;
  5301. UINT iArraySav = iArray;
  5302. LPCWSTR rgSpaceTags[] =
  5303. {
  5304. L"DESIGNTIMESP",
  5305. L"DESIGNTIMEURL",
  5306. };
  5307. int indexAppletStart, ichAppletStart, indexAppletEnd, i, indexAppletTagClose;
  5308. UINT cchtag, cbNeed, cchURL;
  5309. int indexDSU = -1; // init
  5310. int indexDSUEnd = -1; // init
  5311. int indexDSP = -1; // init
  5312. int indexDSPEnd = -1; // init
  5313. int indexCB = -1; // init (CODEBASE index)
  5314. int indexCBEnd = -1; // init (CODEBASE index)
  5315. BOOL fCodeBaseFound = FALSE;
  5316. ASSERT(pTokArray[iArray].token.tok == TokElem_APPLET);
  5317. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  5318. indexAppletTagClose = iArraySav;
  5319. // get the matching </applet> tag
  5320. indexAppletEnd = pTokArray[iArraySav].iNextprev;
  5321. if (indexAppletEnd == -1) // error case, we don't have matching </applet> tag
  5322. {
  5323. iArray = iArraySav + 1;
  5324. goto LRet;
  5325. }
  5326. // get ending '>' of the <applet ...>
  5327. i = iArraySav;
  5328. while (i < (int)ptep->m_cMaxToken)
  5329. {
  5330. if ( (pTokArray[i].token.tok == TokTag_CLOSE) /* > */
  5331. && (pTokArray[i].token.tokClass == tokTag)
  5332. )
  5333. {
  5334. indexAppletTagClose = i;
  5335. break;
  5336. }
  5337. i++;
  5338. }
  5339. if (i >= (int)ptep->m_cMaxToken) // invalid case
  5340. {
  5341. iArray = iArraySav + 1;
  5342. goto LRet;
  5343. }
  5344. // look for DESIGNTIMESP & DESIGNTIMEURL inside the <applet> tag
  5345. cchtag = wcslen(rgSpaceTags[0]);
  5346. cchURL = wcslen(rgSpaceTags[1]);
  5347. for (i = iArraySav; i < indexAppletTagClose; i++)
  5348. {
  5349. if ( pTokArray[i].token.tok == 0
  5350. && pTokArray[i].token.tokClass == tokSpace
  5351. && cchtag == pTokArray[i].token.ibTokMac - pTokArray[i].token.ibTokMin
  5352. && (0 == _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[i].token.ibTokMin], cchtag))
  5353. )
  5354. {
  5355. indexDSP = i;
  5356. }
  5357. else if ( pTokArray[i].token.tok == 0
  5358. && pTokArray[i].token.tokClass == tokSpace
  5359. && cchURL == pTokArray[i].token.ibTokMac - pTokArray[i].token.ibTokMin
  5360. && (0 == _wcsnicmp(rgSpaceTags[1], &pwOld[pTokArray[i].token.ibTokMin], cchURL))
  5361. )
  5362. {
  5363. indexDSU = i;
  5364. }
  5365. else if ( pTokArray[i].token.tok == TokAttrib_CODEBASE
  5366. && pTokArray[i].token.tokClass == tokAttr
  5367. )
  5368. {
  5369. indexCB = i;
  5370. }
  5371. } // for ()
  5372. // look for '<' before APPLET
  5373. i = iArraySav;
  5374. while (i >= 0) // generally, it will be the previous token, but just in case...
  5375. {
  5376. if ( (pTokArray[i].token.tok == TokTag_START)
  5377. && (pTokArray[i].token.tokClass == tokTag)
  5378. )
  5379. {
  5380. break;
  5381. }
  5382. i--;
  5383. } // while ()
  5384. if (i < 0) // this can happen only if we have incomplete HTML. Handle error case
  5385. {
  5386. iArray = iArraySav + 1;
  5387. goto LRet;
  5388. }
  5389. indexAppletStart = i;
  5390. ichAppletStart = pTokArray[indexAppletStart].token.ibTokMin;
  5391. // look for '>' of </applet>
  5392. i = indexAppletEnd;
  5393. while (i < (int)ptep->m_cMaxToken) // generally, it will be the next token, but just in case...
  5394. {
  5395. if ( (pTokArray[i].token.tok == TokTag_CLOSE) /* > */
  5396. && (pTokArray[i].token.tokClass == tokTag)
  5397. )
  5398. {
  5399. break;
  5400. }
  5401. i++;
  5402. }
  5403. if (i >= (int)ptep->m_cMaxToken) // this can happen only if we have incomplete HTML. Handle error case
  5404. {
  5405. iArray = iArraySav + 1;
  5406. goto LRet;
  5407. }
  5408. indexAppletEnd = i;
  5409. // step 1 - copy till indexAppletStart
  5410. cbNeed = (ichNewCur+ichAppletStart-ichBeginCopy+3*(indexAppletEnd-indexAppletStart))*sizeof(WCHAR)+cbBufPadding;
  5411. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  5412. goto LRet;
  5413. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  5414. (BYTE *)(&pwOld[ichBeginCopy]),
  5415. (ichAppletStart-ichBeginCopy)*sizeof(WCHAR));
  5416. ichNewCur += (ichAppletStart-ichBeginCopy);
  5417. // step 2 - if (indexDSU != -1), we need to go and restore the CODEBASE atrtribute
  5418. // if (indexDSU == -1), we need to remove CODEBASE attribute
  5419. ASSERT(indexAppletTagClose != -1);
  5420. // get indexDSUEnd
  5421. if (indexDSU != -1)
  5422. {
  5423. i = indexDSU;
  5424. while (i < indexAppletTagClose)
  5425. {
  5426. if ( pTokArray[i].token.tok == 0
  5427. && (pTokArray[i].token.tokClass == tokValue || pTokArray[i].token.tokClass == tokString)
  5428. )
  5429. {
  5430. indexDSUEnd = i;
  5431. break;
  5432. }
  5433. i++;
  5434. }
  5435. if (indexDSUEnd == -1) // we have malformed html
  5436. {
  5437. iArray = iArraySav + 1;
  5438. goto LRet;
  5439. }
  5440. } /* if (indexDSU != -1)*/
  5441. // get indexDSPEnd
  5442. if (indexDSP != -1)
  5443. {
  5444. i = indexDSP;
  5445. indexDSPEnd = -1;
  5446. while (i < indexAppletTagClose)
  5447. {
  5448. if ( pTokArray[i].token.tok == 0
  5449. && (pTokArray[i].token.tokClass == tokValue || pTokArray[i].token.tokClass == tokString)
  5450. )
  5451. {
  5452. indexDSPEnd = i;
  5453. break;
  5454. }
  5455. i++;
  5456. }
  5457. if (indexDSPEnd == -1) // we have malformed html
  5458. {
  5459. iArray = iArraySav + 1;
  5460. goto LRet;
  5461. }
  5462. } /* if (indexDSP != -1) */
  5463. // get indexCBEnd
  5464. if (indexCB != -1)
  5465. {
  5466. i = indexCB;
  5467. while (i < indexAppletTagClose)
  5468. {
  5469. if ( pTokArray[i].token.tok == 0
  5470. && (pTokArray[i].token.tokClass == tokValue || pTokArray[i].token.tokClass == tokString)
  5471. )
  5472. {
  5473. indexCBEnd = i;
  5474. break;
  5475. }
  5476. i++;
  5477. }
  5478. if (indexCBEnd == -1) // we have malformed html
  5479. {
  5480. iArray = iArraySav + 1;
  5481. goto LRet;
  5482. }
  5483. } /* if (indexCB != -1) */
  5484. // if we didn't find DESIGNTIMEURL attribute, that means CODEBASE attribute
  5485. // should be removed because it didn't exist in source view
  5486. i = indexAppletStart;
  5487. while (i <= indexAppletTagClose)
  5488. {
  5489. if ( (indexDSU != -1)
  5490. && (i >= indexDSU && i <= indexDSUEnd)
  5491. )
  5492. {
  5493. i++; // don't copy this token
  5494. }
  5495. else if ( (indexDSP != -1)
  5496. && (i >= indexDSP && i <= indexDSPEnd)
  5497. )
  5498. {
  5499. i++; // don't copy this token
  5500. }
  5501. else if ( pTokArray[i].token.tok == TokAttrib_CODEBASE
  5502. && pTokArray[i].token.tokClass == tokAttr
  5503. && !fCodeBaseFound
  5504. )
  5505. {
  5506. if (indexDSU == -1) // DESIGNTIMEURL not found, so skip CODEBASE
  5507. {
  5508. ASSERT(i == indexCB);
  5509. i = indexCBEnd+1;
  5510. }
  5511. else
  5512. {
  5513. fCodeBaseFound = TRUE;
  5514. memcpy( (BYTE *)&pwNew[ichNewCur],
  5515. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  5516. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  5517. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  5518. i++;
  5519. }
  5520. }
  5521. else if ( pTokArray[i].token.tok == 0
  5522. && pTokArray[i].token.tokClass == tokString || pTokArray[i].token.tokClass == tokValue
  5523. && fCodeBaseFound
  5524. )
  5525. {
  5526. int ichURL, ichURLEnd, ichDSURL, ichDSURLEnd;
  5527. // if the url is now absloute and is just an absolute version of
  5528. // the one at indexDSUEnd, we need to replace it.
  5529. ichURL = (pwOld[pTokArray[i].token.ibTokMin] == '"')
  5530. ? pTokArray[i].token.ibTokMin+1
  5531. : pTokArray[i].token.ibTokMin;
  5532. ichURLEnd = (pwOld[pTokArray[i].token.ibTokMac-1] == '"')
  5533. ? pTokArray[i].token.ibTokMac-1
  5534. : pTokArray[i].token.ibTokMac;
  5535. if (FIsAbsURL((LPOLESTR)&pwOld[ichURL]))
  5536. {
  5537. WCHAR *pszURL1 = NULL;
  5538. WCHAR *pszURL2 = NULL;
  5539. int ich;
  5540. ichDSURL = (pwOld[pTokArray[indexDSUEnd].token.ibTokMin] == '"')
  5541. ? pTokArray[indexDSUEnd].token.ibTokMin+1
  5542. : pTokArray[indexDSUEnd].token.ibTokMin;
  5543. ichDSURLEnd = (pwOld[pTokArray[indexDSUEnd].token.ibTokMac-1] == '"')
  5544. ? pTokArray[indexDSUEnd].token.ibTokMac-1
  5545. : pTokArray[indexDSUEnd].token.ibTokMac;
  5546. // just for comparison purposes, don't look at '/' or '\' separators
  5547. // between filenames & directories...
  5548. pszURL1 = new WCHAR[ichDSURLEnd-ichDSURL + 1];
  5549. pszURL2 = new WCHAR[ichDSURLEnd-ichDSURL + 1];
  5550. if (pszURL1 == NULL || pszURL2 == NULL)
  5551. goto LResumeCopy;
  5552. memcpy((BYTE *)pszURL1, (BYTE *)&pwOld[ichDSURL], (ichDSURLEnd-ichDSURL)*sizeof(WCHAR));
  5553. memcpy((BYTE *)pszURL2, (BYTE *)&pwOld[ichURLEnd-(ichDSURLEnd-ichDSURL)], (ichDSURLEnd-ichDSURL)*sizeof(WCHAR));
  5554. pszURL1[ichDSURLEnd-ichDSURL] = '\0';
  5555. pszURL2[ichDSURLEnd-ichDSURL] = '\0';
  5556. for (ich = 0; ich < ichDSURLEnd-ichDSURL; ich++)
  5557. {
  5558. if (pszURL1[ich] == '/')
  5559. pszURL1[ich] = '\\';
  5560. if (pszURL2[ich] == '/')
  5561. pszURL2[ich] = '\\';
  5562. }
  5563. if (0 == _wcsnicmp(pszURL1, pszURL2, ichDSURLEnd-ichDSURL))
  5564. {
  5565. pwNew[ichNewCur++] = '"';
  5566. memcpy( (BYTE *)&pwNew[ichNewCur],
  5567. (BYTE *)&pwOld[ichDSURL],
  5568. (ichDSURLEnd-ichDSURL)*sizeof(WCHAR));
  5569. ichNewCur += (ichDSURLEnd-ichDSURL);
  5570. pwNew[ichNewCur++] = '"';
  5571. }
  5572. else // copy it as it is
  5573. {
  5574. LResumeCopy:
  5575. memcpy( (BYTE *)&pwNew[ichNewCur],
  5576. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  5577. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  5578. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  5579. }
  5580. if (pszURL1 != NULL)
  5581. delete pszURL1;
  5582. if (pszURL2 != NULL)
  5583. delete pszURL2;
  5584. }
  5585. else // its realtive, simply copy it
  5586. {
  5587. memcpy( (BYTE *)&pwNew[ichNewCur],
  5588. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  5589. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  5590. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  5591. }
  5592. i++;
  5593. }
  5594. else // all other tokens
  5595. {
  5596. // ****NOTE - we can actually do pretty printing here
  5597. // instead of fixing the special cases****
  5598. // fix Trident's behaviour - If Trident sees unknown tag(s) it puts it(them) at the end
  5599. // and inserts EOL before those. In this case, we would have inserted a space before DESIGNTIMESP
  5600. // and Trident would have inserted EOL. If thats not the case, we will ignore it.
  5601. if ( (pTokArray[i].token.tokClass == tokSpace)
  5602. && (pTokArray[i].token.tok == 0)
  5603. && (FIsWhiteSpaceToken(pwOld, pTokArray[i].token.ibTokMin, pTokArray[i].token.ibTokMac))
  5604. )
  5605. {
  5606. if (i != indexDSU-1) // else skip the copy
  5607. pwNew[ichNewCur++] = ' '; // convert space+\r+\n into space
  5608. i++;
  5609. }
  5610. else
  5611. {
  5612. memcpy( (BYTE *)&pwNew[ichNewCur],
  5613. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  5614. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  5615. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  5616. i++;
  5617. }
  5618. }
  5619. } // while ()
  5620. // we have spacing save dfor this tag, lets restore it
  5621. if ( (indexDSP != -1)
  5622. && (dwFlags & dwPreserveSourceCode)
  5623. )
  5624. ptep->RestoreSpacingSpecial(ptep, pwOld, &pwNew, phgNew, pTokArray, indexDSP, &ichNewCur);
  5625. // step 3 - format all stuff between <applet> ... </applet>
  5626. pwNew[ichNewCur] = '\r';
  5627. ichNewCur++;
  5628. pwNew[ichNewCur] = '\n';
  5629. ichNewCur++;
  5630. pwNew[ichNewCur] = '\t'; // replace this with appropriate alignment
  5631. ichNewCur++;
  5632. for (i = indexAppletTagClose+1; i <= indexAppletEnd; i++)
  5633. {
  5634. // copy the tag
  5635. memcpy( (BYTE *)(&pwNew[ichNewCur]),
  5636. (BYTE *)(&pwOld[pTokArray[i].token.ibTokMin]),
  5637. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  5638. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  5639. // if its was TokTag_CLOSE, insert EOL
  5640. if ( pTokArray[i].token.tok == TokTag_CLOSE
  5641. && pTokArray[i].token.tokClass == tokTag)
  5642. {
  5643. pwNew[ichNewCur] = '\r';
  5644. ichNewCur++;
  5645. pwNew[ichNewCur] = '\n';
  5646. ichNewCur++;
  5647. pwNew[ichNewCur] = '\t'; // replace this with appropriate alignment
  5648. ichNewCur++;
  5649. }
  5650. } // for ()
  5651. // remember to set iArray appropriately
  5652. iArray = indexAppletEnd + 1;
  5653. ichBeginCopy = pTokArray[indexAppletEnd].token.ibTokMac;
  5654. LRet:
  5655. *pcchNew = ichNewCur;
  5656. *ppwNew = pwNew;
  5657. *pichNewCur = ichNewCur;
  5658. *pichBeginCopy = ichBeginCopy;
  5659. *piArrayStart = iArray;
  5660. return;
  5661. } /* fnRestoreApplet() */
  5662. void
  5663. CTriEditParse::RestoreSpacingSpecial(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR *ppwNew, HGLOBAL* /*phgNew*/,
  5664. TOKSTRUCT *pTokArray, UINT iArray, UINT *pichNewCur)
  5665. {
  5666. LPWSTR pwNew = *ppwNew;
  5667. UINT ichNewCur = *pichNewCur;
  5668. UINT iArraySav = iArray;
  5669. UINT ichspInfoEndtagEnd, ichBegin;
  5670. WCHAR szIndex[cchspBlockMax]; // will we have more than 20 digit numbers as number of DESIGNTIMESPx?
  5671. WORD *pspInfoEnd, *pspInfoOrder;
  5672. INT cwOrderInfo = 0;
  5673. UINT ichNewCurSav = 0xFFFFFFFF;
  5674. INT cchwspInfo; // spInfo block size in wide chars
  5675. INT cchRange; // number of char for which this spInfo was saved
  5676. INT ichtoktagStart, iArrayValue, index, itoktagStart;
  5677. int ichNewCurAtIndex0 = -1; // we need to adjust the saved ichNewCur because it gets invalidated
  5678. // as soon as the tag moves as a result of restoring pre-tag spaces.
  5679. itoktagStart = iArray; // init
  5680. // found DESIGNTIMESPx. Now, go backwords and look for TokTag_START
  5681. while (itoktagStart >= 0)
  5682. {
  5683. if ( pTokArray[itoktagStart].token.tok == TokTag_START
  5684. && pTokArray[itoktagStart].token.tokClass == tokTag
  5685. )
  5686. {
  5687. break;
  5688. }
  5689. itoktagStart--;
  5690. }
  5691. if (itoktagStart < 0) // didn't find '<' before DESIGNTIMESPx
  5692. goto LRet;
  5693. // found '<' before DESIGNTIMESPx
  5694. // the spacing info saved was for the portion of the document before the '<'
  5695. ASSERT(pTokArray[itoktagStart].token.tok == TokTag_START);
  5696. ASSERT(pTokArray[itoktagStart].token.tokClass == tokTag);
  5697. // we already know that iArray'th token is DESIGNTIMESPx, so get past the '=' that follows it
  5698. // ASSUMPTION - the value of attribute DESIGNTIMESPx will NOT get munged by Trident.
  5699. // NOTE - the above assumption is correct for this release of Trident
  5700. while (iArray < (int)ptep->m_cMaxToken)
  5701. {
  5702. if (*(WORD *)(pwOld+pTokArray[iArray].token.ibTokMin) == '=')
  5703. {
  5704. ASSERT(pTokArray[iArray].token.tokClass == tokOp);
  5705. break;
  5706. }
  5707. else if (*(WORD *)(pwOld+pTokArray[iArray].token.ibTokMin) == '>') // gone too far
  5708. goto LSkip1;
  5709. iArray++;
  5710. }
  5711. if (iArray >= (int)ptep->m_cMaxToken) // didn't find = after DESIGNTIMESPx
  5712. {
  5713. LSkip1:
  5714. goto LRet;
  5715. }
  5716. iArrayValue = -1; // init
  5717. while (iArray < (int)ptep->m_cMaxToken)
  5718. {
  5719. if ( (iArrayValue == -1)
  5720. && ( (pTokArray[iArray].token.tokClass == tokValue)
  5721. || (pTokArray[iArray].token.tokClass == tokString)
  5722. )
  5723. )
  5724. iArrayValue = iArray;
  5725. else if ( pTokArray[iArray].token.tok == TokTag_CLOSE
  5726. && pTokArray[iArray].token.tokClass == tokTag
  5727. )
  5728. {
  5729. ASSERT(*(WORD *)(pwOld+pTokArray[iArray].token.ibTokMin) == '>');
  5730. break;
  5731. }
  5732. iArray++;
  5733. }
  5734. if (iArrayValue == -1 || iArray >= (int)ptep->m_cMaxToken) // didn't find tokValue after DESIGNTIMESPx
  5735. {
  5736. // BUG 9040
  5737. //if (iArray >= (int)ptep->m_cMaxToken && iArrayValue != -1)
  5738. //{
  5739. // SOLUTION 1
  5740. // overwrite the stuff from pwOld[pTokArray[iArraySav].token.ibTokMin]
  5741. // to pwOld[pTokArray[iArrayValue].token.ibTokMac - 1]
  5742. // SOLUTION 2
  5743. // look for DESIGNTIMESP from pwOld[pTokArray[itokTagStart].token.ibTokMac - 1]
  5744. // to pwOld[pTokArray[iArray].token.ibTokMac - 1] and overwrite all of those
  5745. // strings with spaces. We could NULL those and do the blts, but why bother
  5746. // when the html isn't valid!
  5747. // make sure that all DESIGNTIMESPs are stripped off if we encountered this error case
  5748. //}
  5749. goto LRet;
  5750. }
  5751. // we know that 4 blocks of info was saved for each DESIGNTIMESPx attribute
  5752. // before tag, within tag, after tag, before matching end-tag
  5753. // even if no info was saved, the block will still exist with 2 words (size,# of char)
  5754. ichspInfoEndtagEnd = pTokArray[iArray].token.ibTokMac;
  5755. // first copy the document till DESIGNTIMESPx
  5756. // skip DESIGNTIMESPx and its value and set ichBeginCopy to be after that
  5757. // NOTE - token before iArraySav'th one should be tokSpace with lenght 1
  5758. // and with a value of chSpace (unless Trident has modified it). If thats TRUE,
  5759. // we should skip that too, because we added it when we put in DESIGNTIMESPx.
  5760. // fix Trident's behaviour - If Trident sees unknown tag(s) it puts it(them) at the end
  5761. // and inserts EOL before those. In this case, we would have inserted a space before DESIGNTIMESP
  5762. // and Trident would have inserted EOL. If thats not the case, we will ignore it.
  5763. if ( (iArraySav-1 > 0) /* validation */
  5764. && ( ( (pTokArray[iArraySav-1].token.ibTokMac - pTokArray[iArraySav-1].token.ibTokMin == 1)
  5765. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin] == ' ')
  5766. )
  5767. || ( (pTokArray[iArraySav-1].token.ibTokMac - pTokArray[iArraySav-1].token.ibTokMin == 3)
  5768. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin] == ' ')
  5769. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin+1] == '\r')
  5770. && (pwOld[pTokArray[iArraySav-1].token.ibTokMin+2] == '\n')
  5771. )
  5772. )
  5773. )
  5774. {
  5775. ichBegin = pTokArray[iArraySav-1].token.ibTokMin;
  5776. }
  5777. else
  5778. ichBegin = pTokArray[iArraySav].token.ibTokMin;
  5779. #ifdef NEEDED
  5780. ASSERT(ichBegin >= ichBeginCopy);
  5781. cbNeed = (ichNewCur+(ichBegin-ichBeginCopy))*sizeof(WCHAR) + cbBufPadding;
  5782. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  5783. {
  5784. iArray = iArraySav + 1;
  5785. goto LRet;
  5786. }
  5787. // BUG 15389 - look at the case of DESIGNTIMESP & convert the tag into upper/lower case...
  5788. //memcpy( (BYTE *)(pwNew+ichNewCur),
  5789. // (BYTE *)(pwOld+ichBeginCopy),
  5790. // (ichBegin-ichBeginCopy)*sizeof(WCHAR));
  5791. //ichNewCur += (ichBegin-ichBeginCopy);
  5792. if (ichBegin-ichBeginCopy >= 0)
  5793. {
  5794. // step 1 - copy from ichBeginCopy to '<' of the current tag
  5795. if ((int)(pTokArray[itoktagStart].token.ibTokMac-ichBeginCopy) > 0)
  5796. {
  5797. memcpy( (BYTE *)(pwNew+ichNewCur),
  5798. (BYTE *)(pwOld+ichBeginCopy),
  5799. (pTokArray[itoktagStart].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  5800. ichNewCur += (pTokArray[itoktagStart].token.ibTokMac-ichBeginCopy);
  5801. ichNewCurSav = ichNewCur+1; // used as a peg to get preceding tokTag_START i.e. '<'
  5802. }
  5803. // step 2 - convert current tag into upper/lower case & copy it
  5804. if (ichBeginCopy < pTokArray[itoktagStart+1].token.ibTokMin)
  5805. {
  5806. ASSERT((int)(pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin) > 0);
  5807. memcpy( (BYTE *)(pwNew+ichNewCur),
  5808. (BYTE *)(pwOld+pTokArray[itoktagStart+1].token.ibTokMin),
  5809. (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin)*sizeof(WCHAR));
  5810. if (iswupper(pwOld[pTokArray[iArraySav].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  5811. {
  5812. // convert the tag into upper case. ASSUME that the tag is at itoktagStart+1
  5813. _wcsupr(&pwNew[ichNewCur]);
  5814. }
  5815. else
  5816. {
  5817. // convert the tag into lower case. ASSUME that the tag is at itoktagStart+1
  5818. _wcslwr(&pwNew[ichNewCur]);
  5819. }
  5820. ichNewCur += (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin);
  5821. }
  5822. else // this tag is alreay been copied
  5823. {
  5824. // hack
  5825. if (pTokArray[itoktagStart+1].token.ibTokMac == ichBeginCopy) // means we are just past the current tag
  5826. {
  5827. if (iswupper(pwOld[pTokArray[iArraySav].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  5828. {
  5829. ASSERT(ichNewCur >= (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin));
  5830. // convert the tag into upper case. ASSUME that the tag is at itoktagStart+1
  5831. _wcsupr(&pwNew[ichNewCur-(pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin)]);
  5832. }
  5833. else
  5834. {
  5835. ASSERT(ichNewCur >= (pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin));
  5836. // convert the tag into lower case. ASSUME that the tag is at itoktagStart+1
  5837. _wcslwr(&pwNew[ichNewCur-(pTokArray[itoktagStart+1].token.ibTokMac-pTokArray[itoktagStart+1].token.ibTokMin)]);
  5838. }
  5839. }
  5840. }
  5841. // step 3 - copy from after the tag (which is at ichtoktagStart+1) to ichBegin
  5842. if ((int)(ichBegin-pTokArray[itoktagStart+1].token.ibTokMac) > 0)
  5843. {
  5844. memcpy( (BYTE *)(pwNew+ichNewCur),
  5845. (BYTE *)(pwOld+pTokArray[itoktagStart+1].token.ibTokMac),
  5846. (ichBegin-pTokArray[itoktagStart+1].token.ibTokMac)*sizeof(WCHAR));
  5847. ichNewCur += (ichBegin-pTokArray[itoktagStart+1].token.ibTokMac);
  5848. }
  5849. }
  5850. // set ichBeginCopy
  5851. ichBeginCopy = ichspInfoEndtagEnd; // make it ready for next copy
  5852. // copy the rest of the tag (skipping DESIGNTIMESPx = value)
  5853. ASSERT((INT)(ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac) >= 0);
  5854. memcpy( (BYTE *)(pwNew+ichNewCur),
  5855. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMac),
  5856. (ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac)*sizeof(WCHAR));
  5857. ichNewCur += (ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac);
  5858. #endif //NEEDED
  5859. memset((BYTE *)szIndex, 0, sizeof(szIndex));
  5860. // check if the value has quotes around it and don't copy them to szIndex
  5861. if ( pwOld[pTokArray[iArrayValue].token.ibTokMin] == '"'
  5862. && pwOld[pTokArray[iArrayValue].token.ibTokMac-1] == '"'
  5863. )
  5864. {
  5865. memcpy( (BYTE *)szIndex,
  5866. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMin+1),
  5867. (pTokArray[iArrayValue].token.ibTokMac-pTokArray[iArrayValue].token.ibTokMin-2)*sizeof(WCHAR));
  5868. }
  5869. else
  5870. {
  5871. memcpy( (BYTE *)szIndex,
  5872. (BYTE *)(pwOld+pTokArray[iArrayValue].token.ibTokMin),
  5873. (pTokArray[iArrayValue].token.ibTokMac-pTokArray[iArrayValue].token.ibTokMin)*sizeof(WCHAR));
  5874. }
  5875. ptep->m_ispInfoBlock = _wtoi(szIndex);
  5876. ptep->m_ispInfoBlock -= ptep->m_ispInfoBase;
  5877. if (ptep->m_ispInfoBlock < 0)
  5878. goto LRet;
  5879. // NOTE - we can cache this info in a link list at the begining
  5880. // get to the ptep->m_ispInfoBlock'th block from ptep->m_pspInfoOutStart
  5881. ASSERT(ptep->m_cchspInfoTotal >= 0);
  5882. pspInfoEnd = ptep->m_pspInfoOutStart + ptep->m_cchspInfoTotal;
  5883. ptep->m_pspInfoOut = ptep->m_pspInfoOutStart;
  5884. for (index = 0; index < ptep->m_ispInfoBlock; index++)
  5885. {
  5886. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // before <
  5887. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // between <>
  5888. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // Order Info
  5889. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // after >
  5890. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // before matching </
  5891. // we somehow have gone beyond the data that was saved for spacing
  5892. if (ptep->m_pspInfoOut >= pspInfoEnd)
  5893. {
  5894. goto LRet;
  5895. }
  5896. }
  5897. // get the Order Info
  5898. pspInfoOrder = ptep->m_pspInfoOut;
  5899. pspInfoOrder += *(WORD *)pspInfoOrder; // skip info saved for spacing before '<'
  5900. pspInfoOrder += *(WORD *)pspInfoOrder; // skip info saved for spacing between '<>'
  5901. // now pspInfoOrder is at correct place
  5902. cwOrderInfo = *(WORD *)pspInfoOrder++;
  5903. ASSERT(cwOrderInfo >= 1);
  5904. // process this info
  5905. #ifdef NEEDED
  5906. if (cwOrderInfo > 1) // means that we saved some info
  5907. {
  5908. INT cchNewCopy;
  5909. cchNewCopy = (ichBegin-pTokArray[itoktagStart].token.ibTokMin) + (ichspInfoEndtagEnd-pTokArray[iArrayValue].token.ibTokMac);
  5910. ptep->FRestoreOrder(pwNew, pwOld, pspInfoOrder, &ichNewCur, cwOrderInfo, pTokArray, itoktagStart, iArray, iArraySav, iArrayValue, cchNewCopy, phgNew);
  5911. }
  5912. #endif //NEEDED
  5913. ichtoktagStart = ichNewCur; // init
  5914. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  5915. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  5916. for (index = 0; index < 4; index++)
  5917. {
  5918. BOOL fLookback = FALSE;
  5919. cchwspInfo = *(WORD *)ptep->m_pspInfoOut++;
  5920. cchRange = *(WORD *)ptep->m_pspInfoOut++;
  5921. if (cchwspInfo == 2) // we didn't save any spacing info
  5922. {
  5923. if (index == 0) // special case BUG 8741
  5924. {
  5925. // Note that we didn't save anything before this tag. which means that
  5926. // we had '>' or some text immediately before the < tag.
  5927. ichtoktagStart = ichNewCur;
  5928. while (ichtoktagStart >= 0)
  5929. {
  5930. if (pwNew[ichtoktagStart] == '<')
  5931. {
  5932. ichtoktagStart--;
  5933. break;
  5934. }
  5935. ichtoktagStart--;
  5936. }
  5937. if (ichtoktagStart >= 0)
  5938. {
  5939. int cws = 0;
  5940. int ichtagStart = ichtoktagStart;
  5941. // remove any such white space trident inserts.
  5942. while ( pwNew[ichtoktagStart] == ' '
  5943. || pwNew[ichtoktagStart] == '\r'
  5944. || pwNew[ichtoktagStart] == '\n'
  5945. || pwNew[ichtoktagStart] == '\t')
  5946. {
  5947. cws++;
  5948. ichtoktagStart--;
  5949. }
  5950. if (cws > 0)
  5951. {
  5952. ASSERT((int)(ichNewCur-ichtagStart-1) >= 0);
  5953. //ichtokTagStart now points to either '>' or a non-whitespace char
  5954. memmove((BYTE*)&pwNew[ichtoktagStart+1],
  5955. (BYTE*)&pwNew[ichtoktagStart+1+cws],
  5956. (ichNewCur-ichtagStart-1)*sizeof(WCHAR));
  5957. ichNewCur -= cws;
  5958. }
  5959. } // if (ichtoktagStart >= 0)
  5960. } // if (index == 0)
  5961. goto LNext;
  5962. }
  5963. // note that ichtoktagStart is a position in pwNew
  5964. switch (index)
  5965. {
  5966. case 0: // before < of the tag
  5967. fLookback = TRUE;
  5968. ichtoktagStart = (ichNewCurSav == -1)?ichNewCur:ichNewCurSav;// handle < ... <%..%>...> case correctly
  5969. ichNewCurAtIndex0 = ichNewCur; // lets save the ichNewCur before we restore pre-tag spacing
  5970. while (ichtoktagStart >= 0)
  5971. {
  5972. if (pwNew[ichtoktagStart] == '<' && pwNew[ichtoktagStart+1] != '%')
  5973. {
  5974. ichtoktagStart--;
  5975. break;
  5976. }
  5977. ichtoktagStart--;
  5978. }
  5979. if (ichtoktagStart < 0) // looks to be an error, don't try to restore the spacing
  5980. {
  5981. ptep->m_pspInfoOut += cchwspInfo-2;
  5982. continue;
  5983. }
  5984. break;
  5985. case 1: // between <> of the tag
  5986. fLookback = FALSE;
  5987. // NOTE - we can assume that in 'case 0' we had put ichtoktagStart is just before '<'
  5988. // so that we can avoid this while loop. but what if we skipped case '0'?
  5989. // adjust ichNewCurSav to reflect the pre-tag spacing so that it doesn't become invalid
  5990. // we may need to adjust it in ichNewCur-ichNewCurAtIndex0 < 0 case as well, but lets not
  5991. // add code at this stage that we don't have to. (4/30/98)
  5992. if (ichNewCurAtIndex0 != -1 && ichNewCurSav != -1 && ichNewCur-ichNewCurAtIndex0 > 0)
  5993. ichNewCurSav = ichNewCurSav + (ichNewCur-ichNewCurAtIndex0);
  5994. ichtoktagStart = (ichNewCurSav == -1)?ichNewCur:ichNewCurSav;// handle < ... <%..%>...> case correctly
  5995. while (ichtoktagStart >= 0)
  5996. {
  5997. if (pwNew[ichtoktagStart] == '<' && pwNew[ichtoktagStart+1] != '%')
  5998. {
  5999. ichtoktagStart++;
  6000. break;
  6001. }
  6002. ichtoktagStart--;
  6003. }
  6004. if (ichtoktagStart < 0) // looks to be an error, don't try to restore the spacing
  6005. {
  6006. ptep->m_pspInfoOut += cchwspInfo-2; // for spacing info
  6007. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut; // for Order Info
  6008. continue;
  6009. }
  6010. break;
  6011. case 2: // after > of the tag
  6012. // Observation - Trident messes up the document in following way -
  6013. // If we had an EOL after '>' which is followed by HTML text,
  6014. // trident eats that EOL
  6015. // BUT
  6016. // If we had a space/tab before that EOL trident doesn't eat it!!!
  6017. // so I have added the conditions
  6018. // && (pwOld[pTokArray[iArray+1].token.ibTokMin] != ' ')
  6019. // && (pwOld[pTokArray[iArray+1].token.ibTokMin] != '\t')
  6020. // here is the deal - If the next tone happens to be plain text, there is no danger
  6021. // of applying the same format twice.( i.e. once for after '>' and the next time for
  6022. // before the next '<')
  6023. if ( (iArray+1 < (INT)ptep->m_cMaxToken) /*validation*/
  6024. && pTokArray[iArray+1].token.tok == 0
  6025. && pTokArray[iArray+1].token.tokClass == tokIDENTIFIER
  6026. && (pwOld[pTokArray[iArray+1].token.ibTokMin] != '\r')
  6027. && (pwOld[pTokArray[iArray+1].token.ibTokMin] != ' ')
  6028. && (pwOld[pTokArray[iArray+1].token.ibTokMin] != '\t')
  6029. )
  6030. {
  6031. fLookback = FALSE;
  6032. ichtoktagStart = ichNewCur;
  6033. while (ichtoktagStart >= 0)
  6034. {
  6035. if (pwNew[ichtoktagStart] == '>')
  6036. {
  6037. ichtoktagStart++;
  6038. break;
  6039. }
  6040. ichtoktagStart--;
  6041. }
  6042. if (ichtoktagStart < 0) // looks to be an error, don't try to restore the spacing
  6043. {
  6044. ptep->m_pspInfoOut += cchwspInfo-2;
  6045. continue;
  6046. }
  6047. }
  6048. else
  6049. {
  6050. ptep->m_pspInfoOut += cchwspInfo-2; // we ignore this info
  6051. continue;
  6052. }
  6053. break;
  6054. case 3: // before matching end tag
  6055. ptep->m_pspInfoOut += cchwspInfo-2; // we ignore this info
  6056. continue;
  6057. //fLookback = TRUE;
  6058. //ichtoktagStart = 0; // we ignore this info
  6059. break;
  6060. }
  6061. if (index == 3) // skip this info, because we have not reached matching end tag yet
  6062. ptep->m_pspInfoOut += cchwspInfo-2;
  6063. //else if (index == 0)
  6064. // ptep->FRestoreSpacingInHTML(pwNew, pwOld, &ichNewCur, &cchwspInfo, cchRange, ichtoktagStart, fLookback, index);
  6065. else
  6066. ptep->FRestoreSpacing(pwNew, pwOld, &ichNewCur, &cchwspInfo, cchRange, ichtoktagStart, fLookback, index);
  6067. LNext:
  6068. if (index == 1) // we have already processed this info, just move the pointer ahead
  6069. ptep->m_pspInfoOut += *(WORD *)ptep->m_pspInfoOut;
  6070. } // for ()
  6071. LRet:
  6072. *ppwNew = pwNew; // in case this changed
  6073. *pichNewCur = ichNewCur;
  6074. } /* RestoreSpacingSpecial() */
  6075. void
  6076. CTriEditParse::SaveSpacingSpecial(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR *ppwNew, HGLOBAL *phgNew,
  6077. TOKSTRUCT *pTokArray, INT iArray, UINT *pichNewCur)
  6078. {
  6079. UINT ichNewCur = *pichNewCur;
  6080. LPWSTR pwNew = *ppwNew;
  6081. int iArrayPrevTag, iArrayMatch;
  6082. UINT iArrayElem, iArrayTagStart;
  6083. INT ichEndMatch, ichBeginMatch, ichEndPrev, ichBeginPrev, ichEndNext, ichBeginNext, ichEndTag, ichBeginTag, ichBegin, ichEnd;
  6084. UINT cbNeed;
  6085. WCHAR szIndex[cchspBlockMax]; // will we have more than 20 digit numbers as number of DESIGNTIMESPx?
  6086. LPCWSTR rgSpaceTags[] =
  6087. {
  6088. L" DESIGNTIMESP=",
  6089. L" DESIGNTIMESP1=",
  6090. L" designtimesp=",
  6091. };
  6092. iArrayElem = 0xFFFFFFFF; // init
  6093. //
  6094. // look for TokTag_START
  6095. while (iArray >= 0)
  6096. {
  6097. if ( pTokArray[iArray].token.tokClass == tokTag
  6098. && pTokArray[iArray].token.tok == TokTag_START
  6099. )
  6100. {
  6101. break;
  6102. }
  6103. iArray--;
  6104. }
  6105. if (iArray < 0) // error case
  6106. goto LRet;
  6107. iArrayTagStart = iArray;
  6108. //
  6109. // step 1
  6110. // look for > that matches with <. we already are at ft.tokBegin2 i.e. <
  6111. ASSERT(pTokArray[iArray].token.tok == TokTag_START);
  6112. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  6113. ichBeginTag = pTokArray[iArray].token.ibTokMac;
  6114. while (iArray < (int)ptep->m_cMaxToken)
  6115. {
  6116. if ( pTokArray[iArray].token.tok == TokTag_CLOSE
  6117. && pTokArray[iArray].token.tokClass == tokTag) // ft.tokEnd2 is -1
  6118. break;
  6119. if (pTokArray[iArray].token.tokClass == tokElem)
  6120. iArrayElem = iArray;
  6121. iArray++;
  6122. }
  6123. if (iArray >= (int)ptep->m_cMaxToken) // didn't find >
  6124. {
  6125. goto LRet;
  6126. }
  6127. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE); // found >
  6128. ASSERT(pTokArray[iArray].token.tokClass == tokTag); // found >
  6129. ichEndTag = ichBegin = pTokArray[iArray].token.ibTokMin;
  6130. ichEnd = pTokArray[iArray].token.ibTokMac;
  6131. // step 2
  6132. // look for > before iArrayTagStart. Boundary case will be for the first < in the document
  6133. // save the spacing info
  6134. ASSERT(pTokArray[iArrayTagStart].token.tok == TokTag_START);
  6135. ASSERT(pTokArray[iArrayTagStart].token.tokClass == tokTag);
  6136. ichEndPrev = pTokArray[iArrayTagStart].token.ibTokMin;
  6137. ichBeginPrev = ichEndPrev-1;
  6138. // look for previous TokTag_CLOSE
  6139. // if the tag ending tag, ichBeginPrev becomes ibTokMac of '>' tag
  6140. // if the tag is starting tag, ichBeginPrev becomes ibTokMac+(white space just after that tag)
  6141. iArrayPrevTag = iArrayTagStart; // this is TokTag_START
  6142. while (iArrayPrevTag >= 0)
  6143. {
  6144. if ( ( pTokArray[iArrayPrevTag].token.tokClass == tokTag
  6145. && pTokArray[iArrayPrevTag].token.tok == TokTag_CLOSE
  6146. )
  6147. || ( pTokArray[iArrayPrevTag].token.tokClass == tokSSS
  6148. && pTokArray[iArrayPrevTag].token.tok == TokTag_SSSCLOSE
  6149. )/* VID6 - bug 22787 */
  6150. )
  6151. {
  6152. break;
  6153. }
  6154. iArrayPrevTag--;
  6155. }
  6156. if (iArrayPrevTag < 0) // handle error case
  6157. {
  6158. // leave the old behaviour as is for V1
  6159. while (ichBeginPrev >= 0)
  6160. {
  6161. if ( pwOld[ichBeginPrev] != ' '
  6162. && pwOld[ichBeginPrev] != '\r'
  6163. && pwOld[ichBeginPrev] != '\n'
  6164. && pwOld[ichBeginPrev] != '\t'
  6165. )
  6166. break;
  6167. ichBeginPrev--;
  6168. }
  6169. goto LGotEndNext;
  6170. }
  6171. ichBeginPrev = pTokArray[iArrayPrevTag].token.ibTokMac - 1;
  6172. LGotEndNext:
  6173. if (ichBeginPrev < 0)
  6174. ichBeginPrev = 0;
  6175. else
  6176. ichBeginPrev++;
  6177. // step 3
  6178. // look for TokTag_START after iArray(which currently is TokTag_CLOSE)
  6179. // save spacing info
  6180. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  6181. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  6182. //iArrayNextStart = iArray;
  6183. ichBeginNext = pTokArray[iArray].token.ibTokMac;
  6184. ASSERT(ichBeginNext == ichEnd);
  6185. ichEndNext = ichBeginNext;
  6186. while (ichEndNext < (INT)pTokArray[ptep->m_cMaxToken-1].token.ibTokMac)
  6187. {
  6188. if ( pwOld[ichEndNext] != ' '
  6189. && pwOld[ichEndNext] != '\r'
  6190. && pwOld[ichEndNext] != '\n'
  6191. && pwOld[ichEndNext] != '\t'
  6192. )
  6193. break;
  6194. ichEndNext++;
  6195. }
  6196. if (ichEndNext >= (INT)pTokArray[ptep->m_cMaxToken-1].token.ibTokMac)
  6197. ichEndNext = pTokArray[ptep->m_cMaxToken-1].token.ibTokMac;
  6198. // step 4
  6199. // if iArrayElem != -1, look for pTokArray[iArrayElem].iNextprev. If its not -1, set iArrayMatch
  6200. // look for previous TokTag_START/TokTag_END. look for previous TokTag_CLOSE
  6201. // save spacing info
  6202. if (iArrayElem == -1) // this can happen if we have incomplete HTML
  6203. {
  6204. ichEndMatch = ichBeginMatch = 0;
  6205. goto LSkipMatchCalc;
  6206. }
  6207. iArrayMatch = pTokArray[iArrayElem].iNextprev;
  6208. if (iArrayMatch != -1) // match was set while tokenizing
  6209. {
  6210. ichBeginMatch = ichEndMatch = 0; //init
  6211. ASSERT(pTokArray[iArray].token.tok == TokTag_CLOSE);
  6212. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  6213. while (iArrayMatch >= iArray) // iArray is TokTag_CLOSE of the current tag (i.e. '>')
  6214. {
  6215. if ( pTokArray[iArrayMatch].token.tokClass == tokTag
  6216. && ( pTokArray[iArrayMatch].token.tok == TokTag_START
  6217. || pTokArray[iArrayMatch].token.tok == TokTag_END
  6218. )
  6219. )
  6220. break;
  6221. iArrayMatch--;
  6222. }
  6223. if (iArrayMatch > iArray) // did find '</' or '<' after the current tag
  6224. {
  6225. ichEndMatch = pTokArray[iArrayMatch].token.ibTokMin;
  6226. ichBeginMatch = ichEndMatch; // init
  6227. // look for '>' and set ichBeginMatch
  6228. while (iArrayMatch >= iArray) // iArray is TokTag_CLOSE of the current tag (i.e. '>')
  6229. {
  6230. if ( ( pTokArray[iArrayMatch].token.tokClass == tokTag
  6231. && pTokArray[iArrayMatch].token.tok == TokTag_CLOSE
  6232. )
  6233. || ( pTokArray[iArrayMatch].token.tokClass == tokSSS
  6234. && pTokArray[iArrayMatch].token.tok == TokTag_SSSCLOSE
  6235. )/* VID6 - bug 22787 */
  6236. )
  6237. break;
  6238. iArrayMatch--;
  6239. }
  6240. if (iArrayMatch >= iArray) // they may very well be the same
  6241. {
  6242. ichBeginMatch = pTokArray[iArrayMatch].token.ibTokMac;
  6243. ASSERT(ichBeginMatch <= ichEndMatch);
  6244. ASSERT(ichBeginMatch >= ichEnd);
  6245. }
  6246. }
  6247. }
  6248. else
  6249. {
  6250. // don't bother saving any info from here
  6251. ichEndMatch = ichBeginMatch = 0;
  6252. }
  6253. LSkipMatchCalc:
  6254. if (ichEndPrev > ichBeginPrev)
  6255. ptep->hrMarkSpacing(pwOld, ichEndPrev, &ichBeginPrev);
  6256. else
  6257. ptep->hrMarkSpacing(pwOld, ichEndPrev, &ichEndPrev);
  6258. if (ichEndTag > ichBeginTag)
  6259. {
  6260. INT ichBeginTagSav = ichBeginTag;
  6261. ptep->hrMarkSpacing(pwOld, ichEndTag, &ichBeginTag);
  6262. // iArray'th token is TokTag_CLOSE & iArrayTagStart is TokTag_START
  6263. ptep->hrMarkOrdering(pwOld, pTokArray, iArrayTagStart, iArray, ichEndTag, &ichBeginTagSav);
  6264. }
  6265. else
  6266. {
  6267. INT ichEndTagSav = ichEndTag;
  6268. ptep->hrMarkSpacing(pwOld, ichEndTag, &ichEndTag);
  6269. // iArray'th token is TokTag_CLOSE & iArrayTagStart is TokTag_START
  6270. ptep->hrMarkOrdering(pwOld, pTokArray, iArrayTagStart, iArray, ichEndTagSav, &ichEndTagSav);
  6271. }
  6272. if (ichEndNext > ichBeginNext)
  6273. ptep->hrMarkSpacing(pwOld, ichEndNext, &ichBeginNext);
  6274. else
  6275. ptep->hrMarkSpacing(pwOld, ichEndNext, &ichEndNext);
  6276. if (ichEndMatch > ichBeginMatch)
  6277. ptep->hrMarkSpacing(pwOld, ichEndMatch, &ichBeginMatch);
  6278. else
  6279. ptep->hrMarkSpacing(pwOld, ichEndMatch, &ichEndMatch);
  6280. // realloc if needed
  6281. cbNeed = (ichNewCur+3*wcslen(rgSpaceTags[0])+(ichEnd-ichBegin))*sizeof(WCHAR);
  6282. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6283. goto LRet;
  6284. if (iswupper(pwOld[pTokArray[iArrayTagStart+1].token.ibTokMin]) != 0) // upper case
  6285. {
  6286. memcpy( (BYTE *)(pwNew+ichNewCur),
  6287. (BYTE *)(rgSpaceTags[0]),
  6288. (wcslen(rgSpaceTags[0]))*sizeof(WCHAR));
  6289. ichNewCur += wcslen(rgSpaceTags[0]);
  6290. }
  6291. else
  6292. {
  6293. memcpy( (BYTE *)(pwNew+ichNewCur),
  6294. (BYTE *)(rgSpaceTags[2]),
  6295. (wcslen(rgSpaceTags[2]))*sizeof(WCHAR));
  6296. ichNewCur += wcslen(rgSpaceTags[2]);
  6297. }
  6298. (WCHAR)_itow(ptep->m_ispInfoBlock+ptep->m_ispInfoBase, szIndex, 10);
  6299. ptep->m_ispInfoBlock++;
  6300. ASSERT(wcslen(szIndex) < sizeof(szIndex));
  6301. ASSERT(sizeof(szIndex) == cchspBlockMax*sizeof(WCHAR));
  6302. memcpy( (BYTE *)(pwNew+ichNewCur),
  6303. (BYTE *)(szIndex),
  6304. wcslen(szIndex)*sizeof(WCHAR));
  6305. ichNewCur += wcslen(szIndex);
  6306. LRet:
  6307. //*pcchNew = ichNewCur;
  6308. *ppwNew = pwNew;
  6309. *pichNewCur = ichNewCur;
  6310. return;
  6311. } /* SaveSpacingSpecial() */
  6312. void
  6313. CTriEditParse::fnSaveAImgLink(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  6314. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  6315. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  6316. DWORD dwFlags)
  6317. {
  6318. UINT ichNewCur = *pichNewCur;
  6319. UINT ichBeginCopy = *pichBeginCopy;
  6320. UINT iArray = *piArrayStart;
  6321. LPWSTR pwNew = *ppwNew;
  6322. UINT cbNeed;
  6323. int cchURL = 0;
  6324. int ichURL = 0;
  6325. int index = iArray;
  6326. LPCWSTR rgDspURL[] =
  6327. {
  6328. L" DESIGNTIMEURL=",
  6329. };
  6330. ASSERT( pTokArray[iArray].token.tok == TokElem_A
  6331. || pTokArray[iArray].token.tok == TokElem_IMG
  6332. || pTokArray[iArray].token.tok == TokElem_LINK);
  6333. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  6334. if (!FURLNeedSpecialHandling(pTokArray, iArray, pwOld, (int)ptep->m_cMaxToken, &ichURL, &cchURL))
  6335. iArray++;
  6336. else // save the URL as an attribute value of DESIGNTIMEURL
  6337. {
  6338. // make sure we have enough space in pwNew.
  6339. // copy from ichBeginCopy till current token's ending '>'.
  6340. // index points to A/IMG/LINK
  6341. while (index < (int)ptep->m_cMaxToken)
  6342. {
  6343. if ( pTokArray[index].token.tok == TokTag_CLOSE
  6344. && pTokArray[index].token.tokClass == tokTag
  6345. )
  6346. break;
  6347. index++;
  6348. }
  6349. if (index >= (int)ptep->m_cMaxToken) // invalid HTML, we didn't find '>'
  6350. {
  6351. iArray++;
  6352. goto LRet;
  6353. }
  6354. cbNeed = (ichNewCur+pTokArray[index].token.ibTokMin-ichBeginCopy+wcslen(rgDspURL[0])+cchURL+3/*eq,quotes*/)*sizeof(WCHAR)+cbBufPadding;
  6355. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6356. {
  6357. iArray++;
  6358. goto LRet;
  6359. }
  6360. // index points to '>'
  6361. if ((int) (pTokArray[index].token.ibTokMin-ichBeginCopy) > 0)
  6362. {
  6363. memcpy( (BYTE *)&pwNew[ichNewCur],
  6364. (BYTE *)&pwOld[ichBeginCopy],
  6365. (pTokArray[index].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  6366. ichNewCur += (pTokArray[index].token.ibTokMin-ichBeginCopy);
  6367. }
  6368. if (cchURL != 0)
  6369. {
  6370. // add 'DESIGNTIMEURL=' followed by the current URL as quoted value
  6371. memcpy( (BYTE *)&pwNew[ichNewCur],
  6372. (BYTE *)rgDspURL[0],
  6373. wcslen(rgDspURL[0])*sizeof(WCHAR));
  6374. ichNewCur += wcslen(rgDspURL[0]);
  6375. pwNew[ichNewCur++] = '"';
  6376. memcpy( (BYTE *)&pwNew[ichNewCur],
  6377. (BYTE *)&pwOld[ichURL],
  6378. cchURL*sizeof(WCHAR));
  6379. ichNewCur += cchURL;
  6380. pwNew[ichNewCur++] = '"';
  6381. }
  6382. if (dwFlags & dwPreserveSourceCode)
  6383. ptep->SaveSpacingSpecial(ptep, pwOld, &pwNew, phgNew, pTokArray, iArray-1, &ichNewCur);
  6384. // add ending '>' and set ichBeginCopy, iArray, ichNewCur appropriately
  6385. memcpy( (BYTE *)&pwNew[ichNewCur],
  6386. (BYTE *)&pwOld[pTokArray[index].token.ibTokMin],
  6387. (pTokArray[index].token.ibTokMac-pTokArray[index].token.ibTokMin)*sizeof(WCHAR));
  6388. ichNewCur += (pTokArray[index].token.ibTokMac-pTokArray[index].token.ibTokMin);
  6389. iArray = index+1;
  6390. ichBeginCopy = pTokArray[index].token.ibTokMac;
  6391. }
  6392. LRet:
  6393. *pcchNew = ichNewCur;
  6394. *ppwNew = pwNew;
  6395. *pichNewCur = ichNewCur;
  6396. *pichBeginCopy = ichBeginCopy;
  6397. *piArrayStart = iArray;
  6398. return;
  6399. } /* fnSaveAImgLink() */
  6400. void
  6401. CTriEditParse::fnRestoreAImgLink(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  6402. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  6403. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  6404. DWORD dwFlags)
  6405. {
  6406. UINT ichNewCur = *pichNewCur;
  6407. UINT ichBeginCopy = *pichBeginCopy;
  6408. UINT iArray = *piArrayStart;
  6409. LPWSTR pwNew = *ppwNew;
  6410. UINT iArraySav = iArray;
  6411. LPCWSTR rgTags[] =
  6412. {
  6413. L"DESIGNTIMESP",
  6414. L"DESIGNTIMEREF",
  6415. L"DESIGNTIMEURL",
  6416. };
  6417. int indexStart, indexEnd, i, indexDSR, indexDSP, indexDSU;
  6418. UINT cchsptag, cchhreftag, cchdsurltag;
  6419. CComBSTR bstrRelativeURL;
  6420. BOOL fHrefSrcFound = FALSE;
  6421. UINT cbNeed;
  6422. // we know that DESIGNTIMESP is not saved for these tags, but check it just to be sure.
  6423. // if we find DESIGNTIMEREF, it means that the HREF was dragged on the page while in design view.
  6424. ASSERT( pTokArray[iArray].token.tok == TokElem_A
  6425. || pTokArray[iArray].token.tok == TokElem_IMG
  6426. || pTokArray[iArray].token.tok == TokElem_LINK);
  6427. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  6428. indexDSP = indexDSR = indexDSU = -1;
  6429. //get the start tag
  6430. indexStart = iArray;
  6431. while (indexStart >= 0) // generally, it will be the previous token, but just in case...
  6432. {
  6433. if ( (pTokArray[indexStart].token.tok == TokTag_START)
  6434. && (pTokArray[indexStart].token.tokClass == tokTag)
  6435. )
  6436. {
  6437. break;
  6438. }
  6439. indexStart--;
  6440. } // while ()
  6441. if (indexStart < 0) // this can happen only if we have incomplete HTML. Handle error case
  6442. {
  6443. iArray = iArraySav + 1;
  6444. goto LRet;
  6445. }
  6446. indexEnd = iArray;
  6447. while (indexEnd < (int)ptep->m_cMaxToken) // generally, it will be the next token, but just in case...
  6448. {
  6449. if ( (pTokArray[indexEnd].token.tok == TokTag_CLOSE) /* > */
  6450. && (pTokArray[indexEnd].token.tokClass == tokTag)
  6451. )
  6452. {
  6453. break;
  6454. }
  6455. indexEnd++;
  6456. }
  6457. if (indexEnd >= (int)ptep->m_cMaxToken) // error case
  6458. {
  6459. iArray = iArraySav + 1;
  6460. goto LRet;
  6461. }
  6462. // look for DESIGNTIMEREF inside the tags
  6463. cchsptag = wcslen(rgTags[0]);
  6464. cchhreftag = wcslen(rgTags[1]);
  6465. cchdsurltag = wcslen(rgTags[2]);
  6466. for (i = iArray; i < indexEnd; i++)
  6467. {
  6468. if ( pTokArray[i].token.tok == 0
  6469. && pTokArray[i].token.tokClass == tokSpace
  6470. && cchsptag == pTokArray[i].token.ibTokMac - pTokArray[i].token.ibTokMin
  6471. && (0 == _wcsnicmp(rgTags[0], &pwOld[pTokArray[i].token.ibTokMin], cchsptag))
  6472. )
  6473. {
  6474. indexDSP = i;
  6475. if (indexDSR != -1 && indexDSU != -1) // already initilized
  6476. break;
  6477. }
  6478. else if ( pTokArray[i].token.tok == 0
  6479. && pTokArray[i].token.tokClass == tokSpace
  6480. && cchhreftag == pTokArray[i].token.ibTokMac - pTokArray[i].token.ibTokMin
  6481. && (0 == _wcsnicmp(rgTags[1], &pwOld[pTokArray[i].token.ibTokMin], cchhreftag))
  6482. )
  6483. {
  6484. indexDSR = i;
  6485. if (indexDSP != -1 && indexDSU != -1) // already initilized
  6486. break;
  6487. }
  6488. else if ( pTokArray[i].token.tok == 0
  6489. && pTokArray[i].token.tokClass == tokSpace
  6490. && cchhreftag == pTokArray[i].token.ibTokMac - pTokArray[i].token.ibTokMin
  6491. && (0 == _wcsnicmp(rgTags[2], &pwOld[pTokArray[i].token.ibTokMin], cchdsurltag))
  6492. )
  6493. {
  6494. indexDSU = i;
  6495. if (indexDSP != -1 && indexDSR != -1) // already initilized
  6496. break;
  6497. }
  6498. } // for ()
  6499. // Here is the deal - If we found DESIGNTIMESP, it means that this A/Img/Link existed
  6500. // while in source view. And in that case, we shouldn't find DESIGNTIMEREF. With the
  6501. // same token, if we found DESINTIMEREF, it means that this A/Img/Link was dropped
  6502. // while in design view, so DESIGNTIMESP shouldn't be there. They are mutually exclusive.
  6503. // Also, DESIGNTIMEURL can exist only if the href was there while in source view
  6504. // and its value was relative. This can coexist with DESIGNTIMESP,
  6505. // but not with DESIGNTIMEREF.
  6506. if (indexDSP != -1 && indexDSU == -1) // we found DESIGNTIMESP, but not DESIGNTIMEURL
  6507. {
  6508. ASSERT(indexDSR == -1); // based on above statement, this better be true
  6509. iArray = iArraySav + 1;
  6510. goto LRet;
  6511. }
  6512. if (indexDSR == -1 && indexDSU == -1)
  6513. {
  6514. iArray = iArraySav + 1;
  6515. goto LRet;
  6516. }
  6517. if (indexDSR != -1)
  6518. {
  6519. ASSERT(indexDSU == -1); // this better be TRUE, because the 2 are mutually exclusive
  6520. // at this point we know that we have DESIGNTIMEREF (that was put in as part
  6521. // of drag-drop operation while in design view)
  6522. // modify the href and copy the tag.
  6523. if ((int) (pTokArray[indexStart].token.ibTokMin-ichBeginCopy) > 0)
  6524. {
  6525. cbNeed = (ichNewCur+pTokArray[indexStart].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  6526. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6527. goto LRet;
  6528. memcpy( (BYTE *)&pwNew[ichNewCur],
  6529. (BYTE *)&pwOld[ichBeginCopy],
  6530. (pTokArray[indexStart].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  6531. ichNewCur += (pTokArray[indexStart].token.ibTokMin-ichBeginCopy);
  6532. }
  6533. cbNeed = (ichNewCur+pTokArray[indexEnd].token.ibTokMac-pTokArray[indexStart].token.ibTokMin)*sizeof(WCHAR)+cbBufPadding;
  6534. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6535. goto LRet;
  6536. // trident mucks with the spacing of these tags and we didn't save any spacing info
  6537. // soput endofline at the end of the tag.
  6538. //pwNew[ichNewCur++] = '\r';
  6539. //pwNew[ichNewCur++] = '\n';
  6540. i = indexStart;
  6541. while (i <= indexEnd)
  6542. {
  6543. if (i == indexDSR)
  6544. i++; // don't copy this token
  6545. else if ( ( pTokArray[i].token.tok == TokAttrib_HREF
  6546. || pTokArray[i].token.tok == TokAttrib_SRC
  6547. )
  6548. && pTokArray[i].token.tokClass == tokAttr
  6549. && !fHrefSrcFound
  6550. )
  6551. {
  6552. fHrefSrcFound = TRUE;
  6553. memcpy( (BYTE *)&pwNew[ichNewCur],
  6554. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6555. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6556. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6557. i++;
  6558. }
  6559. else if ( pTokArray[i].token.tok == 0
  6560. && pTokArray[i].token.tokClass == tokString
  6561. && fHrefSrcFound
  6562. )
  6563. {
  6564. HRESULT hr;
  6565. int cchURL;
  6566. WCHAR *pszURL;
  6567. BOOL fQuote = (pwOld[pTokArray[i].token.ibTokMin] == '"');
  6568. cchURL = (fQuote)
  6569. ? pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin-2
  6570. : pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin;
  6571. pszURL = new WCHAR [cchURL+1];
  6572. fHrefSrcFound = FALSE;
  6573. if (ptep->m_bstrBaseURL != NULL) // get the relative URL
  6574. {
  6575. // get the URL string from pwOld and pass it in to relativise
  6576. memcpy( (BYTE *)pszURL,
  6577. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin + ((fQuote)? 1 : 0)],
  6578. (cchURL)*sizeof(WCHAR));
  6579. pszURL[cchURL] = '\0';
  6580. hr = UtilConvertToRelativeURL((LPOLESTR)pszURL, ptep->m_bstrBaseURL, NULL, &bstrRelativeURL);
  6581. if (SUCCEEDED(hr))
  6582. {
  6583. // can we assume that bstrRelativeURL is NULL terminated?
  6584. LPWSTR pszRelativeURL = bstrRelativeURL;
  6585. if (wcslen(pszRelativeURL) == 0)
  6586. {
  6587. memcpy( (BYTE *)&pwNew[ichNewCur],
  6588. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6589. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6590. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6591. }
  6592. else
  6593. {
  6594. pwNew[ichNewCur++] = '"';
  6595. memcpy( (BYTE *)&pwNew[ichNewCur],
  6596. (BYTE *)pszRelativeURL,
  6597. wcslen(pszRelativeURL)*sizeof(WCHAR));
  6598. ichNewCur += wcslen(pszRelativeURL);
  6599. pwNew[ichNewCur++] = '"';
  6600. }
  6601. }
  6602. else
  6603. {
  6604. memcpy( (BYTE *)&pwNew[ichNewCur],
  6605. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6606. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6607. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6608. }
  6609. }
  6610. else
  6611. {
  6612. memcpy( (BYTE *)&pwNew[ichNewCur],
  6613. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6614. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6615. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6616. }
  6617. delete pszURL;
  6618. i++;
  6619. }
  6620. else // all other tokens
  6621. {
  6622. memcpy( (BYTE *)&pwNew[ichNewCur],
  6623. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6624. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6625. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6626. i++;
  6627. }
  6628. }
  6629. // trident mucks with the spacing of these tags and we didn't save any spacing info
  6630. // so put endofline at the end of the tag.
  6631. //pwNew[ichNewCur++] = '\r';
  6632. //pwNew[ichNewCur++] = '\n';
  6633. }
  6634. else // DESIGNTIMEURL case
  6635. {
  6636. int indexDSUEnd, indexDSPEnd;
  6637. // we found DESIGNTIMEURL. It means, we had this URL while in source view and it was
  6638. // a relative URL then.
  6639. // Check if trident has made it absolute. If it has and the filename is same,
  6640. // we need to restore it. In all other cases, simply copy the URL and return.
  6641. ASSERT(indexDSR == -1); // this better be TRUE, because the 2 are mutually exclusive
  6642. if ((int) (pTokArray[indexStart].token.ibTokMin-ichBeginCopy) > 0)
  6643. {
  6644. cbNeed = (ichNewCur+pTokArray[indexStart].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  6645. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6646. goto LRet;
  6647. memcpy( (BYTE *)&pwNew[ichNewCur],
  6648. (BYTE *)&pwOld[ichBeginCopy],
  6649. (pTokArray[indexStart].token.ibTokMin-ichBeginCopy)*sizeof(WCHAR));
  6650. ichNewCur += (pTokArray[indexStart].token.ibTokMin-ichBeginCopy);
  6651. }
  6652. cbNeed = (ichNewCur+pTokArray[indexEnd].token.ibTokMac-pTokArray[indexStart].token.ibTokMin)*sizeof(WCHAR)+cbBufPadding;
  6653. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6654. goto LRet;
  6655. // get indexDSUEnd
  6656. i = indexDSU;
  6657. indexDSUEnd = -1;
  6658. while (i < indexEnd)
  6659. {
  6660. if ( pTokArray[i].token.tok == 0
  6661. && (pTokArray[i].token.tokClass == tokValue || pTokArray[i].token.tokClass == tokString)
  6662. )
  6663. {
  6664. indexDSUEnd = i;
  6665. break;
  6666. }
  6667. i++;
  6668. }
  6669. if (indexDSUEnd == -1) // we have malformed html
  6670. {
  6671. iArray = iArraySav + 1;
  6672. goto LRet;
  6673. }
  6674. // get indexDSPEnd
  6675. i = indexDSP;
  6676. indexDSPEnd = -1;
  6677. while (i < indexEnd)
  6678. {
  6679. if ( pTokArray[i].token.tok == 0
  6680. && (pTokArray[i].token.tokClass == tokValue || pTokArray[i].token.tokClass == tokString)
  6681. )
  6682. {
  6683. indexDSPEnd = i;
  6684. break;
  6685. }
  6686. i++;
  6687. }
  6688. if (indexDSPEnd == -1) // we have malformed html
  6689. {
  6690. iArray = iArraySav + 1;
  6691. goto LRet;
  6692. }
  6693. i = indexStart;
  6694. while (i <= indexEnd)
  6695. {
  6696. if ( (i >= indexDSU && i <= indexDSUEnd)
  6697. || (i >= indexDSP && i <= indexDSPEnd)
  6698. )
  6699. i++; // don't copy this token
  6700. else if ( ( pTokArray[i].token.tok == TokAttrib_HREF
  6701. || pTokArray[i].token.tok == TokAttrib_SRC
  6702. )
  6703. && pTokArray[i].token.tokClass == tokAttr
  6704. && !fHrefSrcFound
  6705. )
  6706. {
  6707. fHrefSrcFound = TRUE;
  6708. memcpy( (BYTE *)&pwNew[ichNewCur],
  6709. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6710. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6711. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6712. i++;
  6713. }
  6714. else if ( pTokArray[i].token.tok == 0
  6715. && pTokArray[i].token.tokClass == tokString
  6716. && fHrefSrcFound
  6717. )
  6718. {
  6719. int ichURL, ichURLEnd, ichDSURL, ichDSURLEnd;
  6720. // if the url is now absloute and is just an absolute version of
  6721. // the one at indexDSUEnd, we need to replace it.
  6722. ichURL = (pwOld[pTokArray[i].token.ibTokMin] == '"')
  6723. ? pTokArray[i].token.ibTokMin+1
  6724. : pTokArray[i].token.ibTokMin;
  6725. ichURLEnd = (pwOld[pTokArray[i].token.ibTokMac-1] == '"')
  6726. ? pTokArray[i].token.ibTokMac-1
  6727. : pTokArray[i].token.ibTokMac;
  6728. if (FIsAbsURL((LPOLESTR)&pwOld[ichURL]))
  6729. {
  6730. WCHAR *pszURL1 = NULL;
  6731. WCHAR *pszURL2 = NULL;
  6732. int ich;
  6733. ichDSURL = (pwOld[pTokArray[indexDSUEnd].token.ibTokMin] == '"')
  6734. ? pTokArray[indexDSUEnd].token.ibTokMin+1
  6735. : pTokArray[indexDSUEnd].token.ibTokMin;
  6736. ichDSURLEnd = (pwOld[pTokArray[indexDSUEnd].token.ibTokMac-1] == '"')
  6737. ? pTokArray[indexDSUEnd].token.ibTokMac-1
  6738. : pTokArray[indexDSUEnd].token.ibTokMac;
  6739. // just for comparison purposes, don't look at '/' or '\' separators
  6740. // between filenames & directories...
  6741. pszURL1 = new WCHAR[ichDSURLEnd-ichDSURL + 1];
  6742. pszURL2 = new WCHAR[ichDSURLEnd-ichDSURL + 1];
  6743. if (pszURL1 == NULL || pszURL2 == NULL)
  6744. goto LResumeCopy;
  6745. memcpy((BYTE *)pszURL1, (BYTE *)&pwOld[ichDSURL], (ichDSURLEnd-ichDSURL)*sizeof(WCHAR));
  6746. memcpy((BYTE *)pszURL2, (BYTE *)&pwOld[ichURLEnd-(ichDSURLEnd-ichDSURL)], (ichDSURLEnd-ichDSURL)*sizeof(WCHAR));
  6747. pszURL1[ichDSURLEnd-ichDSURL] = '\0';
  6748. pszURL2[ichDSURLEnd-ichDSURL] = '\0';
  6749. for (ich = 0; ich < ichDSURLEnd-ichDSURL; ich++)
  6750. {
  6751. if (pszURL1[ich] == '/')
  6752. pszURL1[ich] = '\\';
  6753. if (pszURL2[ich] == '/')
  6754. pszURL2[ich] = '\\';
  6755. }
  6756. if (0 == _wcsnicmp(pszURL1, pszURL2, ichDSURLEnd-ichDSURL))
  6757. {
  6758. pwNew[ichNewCur++] = '"';
  6759. memcpy( (BYTE *)&pwNew[ichNewCur],
  6760. (BYTE *)&pwOld[ichDSURL],
  6761. (ichDSURLEnd-ichDSURL)*sizeof(WCHAR));
  6762. ichNewCur += (ichDSURLEnd-ichDSURL);
  6763. pwNew[ichNewCur++] = '"';
  6764. }
  6765. else // copy it as it is
  6766. {
  6767. LResumeCopy:
  6768. memcpy( (BYTE *)&pwNew[ichNewCur],
  6769. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6770. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6771. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6772. }
  6773. if (pszURL1 != NULL)
  6774. delete pszURL1;
  6775. if (pszURL2 != NULL)
  6776. delete pszURL2;
  6777. }
  6778. else // its realtive, simply copy it
  6779. {
  6780. memcpy( (BYTE *)&pwNew[ichNewCur],
  6781. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6782. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6783. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6784. }
  6785. i++;
  6786. }
  6787. else // all other tokens
  6788. {
  6789. // ****NOTE - we can actually do pretty printing here
  6790. // instead of fixing the special cases****
  6791. // fix Trident's behaviour - If Trident sees unknown tag(s) it puts it(them) at the end
  6792. // and inserts EOL before those. In this case, we would have inserted a space before DESIGNTIMESP
  6793. // and Trident would have inserted EOL. If thats not the case, we will ignore it.
  6794. if ( (pTokArray[i].token.tokClass == tokSpace)
  6795. && (pTokArray[i].token.tok == 0)
  6796. && (FIsWhiteSpaceToken(pwOld, pTokArray[i].token.ibTokMin, pTokArray[i].token.ibTokMac))
  6797. )
  6798. {
  6799. if (i != indexDSU-1) // else skip the copy
  6800. pwNew[ichNewCur++] = ' '; // convert space+\r+\n into space
  6801. i++;
  6802. }
  6803. else
  6804. {
  6805. memcpy( (BYTE *)&pwNew[ichNewCur],
  6806. (BYTE *)&pwOld[pTokArray[i].token.ibTokMin],
  6807. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  6808. ichNewCur += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  6809. i++;
  6810. }
  6811. }
  6812. } // while (i <= indexEnd)
  6813. } // end of DESIGNTIMEURL case
  6814. // we have spacing save dfor this tag, lets restore it
  6815. if ( (indexDSP != -1)
  6816. && (dwFlags & dwPreserveSourceCode)
  6817. )
  6818. ptep->RestoreSpacingSpecial(ptep, pwOld, &pwNew, phgNew, pTokArray, indexDSP, &ichNewCur);
  6819. // remember to set iArray appropriately
  6820. iArray = indexEnd + 1;
  6821. ichBeginCopy = pTokArray[indexEnd].token.ibTokMac;
  6822. LRet:
  6823. *pcchNew = ichNewCur;
  6824. *ppwNew = pwNew;
  6825. *pichNewCur = ichNewCur;
  6826. *pichBeginCopy = ichBeginCopy;
  6827. *piArrayStart = iArray;
  6828. return;
  6829. } /* fnRestoreAImgLink() */
  6830. void
  6831. CTriEditParse::fnSaveComment(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  6832. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  6833. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  6834. DWORD /*dwFlags*/)
  6835. {
  6836. UINT ichNewCur = *pichNewCur;
  6837. UINT ichBeginCopy = *pichBeginCopy;
  6838. UINT iArray = *piArrayStart;
  6839. LPWSTR pwNew = *ppwNew;
  6840. UINT iArraySav = iArray;
  6841. UINT iCommentStart, iCommentEnd;
  6842. LPCWSTR rgComment[] =
  6843. {
  6844. L"TRIEDITCOMMENT-",
  6845. L"TRIEDITCOMMENTEND-",
  6846. L"TRIEDITPRECOMMENT-",
  6847. };
  6848. int ichSp, cchComment;
  6849. UINT cbNeed;
  6850. // REMOVE METADATA from here, we don't need it because we are checking for end
  6851. // of comment too.
  6852. ASSERT(pTokArray[iArray].token.tok == TokTag_BANG);
  6853. ASSERT(pTokArray[iArray].token.tokClass == tokTag);
  6854. // early return cases
  6855. // 1. see if this is a comment or not. It could be anything that starts with '<!'
  6856. // e.g. <!DOCTYPE
  6857. if ( (iArray+1 < (INT)ptep->m_cMaxToken)
  6858. && (pwOld[pTokArray[iArray+1].token.ibTokMin] == '-')
  6859. && (pwOld[pTokArray[iArray+1].token.ibTokMin+1] == '-')
  6860. && (pwOld[pTokArray[iArray+1].token.ibTokMin+2] == '[')
  6861. && (pwOld[pTokArray[iArray+1].token.ibTokMin+3] == 'i')
  6862. && (pwOld[pTokArray[iArray+1].token.ibTokMin+3] == 'I')
  6863. && (pwOld[pTokArray[iArray+1].token.ibTokMin+4] == 'f')
  6864. && (pwOld[pTokArray[iArray+1].token.ibTokMin+4] == 'F')
  6865. )
  6866. {
  6867. iCommentStart = iArray; // this is a comment we are interested in
  6868. }
  6869. else
  6870. {
  6871. iArray = iArraySav + 1; // not this one
  6872. goto LRet;
  6873. }
  6874. iCommentEnd = iArray + 2;
  6875. ASSERT(iCommentEnd < (INT)ptep->m_cMaxToken);
  6876. if ( pTokArray[iCommentEnd].token.tok != TokTag_CLOSE
  6877. && pTokArray[iCommentEnd].token.tokClass != tokTag)
  6878. {
  6879. // we have found something that looks like a comment to begin with, but its
  6880. // something else like a DTC, webbot stuff or some thing else...
  6881. iArray = iArraySav + 1; // not this one
  6882. goto LRet;
  6883. }
  6884. // write the spacing info, reallocate pwNew if needed
  6885. cchComment = pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin;
  6886. cbNeed = (ichNewCur+2*cchComment+wcslen(rgComment[0])+wcslen(rgComment[1])+(pTokArray[iCommentStart].token.ibTokMac-ichBeginCopy+2))*sizeof(WCHAR)+cbBufPadding;
  6887. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6888. goto LRet;
  6889. // write till '<!--' part of the comment
  6890. memcpy( (BYTE *)&pwNew[ichNewCur],
  6891. (BYTE *)&pwOld[ichBeginCopy],
  6892. (pTokArray[iCommentStart].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  6893. ichNewCur += pTokArray[iCommentStart].token.ibTokMac-ichBeginCopy;
  6894. pwNew[ichNewCur++] = '-';
  6895. pwNew[ichNewCur++] = '-';
  6896. // write the spacing info keyword
  6897. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)rgComment[0], wcslen(rgComment[0])*sizeof(WCHAR));
  6898. ichNewCur += wcslen(rgComment[0]);
  6899. //write spacing block
  6900. ichSp = pTokArray[iCommentStart+1].token.ibTokMin+2; // exclude -- from <!--comment
  6901. while (ichSp < (int)(pTokArray[iCommentStart+1].token.ibTokMac-2))// exclude -- from comment-->
  6902. {
  6903. switch (pwOld[ichSp++])
  6904. {
  6905. case ' ':
  6906. pwNew[ichNewCur++] = chCommentSp;
  6907. break;
  6908. case '\t':
  6909. pwNew[ichNewCur++] = chCommentTab;
  6910. break;
  6911. case '\r':
  6912. pwNew[ichNewCur++] = chCommentEOL;
  6913. break;
  6914. case '\n':
  6915. break;
  6916. default:
  6917. if (pwNew[ichNewCur-1] != ',')
  6918. pwNew[ichNewCur++] = ',';
  6919. break;
  6920. } // switch()
  6921. }
  6922. // write the spacing info keyword
  6923. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)rgComment[1], wcslen(rgComment[1])*sizeof(WCHAR));
  6924. ichNewCur += wcslen(rgComment[1]);
  6925. //write spacing block for pre comment
  6926. // go back from pwOld[ichSp] and see where we have the last non-white space
  6927. ichSp = pTokArray[iCommentStart].token.ibTokMin-1;
  6928. while ( (ichSp >= 0)
  6929. && ( pwOld[ichSp] == ' ' || pwOld[ichSp] == '\t'
  6930. || pwOld[ichSp] == '\r' || pwOld[ichSp] == '\n'
  6931. )
  6932. )
  6933. {
  6934. ichSp--;
  6935. }
  6936. ichSp++; // compensate because ichSp points to non-white space character at this point
  6937. ASSERT(pTokArray[iCommentStart].token.ibTokMin >= (UINT)ichSp);
  6938. cbNeed = (ichNewCur+2*(pTokArray[iCommentStart].token.ibTokMin-ichSp)+wcslen(rgComment[2]))*sizeof(WCHAR)+cbBufPadding;
  6939. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  6940. goto LRet;
  6941. while (ichSp < (int)(pTokArray[iCommentStart].token.ibTokMin))
  6942. {
  6943. switch (pwOld[ichSp++])
  6944. {
  6945. case ' ':
  6946. pwNew[ichNewCur++] = chCommentSp;
  6947. break;
  6948. case '\t':
  6949. pwNew[ichNewCur++] = chCommentTab;
  6950. break;
  6951. case '\r':
  6952. pwNew[ichNewCur++] = chCommentEOL;
  6953. break;
  6954. case '\n':
  6955. break;
  6956. default:
  6957. if (pwNew[ichNewCur-1] != ',')
  6958. pwNew[ichNewCur++] = ',';
  6959. break;
  6960. } // switch()
  6961. }
  6962. // write the spacing info keyword
  6963. memcpy((BYTE *)&pwNew[ichNewCur], (BYTE *)rgComment[2], wcslen(rgComment[2])*sizeof(WCHAR));
  6964. ichNewCur += wcslen(rgComment[2]);
  6965. // write the comment
  6966. memcpy( (BYTE *)&pwNew[ichNewCur],
  6967. (BYTE *)&pwOld[pTokArray[iCommentStart+1].token.ibTokMin+2],
  6968. (pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2)*sizeof(WCHAR));
  6969. ichNewCur += pTokArray[iCommentStart+1].token.ibTokMac-pTokArray[iCommentStart+1].token.ibTokMin-2;
  6970. // write the ending '>'
  6971. pwNew[ichNewCur++] = '>'; // alternatively, we could write iCommentEnd'th token
  6972. // set iArray & ichBeginCopy
  6973. iArray = iCommentEnd+1;
  6974. ichBeginCopy = pTokArray[iCommentEnd].token.ibTokMac;
  6975. LRet:
  6976. *pcchNew = ichNewCur;
  6977. *ppwNew = pwNew;
  6978. *pichNewCur = ichNewCur;
  6979. *pichBeginCopy = ichBeginCopy;
  6980. *piArrayStart = iArray;
  6981. return;
  6982. } /* fnSaveComment() */
  6983. void
  6984. CTriEditParse::fnRestoreComment(CTriEditParse* /*ptep*/,
  6985. LPWSTR /*pwOld*/, LPWSTR* /*ppwNew*/, UINT* /*pcchNew*/, HGLOBAL* /*phgNew*/,
  6986. TOKSTRUCT* /*pTokArray*/, UINT* /*piArrayStart*/, FilterTok /*ft*/,
  6987. INT* /*pcHtml*/, UINT* /*pichNewCur*/, UINT* /*pichBeginCopy*/,
  6988. DWORD /*dwFlags*/)
  6989. {
  6990. ASSERT(FALSE); // this case is handled by fnRestoreObject(), so we shouldn't reach here
  6991. return;
  6992. } /* fnRestoreComment() */
  6993. void
  6994. CTriEditParse::fnSaveTextArea(CTriEditParse *ptep, LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew, HGLOBAL *phgNew,
  6995. TOKSTRUCT *pTokArray, UINT *piArrayStart, FilterTok /*ft*/,
  6996. INT* /*pcHtml*/, UINT *pichNewCur, UINT *pichBeginCopy,
  6997. DWORD /*dwFlags*/)
  6998. {
  6999. UINT ichNewCur = *pichNewCur;
  7000. UINT ichBeginCopy = *pichBeginCopy;
  7001. UINT iArray = *piArrayStart;
  7002. LPWSTR pwNew = *ppwNew;
  7003. UINT iArraySav = iArray;
  7004. UINT cbNeed;
  7005. UINT iTextAreaEnd;
  7006. // look for TEXTAREA block and simply copy it into pwNew. Thereby avoiding the
  7007. // space preservation & stuff.
  7008. ASSERT(pTokArray[iArray].token.tok == TokElem_TEXTAREA);
  7009. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  7010. iTextAreaEnd = pTokArray[iArray].iNextprev;
  7011. if (iTextAreaEnd == -1) // we don't have matching </textarea>
  7012. {
  7013. // ignore this case
  7014. iArray = iArraySav + 1;
  7015. goto LRet;
  7016. }
  7017. // NOTE that we don't even need to get get the '<' before the textarea here because we are
  7018. // not doing anything special with them. We simply are going to copy everything inside the
  7019. // textarea to pwNew. So, we start copying from ichBeginCopy and copy till end of the
  7020. // textarea block.
  7021. // get the '>' after the matching end textarea, generally this will be right after iTextAreaEnd
  7022. while (iTextAreaEnd < (int)ptep->m_cMaxToken)
  7023. {
  7024. if ( (pTokArray[iTextAreaEnd].token.tok == TokTag_CLOSE) /* > */
  7025. && (pTokArray[iTextAreaEnd].token.tokClass == tokTag)
  7026. )
  7027. {
  7028. break;
  7029. }
  7030. iTextAreaEnd++;
  7031. }
  7032. if (iTextAreaEnd >= (int)ptep->m_cMaxToken) // error case
  7033. {
  7034. iArray = iArraySav + 1;
  7035. goto LRet;
  7036. }
  7037. // copy the textarea block into pwNew. Make sure that we have enough space in pwNew
  7038. // NOTE - pTokArray[iTextAreaEnd].token.ibTokMac should be larger than ichBeginCopy,
  7039. // but at this point in the game the assert is of no use, because no one is using
  7040. // debug builds (6/10/98)
  7041. if ((int) (pTokArray[iTextAreaEnd].token.ibTokMac-ichBeginCopy) > 0)
  7042. {
  7043. cbNeed = (ichNewCur+pTokArray[iTextAreaEnd].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR)+cbBufPadding;
  7044. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  7045. goto LRet;
  7046. memcpy( (BYTE *)&pwNew[ichNewCur],
  7047. (BYTE *)&pwOld[ichBeginCopy],
  7048. (pTokArray[iTextAreaEnd].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  7049. ichNewCur += (pTokArray[iTextAreaEnd].token.ibTokMac-ichBeginCopy);
  7050. }
  7051. // set iArray & ichBeginCopy
  7052. iArray = iTextAreaEnd+1;
  7053. ichBeginCopy = pTokArray[iTextAreaEnd].token.ibTokMac;
  7054. LRet:
  7055. *pcchNew = ichNewCur;
  7056. *ppwNew = pwNew;
  7057. *pichNewCur = ichNewCur;
  7058. *pichBeginCopy = ichBeginCopy;
  7059. *piArrayStart = iArray;
  7060. return;
  7061. } /* fnSaveTextArea() */
  7062. void
  7063. CTriEditParse::fnRestoreTextArea(CTriEditParse* /*ptep*/,
  7064. LPWSTR /*pwOld*/, LPWSTR* /*ppwNew*/, UINT* /*pcchNew*/, HGLOBAL* /*phgNew*/,
  7065. TOKSTRUCT* /*pTokArray*/, UINT *piArrayStart, FilterTok /*ft*/,
  7066. INT* /*pcHtml*/, UINT* /*pichNewCur*/, UINT* /*pichBeginCopy*/,
  7067. DWORD /*dwFlags*/)
  7068. {
  7069. UINT iArray = *piArrayStart;
  7070. // ideally, (for next version) we should restore the trident-converted &gt's & stuff
  7071. // for now, we are simply going to ignore this tag on the way back from trident
  7072. // NOTE that we never put in designtimesp's in this block, so we souldn't have to look
  7073. // for them here.
  7074. ASSERT(pTokArray[iArray].token.tok == TokElem_TEXTAREA);
  7075. ASSERT(pTokArray[iArray].token.tokClass == tokElem);
  7076. iArray++; // skip this textarea tag
  7077. *piArrayStart = iArray;
  7078. return;
  7079. } /* fnRestoreTextArea() */
  7080. void
  7081. CTriEditParse::FilterHtml(LPWSTR pwOld, LPWSTR* ppwNew, UINT *pcchNew,
  7082. HGLOBAL *phgNew, TOKSTRUCT *pTokArray,
  7083. FilterMode mode, DWORD dwFlags)
  7084. {
  7085. UINT iArray = 0;
  7086. UINT ichNewCur = 0;
  7087. UINT ichBeginCopy = 0;
  7088. HRESULT hr;
  7089. INT index = 0;
  7090. INT iItem;
  7091. INT cItems = 0;
  7092. INT cRuleMid = cRuleMax / 2; // ASSUME that cRuleMax is an even number
  7093. FilterRule fr[cRuleMax] =
  7094. {
  7095. // make sure that modeInput and modeOutput have the matching entries.
  7096. // modeInput entries
  7097. {TokTag_BANG, TokAttrib_STARTSPAN, tokClsIgnore, TokTag_CLOSE, TokAttrib_ENDSPAN, tokClsIgnore, fnSaveDTC},
  7098. {TokTag_SSSOPEN, -1, tokClsIgnore, TokTag_SSSCLOSE, -1, tokClsIgnore, fnSaveSSS},
  7099. {TokTag_START, TokElem_HTML, tokClsIgnore, TokTag_CLOSE, TokElem_HTML, tokClsIgnore, fnSaveHtmlTag},
  7100. {-1, -1, tokEntity, -1, -1, tokEntity, fnSaveNBSP},
  7101. {-1, TokElem_BODY, tokElem, -1, -1, tokClsIgnore, fnSaveHdr},
  7102. {TokTag_END, TokElem_BODY, tokElem, -1, -1, tokClsIgnore, fnSaveFtr},
  7103. {-1, TokTag_START, tokTag, TokTag_CLOSE, -1, tokClsIgnore, fnSaveSpace},
  7104. {TokTag_START, TokElem_OBJECT, tokElem, TokTag_CLOSE, TokElem_OBJECT, tokElem, fnSaveObject},
  7105. {TokTag_START, TokElem_TBODY, tokElem, TokTag_CLOSE, -1, tokTag, fnSaveTbody},
  7106. {-1, TokElem_APPLET, tokElem, -1, -1, -1, fnSaveApplet},
  7107. {TokTag_START, TokElem_A, tokElem, TokTag_CLOSE, TokAttrib_HREF, tokTag, fnSaveAImgLink},
  7108. {-1, TokTag_BANG, tokTag, -1, -1, tokClsIgnore, fnSaveComment},
  7109. {TokTag_START, TokElem_TEXTAREA, tokElem, TokTag_CLOSE, TokElem_TEXTAREA, tokClsIgnore, fnSaveTextArea},
  7110. // modeOutput entries
  7111. {TokTag_START, TokElem_OBJECT, tokClsIgnore, TokTag_CLOSE, TokElem_OBJECT, tokClsIgnore, fnRestoreDTC},
  7112. {TokTag_START, TokElem_SCRIPT, tokClsIgnore, TokTag_CLOSE, TokElem_SCRIPT, tokClsIgnore, fnRestoreSSS},
  7113. {-1, -1, tokClsIgnore, -1, -1, tokClsIgnore, fnRestoreHtmlTag},
  7114. {-1, -1, tokEntity, -1, -1, tokEntity, fnRestoreNBSP},
  7115. {-1, TokElem_BODY, tokElem, -1, -1, tokClsIgnore, fnRestoreHdr},
  7116. {TokTag_END, TokElem_BODY, tokElem, -1, -1, tokClsIgnore, fnRestoreFtr},
  7117. {TokTag_START, TokTag_END, tokSpace, TokTag_CLOSE, -1, tokClsIgnore, fnRestoreSpace},
  7118. {-1, TokTag_BANG, tokTag, TokTag_CLOSE, -1, tokTag, fnRestoreObject},
  7119. {TokTag_START, TokElem_TBODY, tokElem, TokTag_CLOSE, -1, tokTag, fnRestoreTbody},
  7120. {TokTag_START, TokElem_APPLET, tokElem, TokTag_CLOSE, -1, tokTag, fnRestoreApplet},
  7121. {TokTag_START, TokElem_A, tokElem, TokTag_CLOSE, TokAttrib_HREF, tokTag, fnRestoreAImgLink},
  7122. {-1, TokTag_BANG, tokTag, TokTag_CLOSE, -1, tokTag, fnRestoreObject},
  7123. {TokTag_START, TokElem_TEXTAREA, tokElem, TokTag_CLOSE, TokElem_TEXTAREA, tokClsIgnore, fnRestoreTextArea},
  7124. };
  7125. memcpy(m_FilterRule, fr, sizeof(FilterRule)*cRuleMax);
  7126. ASSERT(pwOld != NULL);
  7127. ASSERT(*ppwNew != NULL);
  7128. if (mode == modeInput)
  7129. {
  7130. cItems = m_cDTC + m_cSSSIn + m_cHtml + m_cNbsp + m_cHdr + m_cFtr + m_cObjIn + m_ispInfoIn + m_cAppletIn + m_cAImgLink;
  7131. while (cItems > 0)
  7132. {
  7133. if (iArray >= m_cMaxToken) // this will catch error cases
  7134. break;
  7135. while (iArray < m_cMaxToken)
  7136. {
  7137. // its OK to enumerate the comparison rules, but once we have
  7138. // a lot of rules, this needs to be made into a function
  7139. if (pTokArray[iArray].token.tok == m_FilterRule[0].ft.tokBegin2 && m_cDTC > 0)
  7140. {
  7141. m_cDTC--;
  7142. iItem = 1;
  7143. index = 0;
  7144. break;
  7145. }
  7146. else if ( (m_FilterRule[1].ft.tokBegin2 != -1)
  7147. ? (pTokArray[iArray].token.tok == m_FilterRule[1].ft.tokBegin2 && m_cSSSIn > 0)
  7148. : (pTokArray[iArray].token.tok == m_FilterRule[1].ft.tokBegin && m_cSSSIn > 0)
  7149. )
  7150. {
  7151. m_cSSSIn--;
  7152. iItem = 1;
  7153. index = 1;
  7154. break;
  7155. }
  7156. else if (pTokArray[iArray].token.tok == m_FilterRule[2].ft.tokBegin2 && m_cHtml > 0)
  7157. {
  7158. m_cHtml--;
  7159. iItem = 1;
  7160. index = 2;
  7161. break;
  7162. }
  7163. else if ( m_FilterRule[3].ft.tokBegin == -1
  7164. && m_FilterRule[3].ft.tokBegin2 == -1
  7165. && m_FilterRule[3].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7166. && m_cNbsp > 0)
  7167. {
  7168. m_cNbsp--;
  7169. iItem = 1;
  7170. index = 3;
  7171. break;
  7172. }
  7173. else if (pTokArray[iArray].token.tok == m_FilterRule[4].ft.tokBegin2 && m_cHdr > 0)
  7174. {
  7175. m_cHdr--;
  7176. iItem = 1;
  7177. index = 4;
  7178. break;
  7179. }
  7180. else if ( pTokArray[iArray].token.tok == m_FilterRule[5].ft.tokBegin2
  7181. && pTokArray[iArray-1].token.tok == m_FilterRule[5].ft.tokBegin
  7182. && m_cFtr > 0
  7183. )
  7184. {
  7185. m_cFtr--;
  7186. iItem = 1;
  7187. index = 5;
  7188. break;
  7189. }
  7190. else if ( pTokArray[iArray].token.tok == m_FilterRule[6].ft.tokBegin2
  7191. && m_FilterRule[6].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7192. && m_ispInfoIn > 0
  7193. && (dwFlags & dwPreserveSourceCode)
  7194. )
  7195. {
  7196. cItems++; // to compensate for cItems-- after the pfn() call
  7197. index = 6;
  7198. break;
  7199. }
  7200. else if ( pTokArray[iArray].token.tok == m_FilterRule[7].ft.tokBegin2
  7201. && pTokArray[iArray].token.tokClass == m_FilterRule[7].ft.tokClsBegin
  7202. && pTokArray[iArray-1].token.tok == TokTag_START
  7203. && pTokArray[iArray-1].token.tokClass == tokTag
  7204. && m_cObjIn > 0
  7205. )
  7206. {
  7207. m_cObjIn--;
  7208. iItem = 1;
  7209. index = 7;
  7210. break;
  7211. }
  7212. else if ( pTokArray[iArray].token.tok == m_FilterRule[8].ft.tokBegin2
  7213. && pTokArray[iArray].token.tokClass == m_FilterRule[8].ft.tokClsBegin
  7214. && pTokArray[iArray-1].token.tok == TokTag_START
  7215. && pTokArray[iArray-1].token.tokClass == tokTag
  7216. && (dwFlags & dwPreserveSourceCode)
  7217. )
  7218. {
  7219. cItems++; //to compensate for cItems-- after the pfn() call
  7220. iItem = 1;
  7221. index = 8;
  7222. break;
  7223. }
  7224. else if ( pTokArray[iArray].token.tok == m_FilterRule[9].ft.tokBegin2
  7225. && m_FilterRule[9].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7226. && m_cAppletIn > 0
  7227. )
  7228. {
  7229. cItems++; //to compensate for cItems-- after the pfn() call
  7230. m_cAppletIn--;
  7231. index = 9;
  7232. break;
  7233. }
  7234. else if ( ( pTokArray[iArray].token.tok == m_FilterRule[10].ft.tokBegin2
  7235. || pTokArray[iArray].token.tok == TokElem_IMG
  7236. || pTokArray[iArray].token.tok == TokElem_LINK)
  7237. && m_FilterRule[10].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7238. && m_cAImgLink > 0
  7239. && (pTokArray[iArray-1].token.tok == m_FilterRule[10].ft.tokBegin)
  7240. )
  7241. {
  7242. cItems++; // to compensate for cItems-- after the pfn() call
  7243. index = 10;
  7244. break;
  7245. }
  7246. else if ( pTokArray[iArray].token.tok == m_FilterRule[11].ft.tokBegin2
  7247. && m_FilterRule[11].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7248. )
  7249. {
  7250. cItems++; // to compensate for cItems-- after the pfn() call
  7251. index = 11;
  7252. break;
  7253. }
  7254. else if ( pTokArray[iArray].token.tok == m_FilterRule[12].ft.tokBegin2
  7255. && m_FilterRule[12].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7256. && pTokArray[iArray-1].token.tok == m_FilterRule[12].ft.tokBegin
  7257. && pTokArray[iArray-1].token.tokClass == tokTag
  7258. )
  7259. {
  7260. cItems++; // to compensate for cItems-- after the pfn() call
  7261. index = 12;
  7262. break;
  7263. }
  7264. iArray++;
  7265. }
  7266. if (iArray < m_cMaxToken) // we found a match
  7267. {
  7268. // call that function
  7269. m_FilterRule[index].pfn( this, pwOld, ppwNew, pcchNew, phgNew, pTokArray,
  7270. &iArray, m_FilterRule[index].ft, &iItem,
  7271. &ichNewCur, &ichBeginCopy,
  7272. dwFlags);
  7273. }
  7274. cItems--;
  7275. } // while (cItems > 0)
  7276. }
  7277. else if (mode == modeOutput)
  7278. {
  7279. cItems = m_cObj + m_cSSSOut + m_cHtml + m_cNbsp + m_cHdr + m_cFtr + m_cComment + m_ispInfoOut + m_cAppletOut + m_cAImgLink;
  7280. while (cItems > 0)
  7281. {
  7282. if (iArray >= m_cMaxToken) // this will catch error cases
  7283. break;
  7284. while (iArray < m_cMaxToken)
  7285. {
  7286. // its OK to enumerate the comparison rules, but once we have
  7287. // a lot of rules, this needs to be made into a function
  7288. if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid].ft.tokBegin2
  7289. && pTokArray[iArray-1].token.tok == TokTag_START
  7290. && m_cObj > 0
  7291. )
  7292. {
  7293. m_cObj--;
  7294. index = cRuleMid;
  7295. iItem = m_iControl;
  7296. break;
  7297. }
  7298. else if (pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+1].ft.tokBegin2 && m_cSSSOut > 0)
  7299. {
  7300. m_cSSSOut--;
  7301. iItem = 1;
  7302. index = cRuleMid+1;
  7303. break;
  7304. }
  7305. else if (pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+2].ft.tokBegin2 && m_cHtml > 0)
  7306. {
  7307. m_cHtml--;
  7308. iItem = 1;
  7309. index = cRuleMid+2;
  7310. break;
  7311. }
  7312. else if ( m_FilterRule[cRuleMid+3].ft.tokBegin == -1
  7313. && m_FilterRule[cRuleMid+3].ft.tokBegin2 == -1
  7314. && m_FilterRule[cRuleMid+3].ft.tokClsBegin == tokEntity
  7315. && m_cNbsp > 0)
  7316. {
  7317. m_cNbsp--;
  7318. iItem = 1;
  7319. index = cRuleMid+3;
  7320. break;
  7321. }
  7322. else if (pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+4].ft.tokBegin2 && m_cHdr > 0)
  7323. {
  7324. m_cHdr--;
  7325. iItem = 1;
  7326. index = cRuleMid+4;
  7327. break;
  7328. }
  7329. else if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+5].ft.tokBegin2
  7330. && pTokArray[iArray-1].token.tok == m_FilterRule[cRuleMid+5].ft.tokBegin
  7331. && m_cFtr > 0)
  7332. {
  7333. m_cFtr--;
  7334. iItem = 1;
  7335. index = cRuleMid+5;
  7336. break;
  7337. }
  7338. else if ( ( pTokArray[iArray].token.tokClass == m_FilterRule[cRuleMid+6].ft.tokClsBegin
  7339. || ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+6].ft.tokBegin2
  7340. && pTokArray[iArray].token.tokClass == tokTag
  7341. )
  7342. )
  7343. && (dwFlags & dwPreserveSourceCode)
  7344. )
  7345. {
  7346. index = cRuleMid+6;
  7347. cItems++; // to compensate for cItems-- after the pfn() call
  7348. break;
  7349. }
  7350. else if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+7].ft.tokBegin2
  7351. && pTokArray[iArray].token.tokClass == m_FilterRule[cRuleMid+7].ft.tokClsBegin
  7352. && m_cComment > 0
  7353. )
  7354. {
  7355. m_cComment--;
  7356. iItem = 1;
  7357. index = cRuleMid+7;
  7358. break;
  7359. }
  7360. else if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+8].ft.tokBegin2
  7361. && pTokArray[iArray].token.tokClass == m_FilterRule[cRuleMid+8].ft.tokClsBegin
  7362. && (dwFlags & dwPreserveSourceCode)
  7363. )
  7364. {
  7365. // Note that TBody filtering is tied in with space preservation.
  7366. // In ideal world it shouldn't be, but thats acceptable to the most.
  7367. // If this view changes, we need to add some other designtime attribute
  7368. // along with spacing attributes. This will be somewhat big change than
  7369. // simply adding an attribute because then we need to change the code to
  7370. // start going backwards in the token array in the main loop.
  7371. iItem = 1;
  7372. index = cRuleMid+8;
  7373. cItems++; // to compensate for cItems-- after the pfn() call
  7374. break;
  7375. }
  7376. else if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+9].ft.tokBegin2
  7377. && pTokArray[iArray].token.tokClass == m_FilterRule[cRuleMid+9].ft.tokClsBegin
  7378. && pTokArray[iArray-1].token.tok == m_FilterRule[cRuleMid+9].ft.tokBegin
  7379. && m_cAppletOut > 0
  7380. )
  7381. {
  7382. cItems++; // to compensate for cItems-- after the pfn() call
  7383. m_cAppletOut--;
  7384. index = cRuleMid+9;
  7385. break;
  7386. }
  7387. else if ( ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+10].ft.tokBegin2
  7388. || pTokArray[iArray].token.tok == TokElem_IMG
  7389. || pTokArray[iArray].token.tok == TokElem_LINK)
  7390. && m_FilterRule[cRuleMid+10].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7391. && m_cAImgLink > 0
  7392. && (pTokArray[iArray-1].token.tok == m_FilterRule[cRuleMid+10].ft.tokBegin)
  7393. )
  7394. {
  7395. index = cRuleMid+10;
  7396. cItems++; // to compensate for cItems-- after the pfn() call
  7397. break;
  7398. }
  7399. else if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+11].ft.tokBegin2
  7400. && pTokArray[iArray].token.tokClass == m_FilterRule[cRuleMid+11].ft.tokClsBegin
  7401. )
  7402. {
  7403. // actually, we won't reach here - just a dummy
  7404. cItems++; // to compensate for cItems-- after the pfn() call
  7405. index = cRuleMid+11;
  7406. break;
  7407. }
  7408. else if ( pTokArray[iArray].token.tok == m_FilterRule[cRuleMid+12].ft.tokBegin2
  7409. && m_FilterRule[cRuleMid+12].ft.tokClsBegin == pTokArray[iArray].token.tokClass
  7410. && pTokArray[iArray-1].token.tok == m_FilterRule[cRuleMid+12].ft.tokBegin
  7411. && pTokArray[iArray-1].token.tokClass == tokTag
  7412. )
  7413. {
  7414. cItems++; // to compensate for cItems-- after the pfn() call
  7415. index = cRuleMid+12;
  7416. break;
  7417. }
  7418. iArray++;
  7419. }
  7420. if (iArray < m_cMaxToken) // we found a match
  7421. {
  7422. // call that function
  7423. m_FilterRule[index].pfn( this, pwOld, ppwNew, pcchNew, phgNew, pTokArray,
  7424. &iArray, m_FilterRule[index].ft, &iItem,
  7425. &ichNewCur, &ichBeginCopy,
  7426. dwFlags);
  7427. }
  7428. if (m_fDontDeccItem) // we can do things differently next time
  7429. {
  7430. m_fDontDeccItem = FALSE;
  7431. cItems++;
  7432. }
  7433. cItems--;
  7434. } // while (cItems > 0)
  7435. }
  7436. else
  7437. ASSERT(FALSE);
  7438. if (cItems == 0) // everything ok, copy rest of the doc
  7439. {
  7440. LIncorrectcItems:
  7441. // copy rest of the stuff into pwNew
  7442. /* REALLOCATE pwNew IF NEEDED here use cache value for GlobalSize(*phgNew) and don't forget to update it too */
  7443. if (GlobalSize(*phgNew) < (ichNewCur+pTokArray[m_cMaxToken-1].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR))
  7444. {
  7445. hr = ReallocBuffer( phgNew,
  7446. (ichNewCur+pTokArray[m_cMaxToken-1].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR),
  7447. GMEM_MOVEABLE|GMEM_ZEROINIT);
  7448. if (hr == E_OUTOFMEMORY)
  7449. goto LCopyAndRet;
  7450. ASSERT(*phgNew != NULL);
  7451. *ppwNew = (WCHAR *)GlobalLock(*phgNew);
  7452. }
  7453. memcpy( (BYTE *)(*ppwNew+ichNewCur),
  7454. (BYTE *)(pwOld+ichBeginCopy),
  7455. (pTokArray[m_cMaxToken-1].token.ibTokMac-ichBeginCopy)*sizeof(WCHAR));
  7456. ichNewCur += (pTokArray[m_cMaxToken-1].token.ibTokMac-ichBeginCopy);
  7457. *pcchNew = ichNewCur;
  7458. }
  7459. else
  7460. {
  7461. // this means that we calculated one of m_c's incorrectly. We need to fix that
  7462. // case in M4
  7463. goto LIncorrectcItems;
  7464. LCopyAndRet:
  7465. memcpy( (BYTE *)*ppwNew,
  7466. (BYTE *)pwOld,
  7467. (pTokArray[m_cMaxToken-1].token.ibTokMac)*sizeof(WCHAR));
  7468. *pcchNew = pTokArray[m_cMaxToken-1].token.ibTokMac;
  7469. }
  7470. } /* CTriEditParse::FilterHtml() */
  7471. int
  7472. CTriEditParse::ValidateTag(LPWSTR pszText)
  7473. {
  7474. int len = 0;
  7475. if (pszText == NULL)
  7476. return(0);
  7477. // check for the first non Alpha in the pszText and return it. Add '\0' at the end
  7478. while ( (*(pszText+len) >= _T('A') && *(pszText+len) <= _T('Z'))
  7479. || (*(pszText+len) >= _T('a') && *(pszText+len) <= _T('z'))
  7480. || (*(pszText+len) >= _T('0') && *(pszText+len) <= _T('9'))
  7481. )
  7482. {
  7483. len++;
  7484. }
  7485. return(len);
  7486. }
  7487. INT
  7488. CTriEditParse::GetTagID(LPWSTR pszText, TXTB token)
  7489. {
  7490. WCHAR szTag[MAX_TOKIDLEN+1];
  7491. int len;
  7492. int tagID;
  7493. len = ValidateTag(pszText+token.ibTokMin);
  7494. if (len == 0 || len != (int)(token.ibTokMac-token.ibTokMin))
  7495. tagID = -1;
  7496. else
  7497. {
  7498. if (token.tok == 0 && token.tokClass == tokIDENTIFIER)
  7499. tagID = -1;
  7500. else
  7501. {
  7502. memcpy((BYTE *)szTag, (BYTE *)(pszText+token.ibTokMin), (min(len, MAX_TOKIDLEN))*sizeof(WCHAR));
  7503. szTag[min(len, MAX_TOKIDLEN)] = '\0';
  7504. tagID = IndexFromElementName((LPCTSTR) szTag);
  7505. }
  7506. }
  7507. return(tagID);
  7508. }
  7509. void
  7510. CTriEditParse::PreProcessToken(TOKSTRUCT *pTokArray, INT *pitokCur, LPWSTR /*pszText*/,
  7511. UINT /*cbCur*/, TXTB token, DWORD lxs, INT tagID, FilterMode mode)
  7512. {
  7513. TOKSTRUCT *pTokT = pTokArray + *pitokCur;
  7514. if (*pitokCur == -1) // the buffer reallocation must have failed
  7515. goto LSkipArrayOp;
  7516. // if (lxs & inTag) then we can ASSERT(token.tok == TokTag_START)
  7517. //put the new token into pTokArray at *pitokCur position
  7518. pTokT->token = token;
  7519. pTokT->fStart = (lxs & inEndTag)?FALSE:TRUE;
  7520. pTokT->ichStart = token.ibTokMin;
  7521. pTokT->iNextprev = 0xFFFFFFFF; // init value
  7522. pTokT->iNextPrevAlternate = 0xFFFFFFFF; // init value
  7523. pTokT->tagID = tagID;
  7524. if (mode == modeInput)
  7525. {
  7526. if ( pTokT->token.tok == TokTag_SSSOPEN
  7527. && pTokT->token.tokClass == tokSSS
  7528. && ((lxs & inSCRIPT) || (lxs & inAttribute))
  7529. )
  7530. {
  7531. pTokT->token.tok = TokTag_SSSOPEN_TRIEDIT;
  7532. }
  7533. if ( pTokT->token.tok == TokTag_SSSCLOSE
  7534. && pTokT->token.tokClass == tokSSS
  7535. && ((lxs & inSCRIPT) || (lxs & inAttribute))
  7536. )
  7537. {
  7538. pTokT->token.tok = TokTag_SSSCLOSE_TRIEDIT;
  7539. }
  7540. }
  7541. *pitokCur += 1;
  7542. LSkipArrayOp:
  7543. return;
  7544. } /* CTriEditParse::PreProcessToken() */
  7545. // Handle special cases of replacing things and saving the replaced contents
  7546. void
  7547. CTriEditParse::PostProcessToken(OLECHAR* /*pwOld*/, OLECHAR* /*pwNew*/, UINT* /*pcbNew*/,
  7548. UINT /*cbCur*/, UINT /*cbCurSav*/, TXTB token,
  7549. FilterMode mode, DWORD lxs, DWORD dwFlags)
  7550. {
  7551. // handle special cases of replacing the DTCs, ServerSideScripts etc.
  7552. // save the contents into a buffer if (mode == modeInput)
  7553. // put the contents back into buffer if (mode == modeOutput)
  7554. if (mode == modeInput)
  7555. {
  7556. if ( token.tok == TokAttrib_ENDSPAN
  7557. && token.tokClass == tokAttr
  7558. && (dwFlags & (dwFilterDTCs | dwFilterDTCsWithoutMetaTags))
  7559. )
  7560. {
  7561. m_cDTC++;
  7562. }
  7563. if ( token.tok == TokTag_SSSCLOSE
  7564. && token.tokClass == tokSSS
  7565. && !(lxs & inAttribute) // !(lxs & inValue && lxs & inTag)
  7566. && !(lxs & inSCRIPT)
  7567. && (dwFlags & dwFilterServerSideScripts)
  7568. )
  7569. {
  7570. m_cSSSIn++;
  7571. }
  7572. if ( token.tokClass == tokEntity
  7573. && dwFlags != dwFilterNone
  7574. )
  7575. {
  7576. m_cNbsp++;
  7577. }
  7578. if ( (token.tok == TokElem_OBJECT)
  7579. && (token.tokClass == tokElem)
  7580. && (lxs & inEndTag)
  7581. && (dwFlags != dwFilterNone)
  7582. )
  7583. {
  7584. m_cObjIn++;
  7585. }
  7586. if ( token.tok == TokElem_APPLET
  7587. && token.tokClass == tokElem
  7588. && (lxs & inEndTag)
  7589. && (dwFlags != dwFilterNone)
  7590. )
  7591. {
  7592. m_cAppletIn++;
  7593. }
  7594. }
  7595. else if (mode == modeOutput)
  7596. {
  7597. if ( token.tok == TokElem_OBJECT
  7598. && token.tokClass == tokElem
  7599. && (lxs & inTag && !(lxs & inEndTag))
  7600. && (dwFlags & (dwFilterDTCs | dwFilterDTCsWithoutMetaTags))
  7601. )
  7602. {
  7603. m_cObj++;
  7604. }
  7605. if ( token.tok == TokElem_SCRIPT
  7606. && token.tokClass == tokElem
  7607. && (lxs & inEndTag)
  7608. && (dwFlags & dwFilterServerSideScripts)
  7609. )
  7610. {
  7611. m_cSSSOut++;
  7612. }
  7613. if ( token.tok == TokTag_BANG
  7614. && token.tokClass == tokTag
  7615. )
  7616. {
  7617. m_cComment++;
  7618. }
  7619. if ( token.tok == TokElem_APPLET
  7620. && token.tokClass == tokElem
  7621. && (lxs & inEndTag)
  7622. && (dwFlags != dwFilterNone)
  7623. )
  7624. {
  7625. m_cAppletOut++;
  7626. }
  7627. }
  7628. } /* CTriEditParse::PostProcessToken() */
  7629. HRESULT
  7630. CTriEditParse::ProcessToken(DWORD &lxs, TXTB &tok, LPWSTR pszText,
  7631. UINT /*cbCur*/, TOKSTACK *pTokStack, INT *pitokTop,
  7632. TOKSTRUCT *pTokArray, INT iArrayPos, INT tagID)
  7633. {
  7634. TXTB token = tok;
  7635. if (*pitokTop == -1) // the buffer reallocation must have failed
  7636. goto LSkipStackOp;
  7637. if (lxs & inEndTag) // end tag begins, set m_fEndTagFound
  7638. m_fEndTagFound = TRUE;
  7639. if (tagID == -1) // we need to put only the IDENTIFIERS on the stack
  7640. {
  7641. // special cases (1)<%, (2)%>, (3)startspan, (4)endspan
  7642. if (token.tok == TokTag_SSSOPEN && token.tokClass == tokSSS /*&& !(lxs & inAttribute)*/) // <%
  7643. {
  7644. token.tok = TokTag_SSSCLOSE; // fake it so that we can use the same code for matching %>
  7645. goto LSpecialCase;
  7646. }
  7647. else if (token.tok == TokTag_SSSCLOSE && token.tokClass == tokSSS /*&& !(lxs & inAttribute)*/) // %>
  7648. {
  7649. m_fEndTagFound = TRUE; // lxs is not inEndTag when we get TokTag_SSSCLOSE
  7650. goto LSpecialCase;
  7651. }
  7652. else if (token.tok == TokAttrib_STARTSPAN && token.tokClass == tokAttr) // startspan
  7653. {
  7654. token.tok = TokAttrib_ENDSPAN; // fake it so that we can use the same code for matching endspan
  7655. goto LSpecialCase;
  7656. }
  7657. else if (token.tok == TokAttrib_ENDSPAN && token.tokClass == tokAttr) // endspan
  7658. {
  7659. LPCWSTR szDesignerControl[] =
  7660. {
  7661. L"\"DesignerControl\"",
  7662. L"DesignerControl",
  7663. };
  7664. // HACK to fix FrontPage BUG - DaVinci puts a dummy endspan & startspan between
  7665. // the "DESIGNERCONTROL" startspan-endspan pair. We want to make sure that
  7666. // our pTokArray has correct matching iNextprev for the TokAttrib_STARTSPAN
  7667. // Refer VID bug 3991
  7668. if ( (iArrayPos-3 >= 0) /* validation */
  7669. && ( 0 == _wcsnicmp(szDesignerControl[0], &pszText[pTokArray[iArrayPos-3].token.ibTokMin], wcslen(szDesignerControl[0]))
  7670. || 0 == _wcsnicmp(szDesignerControl[1], &pszText[pTokArray[iArrayPos-3].token.ibTokMin], wcslen(szDesignerControl[1]))
  7671. )
  7672. )
  7673. {
  7674. m_fEndTagFound = TRUE; // lxs is not inEndTag when we get TokAttrib_ENDSPAN
  7675. goto LSpecialCase;
  7676. }
  7677. else
  7678. goto LSkipStackOp;
  7679. }
  7680. else
  7681. {
  7682. if (m_fEndTagFound)
  7683. m_fEndTagFound = FALSE;
  7684. goto LSkipStackOp;
  7685. }
  7686. }
  7687. LSpecialCase:
  7688. if (m_fEndTagFound) // end tag was found previously, means pop from the stack
  7689. {
  7690. TOKSTACK *pTokT;
  7691. if (*pitokTop == 0) // we don't have anything on stack, we can't delete it
  7692. goto LSkipStackOp;
  7693. pTokT = pTokStack + *pitokTop - 1;
  7694. m_fEndTagFound = FALSE; // reset
  7695. // if we get an end tag, in ideal case, the top of the stack should
  7696. // match with what we got
  7697. if (tagID == pTokT->tagID)
  7698. {
  7699. if (tagID == -1) // special case, match token.tok & token.tokClass
  7700. {
  7701. if ( (pTokT->token.tok == TokTag_SSSCLOSE) /* faked token for <% */
  7702. && (pTokT->token.tokClass == tokSSS)
  7703. )
  7704. {
  7705. ASSERT(token.tok == TokTag_SSSCLOSE);
  7706. goto LMatch;
  7707. }
  7708. else if ( (pTokT->token.tok == TokAttrib_ENDSPAN) /* faked token for startspan */
  7709. && (pTokT->token.tokClass == tokAttr)
  7710. )
  7711. {
  7712. ASSERT(token.tok == TokAttrib_ENDSPAN);
  7713. goto LMatch;
  7714. }
  7715. else // we may have found another special case
  7716. {
  7717. goto LNoMatch;
  7718. }
  7719. }
  7720. LMatch:
  7721. ASSERT(iArrayPos - 1 >= 0);
  7722. // put iNextPrev or INextPrevAlternate for the matching start token in pTokArray
  7723. pTokArray[pTokT->iMatch].iNextprev = iArrayPos - 1;
  7724. ASSERT(pTokArray[pTokT->iMatch].fStart == TRUE);
  7725. ASSERT(pTokT->ichStart == pTokArray[pTokT->iMatch].token.ibTokMin);
  7726. pTokArray[iArrayPos-1].iNextprev = pTokT->iMatch;
  7727. ASSERT(*pitokTop >= 0);
  7728. *pitokTop -= 1; // pop the stack
  7729. }
  7730. else
  7731. {
  7732. LNoMatch:
  7733. int index;
  7734. // look for the first entry down the array that matches
  7735. index = *pitokTop - 1;
  7736. while (index >= 0)
  7737. {
  7738. if (tagID == (pTokStack+index)->tagID)
  7739. {
  7740. if (tagID == -1) // special case
  7741. {
  7742. if ( ( ((pTokStack+index)->token.tok == TokTag_SSSCLOSE) /* faked token for <% */
  7743. && ((pTokStack+index)->token.tokClass == tokSSS)
  7744. && (token.tok == TokTag_SSSCLOSE)
  7745. && (token.tokClass == tokSSS)
  7746. )
  7747. || ( ((pTokStack+index)->token.tok == TokAttrib_ENDSPAN) /* faked token for startspan */
  7748. && ((pTokStack+index)->token.tokClass == tokAttr)
  7749. && (token.tok == TokAttrib_ENDSPAN)
  7750. && (token.tokClass == tokAttr)
  7751. )
  7752. )
  7753. break;
  7754. //else actually, this means error case.
  7755. }
  7756. else
  7757. break;
  7758. }
  7759. index--;
  7760. }
  7761. if (index != -1) // match was found at index'th position on the stack
  7762. {
  7763. int i;
  7764. TOKSTACK *pTokIndex = pTokStack + index;
  7765. ASSERT(index >= 0);
  7766. ASSERT(iArrayPos - 1 >= 0);
  7767. if (tagID == -1) // special case, match token.tok & token.tokClass
  7768. {
  7769. ASSERT( ( (pTokIndex->token.tok == TokTag_SSSCLOSE) /* faked token for <% */
  7770. && (pTokIndex->token.tokClass == tokSSS)
  7771. && (token.tok == TokTag_SSSCLOSE)
  7772. && (token.tokClass == tokSSS)
  7773. )
  7774. || ( ((pTokStack+index)->token.tok == TokAttrib_ENDSPAN) /* faked token for startspan */
  7775. && ((pTokStack+index)->token.tokClass == tokAttr)
  7776. && (token.tok == TokAttrib_ENDSPAN)
  7777. && (token.tokClass == tokAttr)
  7778. )
  7779. );
  7780. }
  7781. // first of all fill in appropriate iNextprev
  7782. pTokArray[pTokIndex->iMatch].iNextprev = iArrayPos - 1;
  7783. ASSERT(pTokArray[pTokIndex->iMatch].fStart == TRUE);
  7784. pTokArray[iArrayPos-1].iNextprev = pTokIndex->iMatch;
  7785. // now fill in iNextPrevAlternate for all elements from index to *pitokTop - 1
  7786. for (i = index+1; i <= *pitokTop - 1; i++)
  7787. {
  7788. TOKSTACK *pTokSkip = pTokStack + i;
  7789. pTokArray[pTokSkip->iMatch].iNextPrevAlternate = iArrayPos - 1;
  7790. ASSERT(pTokArray[pTokSkip->iMatch].fStart == TRUE);
  7791. ASSERT(pTokArray[pTokSkip->iMatch].iNextprev == -1);
  7792. } // for ()
  7793. // decrement the stack appropriately
  7794. *pitokTop = index;
  7795. } // else
  7796. } // of if (tagID == pTokT->tagID)
  7797. } // end of if (lxs & inEndTag)
  7798. else // push the token info on the stack
  7799. {
  7800. TOKSTACK *pTokT = pTokStack + *pitokTop;
  7801. ASSERT(iArrayPos - 1 >= 0);
  7802. //push the new token into pTokArray at *pitokCur position
  7803. pTokT->iMatch = iArrayPos - 1;
  7804. pTokT->tagID = tagID;
  7805. pTokT->ichStart = token.ibTokMin;
  7806. pTokT->token = token; // note that this isused ONLY in special cases where tagID is -1
  7807. *pitokTop += 1;
  7808. } //end of else case of if (lxs & inEndTag)
  7809. LSkipStackOp:
  7810. return NOERROR;
  7811. }
  7812. // This function does following
  7813. // (a) reads the stream
  7814. // (b) generates tokens
  7815. // (c) allocates a buffer that holds replaced elements like DTCs
  7816. // (d) does the parsing of the tokens to build a not-so-tree tree of tokens
  7817. // (e) returns the not-so-tree tree of tokens
  7818. // VK 5/19/99: Replaced dwReserved with dwSpecialize.
  7819. // This can currently take PARSE_SPECIAL_HEAD_ONLY to terminate parsing at the <BODY>
  7820. HRESULT CTriEditParse::hrTokenizeAndParse(HGLOBAL hOld, HGLOBAL *phNew, IStream *pStmNew,
  7821. DWORD dwFlags, FilterMode mode,
  7822. int cbSizeIn, UINT *pcbSizeOut, IUnknown *pUnkTrident,
  7823. HGLOBAL *phgTokArray, UINT *pcMaxToken,
  7824. HGLOBAL *phgDocRestore, BSTR bstrBaseURL, DWORD dwSpecialize)
  7825. {
  7826. // FilterRule structure initilization - move this at apporpriate place
  7827. LPSTR pOld, pNew;
  7828. UINT cbOld = 0;
  7829. UINT cbwOld, cchwOld; // number of bytes & chars in the converted unicode string
  7830. UINT cchNew = 0; // number of unicode chars in the new (after filtering) buffer
  7831. HRESULT hrRet = S_OK;
  7832. HGLOBAL hgNew, hgOld, hgTokStack;
  7833. WCHAR *pwOld, *pwNew;
  7834. UINT cbCur = 0; // This is actually the current character position
  7835. TOKSTRUCT *pTokArray;
  7836. TOKSTACK *pTokStack;
  7837. INT itokTop = 0;
  7838. INT itokCur = 0;
  7839. TXTB token;
  7840. INT cStackMax, cArrayMax;
  7841. DWORD lxs = 0;
  7842. INT tagID;
  7843. BOOL fAllocDocRestore = FALSE; // did we allocate *phgDocRestore locally? (Y/N)
  7844. BOOL fUsePstmNew = (dwFlags & dwFilterUsePstmNew);
  7845. HGLOBAL hgPstm = NULL;
  7846. ULARGE_INTEGER li;
  7847. UINT cbT = 0;
  7848. BOOL fBeginTokSelect; // used by special case code that detects server side scripts inside a SELECT block
  7849. BOOL fBeginTokTextarea; // used by special case code that detects server side scripts inside a TEXTAREA block
  7850. BOOL fBeginTokLabel; // used by special case code that detects server side scripts inside a LABEL block
  7851. BOOL fBeginTokListing; // used by special case code that detects server side scripts inside a LISTING block
  7852. BOOL fInDTCOutput, fInDTC;
  7853. #ifdef DEBUG
  7854. DWORD dwErr;
  7855. #endif // DEBUG
  7856. ASSERT((PARSE_SPECIAL_NONE == dwSpecialize) || (PARSE_SPECIAL_HEAD_ONLY == dwSpecialize));
  7857. if ( PARSE_SPECIAL_HEAD_ONLY & dwSpecialize )
  7858. ASSERT ( dwFlags == dwFilterNone );
  7859. // NOTE
  7860. // this could be done another way. We can make m_pUnkTrident public member and set its value
  7861. // at the point where the CTriEditParse object is created. But this looks fine too.
  7862. m_pUnkTrident = pUnkTrident; // we cache this for our use.
  7863. m_fUnicodeFile = FALSE;
  7864. m_bstrBaseURL = bstrBaseURL;
  7865. li.LowPart = li.HighPart = 0;
  7866. // Initialize PTDTC related members
  7867. if (mode == modeInput)
  7868. {
  7869. m_fInHdrIn = TRUE;
  7870. }
  7871. if (fUsePstmNew)
  7872. li.LowPart = li.HighPart = 0;
  7873. // initialize <TBODY> related members
  7874. m_hgTBodyStack = NULL;
  7875. m_pTBodyStack = NULL;
  7876. m_iMaxTBody = m_iTBodyMax = 0;
  7877. // initilize members used by PageTransitionDTC
  7878. if (mode == modeInput)
  7879. {
  7880. m_ichPTDTC = m_cchPTDTCObj = m_cchPTDTC = 0;
  7881. m_indexBeginBody = m_indexEndBody = 0;
  7882. m_hgPTDTC = m_pPTDTC = NULL;
  7883. }
  7884. else
  7885. {
  7886. ASSERT(m_hgPTDTC == NULL); // make sure that it was freed (if we allocated it in modeInput case)
  7887. }
  7888. if (mode == modeInput)
  7889. {
  7890. m_fHasTitleIn = FALSE;
  7891. m_indexTitleIn = -1;
  7892. m_ichTitleIn = -1;
  7893. m_cchTitleIn = -1;
  7894. m_ichBeginBodyTagIn = -1;
  7895. m_ichBeginHeadTagIn = -1;
  7896. m_indexHttpEquivIn = -1;
  7897. }
  7898. //initilize fBeginTokSelect (used by special case code that
  7899. // detects server side scripts inside a SELECT block)
  7900. fBeginTokSelect = fBeginTokTextarea = fBeginTokLabel = fBeginTokListing = FALSE;
  7901. fInDTCOutput = fInDTC = FALSE;
  7902. pOld = (LPSTR) GlobalLock(hOld);
  7903. if (cbSizeIn == -1)
  7904. cbOld = SAFE_INT64_TO_DWORD(GlobalSize(hOld));
  7905. else
  7906. cbOld = cbSizeIn;
  7907. if (cbOld == 0) // zero sized file
  7908. {
  7909. if (pcbSizeOut)
  7910. *pcbSizeOut = 0;
  7911. hrRet = E_OUTOFMEMORY;
  7912. *pcMaxToken = 0;
  7913. if (fUsePstmNew)
  7914. pStmNew->SetSize(li);
  7915. else
  7916. *phNew = NULL;
  7917. *phgTokArray = NULL;
  7918. goto LRetOnly;
  7919. }
  7920. hgNew = hgOld = hgTokStack = NULL;
  7921. if (*((BYTE *)pOld) == 0xff && *((BYTE *)pOld+1) == 0xfe)
  7922. {
  7923. m_fUnicodeFile = TRUE;
  7924. if (dwFlags & dwFilterMultiByteStream)
  7925. dwFlags &= ~dwFilterMultiByteStream;
  7926. }
  7927. // allocate a buffer that will hold token structs. This is returned
  7928. *phgTokArray = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, MIN_TOK*sizeof(TOKSTRUCT)); // stack
  7929. if (*phgTokArray == NULL)
  7930. {
  7931. hrRet = E_OUTOFMEMORY;
  7932. goto LOOM;
  7933. }
  7934. pTokArray = (TOKSTRUCT *) GlobalLock(*phgTokArray);
  7935. ASSERT(pTokArray != NULL);
  7936. cArrayMax = MIN_TOK;
  7937. // allocate temporary buffers that for the current & filtered html documents
  7938. hgTokStack = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, MIN_TOK*sizeof(TOKSTRUCT)); // stack
  7939. if (hgTokStack == NULL)
  7940. {
  7941. hrRet = E_OUTOFMEMORY;
  7942. goto LOOM;
  7943. }
  7944. pTokStack = (TOKSTACK *) GlobalLock(hgTokStack);
  7945. ASSERT(pTokStack != NULL);
  7946. cStackMax = MIN_TOK;
  7947. // In most cases for NON-UNICODE streams,
  7948. // (cbOld+1/*for NULL*/)*sizeof(WCHAR) will endup being lot more than what we need
  7949. hgOld = GlobalAlloc(GMEM_ZEROINIT, (dwFlags & dwFilterMultiByteStream)
  7950. ? (cbOld+1/*for NULL*/)*sizeof(WCHAR)
  7951. : (cbOld+2/*for NULL*/));
  7952. if (hgOld == NULL)
  7953. {
  7954. hrRet = E_OUTOFMEMORY;
  7955. goto LOOM;
  7956. }
  7957. pwOld = (WCHAR *) GlobalLock(hgOld);
  7958. ASSERT(pwOld != NULL);
  7959. // we could just allocate cbOld bytes in modeInput and modeOutput.
  7960. // But reallocs are expensive and in both cases, we will grow by some bytes
  7961. // if we have DTCs and/or SSSs.
  7962. if (dwFlags & dwFilterNone) // the caller has called this function only for tokenizing
  7963. {
  7964. if (dwFlags & dwFilterMultiByteStream)
  7965. cbT = (cbOld+1/*for NULL*/)*sizeof(WCHAR); // this will be bigger than what we need.
  7966. else
  7967. cbT = cbOld + sizeof(WCHAR); // for NULL
  7968. }
  7969. else
  7970. {
  7971. if (dwFlags & dwFilterMultiByteStream)
  7972. cbT = (cbOld+1)*sizeof(WCHAR) + cbBufPadding;
  7973. else
  7974. cbT = cbOld + cbBufPadding; // no need to add +2
  7975. }
  7976. hgNew = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cbT);
  7977. if (hgNew == NULL)
  7978. {
  7979. hrRet = E_OUTOFMEMORY;
  7980. goto LOOM;
  7981. }
  7982. pwNew = (WCHAR *) GlobalLock(hgNew);
  7983. ASSERT(pwNew != NULL);
  7984. // buffer to save all contents before/after <BODY> tag
  7985. m_hgDocRestore = phgDocRestore ? *phgDocRestore : NULL;
  7986. if (m_hgDocRestore == NULL)
  7987. {
  7988. fAllocDocRestore = TRUE;
  7989. m_hgDocRestore = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cbHeader);
  7990. if (m_hgDocRestore == NULL)
  7991. {
  7992. hrRet = E_OUTOFMEMORY;
  7993. goto LOOM;
  7994. }
  7995. }
  7996. // at this point we know that m_hgDocRestore is not going to be null, but lets be cautious
  7997. // we call FilterIn only once when we load the document. (bug 15393)
  7998. if (m_hgDocRestore != NULL && mode == modeInput)
  7999. {
  8000. WCHAR *pwDocRestore;
  8001. DWORD cbDocRestore;
  8002. // lock
  8003. pwDocRestore = (WCHAR *) GlobalLock(m_hgDocRestore);
  8004. // fill with zeros
  8005. cbDocRestore = SAFE_INT64_TO_DWORD(GlobalSize(m_hgDocRestore));
  8006. memset((BYTE *)pwDocRestore, 0, cbDocRestore);
  8007. // unlock
  8008. GlobalUnlock(m_hgDocRestore);
  8009. }
  8010. m_fEndTagFound = FALSE; // initialize
  8011. m_cMaxToken = m_cDTC = m_cObj = m_cSSSIn = m_cSSSOut = m_cNbsp = m_iControl = m_cComment = m_cObjIn = 0;
  8012. m_cAppletIn = m_cAppletOut = 0;
  8013. m_fSpecialSSS = FALSE;
  8014. m_cHtml = (mode == modeInput)? 0 : 0; // assume that we atleast have one <HTML> tag in modeInput case
  8015. m_cHdr = m_cFtr = m_cAImgLink = 1;
  8016. m_pspInfoCur = m_pspInfo = m_pspInfoOut = m_pspInfoOutStart = NULL;
  8017. m_hgspInfo = NULL;
  8018. m_ichStartSP = 0;
  8019. if (dwFlags & dwPreserveSourceCode)
  8020. {
  8021. m_ispInfoIn = (mode == modeInput)? 1 : 0;
  8022. m_ispInfoOut = (mode == modeOutput)? 1 : 0;
  8023. if (mode == modeInput)
  8024. {
  8025. srand((unsigned)time(NULL));
  8026. m_ispInfoBase = rand();
  8027. if (0x0fffffff-m_ispInfoBase < 0x000fffff)
  8028. m_ispInfoBase = 0;
  8029. }
  8030. }
  8031. else
  8032. {
  8033. m_ispInfoIn = 0;
  8034. m_ispInfoOut = 0;
  8035. }
  8036. m_iArrayspLast = 0;
  8037. m_ispInfoBlock = 0; // index of the block. stored as value of DESIGNTIMESPx tag
  8038. m_cchspInfoTotal = 0;
  8039. m_fDontDeccItem = FALSE; // we can do this differently next time
  8040. // if we have multiple of these tags, we need to warn the user before going to design view
  8041. // and not let the user switch views (bug 18474)
  8042. m_cBodyTags = m_cHtmlTags = m_cTitleTags = m_cHeadTags = 0;
  8043. if (dwFlags & dwFilterMultiByteStream)
  8044. {
  8045. // note that cbOld is actually number of characters in single byte world
  8046. cchwOld = MultiByteToWideChar(CP_ACP, 0, pOld, (cbSizeIn==-1)?-1:cbOld, NULL, 0);
  8047. MultiByteToWideChar(CP_ACP, 0, pOld, (cbSizeIn==-1)?-1:cbOld, pwOld, cchwOld);
  8048. }
  8049. else
  8050. {
  8051. memcpy((BYTE *)pwOld, (BYTE *)pOld, cbOld); // we are already UNICODE
  8052. // Assume that in UNICODE world we can simply divide cbOld by sizeof(WCHAR)
  8053. cchwOld = cbOld/sizeof(WCHAR);
  8054. }
  8055. *(pwOld+cchwOld) = '\0';
  8056. // get the token & save it into a buffer
  8057. cbwOld = cchwOld * sizeof(WCHAR);
  8058. while (cbCur < cchwOld)
  8059. {
  8060. UINT cbCurSav = cbCur;
  8061. NextToken(pwOld, cchwOld, &cbCur, &lxs, &token);
  8062. tagID = GetTagID(pwOld, token); // only if inAttribute & inTag ????
  8063. // if we have more of any of these tags, Trident removes them, so lets warn the user and
  8064. // not the user go to design view (bug 18474)
  8065. if ( (mode == modeInput)
  8066. && (token.tokClass == tokElem)
  8067. && (lxs & inTag)
  8068. && !(lxs & inEndTag) /* this may be redundant, but having it does no harm */
  8069. )
  8070. {
  8071. switch (token.tok)
  8072. {
  8073. case TokElem_BODY:
  8074. m_cBodyTags++;
  8075. break;
  8076. case TokElem_HTML:
  8077. m_cHtmlTags++;
  8078. break;
  8079. case TokElem_TITLE:
  8080. m_cTitleTags++;
  8081. break;
  8082. case TokElem_HEAD:
  8083. m_cHeadTags++;
  8084. break;
  8085. };
  8086. if (m_cBodyTags > 1 || m_cHtmlTags > 1 || m_cTitleTags > 1 || m_cHeadTags > 1)
  8087. {
  8088. // skip tokenizing. we can't let this go to Trident
  8089. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8090. cchNew = cchwOld;
  8091. hrRet = E_FILTER_MULTIPLETAGS;
  8092. goto LSkipTokFilter;
  8093. }
  8094. }
  8095. if ( (token.tokClass == tokElem)
  8096. && ( (token.tok == TokElem_FRAME)
  8097. || (token.tok == TokElem_FRAMESET)
  8098. )
  8099. )
  8100. {
  8101. // skip tokenizing. we can't let this go to Trident
  8102. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8103. cchNew = cchwOld;
  8104. hrRet = E_FILTER_FRAMESET;
  8105. goto LSkipTokFilter;
  8106. }
  8107. if ( (token.tok == TokTag_SSSOPEN)
  8108. && (token.tokClass == tokSSS)
  8109. && (lxs & inAttribute)
  8110. && !(lxs & inString)
  8111. && !(lxs & inStringA)
  8112. && !(fInDTCOutput)
  8113. && (mode == modeInput)
  8114. )
  8115. {
  8116. // skip tokenizing. we can't let this go to Trident
  8117. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8118. cchNew = cchwOld;
  8119. hrRet = E_FILTER_SERVERSCRIPT;
  8120. goto LSkipTokFilter;
  8121. }
  8122. if ( (token.tok == 0)
  8123. && (token.tokClass == tokSSS)
  8124. && (lxs & inTag)
  8125. && (lxs & inHTXTag)
  8126. && (lxs & inAttribute)
  8127. && (lxs & inString || lxs & inStringA)
  8128. && (lxs & inNestedQuoteinSSS)
  8129. && !(fInDTCOutput)
  8130. )
  8131. {
  8132. // skip tokenizing. we can't let this go to Trident
  8133. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8134. cchNew = cchwOld;
  8135. hrRet = E_FILTER_SERVERSCRIPT;
  8136. goto LSkipTokFilter;
  8137. }
  8138. // REVIEW TODO LATER - For all following special cases, we need to add !fInDTCOutput
  8139. if ( (fBeginTokSelect)
  8140. && (token.tok == TokTag_SSSOPEN || token.tok == TokElem_SCRIPT)
  8141. )
  8142. {
  8143. // skip tokenizing. we can't let this go to Trident
  8144. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8145. cchNew = cchwOld;
  8146. hrRet = E_FILTER_SCRIPTSELECT;
  8147. goto LSkipTokFilter;
  8148. }
  8149. if ( (fBeginTokTextarea)
  8150. && (token.tok == TokTag_SSSOPEN && token.tokClass == tokSSS)
  8151. )
  8152. {
  8153. // skip tokenizing. we can't let this go to Trident
  8154. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8155. cchNew = cchwOld;
  8156. hrRet = E_FILTER_SCRIPTTEXTAREA;
  8157. goto LSkipTokFilter;
  8158. }
  8159. if ( (fBeginTokLabel)
  8160. && (token.tok == TokTag_SSSOPEN && token.tokClass == tokSSS)
  8161. )
  8162. {
  8163. // skip tokenizing. we can't let this go to Trident
  8164. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8165. cchNew = cchwOld;
  8166. hrRet = E_FILTER_SCRIPTLABEL;
  8167. goto LSkipTokFilter;
  8168. }
  8169. if ( (fBeginTokListing)
  8170. && (token.tok == TokTag_SSSOPEN && token.tokClass == tokSSS)
  8171. )
  8172. {
  8173. // skip tokenizing. we can't let this go to Trident
  8174. memcpy((BYTE *)pwNew, (BYTE *)pwOld, cchwOld*sizeof(WCHAR));
  8175. cchNew = cchwOld;
  8176. hrRet = E_FILTER_SCRIPTLISTING;
  8177. goto LSkipTokFilter;
  8178. }
  8179. // Special cases Begin
  8180. // special case - check if the document has <!DOCTYPE before going to Design view.
  8181. // If it does, set m_fHasDocType flag. Trident always inserts this flag and we
  8182. // want to remove it on the way out from Design view.
  8183. if ( (token.tok == TokElem_TITLE)
  8184. && (token.tokClass == tokElem)
  8185. )
  8186. {
  8187. if (mode == modeInput)
  8188. {
  8189. m_fHasTitleIn = TRUE;
  8190. if (m_indexTitleIn == -1)
  8191. m_indexTitleIn = itokCur;
  8192. }
  8193. }
  8194. if ( (token.tok == TokElem_BODY)
  8195. && (token.tokClass == tokElem)
  8196. && (m_ichBeginBodyTagIn == -1)
  8197. )
  8198. {
  8199. if ( PARSE_SPECIAL_HEAD_ONLY & dwSpecialize )
  8200. break;
  8201. if (mode == modeInput)
  8202. m_ichBeginBodyTagIn = token.ibTokMin;
  8203. }
  8204. if ( (token.tok == TokAttrib_HTTPEQUIV || token.tok == TokAttrib_HTTP_EQUIV)
  8205. && (token.tokClass == tokAttr)
  8206. && (mode == modeInput)
  8207. )
  8208. {
  8209. if (m_indexHttpEquivIn == -1)
  8210. m_indexHttpEquivIn = itokCur;
  8211. }
  8212. if ( (token.tok == TokElem_HEAD)
  8213. && (token.tokClass == tokElem)
  8214. && (m_ichBeginHeadTagIn == -1)
  8215. && (mode == modeInput)
  8216. )
  8217. {
  8218. m_ichBeginHeadTagIn = token.ibTokMin;
  8219. }
  8220. if ( (token.tok == TokElem_SELECT)
  8221. && (token.tokClass == tokElem)
  8222. && (mode == modeInput)
  8223. && !(lxs & inSCRIPT)
  8224. )
  8225. {
  8226. if ( (pTokArray[itokCur-1].token.tok == TokTag_START)
  8227. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8228. )
  8229. fBeginTokSelect = TRUE;
  8230. else if ( (pTokArray[itokCur-1].token.tok == TokTag_END)
  8231. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8232. )
  8233. fBeginTokSelect = FALSE;
  8234. }
  8235. if ( (token.tok == TokElem_TEXTAREA)
  8236. && (token.tokClass == tokElem)
  8237. && (mode == modeInput)
  8238. )
  8239. {
  8240. if ( (pTokArray[itokCur-1].token.tok == TokTag_START)
  8241. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8242. )
  8243. fBeginTokTextarea = TRUE;
  8244. else if ( (pTokArray[itokCur-1].token.tok == TokTag_END)
  8245. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8246. )
  8247. fBeginTokTextarea = FALSE;
  8248. }
  8249. if ( (token.tok == TokElem_LABEL)
  8250. && (token.tokClass == tokElem)
  8251. && (mode == modeInput)
  8252. )
  8253. {
  8254. if ( (pTokArray[itokCur-1].token.tok == TokTag_START)
  8255. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8256. )
  8257. fBeginTokLabel = TRUE;
  8258. else if ( (pTokArray[itokCur-1].token.tok == TokTag_END)
  8259. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8260. )
  8261. fBeginTokLabel = FALSE;
  8262. }
  8263. if ( (token.tok == TokElem_LISTING)
  8264. && (token.tokClass == tokElem)
  8265. && (mode == modeInput)
  8266. )
  8267. {
  8268. if ( (pTokArray[itokCur-1].token.tok == TokTag_START)
  8269. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8270. )
  8271. fBeginTokListing = TRUE;
  8272. else if ( (pTokArray[itokCur-1].token.tok == TokTag_END)
  8273. && (pTokArray[itokCur-1].token.tokClass == tokTag)
  8274. )
  8275. fBeginTokListing = FALSE;
  8276. }
  8277. if ( (token.tok == TokAttrib_STARTSPAN)
  8278. && (token.tokClass == tokAttr)
  8279. && (mode == modeInput)
  8280. )
  8281. fInDTC = TRUE;
  8282. if ( (token.tok == TokElem_OBJECT)
  8283. && (token.tokClass == tokElem)
  8284. && (lxs & inEndTag)
  8285. && (fInDTC)
  8286. && (mode == modeInput)
  8287. )
  8288. fInDTCOutput = TRUE;
  8289. if ( (token.tok == TokAttrib_ENDSPAN)
  8290. && (token.tokClass == tokAttr)
  8291. && (mode == modeInput)
  8292. )
  8293. {
  8294. fInDTCOutput = FALSE;
  8295. fInDTC = FALSE;
  8296. }
  8297. // Special cases End
  8298. if (itokCur == cArrayMax - 1) //allocate more memory for the array
  8299. {
  8300. HGLOBAL hgTokArray;
  8301. GlobalUnlock(*phgTokArray);
  8302. hgTokArray = *phgTokArray;
  8303. #pragma prefast(suppress:308, "noise")
  8304. *phgTokArray = GlobalReAlloc(*phgTokArray, (cArrayMax+MIN_TOK)*sizeof(TOKSTRUCT), GMEM_MOVEABLE|GMEM_ZEROINIT);
  8305. // if this alloc failed, we may still want to continue
  8306. if (*phgTokArray == NULL)
  8307. {
  8308. GlobalFree(hgTokArray);
  8309. hrRet = E_OUTOFMEMORY;
  8310. *pcMaxToken = itokCur;
  8311. if (fUsePstmNew)
  8312. pStmNew->SetSize(li);
  8313. else
  8314. *phNew = NULL;
  8315. goto LOOM;
  8316. }
  8317. else
  8318. {
  8319. pTokArray = (TOKSTRUCT *)GlobalLock(*phgTokArray); // do we need to unlock this first?
  8320. ASSERT(pTokArray != NULL);
  8321. cArrayMax += MIN_TOK;
  8322. }
  8323. }
  8324. ASSERT(itokCur < cArrayMax);
  8325. PreProcessToken(pTokArray, &itokCur, pwOld, cbCur, token, lxs, tagID, mode); //saves the token into the buffer
  8326. if (itokTop == cStackMax - 1) //allocate more memory for the stack
  8327. {
  8328. HGLOBAL hg;
  8329. GlobalUnlock(hgTokStack);
  8330. hg = hgTokStack;
  8331. #pragma prefast(suppress: 308, "noise")
  8332. hgTokStack = GlobalReAlloc(hgTokStack, (cStackMax+MIN_TOK)*sizeof(TOKSTACK), GMEM_MOVEABLE|GMEM_ZEROINIT);
  8333. // if this alloc failed, we may still want to continue
  8334. if (hgTokStack == NULL)
  8335. {
  8336. GlobalFree(hg);
  8337. hrRet = E_OUTOFMEMORY;
  8338. *pcMaxToken = itokCur;
  8339. if (fUsePstmNew)
  8340. pStmNew->SetSize(li);
  8341. else
  8342. *phNew = NULL;
  8343. goto LOOM;
  8344. }
  8345. else
  8346. {
  8347. pTokStack = (TOKSTACK *)GlobalLock(hgTokStack); // do we need to unlock this first?
  8348. ASSERT(pTokStack != NULL);
  8349. cStackMax += MIN_TOK;
  8350. }
  8351. }
  8352. ASSERT(itokTop < cStackMax);
  8353. ProcessToken(lxs, token, pwOld, cbCur, pTokStack, &itokTop, pTokArray, itokCur, tagID); //push/pop stack, determine error states
  8354. PostProcessToken(pwOld, pwNew, &cchNew, cbCur, cbCurSav, token, mode, lxs, dwFlags); // handle special cases of replacement
  8355. } // while (cbCur < cchwOld)
  8356. *pcMaxToken = m_cMaxToken = itokCur;
  8357. ASSERT(cchNew < GlobalSize(hgNew)); // or compare the cached value
  8358. ASSERT(dwFlags != dwFilterDefaults);
  8359. if ( dwFlags & dwFilterDTCs
  8360. || dwFlags & dwFilterDTCsWithoutMetaTags
  8361. || dwFlags & dwFilterServerSideScripts
  8362. || dwFlags & dwPreserveSourceCode
  8363. )
  8364. {
  8365. ASSERT(!(dwFlags & dwFilterNone));
  8366. // check dwSpacing flag here
  8367. if ((mode == modeOutput) && (dwFlags & dwPreserveSourceCode))
  8368. {
  8369. INT cchBeforeBody = 0;
  8370. INT cchAfterBody = 0;
  8371. INT cchPreEndBody = 0;
  8372. ASSERT(m_pspInfoOut == NULL);
  8373. ASSERT(m_hgDocRestore != NULL);
  8374. m_pspInfoOut = (WORD *)GlobalLock(m_hgDocRestore);
  8375. cchBeforeBody = (int)*m_pspInfoOut; // we are assuming that cchBeforeBody exists in this block
  8376. m_pspInfoOut += cchBeforeBody + (sizeof(INT))/sizeof(WCHAR); // for cchBeforeBody
  8377. cchAfterBody = (int)*m_pspInfoOut;
  8378. m_pspInfoOut += cchAfterBody + (sizeof(INT))/sizeof(WCHAR); // for cchAfterBody
  8379. cchPreEndBody = (int)*m_pspInfoOut;
  8380. m_pspInfoOut += cchPreEndBody + (sizeof(INT))/sizeof(WCHAR); // for cchPreEndBody
  8381. m_cchspInfoTotal = (int)*m_pspInfoOut;
  8382. m_pspInfoOut += sizeof(INT)/sizeof(WCHAR);
  8383. m_pspInfoOutStart = m_pspInfoOut;
  8384. }
  8385. ASSERT(pTokArray != NULL);
  8386. FilterHtml( pwOld, &pwNew, &cchNew, &hgNew, pTokArray,
  8387. mode, dwFlags);
  8388. // check dwSpacing flag here
  8389. if ((mode == modeOutput) && (dwFlags & dwPreserveSourceCode))
  8390. {
  8391. if (m_pspInfoOut != NULL)
  8392. {
  8393. ASSERT(m_hgDocRestore != NULL);
  8394. GlobalUnlock(m_hgDocRestore);
  8395. }
  8396. }
  8397. }
  8398. LSkipTokFilter:
  8399. if (fUsePstmNew)
  8400. {
  8401. if (dwFlags & dwFilterMultiByteStream)
  8402. li.LowPart = WideCharToMultiByte(CP_ACP, 0, pwNew, -1, NULL, 0, NULL, NULL) - 1; // to compensate for NULL character at end
  8403. else
  8404. li.LowPart = (cchNew)*sizeof(WCHAR);
  8405. li.HighPart = 0;
  8406. if (S_OK != pStmNew->SetSize(li))
  8407. {
  8408. hrRet = E_OUTOFMEMORY;
  8409. goto LOOM;
  8410. }
  8411. if (S_OK != GetHGlobalFromStream(pStmNew, &hgPstm))
  8412. {
  8413. hrRet = E_INVALIDARG;
  8414. goto LOOM;
  8415. }
  8416. pNew = (LPSTR) GlobalLock(hgPstm);
  8417. }
  8418. else
  8419. {
  8420. // cchNew is # of unicode characters in pwNew
  8421. // If we want to convert this UNICODE string into MultiByte string,
  8422. // we will need anywhere between cchNew bytes & cchNew*sizeof(WCHAR) bytes.
  8423. // and we don't know it at this point, so lets leave the max size for allocation.
  8424. *phNew = GlobalAlloc(GMEM_ZEROINIT, (cchNew+1)*sizeof(WCHAR));
  8425. if (*phNew == NULL)
  8426. {
  8427. hrRet = E_OUTOFMEMORY;
  8428. goto LOOM;
  8429. }
  8430. pNew = (LPSTR) GlobalLock(*phNew);
  8431. }
  8432. if (dwFlags & dwFilterMultiByteStream)
  8433. {
  8434. INT cbSize;
  8435. cbSize = WideCharToMultiByte(CP_ACP, 0, pwNew, -1, NULL, 0, NULL, NULL) - 1; // to compensate for NULL character at end
  8436. if (pcbSizeOut)
  8437. *pcbSizeOut = cbSize;
  8438. // we assume that number of characters will be the same in UNICODE or MBCS world
  8439. // what changes is the number of bytes they need.
  8440. WideCharToMultiByte(CP_ACP, 0, pwNew, -1, pNew, cbSize, NULL, NULL);
  8441. }
  8442. else
  8443. {
  8444. // NOTE - that we always set *pcbSizeOut to the number of BYTES in the new buffer
  8445. if (pcbSizeOut)
  8446. *pcbSizeOut = cchNew*sizeof(WCHAR);
  8447. memcpy((BYTE *)pNew, (BYTE *)pwNew, cchNew*sizeof(WCHAR)); // we want to remain UNICODE
  8448. }
  8449. #ifdef DEBUG
  8450. dwErr = GetLastError();
  8451. #endif // DEBUG
  8452. if (fUsePstmNew)
  8453. GlobalUnlock(hgPstm);
  8454. else
  8455. GlobalUnlock(*phNew);
  8456. LOOM:
  8457. // assume that the caller will free *phgTokArray
  8458. if (*phgTokArray != NULL)
  8459. GlobalUnlock(*phgTokArray); // do we need to check if this was already Unlocked?
  8460. // assume that the caller will free *phgDocRestore if the caller allocated it
  8461. if (fAllocDocRestore && m_hgDocRestore != NULL) // we allocated it here, so the caller doesn't need it
  8462. GlobalUnlockFreeNull(&m_hgDocRestore);
  8463. if (phgDocRestore)
  8464. *phgDocRestore = m_hgDocRestore; // in case of a realloc, this may have changed.
  8465. if (hgTokStack != NULL)
  8466. GlobalUnlockFreeNull(&hgTokStack);
  8467. if (hgNew != NULL)
  8468. GlobalUnlockFreeNull(&hgNew);
  8469. if (hgOld != NULL)
  8470. GlobalUnlockFreeNull(&hgOld);
  8471. if (m_hgTBodyStack != NULL)
  8472. GlobalUnlockFreeNull(&m_hgTBodyStack);
  8473. // check dwSpacing flag here
  8474. if ((m_hgspInfo != NULL) && (dwFlags & dwPreserveSourceCode))
  8475. {
  8476. if (mode == modeInput && phgDocRestore)
  8477. {
  8478. WCHAR *pHdr, *pHdrSav;
  8479. INT cchBeforeBody, cchAfterBody, cchPreEndBody;
  8480. pHdr = (WCHAR *)GlobalLock(*phgDocRestore);
  8481. ASSERT(pHdr != NULL);
  8482. pHdrSav = pHdr;
  8483. memcpy((BYTE *)&cchBeforeBody, (BYTE *)pHdr, sizeof(INT));
  8484. pHdr += cchBeforeBody + sizeof(INT)/sizeof(WCHAR);
  8485. memcpy((BYTE *)&cchAfterBody, (BYTE *)pHdr, sizeof(INT));
  8486. pHdr += cchAfterBody + sizeof(INT)/sizeof(WCHAR);
  8487. memcpy((BYTE *)&cchPreEndBody, (BYTE *)pHdr, sizeof(INT));
  8488. pHdr += cchPreEndBody + sizeof(INT)/sizeof(WCHAR);
  8489. if (GlobalSize(*phgDocRestore) < SAFE_PTR_DIFF_TO_INT(pHdr - pHdrSav)*sizeof(WCHAR) + SAFE_PTR_DIFF_TO_INT(m_pspInfoCur-m_pspInfo)*sizeof(WORD)+sizeof(int))
  8490. {
  8491. INT cdwSize = SAFE_PTR_DIFF_TO_INT(pHdr - pHdrSav);
  8492. ASSERT(cdwSize >= 0); // validation
  8493. hrRet = ReallocBuffer( phgDocRestore,
  8494. SAFE_INT64_TO_DWORD(pHdr - pHdrSav)*sizeof(WCHAR) + SAFE_INT64_TO_DWORD(m_pspInfoCur-m_pspInfo)*sizeof(WORD)+sizeof(int),
  8495. GMEM_MOVEABLE|GMEM_ZEROINIT);
  8496. if (hrRet == E_OUTOFMEMORY)
  8497. goto LRet;
  8498. ASSERT(*phgDocRestore != NULL);
  8499. pHdr = (WORD *)GlobalLock(*phgDocRestore);
  8500. pHdr += cdwSize;
  8501. }
  8502. *(int*)pHdr = SAFE_PTR_DIFF_TO_INT(m_pspInfoCur-m_pspInfo);
  8503. pHdr += sizeof(INT)/sizeof(WCHAR);
  8504. memcpy( (BYTE *)pHdr,
  8505. (BYTE *)m_pspInfo,
  8506. SAFE_PTR_DIFF_TO_INT(m_pspInfoCur-m_pspInfo)*sizeof(WORD));
  8507. LRet:
  8508. GlobalUnlock(*phgDocRestore);
  8509. }
  8510. GlobalUnlockFreeNull(&m_hgspInfo);
  8511. }
  8512. GlobalUnlock(hOld);
  8513. LRetOnly:
  8514. return(hrRet);
  8515. }
  8516. void
  8517. CTriEditParse::SetSPInfoState(WORD inState, WORD *pdwState, WORD *pdwStatePrev, BOOL *pfSave)
  8518. {
  8519. *pfSave = TRUE;
  8520. *pdwStatePrev = *pdwState;
  8521. *pdwState = inState;
  8522. }
  8523. HRESULT
  8524. CTriEditParse::hrMarkOrdering(WCHAR *pwOld, TOKSTRUCT *pTokArray, INT iArrayStart, int iArrayEnd,
  8525. UINT cbCur, INT *pichStartOR)
  8526. {
  8527. HRESULT hr = S_OK;
  8528. WORD *pspInfoSize;
  8529. WORD cAttr = 0;
  8530. ASSERT(m_pspInfo != NULL);
  8531. if (m_pspInfo == NULL)
  8532. {
  8533. hr = E_OUTOFMEMORY;
  8534. goto LRetOnly;
  8535. }
  8536. pspInfoSize = m_pspInfoCur; // placeholder to save run size in BYTEs, size includes this DWORD
  8537. *m_pspInfoCur++ = 0xFFFF; // placeholder to save run size in BYTEs, size includes this WORD
  8538. *m_pspInfoCur++ = 0xFFFF; // placeholder to save number of Attr
  8539. // handle the simplest case where we know that there is nothing to save
  8540. if (cbCur == (UINT)*pichStartOR)
  8541. goto LRet;
  8542. // find out the number ot attributes insize this tag
  8543. while (iArrayStart < iArrayEnd)
  8544. {
  8545. if (pTokArray[iArrayStart].token.tokClass == tokAttr)
  8546. {
  8547. INT ichStart, ichEnd;
  8548. INT iArrayQuote = iArrayStart+1;
  8549. INT iArrayEq = -1;
  8550. cAttr++;
  8551. ichStart = pTokArray[iArrayStart].token.ibTokMin;
  8552. ichEnd = pTokArray[iArrayStart].token.ibTokMac;
  8553. ASSERT(ichEnd > ichStart);
  8554. while (iArrayQuote < iArrayEnd) // handle the case of white space before the quotes
  8555. {
  8556. if (pTokArray[iArrayQuote].token.tokClass == tokAttr) // gone too far, found next attr
  8557. break;
  8558. if ( ( pTokArray[iArrayQuote].token.tokClass == tokValue
  8559. || pTokArray[iArrayQuote].token.tokClass == tokString
  8560. )
  8561. && ( pwOld[pTokArray[iArrayQuote].token.ibTokMin] == '"'
  8562. || pwOld[pTokArray[iArrayQuote].token.ibTokMin] == '\''
  8563. )
  8564. )
  8565. break;
  8566. if (pwOld[pTokArray[iArrayQuote].token.ibTokMin] == '=')
  8567. iArrayEq = iArrayQuote;
  8568. iArrayQuote++;
  8569. }
  8570. if ( iArrayEq != -1
  8571. && pTokArray[iArrayEq].token.tokClass == tokOp
  8572. && pwOld[pTokArray[iArrayEq].token.ibTokMin] == '='
  8573. && ( pTokArray[iArrayQuote].token.tokClass == tokValue
  8574. || pTokArray[iArrayQuote].token.tokClass == tokString
  8575. )
  8576. && pwOld[pTokArray[iArrayQuote].token.ibTokMin] == '"'
  8577. )
  8578. {
  8579. *m_pspInfoCur++ = 1;
  8580. }
  8581. else if ( iArrayEq != -1
  8582. && pTokArray[iArrayEq].token.tokClass == tokOp
  8583. && pwOld[pTokArray[iArrayEq].token.ibTokMin] == '='
  8584. && ( pTokArray[iArrayQuote].token.tokClass == tokValue
  8585. || pTokArray[iArrayQuote].token.tokClass == tokString
  8586. )
  8587. && pwOld[pTokArray[iArrayQuote].token.ibTokMin] == '\''
  8588. )
  8589. {
  8590. *m_pspInfoCur++ = 2;
  8591. }
  8592. else
  8593. {
  8594. *m_pspInfoCur++ = 0;
  8595. }
  8596. *m_pspInfoCur++ = (WORD)(ichEnd-ichStart);
  8597. memcpy((BYTE *)m_pspInfoCur, (BYTE *)&(pwOld[ichStart]), (ichEnd-ichStart)*sizeof(WCHAR));
  8598. m_pspInfoCur += (ichEnd-ichStart);
  8599. }
  8600. iArrayStart++;
  8601. }
  8602. LRet:
  8603. *pspInfoSize++ = SAFE_PTR_DIFF_TO_WORD(m_pspInfoCur - pspInfoSize);
  8604. *pspInfoSize = cAttr;
  8605. *pichStartOR = cbCur; // set for next run
  8606. LRetOnly:
  8607. return(hr);
  8608. } /* hrMarkOrdering() */
  8609. BOOL
  8610. CTriEditParse::FRestoreOrder(WCHAR *pwNew, WCHAR *pwOld, WORD *pspInfoOrder, UINT *pichNewCur,
  8611. INT /*cwOrderInfo*/, TOKSTRUCT *pTokArray, INT iArrayStart, INT iArrayEnd,
  8612. INT iArrayDSPStart, INT iArrayDSPEnd, INT cchNewCopy, HGLOBAL *phgNew)
  8613. {
  8614. // iArrayStart points to '<' & iArrayEnd points to '>'. (These refer to pwOld)
  8615. // look at the attributes between iArrayStart & iArrayEnd and compare them with the attributes
  8616. // saved in pspInfoOrder (which already points to the data saved, i.e. past cwOrderInfo)
  8617. // If we find a matching attribute, move it to appropriate position.
  8618. // DON'T touch extra attributes and IGNORE missing attributes because those represent user action
  8619. HGLOBAL hgNewAttr = NULL;
  8620. HGLOBAL hgTokList = NULL;
  8621. BOOL *pTokList, *pTokListSav;
  8622. WCHAR *pNewAttr, *pNewAttrSav;
  8623. INT i, ichStart, ichEnd, iStart, iEnd, cAttr, cchTag, iStartSav, cchNew;
  8624. BOOL fRet = TRUE;
  8625. LPCWSTR rgSpaceTags[] =
  8626. {
  8627. L"DESIGNTIMESP",
  8628. };
  8629. UINT cbNeed;
  8630. ASSERT(pspInfoOrder != NULL);
  8631. cAttr = *(WORD *)pspInfoOrder++;
  8632. ASSERT(cAttr >= 0); // make sure that it was filled in
  8633. if (cAttr == 0)/* || cAttr == 1)*/
  8634. goto LRet;
  8635. hgTokList = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, (iArrayEnd-iArrayStart+1)*(sizeof(BOOL)));
  8636. if (hgTokList == NULL) // don't reorder the attributes
  8637. {
  8638. fRet = FALSE;
  8639. goto LRet;
  8640. }
  8641. pTokList = (BOOL *) GlobalLock(hgTokList);
  8642. pTokListSav = pTokList;
  8643. ichStart = pTokArray[iArrayStart].token.ibTokMin;
  8644. ichEnd = pTokArray[iArrayEnd].token.ibTokMac;
  8645. // cAttr*2 becase we may need to add quotes around each attr value
  8646. hgNewAttr = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, (ichEnd-ichStart+cAttr*2)*(sizeof(WCHAR)));
  8647. if (hgNewAttr == NULL) // don't reorder the attributes
  8648. {
  8649. fRet = FALSE;
  8650. goto LRet;
  8651. }
  8652. pNewAttr = (WCHAR *) GlobalLock(hgNewAttr);
  8653. pNewAttrSav = pNewAttr;
  8654. for (i = iArrayStart; i <= iArrayEnd; i++)
  8655. *pTokList++ = FALSE;
  8656. ASSERT(iArrayDSPEnd > iArrayDSPStart);
  8657. for (i = iArrayDSPStart; i <= iArrayDSPEnd; i++)
  8658. {
  8659. ASSERT(*(pTokListSav+i-iArrayStart) == FALSE);
  8660. *(pTokListSav+i-iArrayStart) = TRUE;
  8661. }
  8662. if (pwOld[pTokArray[iArrayDSPEnd+1].token.ibTokMin] == ' ')
  8663. {
  8664. ASSERT(*(pTokListSav+iArrayDSPEnd+1-iArrayStart) == FALSE);
  8665. *(pTokListSav+iArrayDSPEnd+1-iArrayStart) = TRUE;
  8666. }
  8667. // copy contents from pwOld into pNewAttr till we find the first tokAttr/tokSpace
  8668. iStart = iEnd = iArrayStart;
  8669. cchTag = wcslen(rgSpaceTags[0]);
  8670. while (iEnd < iArrayEnd)
  8671. {
  8672. if ( (pTokArray[iEnd].token.tokClass == tokAttr)
  8673. /*|| ( (pTokArray[iEnd].token.tokClass == tokSpace)
  8674. && (0 != _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[iEnd].token.ibTokMin], cchTag))
  8675. )*/
  8676. )
  8677. {
  8678. break;
  8679. }
  8680. iEnd++;
  8681. }
  8682. if (iEnd >= iArrayEnd) // error
  8683. {
  8684. fRet = FALSE;
  8685. goto LRet;
  8686. }
  8687. for (i = iStart; i < iEnd; i++)
  8688. {
  8689. if (*(pTokListSav+i-iArrayStart) != TRUE) // if not already copied
  8690. {
  8691. if ( (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin == 3)
  8692. && pwOld[pTokArray[i].token.ibTokMin] == ' '
  8693. && pwOld[pTokArray[i].token.ibTokMin+1] == '\r'
  8694. && pwOld[pTokArray[i].token.ibTokMin+2] == '\n'
  8695. )
  8696. {
  8697. memcpy( (BYTE *)pNewAttr,
  8698. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8699. (1)*sizeof(WCHAR));
  8700. pNewAttr++;
  8701. }
  8702. else
  8703. {
  8704. if (pTokArray[i].token.tokClass == tokElem)
  8705. {
  8706. memcpy( (BYTE *)pNewAttr,
  8707. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8708. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  8709. // BUG 15389 - restore proper case here
  8710. if (iswupper(pwOld[pTokArray[iArrayDSPStart].token.ibTokMin]) != 0) // DESIGNTIMESP is upper case
  8711. {
  8712. _wcsupr(pNewAttr);
  8713. }
  8714. else
  8715. {
  8716. _wcslwr(pNewAttr);
  8717. }
  8718. pNewAttr += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  8719. }
  8720. else
  8721. {
  8722. memcpy( (BYTE *)pNewAttr,
  8723. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8724. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  8725. pNewAttr += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  8726. }
  8727. }
  8728. *(pTokListSav+i-iArrayStart) = TRUE;
  8729. }
  8730. }
  8731. iStartSav = iStart = iEnd;
  8732. while (cAttr > 0)
  8733. {
  8734. INT cchAttr;
  8735. BOOL fAddSpace;
  8736. WORD isQuote;
  8737. isQuote = *(WORD *)pspInfoOrder++;
  8738. cchAttr = *(WORD *)pspInfoOrder++;
  8739. ASSERT(cchAttr > 0); // make sure that it was filled in
  8740. while (iStart <= iArrayEnd) //for (i = iStart; i <= iArrayEnd; i++)
  8741. {
  8742. if ( (pTokArray[iStart].token.tokClass == tokAttr)
  8743. && (pTokArray[iStart].token.ibTokMac-pTokArray[iStart].token.ibTokMin == (UINT)cchAttr)
  8744. && (0 == _wcsnicmp(pspInfoOrder, &pwOld[pTokArray[iStart].token.ibTokMin], cchAttr))
  8745. )
  8746. {
  8747. break; // found the match, so copy from ith token to the next tokAttr
  8748. }
  8749. iStart++;
  8750. } // while ()
  8751. if (iStart >= iArrayEnd) // we know that iArrayEnd is actually '>'
  8752. goto LNoMatch;
  8753. // now from iStart go forward till we get the next tokAttr or '>'
  8754. iEnd = iStart+1;
  8755. fAddSpace = FALSE;
  8756. while (iEnd < iArrayEnd)
  8757. {
  8758. if ( (pTokArray[iEnd].token.tokClass == tokAttr)
  8759. || ( (pTokArray[iEnd].token.tokClass == tokSpace)
  8760. && (0 == _wcsnicmp(rgSpaceTags[0], &pwOld[pTokArray[iEnd].token.ibTokMin], cchTag))
  8761. )
  8762. )
  8763. break; // found the next attribute
  8764. iEnd++;
  8765. }
  8766. if (iEnd == iArrayEnd)
  8767. fAddSpace = TRUE;
  8768. iEnd--; // iEnd will be pointing to '>' or the next Attribute, so decrement it
  8769. for (i = iStart; i <= iEnd; i++)
  8770. {
  8771. if (*(pTokListSav+i-iArrayStart) != TRUE) // we didn't copy this token
  8772. {
  8773. if ( (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin == 3)
  8774. && pwOld[pTokArray[i].token.ibTokMin] == ' '
  8775. && pwOld[pTokArray[i].token.ibTokMin+1] == '\r'
  8776. && pwOld[pTokArray[i].token.ibTokMin+2] == '\n'
  8777. )
  8778. {
  8779. memcpy( (BYTE *)pNewAttr,
  8780. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8781. (1)*sizeof(WCHAR));
  8782. pNewAttr++;
  8783. }
  8784. else
  8785. {
  8786. if (pTokArray[i].token.tokClass == tokAttr)
  8787. {
  8788. ASSERT(i == iStart);
  8789. ASSERT((INT)(pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin) == cchAttr);
  8790. ASSERT(0 == _wcsnicmp(pspInfoOrder, &pwOld[pTokArray[i].token.ibTokMin], cchAttr));
  8791. memcpy( (BYTE *)pNewAttr,
  8792. (BYTE *)pspInfoOrder,
  8793. (cchAttr)*sizeof(WCHAR));
  8794. }
  8795. else if ( (isQuote == 1)
  8796. && ( pTokArray[i].token.tokClass == tokValue
  8797. || pTokArray[i].token.tokClass == tokString
  8798. )
  8799. && (pwOld[pTokArray[i-1].token.ibTokMin] != '@') /*hack alert - VID BUG 23597*/
  8800. )
  8801. {
  8802. isQuote = 0; // the quote restoring has been taken care of for this attribute's value
  8803. if (pwOld[pTokArray[i].token.ibTokMin] != '"')
  8804. *pNewAttr++ = '"';
  8805. memcpy( (BYTE *)pNewAttr,
  8806. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8807. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  8808. if (pwOld[pTokArray[i].token.ibTokMin] != '"')
  8809. {
  8810. *(pNewAttr+pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin) = '"';
  8811. pNewAttr++;
  8812. }
  8813. }
  8814. else if ( (isQuote == 2)
  8815. && ( pTokArray[i].token.tokClass == tokValue
  8816. || pTokArray[i].token.tokClass == tokString
  8817. )
  8818. && (pwOld[pTokArray[i-1].token.ibTokMin] != '@') /*hack alert - VID BUG 23597*/
  8819. )
  8820. {
  8821. isQuote = 0; // the quote restoring has been taken care of for this attribute's value
  8822. // if we already have double quote, don't insert another single quote.
  8823. // ideally, we want to replace the double quote, but lets not do it now, because
  8824. // we believe that trident would have inserted double quotes to make it valid html!
  8825. if (pwOld[pTokArray[i].token.ibTokMin] != '\'' && pwOld[pTokArray[i].token.ibTokMin] != '"')
  8826. *pNewAttr++ = '\'';
  8827. memcpy( (BYTE *)pNewAttr,
  8828. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8829. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  8830. if (pwOld[pTokArray[i].token.ibTokMin] != '\'' && pwOld[pTokArray[i].token.ibTokMin] != '"')
  8831. {
  8832. *(pNewAttr+pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin) = '\'';
  8833. pNewAttr++;
  8834. }
  8835. }
  8836. else
  8837. {
  8838. memcpy( (BYTE *)pNewAttr,
  8839. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8840. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  8841. }
  8842. pNewAttr += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  8843. }
  8844. *(pTokListSav+i-iArrayStart) = TRUE;
  8845. }
  8846. }
  8847. if (fAddSpace)
  8848. *pNewAttr++ = ' ';
  8849. LNoMatch:
  8850. iStart = iStartSav;
  8851. pspInfoOrder += cchAttr;
  8852. cAttr--;
  8853. } // while (cAttr > 0)
  8854. // do we want to insert an extra space into pNewAttr here?
  8855. // all the saved attributes are accounted for, lets copy remaining stuff
  8856. for (i = iStartSav; i <= iArrayEnd; i++)
  8857. {
  8858. if (*(pTokListSav+i-iArrayStart) != TRUE) // we didn't copy this token
  8859. {
  8860. if ( (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin == 3)
  8861. && pwOld[pTokArray[i].token.ibTokMin] == ' '
  8862. && pwOld[pTokArray[i].token.ibTokMin+1] == '\r'
  8863. && pwOld[pTokArray[i].token.ibTokMin+2] == '\n'
  8864. )
  8865. {
  8866. memcpy( (BYTE *)pNewAttr,
  8867. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8868. (1)*sizeof(WCHAR));
  8869. pNewAttr++;
  8870. }
  8871. else
  8872. {
  8873. memcpy( (BYTE *)pNewAttr,
  8874. (BYTE *)(pwOld+pTokArray[i].token.ibTokMin),
  8875. (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin)*sizeof(WCHAR));
  8876. pNewAttr += (pTokArray[i].token.ibTokMac-pTokArray[i].token.ibTokMin);
  8877. }
  8878. *(pTokListSav+i-iArrayStart) = TRUE;
  8879. }
  8880. } // for ()
  8881. cchNew = SAFE_PTR_DIFF_TO_INT(pNewAttr - pNewAttrSav);
  8882. cbNeed = *pichNewCur+cchNew-cchNewCopy;
  8883. ASSERT(cbNeed*sizeof(WCHAR) <= GlobalSize(*phgNew));
  8884. if (S_OK != ReallocIfNeeded(phgNew, &pwNew, cbNeed, GMEM_MOVEABLE|GMEM_ZEROINIT))
  8885. {
  8886. fRet = FALSE;
  8887. goto LRet;
  8888. }
  8889. memcpy( (BYTE *)(pwNew+*pichNewCur-cchNewCopy),
  8890. (BYTE *)(pNewAttrSav),
  8891. cchNew*sizeof(WCHAR));
  8892. *pichNewCur += (cchNew-cchNewCopy);
  8893. // NOTE - Find a better way to account for the extra space added when we moved
  8894. // the attributes. We can't avoid adding space because when we move the last attribute,
  8895. // there may not be a space between that and the '>'.
  8896. if ( /*(cchNew > cchNewCopy)
  8897. &&*/ (pwNew[*pichNewCur-1] == '>' && pwNew[*pichNewCur-2] == ' ')
  8898. )
  8899. {
  8900. pwNew[*pichNewCur-2] = pwNew[*pichNewCur-1];
  8901. pwNew[*pichNewCur-1] = '\0';
  8902. *pichNewCur -= 1;
  8903. }
  8904. LRet:
  8905. if (hgNewAttr != NULL)
  8906. GlobalUnlockFreeNull(&hgNewAttr);
  8907. if (hgTokList != NULL)
  8908. GlobalUnlockFreeNull(&hgTokList);
  8909. return(fRet);
  8910. } /* FRestoreOrder() */
  8911. HRESULT
  8912. CTriEditParse::hrMarkSpacing(WCHAR *pwOld, UINT cbCur, INT *pichStartSP)
  8913. {
  8914. HRESULT hrRet = S_OK;
  8915. UINT i;
  8916. WORD cSpace, cEOL, cTab, cChar, cTagOpen, cTagClose, cTagEq;
  8917. WORD dwState = initState;
  8918. WORD dwStatePrev = initState;
  8919. BOOL fSave = FALSE;
  8920. WORD *pspInfoSize;
  8921. if (m_pspInfo == NULL) // allocate it
  8922. {
  8923. m_hgspInfo = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cbHeader*sizeof(WORD));
  8924. if (m_hgspInfo == NULL)
  8925. {
  8926. hrRet = E_OUTOFMEMORY;
  8927. goto LRet;
  8928. }
  8929. m_pspInfo = (WORD *) GlobalLock(m_hgspInfo);
  8930. ASSERT(m_pspInfo != NULL);
  8931. m_pspInfoCur = m_pspInfo;
  8932. //ASSERT(m_ispInfoIn == 0);
  8933. }
  8934. else // reallocate if needed
  8935. {
  8936. // assumption here is that we can't have more runs than the number of characters we have to scan
  8937. // we use *2 to reduce future reallocations
  8938. if (GlobalSize(m_hgspInfo) < SAFE_PTR_DIFF_TO_INT(m_pspInfoCur-m_pspInfo)*sizeof(WORD) + (cbCur-*pichStartSP)*2*sizeof(WORD) + cbBufPadding)
  8939. {
  8940. int cdwSize = SAFE_PTR_DIFF_TO_INT(m_pspInfoCur-m_pspInfo); // size in DWORDs
  8941. hrRet = ReallocBuffer( &m_hgspInfo,
  8942. SAFE_INT64_TO_DWORD(m_pspInfoCur-m_pspInfo)*sizeof(WORD) + (cbCur-*pichStartSP)*2*sizeof(WORD) + cbBufPadding,
  8943. GMEM_MOVEABLE|GMEM_ZEROINIT);
  8944. if (hrRet == E_OUTOFMEMORY)
  8945. goto LRet;
  8946. ASSERT(m_hgspInfo != NULL);
  8947. m_pspInfo = (WORD *)GlobalLock(m_hgspInfo);
  8948. m_pspInfoCur = m_pspInfo + cdwSize;
  8949. }
  8950. }
  8951. //m_ispInfoIn++;
  8952. pspInfoSize = m_pspInfoCur; // placeholder to save run size in BYTEs, size includes this DWORD
  8953. *m_pspInfoCur++ = 0xFFFF; // placeholder to save run size in BYTEs, size includes this WORD
  8954. *m_pspInfoCur++ = SAFE_INT_DIFF_TO_WORD(cbCur-*pichStartSP);
  8955. cSpace = cEOL = cTab = cChar = cTagOpen = cTagClose = cTagEq = 0;
  8956. //scan from ichStartSP till cbCur for space, tab, eol
  8957. // NOTE - Optimization note
  8958. // part of this info is already in pTokArray. We should use it
  8959. // to reduce the time in this function
  8960. for (i = *pichStartSP; i < cbCur; i++)
  8961. {
  8962. switch (pwOld[i])
  8963. {
  8964. case ' ':
  8965. if (dwState != inSpace)
  8966. {
  8967. SetSPInfoState(inSpace, &dwState, &dwStatePrev, &fSave);
  8968. ASSERT(cSpace == 0);
  8969. }
  8970. cSpace++;
  8971. break;
  8972. case '\r':
  8973. case '\n':
  8974. if (dwState != inEOL)
  8975. {
  8976. SetSPInfoState(inEOL, &dwState, &dwStatePrev, &fSave);
  8977. ASSERT(cEOL == 0);
  8978. }
  8979. if (pwOld[i] == '\n')
  8980. cEOL++;
  8981. break;
  8982. case '\t':
  8983. if (dwState != inTab)
  8984. {
  8985. SetSPInfoState(inTab, &dwState, &dwStatePrev, &fSave);
  8986. ASSERT(cTab == 0);
  8987. }
  8988. cTab++;
  8989. break;
  8990. case '<':
  8991. if (dwState != inTagOpen)
  8992. {
  8993. SetSPInfoState(inTagOpen, &dwState, &dwStatePrev, &fSave);
  8994. ASSERT(cTagOpen == 0);
  8995. }
  8996. cTagOpen++;
  8997. break;
  8998. case '>':
  8999. if (dwState != inTagClose)
  9000. {
  9001. SetSPInfoState(inTagClose, &dwState, &dwStatePrev, &fSave);
  9002. ASSERT(cTagClose == 0);
  9003. }
  9004. cTagClose++;
  9005. break;
  9006. case '=':
  9007. if (dwState != inTagEq)
  9008. {
  9009. SetSPInfoState(inTagEq, &dwState, &dwStatePrev, &fSave);
  9010. ASSERT(cTagEq == 0);
  9011. }
  9012. cTagEq++;
  9013. break;
  9014. default:
  9015. if (dwState != inChar)
  9016. {
  9017. SetSPInfoState(inChar, &dwState, &dwStatePrev, &fSave);
  9018. ASSERT(cChar == 0);
  9019. }
  9020. cChar++;
  9021. break;
  9022. } /* switch */
  9023. if (fSave) // save previous run
  9024. {
  9025. if (dwStatePrev != initState)
  9026. {
  9027. switch (dwStatePrev)
  9028. {
  9029. case inSpace:
  9030. *m_pspInfoCur++ = inSpace;
  9031. *m_pspInfoCur++ = cSpace;
  9032. cSpace = 0;
  9033. break;
  9034. case inEOL:
  9035. *m_pspInfoCur++ = inEOL;
  9036. *m_pspInfoCur++ = cEOL;
  9037. cEOL = 0;
  9038. break;
  9039. case inTab:
  9040. *m_pspInfoCur++ = inTab;
  9041. *m_pspInfoCur++ = cTab;
  9042. cTab = 0;
  9043. break;
  9044. case inTagOpen:
  9045. *m_pspInfoCur++ = inTagOpen;
  9046. *m_pspInfoCur++ = cTagOpen;
  9047. cTagOpen = 0;
  9048. break;
  9049. case inTagClose:
  9050. *m_pspInfoCur++ = inTagClose;
  9051. *m_pspInfoCur++ = cTagClose;
  9052. cTagClose = 0;
  9053. break;
  9054. case inTagEq:
  9055. *m_pspInfoCur++ = inTagEq;
  9056. *m_pspInfoCur++ = cTagEq;
  9057. cTagEq = 0;
  9058. break;
  9059. case inChar:
  9060. *m_pspInfoCur++ = inChar;
  9061. *m_pspInfoCur++ = cChar;
  9062. cChar = 0;
  9063. break;
  9064. }
  9065. }
  9066. fSave = FALSE;
  9067. } // if (fSave)
  9068. } // for ()
  9069. *pichStartSP = cbCur; // set for next run
  9070. //if (pwOld[i] == '\0') // end of file and we wouldn't have saved the last run
  9071. //{
  9072. if (cSpace > 0)
  9073. dwStatePrev = inSpace;
  9074. else if (cEOL > 0)
  9075. dwStatePrev = inEOL;
  9076. else if (cTab > 0)
  9077. dwStatePrev = inTab;
  9078. else if (cTagOpen > 0)
  9079. dwStatePrev = inTagOpen;
  9080. else if (cTagClose > 0)
  9081. dwStatePrev = inTagClose;
  9082. else if (cTagEq > 0)
  9083. dwStatePrev = inTagEq;
  9084. else if (cChar > 0)
  9085. dwStatePrev = inChar;
  9086. else
  9087. dwStatePrev = initState; // handle error case
  9088. switch (dwStatePrev) // repeat of above, make this into a function
  9089. {
  9090. case inSpace:
  9091. *m_pspInfoCur++ = inSpace;
  9092. *m_pspInfoCur++ = cSpace;
  9093. cSpace = 0;
  9094. break;
  9095. case inEOL:
  9096. *m_pspInfoCur++ = inEOL;
  9097. *m_pspInfoCur++ = cEOL;
  9098. cEOL = 0;
  9099. break;
  9100. case inTab:
  9101. *m_pspInfoCur++ = inTab;
  9102. *m_pspInfoCur++ = cTab;
  9103. cTab = 0;
  9104. break;
  9105. case inTagOpen:
  9106. *m_pspInfoCur++ = inTagOpen;
  9107. *m_pspInfoCur++ = cTagOpen;
  9108. cTagOpen = 0;
  9109. break;
  9110. case inTagClose:
  9111. *m_pspInfoCur++ = inTagClose;
  9112. *m_pspInfoCur++ = cTagClose;
  9113. cTagClose = 0;
  9114. break;
  9115. case inTagEq:
  9116. *m_pspInfoCur++ = inTagEq;
  9117. *m_pspInfoCur++ = cTagEq;
  9118. cTagEq = 0;
  9119. break;
  9120. case inChar:
  9121. *m_pspInfoCur++ = inChar;
  9122. *m_pspInfoCur++ = cChar;
  9123. cChar = 0;
  9124. break;
  9125. } // switch()
  9126. //} // if ()
  9127. *pspInfoSize = SAFE_PTR_DIFF_TO_WORD(m_pspInfoCur - pspInfoSize);
  9128. LRet:
  9129. return(hrRet);
  9130. } /* hrMarkSpacing() */
  9131. BOOL
  9132. CTriEditParse::FRestoreSpacing(LPWSTR pwNew, LPWSTR /*pwOld*/, UINT *pichNewCur, INT *pcchwspInfo,
  9133. INT cchRange, INT ichtoktagStart, BOOL fLookback, INT index)
  9134. {
  9135. BOOL fRet = TRUE;
  9136. INT ichNewCur = (INT)*pichNewCur;
  9137. INT cchwspInfo = *pcchwspInfo;
  9138. WORD *pspInfoCur;
  9139. INT cchwspInfoSav, cspInfopair, cchIncDec;
  9140. BOOL fInValue = FALSE;
  9141. cchwspInfo -= 2; // skip the cch & cchRange
  9142. cchwspInfoSav = cchwspInfo;
  9143. if (fLookback)
  9144. pspInfoCur = m_pspInfoOut + cchwspInfo-1; // cch is actual number of char, so its 1 based
  9145. else
  9146. pspInfoCur = m_pspInfoOut;
  9147. cspInfopair = cchwspInfo / 2; // we assume that cchwspInfo will be even number
  9148. ASSERT(cchwspInfo % 2 == 0);
  9149. cchIncDec = (fLookback)? -1 : 1;
  9150. while (cspInfopair > 0)//(pspInfoCur >= m_pspInfoOut)
  9151. {
  9152. WORD dwState, count;
  9153. cspInfopair--; // ready to get next cch & its type
  9154. if (fLookback)
  9155. {
  9156. count = *(WORD *)pspInfoCur--;
  9157. dwState = *(WORD *)pspInfoCur--;
  9158. }
  9159. else
  9160. {
  9161. dwState = *(WORD *)pspInfoCur++;
  9162. count = *(WORD *)pspInfoCur++;
  9163. }
  9164. cchwspInfo -= 2; // previous pair of cch and its type
  9165. switch (dwState)
  9166. {
  9167. case inChar:
  9168. ASSERT(index == 1 || index == 0 || index == 3);
  9169. if (index == 0 || index == 3)
  9170. {
  9171. int countws = 0; // count of white space chars
  9172. while ( pwNew[ichtoktagStart-countws] == ' '
  9173. || pwNew[ichtoktagStart-countws] == '\t'
  9174. || pwNew[ichtoktagStart-countws] == '\r'
  9175. || pwNew[ichtoktagStart-countws] == '\n'
  9176. )
  9177. {
  9178. // skip these white space chars. They shouldn't be here
  9179. countws++;
  9180. if (ichtoktagStart-countws <= 0)
  9181. break;
  9182. }
  9183. if (countws > 0)
  9184. {
  9185. if (ichtoktagStart-countws >= 0)
  9186. {
  9187. memcpy((BYTE*)&pwNew[ichtoktagStart-countws+1], (BYTE *)&pwNew[ichtoktagStart+1], (ichNewCur-ichtoktagStart-1)*sizeof(WCHAR));
  9188. ichNewCur -= countws;
  9189. ichtoktagStart -= countws;
  9190. }
  9191. }
  9192. } // if (index == 0 || index == 3)
  9193. while ( pwNew[ichtoktagStart] != ' '
  9194. && pwNew[ichtoktagStart] != '\t'
  9195. && pwNew[ichtoktagStart] != '\n'
  9196. && pwNew[ichtoktagStart] != '\r'
  9197. && pwNew[ichtoktagStart] != '<'
  9198. && pwNew[ichtoktagStart] != '>'
  9199. && pwNew[ichtoktagStart] != '='
  9200. && (ichNewCur > ichtoktagStart)
  9201. && count > 0
  9202. )
  9203. {
  9204. count--;
  9205. ichtoktagStart += cchIncDec;
  9206. cchRange--;
  9207. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9208. {
  9209. fRet = FALSE;
  9210. goto LRet;
  9211. }
  9212. }
  9213. if (count == 0) // we match the exact chars, we may have more contiguous chars in pwNew
  9214. {
  9215. while ( pwNew[ichtoktagStart] != ' '
  9216. && pwNew[ichtoktagStart] != '\t'
  9217. && pwNew[ichtoktagStart] != '\n'
  9218. && pwNew[ichtoktagStart] != '\r'
  9219. && pwNew[ichtoktagStart] != '<'
  9220. && pwNew[ichtoktagStart] != '>'
  9221. && (pwNew[ichtoktagStart] != '=' || (fInValue /*&& index == 1*/))
  9222. && (ichNewCur > ichtoktagStart)
  9223. )
  9224. {
  9225. ichtoktagStart += cchIncDec;
  9226. cchRange--;
  9227. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9228. {
  9229. fRet = FALSE;
  9230. goto LRet;
  9231. }
  9232. }
  9233. }
  9234. break;
  9235. case inTagOpen:
  9236. case inTagClose:
  9237. case inTagEq:
  9238. // make sure that we have atleast count number of spaces at
  9239. // pwNew[ichtoktagStart-count]
  9240. if (pwNew[ichtoktagStart] == '=' /* && index == 1*/)
  9241. fInValue = TRUE;
  9242. else
  9243. fInValue = FALSE;
  9244. while ( (pwNew[ichtoktagStart] == '<' || pwNew[ichtoktagStart] == '>' || pwNew[ichtoktagStart] == '=')
  9245. && count > 0
  9246. )
  9247. {
  9248. count--;
  9249. ichtoktagStart += cchIncDec;
  9250. cchRange--;
  9251. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9252. {
  9253. fRet = FALSE;
  9254. goto LRet;
  9255. }
  9256. }
  9257. break;
  9258. case inSpace:
  9259. // make sure that we have atleast count number of spaces at
  9260. // pwNew[ichtoktagStart-count]
  9261. fInValue = FALSE;
  9262. while (pwNew[ichtoktagStart] == ' ' && count > 0)
  9263. {
  9264. count--;
  9265. ichtoktagStart += cchIncDec;
  9266. cchRange--;
  9267. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9268. {
  9269. fRet = FALSE;
  9270. goto LRet;
  9271. }
  9272. }
  9273. if (count == 0) // we matched exact spaces, we may have more spaces in pwNew
  9274. {
  9275. if (fLookback)
  9276. {
  9277. INT countT = 0;
  9278. //INT ichtoktagStartSav = ichtoktagStart;
  9279. if (cspInfopair == 0)
  9280. break;
  9281. ASSERT(index == 0 || index == 3);
  9282. // REMOVE EXTRA SPACES here.
  9283. while (pwNew[ichtoktagStart-countT] == ' ')
  9284. countT++;
  9285. if (countT > 0)
  9286. {
  9287. if (ichNewCur-(ichtoktagStart) > 0)
  9288. {
  9289. memmove((BYTE *)(pwNew+ichtoktagStart-countT+1),
  9290. (BYTE *)(pwNew+ichtoktagStart),
  9291. (ichNewCur-(ichtoktagStart))*sizeof(WCHAR));
  9292. ichNewCur -= (countT-1);
  9293. ichtoktagStart -= (countT-1);
  9294. while (countT > 1)
  9295. {
  9296. pwNew[ichNewCur+countT-2] = '\0';
  9297. countT--;
  9298. }
  9299. }
  9300. }
  9301. }
  9302. else if (!fLookback)
  9303. {
  9304. INT countT = -1;
  9305. ASSERT(index == 1 || index == 2);
  9306. // look ahead into pspInfoCur to see what the next parameters should be
  9307. if ((index == 1) && (*(WORD *)pspInfoCur == inChar))
  9308. {
  9309. while ( pwNew[ichtoktagStart] == ' '
  9310. || pwNew[ichtoktagStart] == '\r'
  9311. || pwNew[ichtoktagStart] == '\n'
  9312. || pwNew[ichtoktagStart] == '\t'
  9313. )
  9314. {
  9315. countT++;
  9316. ichtoktagStart += cchIncDec;
  9317. }
  9318. }
  9319. else
  9320. {
  9321. while (pwNew[ichtoktagStart] == ' ')
  9322. {
  9323. countT++;
  9324. ichtoktagStart += cchIncDec;
  9325. }
  9326. }
  9327. if (countT > 0)
  9328. {
  9329. if (ichNewCur-(ichtoktagStart+1) > 0)
  9330. {
  9331. memmove((BYTE *)(pwNew+ichtoktagStart-countT-1),
  9332. (BYTE *)(pwNew+ichtoktagStart),
  9333. (ichNewCur-ichtoktagStart)*sizeof(WCHAR));
  9334. ichNewCur -= (countT+1);
  9335. ichtoktagStart -= (countT+1);
  9336. while (countT >= 0)
  9337. {
  9338. pwNew[ichNewCur+countT] = '\0';
  9339. countT--;
  9340. }
  9341. }
  9342. }
  9343. }
  9344. }
  9345. else
  9346. {
  9347. if (fLookback)
  9348. {
  9349. ASSERT(index == 0 || index == 3);
  9350. if ((int)(ichNewCur-ichtoktagStart-1) >= 0)
  9351. {
  9352. // insert spaces after ichtoktagStart
  9353. memmove((BYTE *)&pwNew[ichtoktagStart+1+count],
  9354. (BYTE *)&pwNew[ichtoktagStart+1],
  9355. (ichNewCur-ichtoktagStart-1)*sizeof(WCHAR));
  9356. ichNewCur += count;
  9357. //ichtoktagStart++;
  9358. while (count > 0)
  9359. {
  9360. pwNew[ichtoktagStart+count] = ' ';
  9361. count--;
  9362. }
  9363. //ichtoktagStart--; // compensate
  9364. }
  9365. }
  9366. else
  9367. {
  9368. ASSERT(index == 1 || index == 2);
  9369. if ((int)(ichNewCur-ichtoktagStart) >= 0)
  9370. {
  9371. int countT = count;
  9372. // insert spaces at ichtoktagStart and set ichtoktagStart after last space
  9373. memmove((BYTE *)&pwNew[ichtoktagStart+count],
  9374. (BYTE *)&pwNew[ichtoktagStart],
  9375. (ichNewCur-ichtoktagStart)*sizeof(WCHAR));
  9376. ichNewCur += count;
  9377. while (count > 0)
  9378. {
  9379. ASSERT((INT)(ichtoktagStart+count-1) >= 0);
  9380. pwNew[ichtoktagStart+count-1] = ' ';
  9381. count--;
  9382. }
  9383. ichtoktagStart += countT;
  9384. }
  9385. }
  9386. }
  9387. break;
  9388. case inEOL:
  9389. // make sure that we have atleast count number of EOLs at
  9390. // pwNew[ichtoktagStart-count]
  9391. // if fLookback, then we get '\n', else we get '\r'
  9392. fInValue = FALSE;
  9393. while ((pwNew[ichtoktagStart] == '\n' || pwNew[ichtoktagStart] == '\r') && count > 0)
  9394. {
  9395. count--;
  9396. cchRange -= 2;
  9397. ichtoktagStart += cchIncDec; // assume '\r' or '\n'
  9398. ichtoktagStart += cchIncDec; // assume '\r' or '\n'
  9399. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9400. {
  9401. fRet = FALSE;
  9402. goto LRet;
  9403. }
  9404. }
  9405. if (count == 0) // we matched exact EOLs, we may have more EOLs in pwNew
  9406. {
  9407. if (fLookback)
  9408. {
  9409. INT countT = 0;
  9410. ASSERT(index == 0 || index == 3);
  9411. // REMOVE EXTRA EOLs here.
  9412. while ( pwNew[ichtoktagStart-countT] == '\r'
  9413. || pwNew[ichtoktagStart-countT] == '\n'
  9414. )
  9415. countT++;
  9416. if (countT > 0)
  9417. {
  9418. if (ichNewCur-(ichtoktagStart) > 0)
  9419. {
  9420. memmove((BYTE *)(pwNew+ichtoktagStart-countT+1),
  9421. (BYTE *)(pwNew+ichtoktagStart),
  9422. (ichNewCur-(ichtoktagStart))*sizeof(WCHAR));
  9423. ichNewCur -= (countT-1);
  9424. ichtoktagStart -= (countT-1);
  9425. while (countT > 1)
  9426. {
  9427. pwNew[ichNewCur+countT-2] = '\0';
  9428. countT--;
  9429. }
  9430. }
  9431. }
  9432. }
  9433. else if (!fLookback)
  9434. {
  9435. INT countT = 0;
  9436. ASSERT(index == 1 || index == 2);
  9437. // REMOVE EXTRA EOLS here.
  9438. // look ahead into pspInfoCur to see what the next parameters should be
  9439. if ((index == 1) && (*(WORD *)pspInfoCur == inChar))
  9440. {
  9441. while ( pwNew[ichtoktagStart] == ' '
  9442. || pwNew[ichtoktagStart] == '\r'
  9443. || pwNew[ichtoktagStart] == '\n'
  9444. || pwNew[ichtoktagStart] == '\t'
  9445. )
  9446. {
  9447. countT++;
  9448. ichtoktagStart += cchIncDec;
  9449. }
  9450. }
  9451. else
  9452. {
  9453. while ( pwNew[ichtoktagStart] == '\r'
  9454. || pwNew[ichtoktagStart] == '\n'
  9455. )
  9456. {
  9457. countT++;
  9458. ichtoktagStart += cchIncDec;
  9459. }
  9460. }
  9461. //ASSERT(countT % 2 == 0); // assert that countT is an even number, because we should find \r & \n always in pair
  9462. if (countT > 0)
  9463. {
  9464. if (ichNewCur-(ichtoktagStart+1) > 0)
  9465. {
  9466. memmove((BYTE *)(pwNew+ichtoktagStart-countT),
  9467. (BYTE *)(pwNew+ichtoktagStart),
  9468. (ichNewCur-ichtoktagStart)*sizeof(WCHAR));
  9469. ichNewCur -= (countT);
  9470. ichtoktagStart -= (countT);
  9471. while (countT >= 0)
  9472. {
  9473. pwNew[ichNewCur+countT] = '\0';
  9474. countT--;
  9475. }
  9476. }
  9477. }
  9478. }
  9479. }
  9480. else
  9481. {
  9482. if (fLookback)
  9483. {
  9484. INT i;
  9485. ASSERT(index == 0 || index == 3);
  9486. if ((int)(ichNewCur-ichtoktagStart-1) >= 0)
  9487. {
  9488. // insert EOLs after ichtoktagStart
  9489. memmove((BYTE *)&pwNew[ichtoktagStart+1+count*2],
  9490. (BYTE *)&pwNew[ichtoktagStart+1],
  9491. (ichNewCur-ichtoktagStart-1)*sizeof(WCHAR));
  9492. ichNewCur += count*2;
  9493. count *= 2;
  9494. ichtoktagStart++;
  9495. for (i = 0; i < count; i+=2)
  9496. {
  9497. pwNew[ichtoktagStart+i] = '\r';
  9498. pwNew[ichtoktagStart+i+1] = '\n';
  9499. }
  9500. ichtoktagStart--; // compensate for prior increment
  9501. }
  9502. }
  9503. else
  9504. {
  9505. INT i;
  9506. ASSERT(index == 1 || index == 2);
  9507. // insert spaces at ichtoktagStart and set ichtoktagStart after last space
  9508. if ((int)(ichNewCur-ichtoktagStart) >= 0)
  9509. {
  9510. memmove((BYTE *)&pwNew[ichtoktagStart+count*2],
  9511. (BYTE *)&pwNew[ichtoktagStart],
  9512. (ichNewCur-ichtoktagStart)*sizeof(WCHAR));
  9513. ichNewCur += count*2;
  9514. count *= 2;
  9515. for (i=0; i < count; i+=2)
  9516. {
  9517. pwNew[ichtoktagStart+i] = '\r';
  9518. pwNew[ichtoktagStart+i+1] = '\n';
  9519. }
  9520. ichtoktagStart += count;
  9521. }
  9522. }
  9523. }
  9524. break;
  9525. case inTab:
  9526. // make sure that we have atleast count number of spaces at
  9527. // pwNew[ichtoktagStart-count]
  9528. fInValue = FALSE;
  9529. while (pwNew[ichtoktagStart] == '\t' && count > 0)
  9530. {
  9531. count--;
  9532. ichtoktagStart += cchIncDec;
  9533. cchRange--;
  9534. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9535. {
  9536. fRet = FALSE;
  9537. goto LRet;
  9538. }
  9539. }
  9540. if (count == 0) // we matched exact spaces, we may have more tabs in pwNew
  9541. {
  9542. // skip extra spaces in pwNew, if we had more spaces in pwNew than count
  9543. while (pwNew[ichtoktagStart] == '\t')
  9544. {
  9545. ichtoktagStart += cchIncDec;
  9546. cchRange--;
  9547. if (ichtoktagStart < 0 || cchRange < 0) // boundary condition
  9548. {
  9549. fRet = FALSE;
  9550. goto LRet;
  9551. }
  9552. }
  9553. }
  9554. else
  9555. {
  9556. INT ichSav = ichtoktagStart;
  9557. INT i;
  9558. ASSERT(count > 0);
  9559. // insert these many extra tabs at pwNew[ichtoktagStart] and increment ichNewCur
  9560. if (fLookback)
  9561. ichtoktagStart++;
  9562. if (ichNewCur-ichtoktagStart > 0)
  9563. {
  9564. memmove((BYTE *)(pwNew+ichtoktagStart+count),
  9565. (BYTE *)(pwNew+ichtoktagStart),
  9566. (ichNewCur-ichtoktagStart)*sizeof(WCHAR));
  9567. }
  9568. for (i = 0; i < count; i++)
  9569. pwNew[ichtoktagStart+i] = '\t';
  9570. ichNewCur += count;
  9571. if (fLookback)
  9572. ichtoktagStart = ichSav;
  9573. else
  9574. ichtoktagStart += count;
  9575. }
  9576. break;
  9577. } // switch (dwState)
  9578. } // while ()
  9579. if ( cspInfopair == 0
  9580. && pwNew[ichNewCur-1] == '>'
  9581. && ichNewCur > ichtoktagStart
  9582. && !fLookback
  9583. && index == 1)
  9584. {
  9585. INT countT = 0;
  9586. ASSERT(cchIncDec == 1);
  9587. // This means that we may have extra spaces & EOLs from ichtoktagStart to '>'
  9588. // REMOVE EXTRA SPACES EOLS here.
  9589. while ( pwNew[ichtoktagStart+countT] == ' '
  9590. || pwNew[ichtoktagStart+countT] == '\r'
  9591. || pwNew[ichtoktagStart+countT] == '\n'
  9592. || pwNew[ichtoktagStart+countT] == '\t'
  9593. )
  9594. {
  9595. countT++;
  9596. }
  9597. if (countT > 0 && pwNew[ichtoktagStart+countT] == '>')
  9598. {
  9599. if (ichNewCur-(ichtoktagStart+1) > 0)
  9600. {
  9601. memmove((BYTE *)(pwNew+ichtoktagStart),
  9602. (BYTE *)(pwNew+ichtoktagStart+countT),
  9603. (ichNewCur-(ichtoktagStart+countT))*sizeof(WCHAR));
  9604. ichNewCur -= (countT);
  9605. ichtoktagStart -= (countT);
  9606. while (countT > 0)
  9607. {
  9608. pwNew[ichNewCur+countT-1] = '\0';
  9609. countT--;
  9610. }
  9611. }
  9612. }
  9613. // Next time around - we can do the following...
  9614. // look back from ichtoktagStart and check if we have any spaces/eols.
  9615. // if we do, there is a likelihood that these shouldn't have been there.
  9616. // Here is how they get there - If we had spaces between the parameter and
  9617. // the '=' and its value, those spacves are removed by Trident. We then go
  9618. // in and add those spaces at the end rather than at proper place because
  9619. // we don't break up the text. e.g. "width = 23" --> "width=23".
  9620. // Now, because we don't break that text, we end up inserting these spaces
  9621. // at the end. Lets remove them.
  9622. }
  9623. else if ( cspInfopair == 0
  9624. && fLookback
  9625. && (index == 0 || index == 3)) /* VID6 - bug 18207 */
  9626. {
  9627. INT countT = 0;
  9628. ASSERT(cchIncDec == -1);
  9629. // This means that we may have extra spaces & EOLs before ichtoktagStart to '>'
  9630. // REMOVE EXTRA SPACES EOLS here.
  9631. while ( pwNew[ichtoktagStart-countT] == ' '
  9632. || pwNew[ichtoktagStart-countT] == '\r'
  9633. || pwNew[ichtoktagStart-countT] == '\n'
  9634. || pwNew[ichtoktagStart-countT] == '\t'
  9635. )
  9636. {
  9637. countT++;
  9638. }
  9639. if (countT > 0 && pwNew[ichtoktagStart-countT] == '>')
  9640. {
  9641. if (ichNewCur-(ichtoktagStart+1) > 0)
  9642. {
  9643. memmove((BYTE *)(pwNew+ichtoktagStart-countT+1),
  9644. (BYTE *)(pwNew+ichtoktagStart+1),
  9645. (ichNewCur-(ichtoktagStart+1))*sizeof(WCHAR));
  9646. ichNewCur -= countT;
  9647. ichtoktagStart -= (countT); // this doesn't matter because we will exit after this
  9648. while (countT > 0)
  9649. {
  9650. pwNew[ichNewCur+countT-1] = '\0';
  9651. countT--;
  9652. }
  9653. }
  9654. }
  9655. }
  9656. LRet:
  9657. m_pspInfoOut = m_pspInfoOut + cchwspInfoSav;
  9658. *pcchwspInfo = cchwspInfo;
  9659. *pichNewCur = ichNewCur;
  9660. return(fRet);
  9661. }