Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1994.
  5. //
  6. // File: TSource.cxx
  7. //
  8. // Contents: TEXT_SOURCE implementation
  9. //
  10. // Classes: CTextSource
  11. //
  12. // History: 14-Apr-94 KyleP Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <tsource.hxx>
  18. #include <mapper.hxx>
  19. //+-------------------------------------------------------------------------
  20. //
  21. // Member: CTextSource::CTextSource, public
  22. //
  23. // Synopsis: Constructor
  24. //
  25. // Arguments: [pFilter] -- IFilter (source of data)
  26. // [Stat] -- Chunk statistics
  27. //
  28. // History: 01-Aug-93 AmyA Created
  29. // 14-Apr-94 KyleP Sync with wordbreaker spec
  30. //
  31. //--------------------------------------------------------------------------
  32. CTextSource::CTextSource( IFilter * pFilter, STAT_CHUNK & Stat, CSourceMapper* pMapper )
  33. : _pMapper (pMapper),
  34. _pFilter(pFilter),
  35. _Stat( Stat ),
  36. _sc( S_OK )
  37. {
  38. #if CIDBG == 1
  39. CFullPropSpec & ps = *((CFullPropSpec *)&Stat.attribute);
  40. ciDebugOut(( DEB_WORDS,
  41. "TEXT SOURCE: Initial chunk of "
  42. "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\\",
  43. ps.GetPropSet().Data1,
  44. ps.GetPropSet().Data2,
  45. ps.GetPropSet().Data3,
  46. ps.GetPropSet().Data4[0], ps.GetPropSet().Data4[1],
  47. ps.GetPropSet().Data4[2], ps.GetPropSet().Data4[3],
  48. ps.GetPropSet().Data4[4], ps.GetPropSet().Data4[5],
  49. ps.GetPropSet().Data4[6], ps.GetPropSet().Data4[7] ));
  50. if ( ps.IsPropertyName() )
  51. ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME,
  52. "%ws\n", ps.GetPropertyName() ));
  53. else
  54. ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME,
  55. "0x%x\n", ps.GetPropertyPropid() ));
  56. #endif // CIDBG == 1
  57. iEnd = 0;
  58. iCur = 0;
  59. awcBuffer = _awcFilterBuffer;
  60. pfnFillTextBuffer = CTextSource::FillBuf;
  61. if (_pMapper)
  62. {
  63. if (_Stat.idChunk == _Stat.idChunkSource)
  64. {
  65. _pMapper->NewChunk ( _Stat.idChunk, 0 );
  66. }
  67. else
  68. {
  69. _pMapper->NewDerivedChunk (
  70. _Stat.idChunkSource,
  71. _Stat.cwcStartSource,
  72. _Stat.cwcLenSource);
  73. }
  74. }
  75. FillBuf( this );
  76. }
  77. //+-------------------------------------------------------------------------
  78. //
  79. // Member: CTextSource::FillBuf, public
  80. //
  81. // Synopsis: Fills buffer with IFilter::GetText and IFilter::GetChunk
  82. //
  83. // History: 01-Aug-93 AmyA Created
  84. // 20-Apr-94 KyleP Sync with spec
  85. //
  86. // Notes: NOTE! In several places, this function casts const away
  87. // from awcBuffer. This is an acceptable cast from const to
  88. // non-const. The buffer is const to the client but non-const
  89. // to the server.
  90. //
  91. //--------------------------------------------------------------------------
  92. SCODE CTextSource::FillBuf( TEXT_SOURCE * pTextSource )
  93. {
  94. CTextSource * pthis = (CTextSource *)pTextSource;
  95. //
  96. // Never continue past an error condition other than FILTER_E_NO_MORE_TEXT
  97. //
  98. if ( FAILED( pthis->_sc ) && pthis->_sc != FILTER_E_NO_MORE_TEXT )
  99. return( pthis->_sc );
  100. // Don't allow wordbreaker bugs with iEnd/iCur to overwrite memory.
  101. Win4Assert ( pthis->iEnd >= pthis->iCur );
  102. if ( pthis->iCur > pthis->iEnd )
  103. {
  104. pthis->_sc = WBREAK_E_END_OF_TEXT;
  105. return WBREAK_E_END_OF_TEXT;
  106. }
  107. //
  108. // Move any existing text to beginning of buffer.
  109. //
  110. ULONG ccLeftOver = pthis->iEnd - pthis->iCur;
  111. if ( ccLeftOver > 0 )
  112. {
  113. RtlMoveMemory( (WCHAR *)pthis->awcBuffer,
  114. &pthis->awcBuffer[pthis->iCur],
  115. ccLeftOver * sizeof (WCHAR) );
  116. }
  117. if (pthis->_pMapper)
  118. {
  119. // this much has been processed from the current chunk
  120. pthis->_pMapper->Advance ( pthis->iCur );
  121. }
  122. pthis->iCur = 0;
  123. pthis->iEnd = ccLeftOver;
  124. ULONG ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
  125. const BUFFER_SLOP = 10; // Buffer is attempted to be filled until BUFFER_SLOP remains
  126. //
  127. // Get some more text. If *previous* call to GetText returned
  128. // FILTER_S_LAST_TEXT, or FILTER_E_NO_MORE_TEXT then don't even
  129. // bother trying.
  130. //
  131. if ( pthis->_sc == FILTER_S_LAST_TEXT || pthis->_sc == FILTER_E_NO_MORE_TEXT )
  132. pthis->_sc = FILTER_E_NO_MORE_TEXT;
  133. else
  134. {
  135. pthis->_sc = pthis->_pFilter->GetText( &ccRead,
  136. (WCHAR *) &pthis->awcBuffer[ccLeftOver] );
  137. if ( SUCCEEDED( pthis->_sc ) )
  138. {
  139. pthis->iEnd += ccRead;
  140. ccLeftOver += ccRead;
  141. ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
  142. while ( pthis->_sc == S_OK && ccRead > BUFFER_SLOP )
  143. {
  144. //
  145. // Attempt to fill in as much of buffer as possible before returning
  146. //
  147. pthis->_sc = pthis->_pFilter->GetText( &ccRead,
  148. (WCHAR *) &pthis->awcBuffer[ccLeftOver] );
  149. if ( SUCCEEDED( pthis->_sc ) )
  150. {
  151. pthis->iEnd += ccRead;
  152. ccLeftOver += ccRead;
  153. ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
  154. }
  155. }
  156. #if CIDBG == 1
  157. DebugPrintBuffer( pthis );
  158. #endif
  159. //
  160. // Either return FILTER_S_LAST_TEXT or return S_OK because we have succeeded in
  161. // adding text to the buffer
  162. //
  163. if ( pthis->_sc == FILTER_S_LAST_TEXT )
  164. return FILTER_S_LAST_TEXT;
  165. else
  166. return S_OK;
  167. }
  168. if ( pthis->_sc != FILTER_E_NO_MORE_TEXT )
  169. {
  170. //
  171. // Weird failure, hence return, else goto next chunk
  172. //
  173. return pthis->_sc;
  174. }
  175. }
  176. //
  177. // Go to next chunk, if necessary.
  178. //
  179. while ( pthis->_sc == FILTER_E_NO_MORE_TEXT )
  180. {
  181. pthis->_sc = pthis->_pFilter->GetChunk( &pthis->_Stat );
  182. if ( pthis->_sc == FILTER_E_END_OF_CHUNKS )
  183. return WBREAK_E_END_OF_TEXT;
  184. if ( pthis->_sc == FILTER_E_PARTIALLY_FILTERED )
  185. return WBREAK_E_END_OF_TEXT;
  186. if ( FAILED( pthis->_sc ) )
  187. return( pthis->_sc );
  188. if ( pthis->_Stat.flags & CHUNK_VALUE )
  189. {
  190. pthis->_sc = FILTER_E_NO_TEXT;
  191. return WBREAK_E_END_OF_TEXT;
  192. }
  193. if ( pthis->_Stat.breakType != CHUNK_NO_BREAK )
  194. {
  195. pthis->_sc = WBREAK_E_END_OF_TEXT;
  196. return WBREAK_E_END_OF_TEXT;
  197. }
  198. ciDebugOut(( DEB_WORDS, "TEXT SOURCE: NoBreak chunk\n" ));
  199. if (pthis->_pMapper)
  200. {
  201. ULONG idChunk = pthis->_Stat.idChunk;
  202. if (idChunk == pthis->_Stat.idChunkSource)
  203. {
  204. pthis->_pMapper->NewChunk ( idChunk, ccLeftOver );
  205. }
  206. else
  207. {
  208. pthis->_sc = WBREAK_E_END_OF_TEXT;
  209. return WBREAK_E_END_OF_TEXT;
  210. }
  211. }
  212. ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
  213. pthis->_sc = pthis->_pFilter->GetText( &ccRead,
  214. (WCHAR *) &pthis->awcBuffer[ccLeftOver] );
  215. if ( SUCCEEDED( pthis->_sc ) )
  216. {
  217. pthis->iEnd += ccRead;
  218. ccLeftOver += ccRead;
  219. ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
  220. while ( pthis->_sc == S_OK && ccRead > BUFFER_SLOP )
  221. {
  222. //
  223. // Attempt to fill in as much of buffer as possible before returning
  224. //
  225. pthis->_sc = pthis->_pFilter->GetText( &ccRead,
  226. (WCHAR *) &pthis->awcBuffer[ccLeftOver] );
  227. if ( SUCCEEDED( pthis->_sc ) )
  228. {
  229. pthis->iEnd += ccRead;
  230. ccLeftOver += ccRead;
  231. ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
  232. }
  233. }
  234. #if CIDBG == 1
  235. DebugPrintBuffer( pthis );
  236. #endif
  237. //
  238. // Either return FILTER_S_LAST_TEXT or return S_OK because we have succeeded in
  239. // adding text to the buffer
  240. //
  241. if ( pthis->_sc == FILTER_S_LAST_TEXT )
  242. return FILTER_S_LAST_TEXT;
  243. else
  244. return S_OK;
  245. }
  246. }
  247. if ( FAILED( pthis->_sc ) )
  248. return( pthis->_sc );
  249. if ( ccRead == 0 )
  250. return WBREAK_E_END_OF_TEXT;
  251. Win4Assert( pthis->iCur == 0 );
  252. Win4Assert( pthis->iEnd == ccLeftOver );
  253. ciDebugOut(( DEB_WORDS, "TEXT SOURCE: Fill buffer with %d characters. %d left over\n",
  254. pthis->iEnd, ccLeftOver ));
  255. return S_OK;
  256. }
  257. //+-------------------------------------------------------------------------
  258. //
  259. // Member: CTextSource::DebugPrintBuffer
  260. //
  261. // Synopsis: Debug print the text buffer
  262. //
  263. // Arguments: [pThis] -- Pointer to text source
  264. //
  265. // History: 08-Apr-97 SitaramR Created
  266. //
  267. //--------------------------------------------------------------------------
  268. void CTextSource::DebugPrintBuffer( CTextSource *pthis )
  269. {
  270. #if CIDBG == 1
  271. if ( ciInfoLevel & DEB_WORDS )
  272. {
  273. ciDebugOut(( DEB_WORDS, "CTextSource::FillBuf -- iCur = %u, iEnd = %u\n",
  274. pthis->iCur, pthis->iEnd ));
  275. BOOL fOk = TRUE;
  276. for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ )
  277. {
  278. if ( pthis->awcBuffer[i] > 0xFF )
  279. {
  280. fOk = FALSE;
  281. break;
  282. }
  283. }
  284. if ( fOk )
  285. {
  286. unsigned j = 0;
  287. WCHAR awcTemp[71];
  288. for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ )
  289. {
  290. awcTemp[j] = pthis->awcBuffer[i];
  291. j++;
  292. if ( j == sizeof(awcTemp)/sizeof(awcTemp[0]) - 1 )
  293. {
  294. awcTemp[j] = 0;
  295. ciDebugOut(( DEB_WORDS, "%ws\n", awcTemp ));
  296. j = 0;
  297. }
  298. }
  299. awcTemp[j] = 0;
  300. ciDebugOut(( DEB_WORDS, "%ws\n", awcTemp ));
  301. }
  302. else
  303. {
  304. unsigned j = 0;
  305. for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ )
  306. {
  307. if ( 0 == j )
  308. ciDebugOut(( DEB_WORDS, "%04X", pthis->awcBuffer[i] ));
  309. else if ( 14 == j )
  310. {
  311. ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, " %04X\n", pthis->awcBuffer[i] ));
  312. }
  313. else
  314. ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, " %04X", pthis->awcBuffer[i] ));
  315. j++;
  316. if ( j > 14 )
  317. j = 0;
  318. }
  319. ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, "\n" ));
  320. }
  321. }
  322. #endif
  323. }