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.

2463 lines
85 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. _output.h
  5. Abstract:
  6. Performance critical routine for Single Binary
  7. Each function will be created with two flavors FE and non FE
  8. Author:
  9. KazuM Jun.11.1997
  10. Revision History:
  11. --*/
  12. #define WWSB_NEUTRAL_FILE 1
  13. #if !defined(FE_SB)
  14. #error This header file should be included with FE_SB
  15. #endif
  16. #if !defined(WWSB_FE) && !defined(WWSB_NOFE)
  17. #error Either WWSB_FE and WWSB_NOFE must be defined.
  18. #endif
  19. #if defined(WWSB_FE) && defined(WWSB_NOFE)
  20. #error Both WWSB_FE and WWSB_NOFE defined.
  21. #endif
  22. #include "dispatch.h"
  23. #if defined(WWSB_FE)
  24. #pragma alloc_text(FE_TEXT, FE_StreamWriteToScreenBuffer)
  25. #pragma alloc_text(FE_TEXT, FE_WriteRectToScreenBuffer)
  26. #pragma alloc_text(FE_TEXT, FE_WriteRegionToScreen)
  27. #pragma alloc_text(FE_TEXT, FE_WriteToScreen)
  28. #pragma alloc_text(FE_TEXT, FE_WriteOutputString)
  29. #pragma alloc_text(FE_TEXT, FE_FillOutput)
  30. #pragma alloc_text(FE_TEXT, FE_FillRectangle)
  31. #pragma alloc_text(FE_TEXT, FE_PolyTextOutCandidate)
  32. #pragma alloc_text(FE_TEXT, FE_ConsolePolyTextOut)
  33. #endif
  34. #if defined(WWSB_NOFE)
  35. VOID
  36. SB_StreamWriteToScreenBuffer(
  37. IN PWCHAR String,
  38. IN SHORT StringLength,
  39. IN PSCREEN_INFORMATION ScreenInfo
  40. )
  41. #else
  42. VOID
  43. FE_StreamWriteToScreenBuffer(
  44. IN PWCHAR String,
  45. IN SHORT StringLength,
  46. IN PSCREEN_INFORMATION ScreenInfo,
  47. IN PCHAR StringA
  48. )
  49. #endif
  50. {
  51. SHORT RowIndex;
  52. PROW Row;
  53. PWCHAR Char;
  54. COORD TargetPoint;
  55. DBGOUTPUT(("StreamWriteToScreenBuffer\n"));
  56. #ifdef WWSB_FE
  57. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  58. #endif
  59. ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
  60. TargetPoint = ScreenInfo->BufferInfo.TextInfo.CursorPosition;
  61. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
  62. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  63. DBGOUTPUT(("RowIndex = %x, Row = %x, TargetPoint = (%x,%x)\n",
  64. RowIndex, Row, TargetPoint.X, TargetPoint.Y));
  65. //
  66. // copy chars
  67. //
  68. #ifdef WWSB_FE
  69. BisectWrite(StringLength,TargetPoint,ScreenInfo);
  70. if (TargetPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 &&
  71. TargetPoint.X+StringLength >= ScreenInfo->ScreenBufferSize.X &&
  72. *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) & ATTR_LEADING_BYTE
  73. ) {
  74. *(String+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) = UNICODE_SPACE;
  75. *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) = 0;
  76. if (StringLength > ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) {
  77. *(String+ScreenInfo->ScreenBufferSize.X-TargetPoint.X) = UNICODE_SPACE;
  78. *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X) = 0;
  79. }
  80. }
  81. RtlCopyMemory(&Row->CharRow.KAttrs[TargetPoint.X],StringA,StringLength*sizeof(CHAR));
  82. #endif
  83. RtlCopyMemory(&Row->CharRow.Chars[TargetPoint.X],String,StringLength*sizeof(WCHAR));
  84. // recalculate first and last non-space char
  85. Row->CharRow.OldLeft = Row->CharRow.Left;
  86. if (TargetPoint.X < Row->CharRow.Left) {
  87. PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X];
  88. for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++)
  89. ;
  90. Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars);
  91. }
  92. Row->CharRow.OldRight = Row->CharRow.Right;
  93. if ((TargetPoint.X+StringLength) >= Row->CharRow.Right) {
  94. PWCHAR FirstChar = Row->CharRow.Chars;
  95. for (Char=&Row->CharRow.Chars[TargetPoint.X+StringLength-1];*Char==(WCHAR)' ' && Char >= FirstChar;Char--)
  96. ;
  97. Row->CharRow.Right = (SHORT)(Char+1-FirstChar);
  98. }
  99. //
  100. // see if attr string is different. if so, allocate a new
  101. // attr buffer and merge the two strings.
  102. //
  103. if (Row->AttrRow.Length != 1 ||
  104. Row->AttrRow.Attrs->Attr != ScreenInfo->Attributes) {
  105. PATTR_PAIR NewAttrs;
  106. WORD NewAttrsLength;
  107. ATTR_PAIR Attrs;
  108. Attrs.Length = StringLength;
  109. Attrs.Attr = ScreenInfo->Attributes;
  110. if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs,
  111. Row->AttrRow.Length,
  112. &Attrs,
  113. 1,
  114. &NewAttrs,
  115. &NewAttrsLength,
  116. TargetPoint.X,
  117. (SHORT)(TargetPoint.X+StringLength-1),
  118. Row,
  119. ScreenInfo
  120. ))) {
  121. return;
  122. }
  123. if (Row->AttrRow.Length > 1) {
  124. ConsoleHeapFree(Row->AttrRow.Attrs);
  125. }
  126. else {
  127. ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair);
  128. }
  129. Row->AttrRow.Attrs = NewAttrs;
  130. Row->AttrRow.Length = NewAttrsLength;
  131. Row->CharRow.OldLeft = INVALID_OLD_LENGTH;
  132. Row->CharRow.OldRight = INVALID_OLD_LENGTH;
  133. }
  134. ResetTextFlags(ScreenInfo,
  135. TargetPoint.X,
  136. TargetPoint.Y,
  137. TargetPoint.X + StringLength - 1,
  138. TargetPoint.Y);
  139. }
  140. #define CHAR_OF_PCI(p) (((PCHAR_INFO)(p))->Char.AsciiChar)
  141. #define WCHAR_OF_PCI(p) (((PCHAR_INFO)(p))->Char.UnicodeChar)
  142. #define ATTR_OF_PCI(p) (((PCHAR_INFO)(p))->Attributes)
  143. #define SIZEOF_CI_CELL sizeof(CHAR_INFO)
  144. #define CHAR_OF_VGA(p) (p[0])
  145. #define ATTR_OF_VGA(p) (p[1])
  146. #ifdef i386
  147. #define SIZEOF_VGA_CELL 2
  148. #else // risc
  149. #define SIZEOF_VGA_CELL 4
  150. #endif
  151. #define COMMON_LVB_MASK 0x33
  152. #define ATTR_OF_COMMON_LVB(p) (ATTR_OF_VGA(p) + (((p[2] & ~COMMON_LVB_MASK)) << 8))
  153. #define SIZEOF_COMMON_LVB_CELL 4
  154. VOID
  155. WWSB_WriteRectToScreenBuffer(
  156. PBYTE Source,
  157. COORD SourceSize,
  158. PSMALL_RECT SourceRect,
  159. PSCREEN_INFORMATION ScreenInfo,
  160. COORD TargetPoint,
  161. IN UINT Codepage
  162. )
  163. /*++
  164. Routine Description:
  165. This routine copies a rectangular region to the screen buffer.
  166. no clipping is done.
  167. The source should contain Unicode or UnicodeOem chars.
  168. Arguments:
  169. Source - pointer to source buffer (a real VGA buffer or CHAR_INFO[])
  170. SourceSize - dimensions of source buffer
  171. SourceRect - rectangle in source buffer to copy
  172. ScreenInfo - pointer to screen info
  173. TargetPoint - upper left coordinates of target rectangle
  174. Codepage - codepage to translate real VGA buffer from,
  175. 0xFFFFFFF if Source is CHAR_INFO[] (not requiring translation)
  176. Return Value:
  177. none.
  178. --*/
  179. {
  180. PBYTE SourcePtr;
  181. SHORT i,j;
  182. SHORT XSize,YSize;
  183. BOOLEAN WholeSource;
  184. SHORT RowIndex;
  185. PROW Row;
  186. PWCHAR Char;
  187. ATTR_PAIR Attrs[80];
  188. PATTR_PAIR AttrBuf;
  189. PATTR_PAIR Attr;
  190. SHORT AttrLength;
  191. BOOL bVGABuffer;
  192. ULONG ulCellSize;
  193. #ifdef WWSB_FE
  194. PCHAR AttrP;
  195. #endif
  196. DBGOUTPUT(("WriteRectToScreenBuffer\n"));
  197. #ifdef WWSB_FE
  198. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  199. #endif
  200. ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
  201. XSize = (SHORT)(SourceRect->Right - SourceRect->Left + 1);
  202. YSize = (SHORT)(SourceRect->Bottom - SourceRect->Top + 1);
  203. AttrBuf = Attrs;
  204. if (XSize > 80) {
  205. AttrBuf = ConsoleHeapAlloc(TMP_TAG, XSize * sizeof(ATTR_PAIR));
  206. if (AttrBuf == NULL) {
  207. return;
  208. }
  209. }
  210. bVGABuffer = (Codepage != 0xFFFFFFFF);
  211. if (bVGABuffer) {
  212. #ifdef WWSB_FE
  213. ulCellSize = (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL;
  214. #else
  215. ulCellSize = SIZEOF_VGA_CELL;
  216. #endif
  217. } else {
  218. ulCellSize = SIZEOF_CI_CELL;
  219. }
  220. SourcePtr = Source;
  221. WholeSource = FALSE;
  222. if (XSize == SourceSize.X) {
  223. ASSERT (SourceRect->Left == 0);
  224. if (SourceRect->Top != 0) {
  225. SourcePtr += SCREEN_BUFFER_POINTER(SourceRect->Left,
  226. SourceRect->Top,
  227. SourceSize.X,
  228. ulCellSize);
  229. }
  230. WholeSource = TRUE;
  231. }
  232. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
  233. for (i=0;i<YSize;i++) {
  234. if (!WholeSource) {
  235. SourcePtr = Source + SCREEN_BUFFER_POINTER(SourceRect->Left,
  236. SourceRect->Top+i,
  237. SourceSize.X,
  238. ulCellSize);
  239. }
  240. //
  241. // copy the chars and attrs into their respective arrays
  242. //
  243. #ifdef WWSB_FE
  244. if (! bVGABuffer) {
  245. COORD TPoint;
  246. TPoint.X = TargetPoint.X;
  247. TPoint.Y = TargetPoint.Y + i;
  248. BisectWrite(XSize,TPoint,ScreenInfo);
  249. if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 &&
  250. TPoint.X+XSize-1 >= ScreenInfo->ScreenBufferSize.X &&
  251. ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & COMMON_LVB_LEADING_BYTE)
  252. {
  253. WCHAR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE;
  254. ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) &= ~COMMON_LVB_SBCSDBCS;
  255. if (XSize-1 > ScreenInfo->ScreenBufferSize.X-TPoint.X-1) {
  256. WCHAR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE;
  257. ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X) &= ~COMMON_LVB_SBCSDBCS;
  258. }
  259. }
  260. }
  261. #endif
  262. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  263. Char = &Row->CharRow.Chars[TargetPoint.X];
  264. #ifdef WWSB_FE
  265. AttrP = &Row->CharRow.KAttrs[TargetPoint.X];
  266. #endif
  267. Attr = AttrBuf;
  268. Attr->Length = 0;
  269. AttrLength = 1;
  270. /*
  271. * Two version of the following loop to keep it fast:
  272. * one for VGA buffers, one for CHAR_INFO buffers.
  273. */
  274. if (bVGABuffer) {
  275. #ifdef WWSB_FE
  276. Attr->Attr = (ScreenInfo->Console->fVDMVideoMode) ? ATTR_OF_COMMON_LVB(SourcePtr) : ATTR_OF_VGA(SourcePtr);
  277. #else
  278. Attr->Attr = ATTR_OF_VGA(SourcePtr);
  279. #endif
  280. for (j = SourceRect->Left;
  281. j <= SourceRect->Right;
  282. j++,
  283. #ifdef WWSB_FE
  284. SourcePtr += (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL
  285. #else
  286. SourcePtr += SIZEOF_VGA_CELL
  287. #endif
  288. ) {
  289. #ifdef WWSB_FE
  290. UCHAR TmpBuff[2];
  291. if (IsDBCSLeadByteConsole(CHAR_OF_VGA(SourcePtr),&ScreenInfo->Console->OutputCPInfo)) {
  292. if (j+1 > SourceRect->Right) {
  293. *Char = UNICODE_SPACE;
  294. *AttrP = 0;
  295. }
  296. else {
  297. TmpBuff[0] = CHAR_OF_VGA(SourcePtr);
  298. TmpBuff[1] = CHAR_OF_VGA((SourcePtr + ((ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL)));
  299. ConvertOutputToUnicode(Codepage,
  300. TmpBuff,
  301. 2,
  302. Char,
  303. 2);
  304. Char++;
  305. j++;
  306. *AttrP++ = ATTR_LEADING_BYTE;
  307. *Char++ = *(Char-1);
  308. *AttrP++ = ATTR_TRAILING_BYTE;
  309. if (ScreenInfo->Console->fVDMVideoMode) {
  310. if (Attr->Attr == ATTR_OF_COMMON_LVB(SourcePtr)) {
  311. Attr->Length += 1;
  312. }
  313. else {
  314. Attr++;
  315. Attr->Length = 1;
  316. Attr->Attr = ATTR_OF_COMMON_LVB(SourcePtr);
  317. AttrLength += 1;
  318. }
  319. }
  320. else
  321. {
  322. if (Attr->Attr == ATTR_OF_VGA(SourcePtr)) {
  323. Attr->Length += 1;
  324. }
  325. else {
  326. Attr++;
  327. Attr->Length = 1;
  328. Attr->Attr = ATTR_OF_VGA(SourcePtr);
  329. AttrLength += 1;
  330. }
  331. }
  332. SourcePtr += (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL;
  333. }
  334. }
  335. else {
  336. ConvertOutputToUnicode(Codepage,
  337. &CHAR_OF_VGA(SourcePtr),
  338. 1,
  339. Char,
  340. 1);
  341. Char++;
  342. *AttrP++ = 0;
  343. }
  344. #else
  345. *Char++ = SB_CharToWcharGlyph(Codepage, CHAR_OF_VGA(SourcePtr));
  346. #endif
  347. #ifdef WWSB_FE
  348. if (ScreenInfo->Console->fVDMVideoMode) {
  349. if (Attr->Attr == ATTR_OF_COMMON_LVB(SourcePtr)) {
  350. Attr->Length += 1;
  351. }
  352. else {
  353. Attr++;
  354. Attr->Length = 1;
  355. Attr->Attr = ATTR_OF_COMMON_LVB(SourcePtr);
  356. AttrLength += 1;
  357. }
  358. }
  359. else
  360. #endif
  361. if (Attr->Attr == ATTR_OF_VGA(SourcePtr)) {
  362. Attr->Length += 1;
  363. }
  364. else {
  365. Attr++;
  366. Attr->Length = 1;
  367. Attr->Attr = ATTR_OF_VGA(SourcePtr);
  368. AttrLength += 1;
  369. }
  370. }
  371. } else {
  372. #ifdef WWSB_FE
  373. Attr->Attr = ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS;
  374. #else
  375. Attr->Attr = ATTR_OF_PCI(SourcePtr);
  376. #endif
  377. for (j = SourceRect->Left;
  378. j <= SourceRect->Right;
  379. j++, SourcePtr += SIZEOF_CI_CELL) {
  380. *Char++ = WCHAR_OF_PCI(SourcePtr);
  381. #ifdef WWSB_FE
  382. // MSKK Apr.02.1993 V-HirotS For KAttr
  383. *AttrP++ = (CHAR)((ATTR_OF_PCI(SourcePtr) & COMMON_LVB_SBCSDBCS) >>8);
  384. #endif
  385. #ifdef WWSB_FE
  386. if (Attr->Attr == (ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS))
  387. #else
  388. if (Attr->Attr == ATTR_OF_PCI(SourcePtr))
  389. #endif
  390. {
  391. Attr->Length += 1;
  392. }
  393. else {
  394. Attr++;
  395. Attr->Length = 1;
  396. #ifdef WWSB_FE
  397. // MSKK Apr.02.1993 V-HirotS For KAttr
  398. Attr->Attr = ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS;
  399. #else
  400. Attr->Attr = ATTR_OF_PCI(SourcePtr);
  401. #endif
  402. AttrLength += 1;
  403. }
  404. }
  405. }
  406. // recalculate first and last non-space char
  407. Row->CharRow.OldLeft = Row->CharRow.Left;
  408. if (TargetPoint.X < Row->CharRow.Left) {
  409. PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X];
  410. for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++)
  411. ;
  412. Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars);
  413. }
  414. Row->CharRow.OldRight = Row->CharRow.Right;
  415. if ((TargetPoint.X+XSize) >= Row->CharRow.Right) {
  416. SHORT LastNonSpace;
  417. PWCHAR FirstChar = Row->CharRow.Chars;
  418. LastNonSpace = (SHORT)(TargetPoint.X+XSize-1);
  419. for (Char=&Row->CharRow.Chars[(TargetPoint.X+XSize-1)];*Char==(WCHAR)' ' && Char >= FirstChar;Char--)
  420. LastNonSpace--;
  421. //
  422. // if the attributes change after the last non-space, make the
  423. // index of the last attribute change + 1 the length. otherwise
  424. // make the length one more than the last non-space.
  425. //
  426. Row->CharRow.Right = (SHORT)(LastNonSpace+1);
  427. }
  428. //
  429. // see if attr string is different. if so, allocate a new
  430. // attr buffer and merge the two strings.
  431. //
  432. if (AttrLength != Row->AttrRow.Length ||
  433. memcmp(Row->AttrRow.Attrs,AttrBuf,AttrLength*sizeof(*Attr))) {
  434. PATTR_PAIR NewAttrs;
  435. WORD NewAttrsLength;
  436. if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs,
  437. Row->AttrRow.Length,
  438. AttrBuf,
  439. AttrLength,
  440. &NewAttrs,
  441. &NewAttrsLength,
  442. TargetPoint.X,
  443. (SHORT)(TargetPoint.X+XSize-1),
  444. Row,
  445. ScreenInfo
  446. ))) {
  447. if (XSize > 80) {
  448. ConsoleHeapFree(AttrBuf);
  449. }
  450. ResetTextFlags(ScreenInfo,
  451. TargetPoint.X,
  452. TargetPoint.Y,
  453. (SHORT)(TargetPoint.X + XSize - 1),
  454. (SHORT)(TargetPoint.Y + YSize - 1));
  455. return;
  456. }
  457. if (Row->AttrRow.Length > 1) {
  458. ConsoleHeapFree(Row->AttrRow.Attrs);
  459. }
  460. else {
  461. ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair);
  462. }
  463. Row->AttrRow.Attrs = NewAttrs;
  464. Row->AttrRow.Length = NewAttrsLength;
  465. Row->CharRow.OldLeft = INVALID_OLD_LENGTH;
  466. Row->CharRow.OldRight = INVALID_OLD_LENGTH;
  467. }
  468. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  469. RowIndex = 0;
  470. }
  471. }
  472. ResetTextFlags(ScreenInfo,
  473. TargetPoint.X,
  474. TargetPoint.Y,
  475. (SHORT)(TargetPoint.X + XSize - 1),
  476. (SHORT)(TargetPoint.Y + YSize - 1));
  477. if (XSize > 80) {
  478. ConsoleHeapFree(AttrBuf);
  479. }
  480. }
  481. VOID
  482. WWSB_WriteRegionToScreen(
  483. IN PSCREEN_INFORMATION ScreenInfo,
  484. IN PSMALL_RECT Region
  485. )
  486. {
  487. COORD Window;
  488. int i,j;
  489. PATTR_PAIR Attr;
  490. RECT TextRect;
  491. SHORT RowIndex;
  492. SHORT CountOfAttr;
  493. PROW Row;
  494. BOOL OneLine, SimpleWrite; // one line && one attribute per line
  495. PCONSOLE_INFORMATION Console = ScreenInfo->Console;
  496. PWCHAR TransBufferCharacter = NULL ;
  497. #ifdef WWSB_FE
  498. BOOL DoubleColorDbcs;
  499. SHORT CountOfAttrOriginal;
  500. SHORT RegionRight;
  501. BOOL LocalEUDCFlag;
  502. SMALL_RECT CaTextRect;
  503. PCONVERSIONAREA_INFORMATION ConvAreaInfo = ScreenInfo->ConvScreenInfo;
  504. #endif
  505. DBGOUTPUT(("WriteRegionToScreen\n"));
  506. #ifdef WWSB_FE
  507. if (ConvAreaInfo) {
  508. CaTextRect.Left = Region->Left - ScreenInfo->Console->CurrentScreenBuffer->Window.Left - ConvAreaInfo->CaInfo.coordConView.X;
  509. CaTextRect.Right = CaTextRect.Left + (Region->Right - Region->Left);
  510. CaTextRect.Top = Region->Top - ScreenInfo->Console->CurrentScreenBuffer->Window.Top - ConvAreaInfo->CaInfo.coordConView.Y;
  511. CaTextRect.Bottom = CaTextRect.Top + (Region->Bottom - Region->Top);
  512. }
  513. if (Region->Left && (ScreenInfo->BisectFlag & BISECT_LEFT)) {
  514. Region->Left--;
  515. }
  516. if (Region->Right+1 < ScreenInfo->ScreenBufferSize.X && (ScreenInfo->BisectFlag & BISECT_RIGHT)) {
  517. Region->Right++;
  518. }
  519. ScreenInfo->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT);
  520. Console->ConsoleIme.ScrollWaitCountDown = Console->ConsoleIme.ScrollWaitTimeout;
  521. #endif
  522. if (Console->FullScreenFlags == 0) {
  523. //
  524. // if we have a selection, turn it off.
  525. //
  526. InvertSelection(Console, TRUE);
  527. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  528. if (WWSB_PolyTextOutCandidate(ScreenInfo,Region)) {
  529. WWSB_ConsolePolyTextOut(ScreenInfo,Region);
  530. }
  531. else {
  532. #ifdef WWSB_FE
  533. if (ConvAreaInfo) {
  534. Window.Y = Region->Top - Console->CurrentScreenBuffer->Window.Top;
  535. Window.X = Region->Left - Console->CurrentScreenBuffer->Window.Left;
  536. }
  537. else {
  538. #endif
  539. Window.Y = Region->Top - ScreenInfo->Window.Top;
  540. Window.X = Region->Left - ScreenInfo->Window.Left;
  541. #ifdef WWSB_FE
  542. }
  543. #endif
  544. #ifdef WWSB_FE
  545. RowIndex = (ConvAreaInfo ? CaTextRect.Top :
  546. (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y
  547. );
  548. RegionRight = Region->Right;
  549. #else
  550. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y;
  551. #endif
  552. OneLine = (Region->Top==Region->Bottom);
  553. TransBufferCharacter = ConsoleHeapAlloc(TMP_DBCS_TAG,
  554. (ScreenInfo->ScreenBufferSize.X * sizeof(WCHAR)) + sizeof(WCHAR));
  555. if (TransBufferCharacter == NULL) {
  556. RIPMSG0(RIP_WARNING, "WriteRegionToScreen cannot allocate memory");
  557. return;
  558. }
  559. for (i=Region->Top;i<=Region->Bottom;i++,Window.Y++) {
  560. #ifdef WWSB_FE
  561. DoubleColorDbcs = FALSE;
  562. Region->Right = RegionRight;
  563. #endif
  564. //
  565. // copy the chars and attrs from their respective arrays
  566. //
  567. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  568. if (Row->AttrRow.Length == 1) {
  569. Attr = Row->AttrRow.Attrs;
  570. CountOfAttr = ScreenInfo->ScreenBufferSize.X;
  571. SimpleWrite = TRUE;
  572. } else {
  573. SimpleWrite = FALSE;
  574. FindAttrIndex(Row->AttrRow.Attrs,
  575. #ifdef WWSB_FE
  576. (SHORT)(ConvAreaInfo ? CaTextRect.Left : Region->Left),
  577. #else
  578. Region->Left,
  579. #endif
  580. &Attr,
  581. &CountOfAttr
  582. );
  583. }
  584. if (Console->LastAttributes != Attr->Attr) {
  585. TEXTCOLOR_CALL;
  586. #ifdef WWSB_FE
  587. if (Attr->Attr & COMMON_LVB_REVERSE_VIDEO)
  588. {
  589. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr)));
  590. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4)));
  591. }
  592. else{
  593. #endif
  594. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr)));
  595. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4)));
  596. #ifdef WWSB_FE
  597. }
  598. #endif
  599. Console->LastAttributes = Attr->Attr;
  600. }
  601. TextRect.top = Window.Y*SCR_FONTSIZE(ScreenInfo).Y;
  602. TextRect.bottom = TextRect.top + SCR_FONTSIZE(ScreenInfo).Y;
  603. for (j=Region->Left;j<=Region->Right;) {
  604. SHORT NumberOfChars;
  605. int TextLeft;
  606. SHORT LeftChar,RightChar;
  607. if (CountOfAttr > (SHORT)(Region->Right - j + 1)) {
  608. CountOfAttr = (SHORT)(Region->Right - j + 1);
  609. }
  610. #ifdef WWSB_FE
  611. CountOfAttrOriginal = CountOfAttr;
  612. LocalEUDCFlag = FALSE;
  613. if((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED &&
  614. ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalVDMEudcMode)){
  615. LocalEUDCFlag = CheckEudcRangeInString(
  616. Console,
  617. &Row->CharRow.Chars[ConvAreaInfo ?
  618. CaTextRect.Left + (j-Region->Left) : j],
  619. CountOfAttr,
  620. &CountOfAttr);
  621. }
  622. if (!(ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  623. !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) &&
  624. ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalKeisenEudcMode
  625. ) {
  626. SHORT k;
  627. PWCHAR Char2;
  628. Char2 = &Row->CharRow.Chars[ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j];
  629. for ( k = 0 ; k < CountOfAttr ; k++,Char2++){
  630. if (*Char2 < UNICODE_SPACE){
  631. CountOfAttr = k ;
  632. LocalEUDCFlag = TRUE;
  633. break;
  634. }
  635. }
  636. }
  637. #endif
  638. //
  639. // make the bounding rect smaller, if we can. the TEXT_VALID_HINT
  640. // flag gets set each time we write to the screen buffer. it gets
  641. // turned off any time we get asked to redraw the screen
  642. // and we don't know exactly what needs to be redrawn
  643. // (i.e. paint messages).
  644. //
  645. // we have the left and right bounds of the text on the
  646. // line. the opaqueing rectangle and the number of
  647. // chars get set according to those values.
  648. //
  649. // if there's more than one attr per line (!SimpleWrite)
  650. // we bail on the opaqueing rect.
  651. //
  652. if (ScreenInfo->BufferInfo.TextInfo.Flags & TEXT_VALID_HINT && SimpleWrite) {
  653. if (Row->CharRow.OldLeft != INVALID_OLD_LENGTH) {
  654. TextRect.left = (max(min(Row->CharRow.Left,Row->CharRow.OldLeft),j)-ScreenInfo->Window.Left) *
  655. SCR_FONTSIZE(ScreenInfo).X;
  656. } else {
  657. TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X;
  658. }
  659. if (Row->CharRow.OldRight != INVALID_OLD_LENGTH) {
  660. TextRect.right = (min(max(Row->CharRow.Right,Row->CharRow.OldRight),j+CountOfAttr)-ScreenInfo->Window.Left) *
  661. SCR_FONTSIZE(ScreenInfo).X;
  662. } else {
  663. TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X;
  664. }
  665. LeftChar = max(Row->CharRow.Left,j);
  666. RightChar = min(Row->CharRow.Right,j+CountOfAttr);
  667. NumberOfChars = RightChar - LeftChar;
  668. TextLeft = (LeftChar-ScreenInfo->Window.Left)*SCR_FONTSIZE(ScreenInfo).X;
  669. } else {
  670. #ifdef WWSB_FE
  671. LeftChar = ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j;
  672. #else
  673. LeftChar = (SHORT)j;
  674. #endif
  675. TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X;
  676. TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X;
  677. #ifdef WWSB_FE
  678. if (ConvAreaInfo)
  679. NumberOfChars = (Row->CharRow.Right > (SHORT)((CaTextRect.Left+(j-Region->Left)) + CountOfAttr)) ?
  680. (CountOfAttr) : (SHORT)(Row->CharRow.Right-(CaTextRect.Left+(j-Region->Left)));
  681. else
  682. #endif
  683. NumberOfChars = (Row->CharRow.Right > (SHORT)(j + CountOfAttr)) ? (CountOfAttr) : (SHORT)(Row->CharRow.Right-j);
  684. TextLeft = TextRect.left;
  685. }
  686. if (NumberOfChars < 0)
  687. {
  688. NumberOfChars = 0;
  689. #ifdef WWSB_FE
  690. TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X;
  691. TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X;
  692. #endif
  693. }
  694. TEXTOUT_CALL;
  695. #ifdef WWSB_FE
  696. /*
  697. * Text out everything (i.e. SBCS/DBCS, Common LVB attribute, Local EUDC)
  698. */
  699. TextOutEverything(Console,
  700. ScreenInfo,
  701. (SHORT)j,
  702. &Region->Right,
  703. &CountOfAttr,
  704. CountOfAttrOriginal,
  705. &DoubleColorDbcs,
  706. LocalEUDCFlag,
  707. Row,
  708. Attr,
  709. LeftChar,
  710. RightChar,
  711. TextLeft,
  712. TextRect,
  713. NumberOfChars);
  714. #else
  715. NumberOfChars =
  716. (SHORT)RemoveDbcsMarkAll(ScreenInfo,
  717. Row,
  718. &LeftChar,
  719. &TextRect,
  720. &TextLeft,
  721. TransBufferCharacter,
  722. NumberOfChars);
  723. ExtTextOutW(Console->hDC,
  724. TextLeft,
  725. TextRect.top,
  726. ETO_OPAQUE,
  727. &TextRect,
  728. TransBufferCharacter,
  729. NumberOfChars,
  730. NULL
  731. );
  732. #endif
  733. if (OneLine && SimpleWrite) {
  734. break;
  735. }
  736. j+=CountOfAttr;
  737. if (j <= Region->Right) {
  738. Window.X += CountOfAttr;
  739. #ifdef WWSB_FE
  740. if (CountOfAttr < CountOfAttrOriginal){
  741. CountOfAttr = CountOfAttrOriginal - CountOfAttr;
  742. }
  743. else {
  744. #endif
  745. Attr++;
  746. CountOfAttr = Attr->Length;
  747. #ifdef WWSB_FE
  748. }
  749. #endif
  750. #ifdef WWSB_FE
  751. if (Attr->Attr & COMMON_LVB_REVERSE_VIDEO)
  752. {
  753. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr)));
  754. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4)));
  755. }
  756. else{
  757. #endif
  758. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr)));
  759. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4)));
  760. #ifdef WWSB_FE
  761. }
  762. #endif
  763. Console->LastAttributes = Attr->Attr;
  764. }
  765. }
  766. Window.X = Region->Left - ScreenInfo->Window.Left;
  767. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  768. RowIndex = 0;
  769. }
  770. }
  771. GdiFlush();
  772. ConsoleHeapFree(TransBufferCharacter);
  773. }
  774. //
  775. // if we have a selection, turn it on.
  776. //
  777. InvertSelection(Console, FALSE);
  778. }
  779. #ifdef i386
  780. else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
  781. #ifdef WWSB_FE
  782. if (! ScreenInfo->ConvScreenInfo) {
  783. if (ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo) {
  784. WWSB_WriteRegionToScreenHW(ScreenInfo,Region);
  785. }
  786. }
  787. else if (ScreenInfo->Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER)
  788. #endif
  789. WWSB_WriteRegionToScreenHW(ScreenInfo,Region);
  790. }
  791. #endif
  792. #ifdef WWSB_FE
  793. {
  794. SMALL_RECT TmpRegion;
  795. if (ScreenInfo->BisectFlag & BISECT_TOP) {
  796. ScreenInfo->BisectFlag &= ~BISECT_TOP;
  797. if (Region->Top) {
  798. TmpRegion.Top = Region->Top-1;
  799. TmpRegion.Bottom = Region->Top-1;
  800. TmpRegion.Left = ScreenInfo->ScreenBufferSize.X-1;
  801. TmpRegion.Right = ScreenInfo->ScreenBufferSize.X-1;
  802. WWSB_WriteRegionToScreen(ScreenInfo,&TmpRegion);
  803. }
  804. }
  805. if (ScreenInfo->BisectFlag & BISECT_BOTTOM) {
  806. ScreenInfo->BisectFlag &= ~BISECT_BOTTOM;
  807. if (Region->Bottom+1 < ScreenInfo->ScreenBufferSize.Y) {
  808. TmpRegion.Top = Region->Bottom+1;
  809. TmpRegion.Bottom = Region->Bottom+1;
  810. TmpRegion.Left = 0;
  811. TmpRegion.Right = 0;
  812. WWSB_WriteRegionToScreen(ScreenInfo,&TmpRegion);
  813. }
  814. }
  815. }
  816. #endif
  817. }
  818. VOID
  819. WWSB_WriteToScreen(
  820. IN PSCREEN_INFORMATION ScreenInfo,
  821. IN PSMALL_RECT Region
  822. )
  823. /*++
  824. Routine Description:
  825. This routine writes a screen buffer region to the screen.
  826. Arguments:
  827. ScreenInfo - Pointer to screen buffer information.
  828. Region - Region to write in screen buffer coordinates. Region is
  829. inclusive
  830. Return Value:
  831. none.
  832. --*/
  833. {
  834. SMALL_RECT ClippedRegion;
  835. DBGOUTPUT(("WriteToScreen\n"));
  836. //
  837. // update to screen, if we're not iconic. we're marked as
  838. // iconic if we're fullscreen, so check for fullscreen.
  839. //
  840. if (!ACTIVE_SCREEN_BUFFER(ScreenInfo) ||
  841. (ScreenInfo->Console->Flags & (CONSOLE_IS_ICONIC | CONSOLE_NO_WINDOW) &&
  842. ScreenInfo->Console->FullScreenFlags == 0)) {
  843. return;
  844. }
  845. // clip region
  846. ClippedRegion.Left = max(Region->Left, ScreenInfo->Window.Left);
  847. ClippedRegion.Top = max(Region->Top, ScreenInfo->Window.Top);
  848. ClippedRegion.Right = min(Region->Right, ScreenInfo->Window.Right);
  849. ClippedRegion.Bottom = min(Region->Bottom, ScreenInfo->Window.Bottom);
  850. if (ClippedRegion.Right < ClippedRegion.Left ||
  851. ClippedRegion.Bottom < ClippedRegion.Top) {
  852. return;
  853. }
  854. if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) {
  855. if (ScreenInfo->Console->FullScreenFlags == 0) {
  856. WriteRegionToScreenBitMap(ScreenInfo, &ClippedRegion);
  857. }
  858. } else {
  859. ConsoleHideCursor(ScreenInfo);
  860. WWSB_WriteRegionToScreen(ScreenInfo, &ClippedRegion);
  861. #ifdef WWSB_FE
  862. if (!(ScreenInfo->Console->ConsoleIme.ScrollFlag & HIDE_FOR_SCROLL))
  863. {
  864. PCONVERSIONAREA_INFORMATION ConvAreaInfo;
  865. if (! ScreenInfo->Console->CurrentScreenBuffer->ConvScreenInfo) {
  866. WriteConvRegionToScreen(ScreenInfo,
  867. ScreenInfo->Console->ConsoleIme.ConvAreaRoot,
  868. Region);
  869. }
  870. else if (ConvAreaInfo = ScreenInfo->Console->ConsoleIme.ConvAreaRoot) {
  871. do {
  872. if (ConvAreaInfo->ScreenBuffer == ScreenInfo)
  873. break;
  874. } while (ConvAreaInfo = ConvAreaInfo->ConvAreaNext);
  875. if (ConvAreaInfo) {
  876. WriteConvRegionToScreen(ScreenInfo,
  877. ConvAreaInfo->ConvAreaNext,
  878. Region);
  879. }
  880. }
  881. }
  882. #endif
  883. ConsoleShowCursor(ScreenInfo);
  884. }
  885. }
  886. NTSTATUS
  887. WWSB_WriteOutputString(
  888. IN PSCREEN_INFORMATION ScreenInfo,
  889. IN PVOID Buffer,
  890. IN COORD WriteCoord,
  891. IN ULONG StringType,
  892. IN OUT PULONG NumRecords, // this value is valid even for error cases
  893. OUT PULONG NumColumns OPTIONAL
  894. )
  895. /*++
  896. Routine Description:
  897. This routine writes a string of characters or attributes to the
  898. screen buffer.
  899. Arguments:
  900. ScreenInfo - Pointer to screen buffer information.
  901. Buffer - Buffer to write from.
  902. WriteCoord - Screen buffer coordinate to begin writing to.
  903. StringType
  904. One of the following:
  905. CONSOLE_ASCII - write a string of ascii characters.
  906. CONSOLE_REAL_UNICODE - write a string of real unicode characters.
  907. CONSOLE_FALSE_UNICODE - write a string of false unicode characters.
  908. CONSOLE_ATTRIBUTE - write a string of attributes.
  909. NumRecords - On input, the number of elements to write. On output,
  910. the number of elements written.
  911. NumColumns - receives the number of columns output, which could be more
  912. than NumRecords (FE fullwidth chars)
  913. Return Value:
  914. --*/
  915. {
  916. ULONG NumWritten;
  917. SHORT X,Y,LeftX;
  918. SMALL_RECT WriteRegion;
  919. PROW Row;
  920. PWCHAR Char;
  921. SHORT RowIndex;
  922. SHORT j;
  923. PWCHAR TransBuffer;
  924. #ifdef WWSB_NOFE
  925. WCHAR SingleChar;
  926. #endif
  927. UINT Codepage;
  928. #ifdef WWSB_FE
  929. PBYTE AttrP;
  930. PBYTE TransBufferA;
  931. PBYTE BufferA;
  932. ULONG NumRecordsSavedForUnicode;
  933. BOOL fLocalHeap = FALSE;
  934. #endif
  935. DBGOUTPUT(("WriteOutputString\n"));
  936. #ifdef WWSB_FE
  937. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  938. #endif
  939. if (*NumRecords == 0)
  940. return STATUS_SUCCESS;
  941. NumWritten = 0;
  942. X=WriteCoord.X;
  943. Y=WriteCoord.Y;
  944. if (X>=ScreenInfo->ScreenBufferSize.X ||
  945. X<0 ||
  946. Y>=ScreenInfo->ScreenBufferSize.Y ||
  947. Y<0) {
  948. *NumRecords = 0;
  949. return STATUS_SUCCESS;
  950. }
  951. ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
  952. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+WriteCoord.Y) % ScreenInfo->ScreenBufferSize.Y;
  953. if (StringType == CONSOLE_ASCII) {
  954. #ifdef WWSB_FE
  955. PCHAR TmpBuf;
  956. PWCHAR TmpTrans;
  957. ULONG i;
  958. PCHAR TmpTransA;
  959. #endif
  960. if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  961. !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
  962. if (ScreenInfo->Console->OutputCP != WINDOWSCP)
  963. Codepage = USACP;
  964. else
  965. Codepage = WINDOWSCP;
  966. } else {
  967. Codepage = ScreenInfo->Console->OutputCP;
  968. }
  969. #ifdef WWSB_FE
  970. if (*NumRecords > (ULONG)(ScreenInfo->ScreenBufferSize.X * ScreenInfo->ScreenBufferSize.Y)) {
  971. TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(WCHAR));
  972. if (TransBuffer == NULL) {
  973. return STATUS_NO_MEMORY;
  974. }
  975. TransBufferA = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(CHAR));
  976. if (TransBufferA == NULL) {
  977. ConsoleHeapFree(TransBuffer);
  978. return STATUS_NO_MEMORY;
  979. }
  980. fLocalHeap = TRUE;
  981. }
  982. else {
  983. TransBuffer = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter;
  984. TransBufferA = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute;
  985. }
  986. TmpBuf = Buffer;
  987. TmpTrans = TransBuffer;
  988. TmpTransA = TransBufferA; // MSKK Apr.02.1993 V-HirotS For KAttr
  989. for (i=0; i < *NumRecords;) {
  990. if (IsDBCSLeadByteConsole(*TmpBuf,&ScreenInfo->Console->OutputCPInfo)) {
  991. if (i+1 >= *NumRecords) {
  992. *TmpTrans = UNICODE_SPACE;
  993. *TmpTransA = 0;
  994. i++;
  995. }
  996. else {
  997. ConvertOutputToUnicode(Codepage,
  998. TmpBuf,
  999. 2,
  1000. TmpTrans,
  1001. 2);
  1002. *(TmpTrans+1) = *TmpTrans;
  1003. TmpTrans += 2;
  1004. TmpBuf += 2;
  1005. *TmpTransA++ = ATTR_LEADING_BYTE;
  1006. *TmpTransA++ = ATTR_TRAILING_BYTE;
  1007. i += 2;
  1008. }
  1009. }
  1010. else {
  1011. ConvertOutputToUnicode(Codepage,
  1012. TmpBuf,
  1013. 1,
  1014. TmpTrans,
  1015. 1);
  1016. TmpTrans++;
  1017. TmpBuf++;
  1018. *TmpTransA++ = 0; // MSKK APr.02.1993 V-HirotS For KAttr
  1019. i++;
  1020. }
  1021. }
  1022. BufferA = TransBufferA;
  1023. Buffer = TransBuffer;
  1024. #else
  1025. if (*NumRecords == 1) {
  1026. TransBuffer = NULL;
  1027. SingleChar = SB_CharToWcharGlyph(Codepage, *((char *)Buffer));
  1028. Buffer = &SingleChar;
  1029. } else {
  1030. TransBuffer = ConsoleHeapAlloc(TMP_TAG, *NumRecords * sizeof(WCHAR));
  1031. if (TransBuffer == NULL) {
  1032. return STATUS_NO_MEMORY;
  1033. }
  1034. ConvertOutputToUnicode(Codepage, Buffer, *NumRecords,
  1035. TransBuffer, *NumRecords);
  1036. Buffer = TransBuffer;
  1037. }
  1038. #endif
  1039. } else if (StringType == CONSOLE_REAL_UNICODE &&
  1040. (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  1041. !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
  1042. RealUnicodeToFalseUnicode(Buffer,
  1043. *NumRecords,
  1044. ScreenInfo->Console->OutputCP
  1045. );
  1046. }
  1047. #ifdef WWSB_FE
  1048. if ((StringType == CONSOLE_REAL_UNICODE) || (StringType == CONSOLE_FALSE_UNICODE)) {
  1049. PWCHAR TmpBuf;
  1050. PWCHAR TmpTrans;
  1051. PCHAR TmpTransA;
  1052. ULONG i,j;
  1053. WCHAR c;
  1054. /* Avoid overflow into TransBufferCharacter , TransBufferAttribute
  1055. * because, if hit by IsConsoleFullWidth()
  1056. * then one unicde character needs two spaces on TransBuffer.
  1057. */
  1058. if ((*NumRecords*2) > (ULONG)(ScreenInfo->ScreenBufferSize.X * ScreenInfo->ScreenBufferSize.Y)) {
  1059. TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(WCHAR));
  1060. if (TransBuffer == NULL) {
  1061. return STATUS_NO_MEMORY;
  1062. }
  1063. TransBufferA = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(CHAR));
  1064. if (TransBufferA == NULL) {
  1065. ConsoleHeapFree(TransBuffer);
  1066. return STATUS_NO_MEMORY;
  1067. }
  1068. fLocalHeap = TRUE;
  1069. }
  1070. else {
  1071. TransBuffer = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter;
  1072. TransBufferA = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute;
  1073. }
  1074. TmpBuf = Buffer;
  1075. TmpTrans = TransBuffer;
  1076. TmpTransA = TransBufferA;
  1077. for (i=0,j=0; i < *NumRecords; i++,j++) {
  1078. *TmpTrans++ = c = *TmpBuf++;
  1079. *TmpTransA = 0;
  1080. if (IsConsoleFullWidth(ScreenInfo->Console->hDC,
  1081. ScreenInfo->Console->OutputCP,c)) {
  1082. *TmpTransA++ = ATTR_LEADING_BYTE;
  1083. *TmpTrans++ = c;
  1084. *TmpTransA = ATTR_TRAILING_BYTE;
  1085. j++;
  1086. }
  1087. TmpTransA++;
  1088. }
  1089. NumRecordsSavedForUnicode = *NumRecords;
  1090. *NumRecords = j;
  1091. Buffer = TransBuffer;
  1092. BufferA = TransBufferA;
  1093. }
  1094. #endif
  1095. if ((StringType == CONSOLE_REAL_UNICODE) ||
  1096. (StringType == CONSOLE_FALSE_UNICODE) ||
  1097. (StringType == CONSOLE_ASCII)) {
  1098. while (TRUE) {
  1099. LeftX = X;
  1100. //
  1101. // copy the chars into their arrays
  1102. //
  1103. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  1104. Char = &Row->CharRow.Chars[X];
  1105. #ifdef WWSB_FE
  1106. AttrP = &Row->CharRow.KAttrs[X];
  1107. #endif
  1108. if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*NumRecords - NumWritten)) {
  1109. /*
  1110. * The text will not hit the right hand edge, copy it all
  1111. */
  1112. #ifdef WWSB_FE
  1113. COORD TPoint;
  1114. TPoint.X = X;
  1115. TPoint.Y = Y;
  1116. BisectWrite((SHORT)(*NumRecords-NumWritten),TPoint,ScreenInfo);
  1117. if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 &&
  1118. (SHORT)(TPoint.X+*NumRecords-NumWritten) >= ScreenInfo->ScreenBufferSize.X &&
  1119. *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & ATTR_LEADING_BYTE
  1120. ) {
  1121. *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE;
  1122. *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = 0;
  1123. if ((SHORT)(*NumRecords-NumWritten) > (SHORT)(ScreenInfo->ScreenBufferSize.X-TPoint.X-1)) {
  1124. *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE;
  1125. *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X) = 0;
  1126. }
  1127. }
  1128. RtlCopyMemory(AttrP,BufferA,(*NumRecords - NumWritten) * sizeof(CHAR));
  1129. #endif
  1130. RtlCopyMemory(Char,Buffer,(*NumRecords - NumWritten) * sizeof(WCHAR));
  1131. X=(SHORT)(X+*NumRecords - NumWritten-1);
  1132. NumWritten = *NumRecords;
  1133. }
  1134. else {
  1135. /*
  1136. * The text will hit the right hand edge, copy only that much
  1137. */
  1138. #ifdef WWSB_FE
  1139. COORD TPoint;
  1140. TPoint.X = X;
  1141. TPoint.Y = Y;
  1142. BisectWrite((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo);
  1143. if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 &&
  1144. TPoint.X+ScreenInfo->ScreenBufferSize.X-X >= ScreenInfo->ScreenBufferSize.X &&
  1145. *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & ATTR_LEADING_BYTE
  1146. ) {
  1147. *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE;
  1148. *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = 0;
  1149. if (ScreenInfo->ScreenBufferSize.X-X > ScreenInfo->ScreenBufferSize.X-TPoint.X-1) {
  1150. *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE;
  1151. *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X) = 0;
  1152. }
  1153. }
  1154. RtlCopyMemory(AttrP,BufferA,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR));
  1155. BufferA = (PVOID)((PBYTE)BufferA + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR)));
  1156. #endif
  1157. RtlCopyMemory(Char,Buffer,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR));
  1158. Buffer = (PVOID)((PBYTE)Buffer + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR)));
  1159. NumWritten += ScreenInfo->ScreenBufferSize.X - X;
  1160. X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1);
  1161. }
  1162. // recalculate first and last non-space char
  1163. Row->CharRow.OldLeft = Row->CharRow.Left;
  1164. if (LeftX < Row->CharRow.Left) {
  1165. PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X];
  1166. for (Char=&Row->CharRow.Chars[LeftX];Char < LastChar && *Char==(WCHAR)' ';Char++)
  1167. ;
  1168. Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars);
  1169. }
  1170. Row->CharRow.OldRight = Row->CharRow.Right;
  1171. if ((X+1) >= Row->CharRow.Right) {
  1172. WORD LastNonSpace;
  1173. PWCHAR FirstChar = Row->CharRow.Chars;
  1174. LastNonSpace = X;
  1175. for (Char=&Row->CharRow.Chars[X];*Char==(WCHAR)' ' && Char >= FirstChar;Char--)
  1176. LastNonSpace--;
  1177. Row->CharRow.Right = (SHORT)(LastNonSpace+1);
  1178. }
  1179. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  1180. RowIndex = 0;
  1181. }
  1182. if (NumWritten < *NumRecords) {
  1183. /*
  1184. * The string hit the right hand edge, so wrap around to the
  1185. * next line by going back round the while loop, unless we
  1186. * are at the end of the buffer - in which case we simply
  1187. * abandon the remainder of the output string!
  1188. */
  1189. X = 0;
  1190. Y++;
  1191. if (Y >= ScreenInfo->ScreenBufferSize.Y) {
  1192. break; // abandon output, string is truncated
  1193. }
  1194. } else {
  1195. break;
  1196. }
  1197. }
  1198. } else if (StringType == CONSOLE_ATTRIBUTE) {
  1199. PWORD SourcePtr=Buffer;
  1200. PATTR_PAIR AttrBuf;
  1201. ATTR_PAIR Attrs[80];
  1202. PATTR_PAIR Attr;
  1203. SHORT AttrLength;
  1204. AttrBuf = Attrs;
  1205. if (ScreenInfo->ScreenBufferSize.X > 80) {
  1206. AttrBuf = ConsoleHeapAlloc(TMP_TAG, ScreenInfo->ScreenBufferSize.X * sizeof(ATTR_PAIR));
  1207. if (AttrBuf == NULL)
  1208. return STATUS_NO_MEMORY;
  1209. }
  1210. #ifdef WWSB_FE
  1211. {
  1212. COORD TPoint;
  1213. TPoint.X = X;
  1214. TPoint.Y = Y;
  1215. if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*NumRecords - NumWritten)) {
  1216. BisectWriteAttr((SHORT)(*NumRecords-NumWritten),TPoint,ScreenInfo);
  1217. }
  1218. else{
  1219. BisectWriteAttr((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo);
  1220. }
  1221. }
  1222. #endif
  1223. while (TRUE) {
  1224. //
  1225. // copy the attrs into the screen buffer arrays
  1226. //
  1227. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  1228. Attr = AttrBuf;
  1229. Attr->Length = 0;
  1230. #ifdef WWSB_FE
  1231. Attr->Attr = *SourcePtr & ~COMMON_LVB_SBCSDBCS;
  1232. #else
  1233. Attr->Attr = *SourcePtr;
  1234. #endif
  1235. AttrLength = 1;
  1236. for (j=X;j<ScreenInfo->ScreenBufferSize.X;j++,SourcePtr++) {
  1237. #ifdef WWSB_FE
  1238. if (Attr->Attr == (*SourcePtr & ~COMMON_LVB_SBCSDBCS))
  1239. #else
  1240. if (Attr->Attr == *SourcePtr)
  1241. #endif
  1242. {
  1243. Attr->Length += 1;
  1244. }
  1245. else {
  1246. Attr++;
  1247. Attr->Length = 1;
  1248. #ifdef WWSB_FE
  1249. Attr->Attr = *SourcePtr & ~COMMON_LVB_SBCSDBCS;
  1250. #else
  1251. Attr->Attr = *SourcePtr;
  1252. #endif
  1253. AttrLength += 1;
  1254. }
  1255. NumWritten++;
  1256. X++;
  1257. if (NumWritten == *NumRecords) {
  1258. break;
  1259. }
  1260. }
  1261. X--;
  1262. // recalculate last non-space char
  1263. //
  1264. // see if attr string is different. if so, allocate a new
  1265. // attr buffer and merge the two strings.
  1266. //
  1267. if (AttrLength != Row->AttrRow.Length ||
  1268. memcmp(Row->AttrRow.Attrs,AttrBuf,AttrLength*sizeof(*Attr))) {
  1269. PATTR_PAIR NewAttrs;
  1270. WORD NewAttrsLength;
  1271. if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs,
  1272. Row->AttrRow.Length,
  1273. AttrBuf,
  1274. AttrLength,
  1275. &NewAttrs,
  1276. &NewAttrsLength,
  1277. (SHORT)((Y == WriteCoord.Y) ? WriteCoord.X : 0),
  1278. X,
  1279. Row,
  1280. ScreenInfo
  1281. ))) {
  1282. if (ScreenInfo->ScreenBufferSize.X > 80) {
  1283. ConsoleHeapFree(AttrBuf);
  1284. }
  1285. ResetTextFlags(ScreenInfo,
  1286. WriteCoord.X,
  1287. WriteCoord.Y,
  1288. X,
  1289. Y);
  1290. return STATUS_NO_MEMORY;
  1291. }
  1292. if (Row->AttrRow.Length > 1) {
  1293. ConsoleHeapFree(Row->AttrRow.Attrs);
  1294. }
  1295. else {
  1296. ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair);
  1297. }
  1298. Row->AttrRow.Attrs = NewAttrs;
  1299. Row->AttrRow.Length = NewAttrsLength;
  1300. Row->CharRow.OldLeft = INVALID_OLD_LENGTH;
  1301. Row->CharRow.OldRight = INVALID_OLD_LENGTH;
  1302. }
  1303. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  1304. RowIndex = 0;
  1305. }
  1306. if (NumWritten < *NumRecords) {
  1307. X = 0;
  1308. Y++;
  1309. if (Y>=ScreenInfo->ScreenBufferSize.Y) {
  1310. break;
  1311. }
  1312. } else {
  1313. break;
  1314. }
  1315. }
  1316. ResetTextFlags(ScreenInfo,
  1317. WriteCoord.X,
  1318. WriteCoord.Y,
  1319. X,
  1320. Y);
  1321. if (ScreenInfo->ScreenBufferSize.X > 80) {
  1322. ConsoleHeapFree(AttrBuf);
  1323. }
  1324. } else {
  1325. *NumRecords = 0;
  1326. return STATUS_INVALID_PARAMETER;
  1327. }
  1328. if ((StringType == CONSOLE_ASCII) && (TransBuffer != NULL)) {
  1329. #ifdef WWSB_FE
  1330. if (fLocalHeap) {
  1331. ConsoleHeapFree(TransBuffer);
  1332. ConsoleHeapFree(TransBufferA);
  1333. }
  1334. #else
  1335. ConsoleHeapFree(TransBuffer);
  1336. #endif
  1337. }
  1338. #ifdef WWSB_FE
  1339. else if ((StringType == CONSOLE_FALSE_UNICODE) || (StringType == CONSOLE_REAL_UNICODE)) {
  1340. if (fLocalHeap) {
  1341. ConsoleHeapFree(TransBuffer);
  1342. ConsoleHeapFree(TransBufferA);
  1343. }
  1344. NumWritten = NumRecordsSavedForUnicode - (*NumRecords - NumWritten);
  1345. }
  1346. #endif
  1347. //
  1348. // determine write region. if we're still on the same line we started
  1349. // on, left X is the X we started with and right X is the one we're on
  1350. // now. otherwise, left X is 0 and right X is the rightmost column of
  1351. // the screen buffer.
  1352. //
  1353. // then update the screen.
  1354. //
  1355. WriteRegion.Top = WriteCoord.Y;
  1356. WriteRegion.Bottom = Y;
  1357. if (Y != WriteCoord.Y) {
  1358. WriteRegion.Left = 0;
  1359. WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1);
  1360. }
  1361. else {
  1362. WriteRegion.Left = WriteCoord.X;
  1363. WriteRegion.Right = X;
  1364. }
  1365. WWSB_WriteToScreen(ScreenInfo,&WriteRegion);
  1366. if (NumColumns) {
  1367. *NumColumns = X + (WriteCoord.Y - Y) * ScreenInfo->ScreenBufferSize.X - WriteCoord.X + 1;
  1368. }
  1369. *NumRecords = NumWritten;
  1370. return STATUS_SUCCESS;
  1371. }
  1372. NTSTATUS
  1373. WWSB_FillOutput(
  1374. IN PSCREEN_INFORMATION ScreenInfo,
  1375. IN WORD Element,
  1376. IN COORD WriteCoord,
  1377. IN ULONG ElementType,
  1378. IN OUT PULONG Length // this value is valid even for error cases
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. This routine fills the screen buffer with the specified character or
  1383. attribute.
  1384. Arguments:
  1385. ScreenInfo - Pointer to screen buffer information.
  1386. Element - Element to write.
  1387. WriteCoord - Screen buffer coordinate to begin writing to.
  1388. ElementType
  1389. CONSOLE_ASCII - element is an ascii character.
  1390. CONSOLE_REAL_UNICODE - element is a real unicode character. These will
  1391. get converted to False Unicode as required.
  1392. CONSOLE_FALSE_UNICODE - element is a False Unicode character.
  1393. CONSOLE_ATTRIBUTE - element is an attribute.
  1394. Length - On input, the number of elements to write. On output,
  1395. the number of elements written.
  1396. Return Value:
  1397. --*/
  1398. {
  1399. ULONG NumWritten;
  1400. SHORT X,Y,LeftX;
  1401. SMALL_RECT WriteRegion;
  1402. PROW Row;
  1403. PWCHAR Char;
  1404. SHORT RowIndex;
  1405. SHORT j;
  1406. #ifdef WWSB_FE
  1407. PCHAR AttrP;
  1408. #endif
  1409. DBGOUTPUT(("FillOutput\n"));
  1410. if (*Length == 0)
  1411. return STATUS_SUCCESS;
  1412. NumWritten = 0;
  1413. X=WriteCoord.X;
  1414. Y=WriteCoord.Y;
  1415. if (X>=ScreenInfo->ScreenBufferSize.X ||
  1416. X<0 ||
  1417. Y>=ScreenInfo->ScreenBufferSize.Y ||
  1418. Y<0) {
  1419. *Length = 0;
  1420. return STATUS_SUCCESS;
  1421. }
  1422. #ifdef WWSB_FE
  1423. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  1424. #endif
  1425. ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
  1426. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+WriteCoord.Y) % ScreenInfo->ScreenBufferSize.Y;
  1427. if (ElementType == CONSOLE_ASCII) {
  1428. UINT Codepage;
  1429. if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  1430. ((ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  1431. if (ScreenInfo->Console->OutputCP != WINDOWSCP)
  1432. Codepage = USACP;
  1433. else
  1434. Codepage = WINDOWSCP;
  1435. } else {
  1436. Codepage = ScreenInfo->Console->OutputCP;
  1437. }
  1438. #ifdef WWSB_FE
  1439. if (ScreenInfo->FillOutDbcsLeadChar == 0){
  1440. if (IsDBCSLeadByteConsole((CHAR)Element,&ScreenInfo->Console->OutputCPInfo)) {
  1441. ScreenInfo->FillOutDbcsLeadChar = (CHAR)Element;
  1442. *Length = 0;
  1443. return STATUS_SUCCESS;
  1444. }else{
  1445. CHAR Char=(CHAR)Element;
  1446. ConvertOutputToUnicode(Codepage,
  1447. &Char,
  1448. 1,
  1449. &Element,
  1450. 1);
  1451. }
  1452. }else{
  1453. CHAR Char[2];
  1454. Char[0]=ScreenInfo->FillOutDbcsLeadChar;
  1455. Char[1]=(BYTE)Element;
  1456. ScreenInfo->FillOutDbcsLeadChar = 0;
  1457. ConvertOutputToUnicode(Codepage,
  1458. Char,
  1459. 2,
  1460. &Element,
  1461. 2);
  1462. }
  1463. #else
  1464. Element = SB_CharToWchar(Codepage, (CHAR)Element);
  1465. #endif
  1466. } else if (ElementType == CONSOLE_REAL_UNICODE &&
  1467. (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  1468. !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
  1469. RealUnicodeToFalseUnicode(&Element,
  1470. 1,
  1471. ScreenInfo->Console->OutputCP
  1472. );
  1473. }
  1474. if ((ElementType == CONSOLE_ASCII) ||
  1475. (ElementType == CONSOLE_REAL_UNICODE) ||
  1476. (ElementType == CONSOLE_FALSE_UNICODE)) {
  1477. #ifdef WWSB_FE
  1478. DWORD StartPosFlag ;
  1479. StartPosFlag = 0;
  1480. #endif
  1481. while (TRUE) {
  1482. //
  1483. // copy the chars into their arrays
  1484. //
  1485. LeftX = X;
  1486. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  1487. Char = &Row->CharRow.Chars[X];
  1488. #ifdef WWSB_FE
  1489. AttrP = &Row->CharRow.KAttrs[X];
  1490. #endif
  1491. if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) {
  1492. #ifdef WWSB_FE
  1493. {
  1494. COORD TPoint;
  1495. TPoint.X = X;
  1496. TPoint.Y = Y;
  1497. BisectWrite((SHORT)(*Length-NumWritten),TPoint,ScreenInfo);
  1498. }
  1499. #endif
  1500. #ifdef WWSB_FE
  1501. if (IsConsoleFullWidth(ScreenInfo->Console->hDC,
  1502. ScreenInfo->Console->OutputCP,(WCHAR)Element)) {
  1503. for (j=0;j<(SHORT)(*Length - NumWritten);j++) {
  1504. *Char++ = (WCHAR)Element;
  1505. *AttrP &= ~ATTR_DBCSSBCS_BYTE;
  1506. if(StartPosFlag++ & 1)
  1507. *AttrP++ |= ATTR_TRAILING_BYTE;
  1508. else
  1509. *AttrP++ |= ATTR_LEADING_BYTE;
  1510. }
  1511. if(StartPosFlag & 1){
  1512. *(Char-1) = UNICODE_SPACE;
  1513. *(AttrP-1) &= ~ATTR_DBCSSBCS_BYTE;
  1514. }
  1515. }
  1516. else {
  1517. #endif
  1518. for (j=0;j<(SHORT)(*Length - NumWritten);j++) {
  1519. *Char++ = (WCHAR)Element;
  1520. #ifdef WWSB_FE
  1521. *AttrP++ &= ~ATTR_DBCSSBCS_BYTE;
  1522. #endif
  1523. }
  1524. #ifdef WWSB_FE
  1525. }
  1526. #endif
  1527. X=(SHORT)(X+*Length - NumWritten - 1);
  1528. NumWritten = *Length;
  1529. }
  1530. else {
  1531. #ifdef WWSB_FE
  1532. {
  1533. COORD TPoint;
  1534. TPoint.X = X;
  1535. TPoint.Y = Y;
  1536. BisectWrite((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo);
  1537. }
  1538. #endif
  1539. #ifdef WWSB_FE
  1540. if (IsConsoleFullWidth(ScreenInfo->Console->hDC,
  1541. ScreenInfo->Console->OutputCP,(WCHAR)Element)) {
  1542. for (j=0;j<ScreenInfo->ScreenBufferSize.X - X;j++) {
  1543. *Char++ = (WCHAR)Element;
  1544. *AttrP &= ~ATTR_DBCSSBCS_BYTE;
  1545. if(StartPosFlag++ & 1)
  1546. *AttrP++ |= ATTR_TRAILING_BYTE;
  1547. else
  1548. *AttrP++ |= ATTR_LEADING_BYTE;
  1549. }
  1550. }
  1551. else {
  1552. #endif
  1553. for (j=0;j<ScreenInfo->ScreenBufferSize.X - X;j++) {
  1554. *Char++ = (WCHAR)Element;
  1555. #ifdef WWSB_FE
  1556. *AttrP++ &= ~ATTR_DBCSSBCS_BYTE;
  1557. #endif
  1558. }
  1559. #ifdef WWSB_FE
  1560. }
  1561. #endif
  1562. NumWritten += ScreenInfo->ScreenBufferSize.X - X;
  1563. X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1);
  1564. }
  1565. // recalculate first and last non-space char
  1566. Row->CharRow.OldLeft = Row->CharRow.Left;
  1567. if (LeftX < Row->CharRow.Left) {
  1568. if (Element == UNICODE_SPACE) {
  1569. Row->CharRow.Left = X+1;
  1570. } else {
  1571. Row->CharRow.Left = LeftX;
  1572. }
  1573. }
  1574. Row->CharRow.OldRight = Row->CharRow.Right;
  1575. if ((X+1) >= Row->CharRow.Right) {
  1576. if (Element == UNICODE_SPACE) {
  1577. Row->CharRow.Right = LeftX;
  1578. } else {
  1579. Row->CharRow.Right = X+1;
  1580. }
  1581. }
  1582. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  1583. RowIndex = 0;
  1584. }
  1585. if (NumWritten < *Length) {
  1586. X = 0;
  1587. Y++;
  1588. if (Y>=ScreenInfo->ScreenBufferSize.Y) {
  1589. break;
  1590. }
  1591. } else {
  1592. break;
  1593. }
  1594. }
  1595. } else if (ElementType == CONSOLE_ATTRIBUTE) {
  1596. ATTR_PAIR Attr;
  1597. #ifdef WWSB_FE
  1598. COORD TPoint;
  1599. TPoint.X = X;
  1600. TPoint.Y = Y;
  1601. if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) {
  1602. BisectWriteAttr((SHORT)(*Length-NumWritten),TPoint,ScreenInfo);
  1603. }
  1604. else{
  1605. BisectWriteAttr((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo);
  1606. }
  1607. #endif
  1608. while (TRUE) {
  1609. //
  1610. // copy the attrs into the screen buffer arrays
  1611. //
  1612. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  1613. if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) {
  1614. X=(SHORT)(X+*Length - NumWritten - 1);
  1615. NumWritten = *Length;
  1616. }
  1617. else {
  1618. NumWritten += ScreenInfo->ScreenBufferSize.X - X;
  1619. X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1);
  1620. }
  1621. // recalculate last non-space char
  1622. //
  1623. // merge the two attribute strings.
  1624. //
  1625. Attr.Length = (SHORT)((Y == WriteCoord.Y) ? (X-WriteCoord.X+1) : (X+1));
  1626. #ifdef WWSB_FE
  1627. Attr.Attr = Element & ~COMMON_LVB_SBCSDBCS;
  1628. #else
  1629. Attr.Attr = Element;
  1630. #endif
  1631. if (1 != Row->AttrRow.Length ||
  1632. memcmp(Row->AttrRow.Attrs,&Attr,sizeof(Attr))) {
  1633. PATTR_PAIR NewAttrs;
  1634. WORD NewAttrsLength;
  1635. if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs,
  1636. Row->AttrRow.Length,
  1637. &Attr,
  1638. 1,
  1639. &NewAttrs,
  1640. &NewAttrsLength,
  1641. (SHORT)(X-Attr.Length+1),
  1642. X,
  1643. Row,
  1644. ScreenInfo
  1645. ))) {
  1646. ResetTextFlags(ScreenInfo,
  1647. WriteCoord.X,
  1648. WriteCoord.Y,
  1649. X,
  1650. Y);
  1651. return STATUS_NO_MEMORY;
  1652. }
  1653. if (Row->AttrRow.Length > 1) {
  1654. ConsoleHeapFree(Row->AttrRow.Attrs);
  1655. }
  1656. else {
  1657. ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair);
  1658. }
  1659. Row->AttrRow.Attrs = NewAttrs;
  1660. Row->AttrRow.Length = NewAttrsLength;
  1661. Row->CharRow.OldLeft = INVALID_OLD_LENGTH;
  1662. Row->CharRow.OldRight = INVALID_OLD_LENGTH;
  1663. }
  1664. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  1665. RowIndex = 0;
  1666. }
  1667. if (NumWritten < *Length) {
  1668. X = 0;
  1669. Y++;
  1670. if (Y>=ScreenInfo->ScreenBufferSize.Y) {
  1671. break;
  1672. }
  1673. } else {
  1674. break;
  1675. }
  1676. }
  1677. ResetTextFlags(ScreenInfo,
  1678. WriteCoord.X,
  1679. WriteCoord.Y,
  1680. X,
  1681. Y);
  1682. } else {
  1683. *Length = 0;
  1684. return STATUS_INVALID_PARAMETER;
  1685. }
  1686. //
  1687. // determine write region. if we're still on the same line we started
  1688. // on, left X is the X we started with and right X is the one we're on
  1689. // now. otherwise, left X is 0 and right X is the rightmost column of
  1690. // the screen buffer.
  1691. //
  1692. // then update the screen.
  1693. //
  1694. #ifdef WWSB_FE
  1695. if (ScreenInfo->ConvScreenInfo) {
  1696. WriteRegion.Top = WriteCoord.Y + ScreenInfo->Window.Left + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.Y;
  1697. WriteRegion.Bottom = Y + ScreenInfo->Window.Left + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.Y;
  1698. if (Y != WriteCoord.Y) {
  1699. WriteRegion.Left = 0;
  1700. WriteRegion.Right = (SHORT)(ScreenInfo->Console->CurrentScreenBuffer->ScreenBufferSize.X-1);
  1701. }
  1702. else {
  1703. WriteRegion.Left = WriteCoord.X + ScreenInfo->Window.Top + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.X;
  1704. WriteRegion.Right = X + ScreenInfo->Window.Top + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.X;
  1705. }
  1706. WriteConvRegionToScreen(ScreenInfo->Console->CurrentScreenBuffer,
  1707. ScreenInfo->ConvScreenInfo,
  1708. &WriteRegion
  1709. );
  1710. ScreenInfo->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT | BISECT_TOP | BISECT_BOTTOM);
  1711. *Length = NumWritten;
  1712. return STATUS_SUCCESS;
  1713. }
  1714. #endif
  1715. WriteRegion.Top = WriteCoord.Y;
  1716. WriteRegion.Bottom = Y;
  1717. if (Y != WriteCoord.Y) {
  1718. WriteRegion.Left = 0;
  1719. WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1);
  1720. }
  1721. else {
  1722. WriteRegion.Left = WriteCoord.X;
  1723. WriteRegion.Right = X;
  1724. }
  1725. WWSB_WriteToScreen(ScreenInfo,&WriteRegion);
  1726. *Length = NumWritten;
  1727. return STATUS_SUCCESS;
  1728. }
  1729. VOID
  1730. WWSB_FillRectangle(
  1731. IN CHAR_INFO Fill,
  1732. IN OUT PSCREEN_INFORMATION ScreenInfo,
  1733. IN PSMALL_RECT TargetRect
  1734. )
  1735. /*++
  1736. Routine Description:
  1737. This routine fills a rectangular region in the screen
  1738. buffer. no clipping is done.
  1739. Arguments:
  1740. Fill - element to copy to each element in target rect
  1741. ScreenInfo - pointer to screen info
  1742. TargetRect - rectangle in screen buffer to fill
  1743. Return Value:
  1744. --*/
  1745. {
  1746. SHORT i,j;
  1747. SHORT XSize;
  1748. SHORT RowIndex;
  1749. PROW Row;
  1750. PWCHAR Char;
  1751. ATTR_PAIR Attr;
  1752. #ifdef WWSB_FE
  1753. PCHAR AttrP;
  1754. BOOL Width;
  1755. #endif
  1756. DBGOUTPUT(("FillRectangle\n"));
  1757. #ifdef WWFE_SB
  1758. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  1759. #endif
  1760. XSize = (SHORT)(TargetRect->Right - TargetRect->Left + 1);
  1761. ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
  1762. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetRect->Top) % ScreenInfo->ScreenBufferSize.Y;
  1763. for (i=TargetRect->Top;i<=TargetRect->Bottom;i++) {
  1764. //
  1765. // copy the chars and attrs into their respective arrays
  1766. //
  1767. #ifdef WWSB_FE
  1768. {
  1769. COORD TPoint;
  1770. TPoint.X = TargetRect->Left;
  1771. TPoint.Y = i;
  1772. BisectWrite(XSize,TPoint,ScreenInfo);
  1773. Width = IsConsoleFullWidth(ScreenInfo->Console->hDC,
  1774. ScreenInfo->Console->OutputCP,Fill.Char.UnicodeChar);
  1775. }
  1776. #endif
  1777. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  1778. Char = &Row->CharRow.Chars[TargetRect->Left];
  1779. #ifdef WWSB_FE
  1780. AttrP = &Row->CharRow.KAttrs[TargetRect->Left];
  1781. #endif
  1782. for (j=0;j<XSize;j++) {
  1783. #ifdef WWSB_FE
  1784. if (Width){
  1785. if (j < XSize-1){
  1786. *Char++ = Fill.Char.UnicodeChar;
  1787. *Char++ = Fill.Char.UnicodeChar;
  1788. *AttrP++ = ATTR_LEADING_BYTE;
  1789. *AttrP++ = ATTR_TRAILING_BYTE;
  1790. j++;
  1791. }
  1792. else{
  1793. *Char++ = UNICODE_SPACE;
  1794. *AttrP++ = 0 ;
  1795. }
  1796. }
  1797. else{
  1798. #endif
  1799. *Char++ = Fill.Char.UnicodeChar;
  1800. #ifdef WWSB_FE
  1801. *AttrP++ = 0 ;
  1802. }
  1803. #endif
  1804. }
  1805. // recalculate first and last non-space char
  1806. Row->CharRow.OldLeft = Row->CharRow.Left;
  1807. if (TargetRect->Left < Row->CharRow.Left) {
  1808. if (Fill.Char.UnicodeChar == UNICODE_SPACE) {
  1809. Row->CharRow.Left = (SHORT)(TargetRect->Right+1);
  1810. }
  1811. else {
  1812. Row->CharRow.Left = (SHORT)(TargetRect->Left);
  1813. }
  1814. }
  1815. Row->CharRow.OldRight = Row->CharRow.Right;
  1816. if (TargetRect->Right >= Row->CharRow.Right) {
  1817. if (Fill.Char.UnicodeChar == UNICODE_SPACE) {
  1818. Row->CharRow.Right = (SHORT)(TargetRect->Left);
  1819. }
  1820. else {
  1821. Row->CharRow.Right = (SHORT)(TargetRect->Right+1);
  1822. }
  1823. }
  1824. Attr.Length = XSize;
  1825. Attr.Attr = Fill.Attributes;
  1826. //
  1827. // merge the two attribute strings.
  1828. //
  1829. if (1 != Row->AttrRow.Length ||
  1830. memcmp(Row->AttrRow.Attrs,&Attr,sizeof(Attr))) {
  1831. PATTR_PAIR NewAttrs;
  1832. WORD NewAttrsLength;
  1833. if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs,
  1834. Row->AttrRow.Length,
  1835. &Attr,
  1836. 1,
  1837. &NewAttrs,
  1838. &NewAttrsLength,
  1839. TargetRect->Left,
  1840. TargetRect->Right,
  1841. Row,
  1842. ScreenInfo
  1843. ))) {
  1844. ResetTextFlags(ScreenInfo,
  1845. TargetRect->Left,
  1846. TargetRect->Top,
  1847. TargetRect->Right,
  1848. TargetRect->Bottom);
  1849. return;
  1850. }
  1851. if (Row->AttrRow.Length > 1) {
  1852. ConsoleHeapFree(Row->AttrRow.Attrs);
  1853. }
  1854. else {
  1855. ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair);
  1856. }
  1857. Row->AttrRow.Attrs = NewAttrs;
  1858. Row->AttrRow.Length = NewAttrsLength;
  1859. Row->CharRow.OldLeft = INVALID_OLD_LENGTH;
  1860. Row->CharRow.OldRight = INVALID_OLD_LENGTH;
  1861. }
  1862. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  1863. RowIndex = 0;
  1864. }
  1865. }
  1866. ResetTextFlags(ScreenInfo,
  1867. TargetRect->Left,
  1868. TargetRect->Top,
  1869. TargetRect->Right,
  1870. TargetRect->Bottom);
  1871. }
  1872. BOOL
  1873. WWSB_PolyTextOutCandidate(
  1874. IN PSCREEN_INFORMATION ScreenInfo,
  1875. IN PSMALL_RECT Region
  1876. )
  1877. /*
  1878. This function returns TRUE if the input region is reasonable to
  1879. pass to ConsolePolyTextOut. The criteria are that there is only
  1880. one attribute per line.
  1881. */
  1882. {
  1883. SHORT RowIndex;
  1884. PROW Row;
  1885. SHORT i;
  1886. #ifdef WWSB_FE
  1887. if((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED &&
  1888. ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalVDMEudcMode)){
  1889. return FALSE;
  1890. }
  1891. if (!(ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  1892. !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) &&
  1893. ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalKeisenEudcMode
  1894. ) {
  1895. return FALSE;
  1896. }
  1897. ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  1898. if (ScreenInfo->BufferInfo.TextInfo.Flags & CONSOLE_CONVERSION_AREA_REDRAW) {
  1899. return FALSE;
  1900. }
  1901. #endif
  1902. if (ScreenInfo->BufferInfo.TextInfo.Flags & SINGLE_ATTRIBUTES_PER_LINE) {
  1903. return TRUE;
  1904. }
  1905. //
  1906. // make sure there is only one attr per line.
  1907. //
  1908. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y;
  1909. for (i=Region->Top;i<=Region->Bottom;i++) {
  1910. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  1911. if (Row->AttrRow.Length != 1) {
  1912. return FALSE;
  1913. }
  1914. if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) {
  1915. RowIndex = 0;
  1916. }
  1917. }
  1918. return TRUE;
  1919. }
  1920. #define MAX_POLY_LINES 80
  1921. #define VERY_BIG_NUMBER 0x0FFFFFFF
  1922. #ifdef WWSB_FE
  1923. typedef struct _KEISEN_INFORMATION {
  1924. COORD Coord;
  1925. WORD n;
  1926. } KEISEN_INFORMATION, *PKEISEN_INFORMATION;
  1927. #endif
  1928. VOID
  1929. WWSB_ConsolePolyTextOut(
  1930. IN PSCREEN_INFORMATION ScreenInfo,
  1931. IN PSMALL_RECT Region
  1932. )
  1933. /*
  1934. This function calls PolyTextOut. The only restriction is that
  1935. there can't be more than one attribute per line in the region.
  1936. */
  1937. {
  1938. PROW Row,LastRow;
  1939. SHORT i,k;
  1940. WORD Attr;
  1941. POLYTEXTW TextInfo[MAX_POLY_LINES];
  1942. RECT TextRect;
  1943. RECTL BoundingRect;
  1944. int xSize = SCR_FONTSIZE(ScreenInfo).X;
  1945. int ySize = SCR_FONTSIZE(ScreenInfo).Y;
  1946. ULONG Flags = ScreenInfo->BufferInfo.TextInfo.Flags;
  1947. int WindowLeft = ScreenInfo->Window.Left;
  1948. int RegionLeft = Region->Left;
  1949. int RegionRight = Region->Right + 1;
  1950. int DefaultLeft = (RegionLeft - WindowLeft) * xSize;
  1951. int DefaultRight = (RegionRight - WindowLeft) * xSize;
  1952. PCONSOLE_INFORMATION Console = ScreenInfo->Console;
  1953. PWCHAR TransPolyTextOut = NULL ;
  1954. #ifdef WWSB_FE
  1955. KEISEN_INFORMATION KeisenInfo[MAX_POLY_LINES];
  1956. SHORT j;
  1957. WORD OldAttr;
  1958. #endif
  1959. //
  1960. // initialize the text rect and window position.
  1961. //
  1962. TextRect.top = (Region->Top - ScreenInfo->Window.Top) * ySize;
  1963. // TextRect.bottom is invalid.
  1964. BoundingRect.top = TextRect.top;
  1965. BoundingRect.left = VERY_BIG_NUMBER;
  1966. BoundingRect.right = 0;
  1967. //
  1968. // copy the chars and attrs from their respective arrays
  1969. //
  1970. Row = &ScreenInfo->BufferInfo.TextInfo.Rows
  1971. [ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top];
  1972. LastRow = &ScreenInfo->BufferInfo.TextInfo.Rows[ScreenInfo->ScreenBufferSize.Y];
  1973. if (Row >= LastRow)
  1974. Row -= ScreenInfo->ScreenBufferSize.Y;
  1975. Attr = Row->AttrRow.AttrPair.Attr;
  1976. if (Console->LastAttributes != Attr) {
  1977. #ifdef WWSB_FE
  1978. if (Attr & COMMON_LVB_REVERSE_VIDEO)
  1979. {
  1980. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr)));
  1981. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4)));
  1982. }
  1983. else{
  1984. #endif
  1985. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr)));
  1986. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4)));
  1987. #ifdef WWSB_FE
  1988. }
  1989. #endif
  1990. Console->LastAttributes = Attr;
  1991. }
  1992. TransPolyTextOut = ConsoleHeapAlloc(TMP_DBCS_TAG,
  1993. ScreenInfo->ScreenBufferSize.X * MAX_POLY_LINES * sizeof(WCHAR));
  1994. if (TransPolyTextOut == NULL) {
  1995. RIPMSG0(RIP_WARNING, "ConsoleTextOut cannot allocate memory");
  1996. return;
  1997. }
  1998. for (i=Region->Top;i<=Region->Bottom;) {
  1999. PWCHAR TmpChar;
  2000. TmpChar = TransPolyTextOut;
  2001. for(k=0;i<=Region->Bottom&&k<MAX_POLY_LINES;i++) {
  2002. SHORT NumberOfChars;
  2003. SHORT LeftChar,RightChar;
  2004. //
  2005. // make the bounding rect smaller, if we can. the TEXT_VALID_HINT
  2006. // flag gets set each time we write to the screen buffer. it gets
  2007. // turned off any time we get asked to redraw the screen
  2008. // and we don't know exactly what needs to be redrawn
  2009. // (i.e. paint messages).
  2010. //
  2011. // we have the left and right bounds of the text on the
  2012. // line. the opaqueing rectangle and the number of
  2013. // chars get set according to those values.
  2014. //
  2015. TextRect.left = DefaultLeft;
  2016. TextRect.right = DefaultRight;
  2017. if (Flags & TEXT_VALID_HINT)
  2018. {
  2019. // We compute an opaquing interval. If A is the old interval of text,
  2020. // B is the new interval, and R is the Region, then the opaquing interval
  2021. // must be R*(A+B), where * represents intersection and + represents union.
  2022. if (Row->CharRow.OldLeft != INVALID_OLD_LENGTH)
  2023. {
  2024. // The min determines the left of (A+B). The max intersects that with
  2025. // the left of the region.
  2026. TextRect.left = (
  2027. max
  2028. (
  2029. min
  2030. (
  2031. Row->CharRow.Left,
  2032. Row->CharRow.OldLeft
  2033. ),
  2034. RegionLeft
  2035. )
  2036. -WindowLeft
  2037. ) * xSize;
  2038. }
  2039. if (Row->CharRow.OldRight != INVALID_OLD_LENGTH)
  2040. {
  2041. // The max determines the right of (A+B). The min intersects that with
  2042. // the right of the region.
  2043. TextRect.right = (
  2044. min
  2045. (
  2046. max
  2047. (
  2048. Row->CharRow.Right,
  2049. Row->CharRow.OldRight
  2050. ),
  2051. RegionRight
  2052. )
  2053. -WindowLeft
  2054. ) * xSize;
  2055. }
  2056. }
  2057. //
  2058. // We've got to draw any new text that appears in the region, so we just
  2059. // intersect the new text interval with the region.
  2060. //
  2061. LeftChar = max(Row->CharRow.Left,RegionLeft);
  2062. RightChar = min(Row->CharRow.Right,RegionRight);
  2063. NumberOfChars = RightChar - LeftChar;
  2064. #ifdef WWSB_FE
  2065. if (Row->CharRow.KAttrs[RightChar-1] & ATTR_LEADING_BYTE){
  2066. if(TextRect.right <= ScreenInfo->Window.Right*xSize) {
  2067. TextRect.right += xSize;
  2068. }
  2069. }
  2070. #endif
  2071. //
  2072. // Empty rows are represented by CharRow.Right=0, CharRow.Left=MAX, so we
  2073. // may have NumberOfChars<0 at this point if there is no text that needs
  2074. // drawing. (I.e. the intersection was empty.)
  2075. //
  2076. if (NumberOfChars < 0) {
  2077. NumberOfChars = 0;
  2078. LeftChar = 0;
  2079. RightChar = 0;
  2080. }
  2081. //
  2082. // We may also have TextRect.right<TextRect.left if the screen
  2083. // is already cleared, and we really don't need to do anything at all.
  2084. //
  2085. if (TextRect.right > TextRect.left)
  2086. {
  2087. NumberOfChars = (SHORT)RemoveDbcsMarkAll(ScreenInfo,Row,&LeftChar,&TextRect,NULL,TmpChar,NumberOfChars);
  2088. TextInfo[k].x = (LeftChar-WindowLeft) * xSize;
  2089. TextInfo[k].y = TextRect.top;
  2090. TextRect.bottom = TextRect.top + ySize;
  2091. TextInfo[k].n = NumberOfChars;
  2092. TextInfo[k].lpstr = TmpChar;
  2093. #ifdef WWSB_FE
  2094. if (CheckBisectStringW(ScreenInfo,
  2095. Console->OutputCP,
  2096. TmpChar,
  2097. NumberOfChars,
  2098. (TextRect.right-max(TextRect.left,TextInfo[k].x))/xSize
  2099. )
  2100. ) {
  2101. TextRect.right += xSize;
  2102. }
  2103. #endif
  2104. TmpChar += NumberOfChars;
  2105. TextInfo[k].rcl = TextRect;
  2106. TextInfo[k].pdx = NULL;
  2107. TextInfo[k].uiFlags = ETO_OPAQUE;
  2108. #ifdef WWSB_FE
  2109. KeisenInfo[k].n = DefaultRight-DefaultLeft ;
  2110. KeisenInfo[k].Coord.Y = (WORD)TextRect.top;
  2111. KeisenInfo[k].Coord.X = (WORD)DefaultLeft;
  2112. #endif
  2113. k++;
  2114. if (BoundingRect.left > TextRect.left) {
  2115. BoundingRect.left = TextRect.left;
  2116. }
  2117. if (BoundingRect.right < TextRect.right) {
  2118. BoundingRect.right = TextRect.right;
  2119. }
  2120. }
  2121. // Advance the high res bounds.
  2122. TextRect.top += ySize;
  2123. // Advance the row pointer.
  2124. if (++Row >= LastRow)
  2125. Row = ScreenInfo->BufferInfo.TextInfo.Rows;
  2126. // Draw now if the attributes are about to change.
  2127. #ifdef WWSB_FE
  2128. OldAttr = Attr ;
  2129. #endif
  2130. if (Attr != Row->AttrRow.AttrPair.Attr) {
  2131. Attr = Row->AttrRow.AttrPair.Attr;
  2132. i++;
  2133. break;
  2134. }
  2135. }
  2136. if (k)
  2137. {
  2138. BoundingRect.bottom = TextRect.top;
  2139. ASSERT(BoundingRect.left != VERY_BIG_NUMBER);
  2140. ASSERT(BoundingRect.left <= BoundingRect.right);
  2141. ASSERT(BoundingRect.top <= BoundingRect.bottom);
  2142. GdiConsoleTextOut(Console->hDC,
  2143. TextInfo,
  2144. k,
  2145. &BoundingRect);
  2146. #ifdef WWSB_FE
  2147. for ( j = 0 ; j < k ; j++){
  2148. RECT TextRect;
  2149. TextRect.left = KeisenInfo[j].Coord.X;
  2150. TextRect.top = KeisenInfo[j].Coord.Y;
  2151. TextRect.right = KeisenInfo[j].n + TextRect.left;
  2152. TextRect.bottom = KeisenInfo[j].Coord.Y + ySize;
  2153. TextOutCommonLVB(ScreenInfo->Console, OldAttr, TextRect);
  2154. }
  2155. #endif
  2156. }
  2157. if (Console->LastAttributes != Attr) {
  2158. #ifdef WWSB_FE
  2159. if (Attr & COMMON_LVB_REVERSE_VIDEO)
  2160. {
  2161. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr)));
  2162. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4)));
  2163. }
  2164. else{
  2165. #endif
  2166. SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr)));
  2167. SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4)));
  2168. #ifdef WWSB_FE
  2169. }
  2170. #endif
  2171. Console->LastAttributes = Attr;
  2172. BoundingRect.top = TextRect.top;
  2173. BoundingRect.left = VERY_BIG_NUMBER;
  2174. BoundingRect.right = 0;
  2175. }
  2176. }
  2177. GdiFlush();
  2178. ConsoleHeapFree(TransPolyTextOut);
  2179. }