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.

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