Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

_output.h

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 _output.h 00008 00009 Abstract: 00010 00011 Performance critical routine for Single Binary 00012 00013 Each function will be created with two flavors FE and non FE 00014 00015 Author: 00016 00017 KazuM Jun.11.1997 00018 00019 Revision History: 00020 00021 --*/ 00022 00023 #define WWSB_NEUTRAL_FILE 1 00024 00025 #if !defined(FE_SB) 00026 #error This header file should be included with FE_SB 00027 #endif 00028 00029 #if !defined(WWSB_FE) && !defined(WWSB_NOFE) 00030 #error Either WWSB_FE and WWSB_NOFE must be defined. 00031 #endif 00032 00033 #if defined(WWSB_FE) && defined(WWSB_NOFE) 00034 #error Both WWSB_FE and WWSB_NOFE defined. 00035 #endif 00036 00037 #include "dispatch.h" 00038 00039 #if defined(WWSB_FE) 00040 #pragma alloc_text(FE_TEXT, FE_StreamWriteToScreenBuffer) 00041 #pragma alloc_text(FE_TEXT, FE_WriteRectToScreenBuffer) 00042 #pragma alloc_text(FE_TEXT, FE_WriteRegionToScreen) 00043 #pragma alloc_text(FE_TEXT, FE_WriteToScreen) 00044 #pragma alloc_text(FE_TEXT, FE_WriteOutputString) 00045 #pragma alloc_text(FE_TEXT, FE_FillOutput) 00046 #pragma alloc_text(FE_TEXT, FE_FillRectangle) 00047 #pragma alloc_text(FE_TEXT, FE_PolyTextOutCandidate) 00048 #pragma alloc_text(FE_TEXT, FE_ConsolePolyTextOut) 00049 #endif 00050 00051 00052 #if defined(WWSB_NOFE) 00053 VOID 00054 SB_StreamWriteToScreenBuffer( 00055 IN PWCHAR String, 00056 IN SHORT StringLength, 00057 IN PSCREEN_INFORMATION ScreenInfo 00058 ) 00059 #else 00060 VOID 00061 FE_StreamWriteToScreenBuffer( 00062 IN PWCHAR String, 00063 IN SHORT StringLength, 00064 IN PSCREEN_INFORMATION ScreenInfo, 00065 IN PCHAR StringA 00066 ) 00067 #endif 00068 { 00069 SHORT RowIndex; 00070 PROW Row; 00071 PWCHAR Char; 00072 COORD TargetPoint; 00073 00074 DBGOUTPUT(("StreamWriteToScreenBuffer\n")); 00075 #ifdef WWSB_FE 00076 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 00077 #endif 00078 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 00079 TargetPoint = ScreenInfo->BufferInfo.TextInfo.CursorPosition; 00080 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y; 00081 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 00082 DBGOUTPUT(("RowIndex = %x, Row = %x, TargetPoint = (%x,%x)\n", 00083 RowIndex, Row, TargetPoint.X, TargetPoint.Y)); 00084 00085 // 00086 // copy chars 00087 // 00088 #ifdef WWSB_FE 00089 BisectWrite(StringLength,TargetPoint,ScreenInfo); 00090 if (TargetPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && 00091 TargetPoint.X+StringLength >= ScreenInfo->ScreenBufferSize.X && 00092 *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) & ATTR_LEADING_BYTE 00093 ) { 00094 *(String+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) = UNICODE_SPACE; 00095 *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) = 0; 00096 if (StringLength > ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) { 00097 *(String+ScreenInfo->ScreenBufferSize.X-TargetPoint.X) = UNICODE_SPACE; 00098 *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X) = 0; 00099 } 00100 } 00101 00102 RtlCopyMemory(&Row->CharRow.KAttrs[TargetPoint.X],StringA,StringLength*sizeof(CHAR)); 00103 #endif 00104 00105 RtlCopyMemory(&Row->CharRow.Chars[TargetPoint.X],String,StringLength*sizeof(WCHAR)); 00106 00107 // recalculate first and last non-space char 00108 00109 Row->CharRow.OldLeft = Row->CharRow.Left; 00110 if (TargetPoint.X < Row->CharRow.Left) { 00111 PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X]; 00112 00113 for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++) 00114 ; 00115 Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars); 00116 } 00117 00118 Row->CharRow.OldRight = Row->CharRow.Right; 00119 if ((TargetPoint.X+StringLength) >= Row->CharRow.Right) { 00120 PWCHAR FirstChar = Row->CharRow.Chars; 00121 00122 for (Char=&Row->CharRow.Chars[TargetPoint.X+StringLength-1];*Char==(WCHAR)' ' && Char >= FirstChar;Char--) 00123 ; 00124 Row->CharRow.Right = (SHORT)(Char+1-FirstChar); 00125 } 00126 00127 // 00128 // see if attr string is different. if so, allocate a new 00129 // attr buffer and merge the two strings. 00130 // 00131 00132 if (Row->AttrRow.Length != 1 || 00133 Row->AttrRow.Attrs->Attr != ScreenInfo->Attributes) { 00134 PATTR_PAIR NewAttrs; 00135 WORD NewAttrsLength; 00136 ATTR_PAIR Attrs; 00137 00138 Attrs.Length = StringLength; 00139 Attrs.Attr = ScreenInfo->Attributes; 00140 if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, 00141 Row->AttrRow.Length, 00142 &Attrs, 00143 1, 00144 &NewAttrs, 00145 &NewAttrsLength, 00146 TargetPoint.X, 00147 (SHORT)(TargetPoint.X+StringLength-1), 00148 Row, 00149 ScreenInfo 00150 ))) { 00151 return; 00152 } 00153 if (Row->AttrRow.Length > 1) { 00154 ConsoleHeapFree(Row->AttrRow.Attrs); 00155 } 00156 else { 00157 ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); 00158 } 00159 Row->AttrRow.Attrs = NewAttrs; 00160 Row->AttrRow.Length = NewAttrsLength; 00161 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 00162 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 00163 } 00164 ResetTextFlags(ScreenInfo,TargetPoint.Y,TargetPoint.Y); 00165 } 00166 00167 00168 #define CHAR_OF_PCI(p) (((PCHAR_INFO)(p))->Char.AsciiChar) 00169 #define WCHAR_OF_PCI(p) (((PCHAR_INFO)(p))->Char.UnicodeChar) 00170 #define ATTR_OF_PCI(p) (((PCHAR_INFO)(p))->Attributes) 00171 #define SIZEOF_CI_CELL sizeof(CHAR_INFO) 00172 00173 #define CHAR_OF_VGA(p) (p[0]) 00174 #define ATTR_OF_VGA(p) (p[1]) 00175 #ifdef i386 00176 #define SIZEOF_VGA_CELL 2 00177 #else // risc 00178 #define SIZEOF_VGA_CELL 4 00179 #endif 00180 00181 00182 #define COMMON_LVB_MASK 0x33 00183 #define ATTR_OF_COMMON_LVB(p) (ATTR_OF_VGA(p) + (((p[2] & ~COMMON_LVB_MASK)) << 8)) 00184 #define SIZEOF_COMMON_LVB_CELL 4 00185 00186 VOID 00187 WWSB_WriteRectToScreenBuffer( 00188 PBYTE Source, 00189 COORD SourceSize, 00190 PSMALL_RECT SourceRect, 00191 PSCREEN_INFORMATION ScreenInfo, 00192 COORD TargetPoint, 00193 IN UINT Codepage 00194 ) 00195 00196 /*++ 00197 00198 Routine Description: 00199 00200 This routine copies a rectangular region to the screen buffer. 00201 no clipping is done. 00202 00203 The source should contain Unicode or UnicodeOem chars. 00204 00205 Arguments: 00206 00207 Source - pointer to source buffer (a real VGA buffer or CHAR_INFO[]) 00208 00209 SourceSize - dimensions of source buffer 00210 00211 SourceRect - rectangle in source buffer to copy 00212 00213 ScreenInfo - pointer to screen info 00214 00215 TargetPoint - upper left coordinates of target rectangle 00216 00217 Codepage - codepage to translate real VGA buffer from, 00218 0xFFFFFFF if Source is CHAR_INFO[] (not requiring translation) 00219 Return Value: 00220 00221 none. 00222 00223 --*/ 00224 00225 { 00226 00227 PBYTE SourcePtr; 00228 SHORT i,j; 00229 SHORT XSize,YSize; 00230 BOOLEAN WholeSource; 00231 SHORT RowIndex; 00232 PROW Row; 00233 PWCHAR Char; 00234 ATTR_PAIR Attrs[80]; 00235 PATTR_PAIR AttrBuf; 00236 PATTR_PAIR Attr; 00237 SHORT AttrLength; 00238 BOOL bVGABuffer; 00239 ULONG ulCellSize; 00240 #ifdef WWSB_FE 00241 PCHAR AttrP; 00242 #endif 00243 00244 DBGOUTPUT(("WriteRectToScreenBuffer\n")); 00245 #ifdef WWSB_FE 00246 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 00247 #endif 00248 00249 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 00250 XSize = (SHORT)(SourceRect->Right - SourceRect->Left + 1); 00251 YSize = (SHORT)(SourceRect->Bottom - SourceRect->Top + 1); 00252 00253 00254 AttrBuf = Attrs; 00255 if (XSize > 80) { 00256 AttrBuf = (PATTR_PAIR)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),XSize * sizeof(ATTR_PAIR)); 00257 if (AttrBuf == NULL) 00258 return; 00259 } 00260 00261 bVGABuffer = (Codepage != 0xFFFFFFFF); 00262 if (bVGABuffer) { 00263 #ifdef WWSB_FE 00264 ulCellSize = (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL; 00265 #else 00266 ulCellSize = SIZEOF_VGA_CELL; 00267 #endif 00268 } else { 00269 ulCellSize = SIZEOF_CI_CELL; 00270 } 00271 00272 SourcePtr = Source; 00273 00274 WholeSource = FALSE; 00275 if (XSize == SourceSize.X) { 00276 ASSERT (SourceRect->Left == 0); 00277 if (SourceRect->Top != 0) { 00278 SourcePtr += SCREEN_BUFFER_POINTER(SourceRect->Left, 00279 SourceRect->Top, 00280 SourceSize.X, 00281 ulCellSize); 00282 } 00283 WholeSource = TRUE; 00284 } 00285 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y; 00286 for (i=0;i<YSize;i++) { 00287 if (!WholeSource) { 00288 SourcePtr = Source + SCREEN_BUFFER_POINTER(SourceRect->Left, 00289 SourceRect->Top+i, 00290 SourceSize.X, 00291 ulCellSize); 00292 } 00293 00294 // 00295 // copy the chars and attrs into their respective arrays 00296 // 00297 00298 #ifdef WWSB_FE 00299 if (! bVGABuffer) { 00300 COORD TPoint; 00301 00302 TPoint.X = TargetPoint.X; 00303 TPoint.Y = TargetPoint.Y + i; 00304 BisectWrite(XSize,TPoint,ScreenInfo); 00305 if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && 00306 TPoint.X+XSize-1 >= ScreenInfo->ScreenBufferSize.X && 00307 ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & COMMON_LVB_LEADING_BYTE) 00308 { 00309 WCHAR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE; 00310 ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) &= ~COMMON_LVB_SBCSDBCS; 00311 if (XSize-1 > ScreenInfo->ScreenBufferSize.X-TPoint.X-1) { 00312 WCHAR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE; 00313 ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X) &= ~COMMON_LVB_SBCSDBCS; 00314 } 00315 } 00316 } 00317 #endif 00318 00319 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 00320 Char = &Row->CharRow.Chars[TargetPoint.X]; 00321 #ifdef WWSB_FE 00322 AttrP = &Row->CharRow.KAttrs[TargetPoint.X]; 00323 #endif 00324 Attr = AttrBuf; 00325 Attr->Length = 0; 00326 AttrLength = 1; 00327 00328 /* 00329 * Two version of the following loop to keep it fast: 00330 * one for VGA buffers, one for CHAR_INFO buffers. 00331 */ 00332 if (bVGABuffer) { 00333 #ifdef WWSB_FE 00334 Attr->Attr = (ScreenInfo->Console->fVDMVideoMode) ? ATTR_OF_COMMON_LVB(SourcePtr) : ATTR_OF_VGA(SourcePtr); 00335 #else 00336 Attr->Attr = ATTR_OF_VGA(SourcePtr); 00337 #endif 00338 for (j = SourceRect->Left; 00339 j <= SourceRect->Right; 00340 j++, 00341 #ifdef WWSB_FE 00342 SourcePtr += (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL 00343 #else 00344 SourcePtr += SIZEOF_VGA_CELL 00345 #endif 00346 ) { 00347 00348 #ifdef WWSB_FE 00349 UCHAR TmpBuff[2]; 00350 00351 if (IsDBCSLeadByteConsole(CHAR_OF_VGA(SourcePtr),&ScreenInfo->Console->OutputCPInfo)) { 00352 if (j+1 > SourceRect->Right) { 00353 *Char = UNICODE_SPACE; 00354 *AttrP = 0; 00355 } 00356 else { 00357 TmpBuff[0] = CHAR_OF_VGA(SourcePtr); 00358 TmpBuff[1] = CHAR_OF_VGA((SourcePtr + ((ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL))); 00359 ConvertOutputToUnicode(Codepage, 00360 TmpBuff, 00361 2, 00362 Char, 00363 2); 00364 Char++; 00365 j++; 00366 *AttrP++ = ATTR_LEADING_BYTE; 00367 *Char++ = *(Char-1); 00368 *AttrP++ = ATTR_TRAILING_BYTE; 00369 00370 if (ScreenInfo->Console->fVDMVideoMode) { 00371 if (Attr->Attr == ATTR_OF_COMMON_LVB(SourcePtr)) { 00372 Attr->Length += 1; 00373 } 00374 else { 00375 Attr++; 00376 Attr->Length = 1; 00377 Attr->Attr = ATTR_OF_COMMON_LVB(SourcePtr); 00378 AttrLength += 1; 00379 } 00380 } 00381 else 00382 { 00383 if (Attr->Attr == ATTR_OF_VGA(SourcePtr)) { 00384 Attr->Length += 1; 00385 } 00386 else { 00387 Attr++; 00388 Attr->Length = 1; 00389 Attr->Attr = ATTR_OF_VGA(SourcePtr); 00390 AttrLength += 1; 00391 } 00392 } 00393 00394 SourcePtr += (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL; 00395 } 00396 } 00397 else { 00398 ConvertOutputToUnicode(Codepage, 00399 &CHAR_OF_VGA(SourcePtr), 00400 1, 00401 Char, 00402 1); 00403 Char++; 00404 *AttrP++ = 0; 00405 } 00406 #else 00407 *Char++ = SB_CharToWcharGlyph(Codepage, CHAR_OF_VGA(SourcePtr)); 00408 #endif 00409 00410 #ifdef WWSB_FE 00411 if (ScreenInfo->Console->fVDMVideoMode) { 00412 if (Attr->Attr == ATTR_OF_COMMON_LVB(SourcePtr)) { 00413 Attr->Length += 1; 00414 } 00415 else { 00416 Attr++; 00417 Attr->Length = 1; 00418 Attr->Attr = ATTR_OF_COMMON_LVB(SourcePtr); 00419 AttrLength += 1; 00420 } 00421 } 00422 else 00423 #endif 00424 if (Attr->Attr == ATTR_OF_VGA(SourcePtr)) { 00425 Attr->Length += 1; 00426 } 00427 else { 00428 Attr++; 00429 Attr->Length = 1; 00430 Attr->Attr = ATTR_OF_VGA(SourcePtr); 00431 AttrLength += 1; 00432 } 00433 } 00434 } else { 00435 #ifdef WWSB_FE 00436 Attr->Attr = ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS; 00437 #else 00438 Attr->Attr = ATTR_OF_PCI(SourcePtr); 00439 #endif 00440 for (j = SourceRect->Left; 00441 j <= SourceRect->Right; 00442 j++, SourcePtr += SIZEOF_CI_CELL) { 00443 00444 *Char++ = WCHAR_OF_PCI(SourcePtr); 00445 #ifdef WWSB_FE 00446 // MSKK Apr.02.1993 V-HirotS For KAttr 00447 *AttrP++ = (CHAR)((ATTR_OF_PCI(SourcePtr) & COMMON_LVB_SBCSDBCS) >>8); 00448 #endif 00449 00450 #ifdef WWSB_FE 00451 if (Attr->Attr == (ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS)) 00452 #else 00453 if (Attr->Attr == ATTR_OF_PCI(SourcePtr)) 00454 #endif 00455 { 00456 Attr->Length += 1; 00457 } 00458 else { 00459 Attr++; 00460 Attr->Length = 1; 00461 #ifdef WWSB_FE 00462 // MSKK Apr.02.1993 V-HirotS For KAttr 00463 Attr->Attr = ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS; 00464 #else 00465 Attr->Attr = ATTR_OF_PCI(SourcePtr); 00466 #endif 00467 AttrLength += 1; 00468 } 00469 } 00470 } 00471 00472 // recalculate first and last non-space char 00473 00474 Row->CharRow.OldLeft = Row->CharRow.Left; 00475 if (TargetPoint.X < Row->CharRow.Left) { 00476 PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X]; 00477 00478 for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++) 00479 ; 00480 Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars); 00481 } 00482 00483 Row->CharRow.OldRight = Row->CharRow.Right; 00484 if ((TargetPoint.X+XSize) >= Row->CharRow.Right) { 00485 SHORT LastNonSpace; 00486 PWCHAR FirstChar = Row->CharRow.Chars; 00487 00488 LastNonSpace = (SHORT)(TargetPoint.X+XSize-1); 00489 for (Char=&Row->CharRow.Chars[(TargetPoint.X+XSize-1)];*Char==(WCHAR)' ' && Char >= FirstChar;Char--) 00490 LastNonSpace--; 00491 00492 // 00493 // if the attributes change after the last non-space, make the 00494 // index of the last attribute change + 1 the length. otherwise 00495 // make the length one more than the last non-space. 00496 // 00497 00498 Row->CharRow.Right = (SHORT)(LastNonSpace+1); 00499 } 00500 00501 // 00502 // see if attr string is different. if so, allocate a new 00503 // attr buffer and merge the two strings. 00504 // 00505 00506 00507 if (AttrLength != Row->AttrRow.Length || 00508 memcmp(Row->AttrRow.Attrs,AttrBuf,AttrLength*sizeof(*Attr))) { 00509 PATTR_PAIR NewAttrs; 00510 WORD NewAttrsLength; 00511 00512 if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, 00513 Row->AttrRow.Length, 00514 AttrBuf, 00515 AttrLength, 00516 &NewAttrs, 00517 &NewAttrsLength, 00518 TargetPoint.X, 00519 (SHORT)(TargetPoint.X+XSize-1), 00520 Row, 00521 ScreenInfo 00522 ))) { 00523 if (XSize > 80) { 00524 ConsoleHeapFree(AttrBuf); 00525 } 00526 ResetTextFlags(ScreenInfo,TargetPoint.Y,(SHORT)(TargetPoint.Y+YSize-1)); 00527 return; 00528 } 00529 if (Row->AttrRow.Length > 1) { 00530 ConsoleHeapFree(Row->AttrRow.Attrs); 00531 } 00532 else { 00533 ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); 00534 } 00535 Row->AttrRow.Attrs = NewAttrs; 00536 Row->AttrRow.Length = NewAttrsLength; 00537 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 00538 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 00539 } 00540 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 00541 RowIndex = 0; 00542 } 00543 } 00544 ResetTextFlags(ScreenInfo,TargetPoint.Y,(SHORT)(TargetPoint.Y+YSize-1)); 00545 00546 if (XSize > 80) { 00547 ConsoleHeapFree(AttrBuf); 00548 } 00549 } 00550 00551 VOID 00552 WWSB_WriteRegionToScreen( 00553 IN PSCREEN_INFORMATION ScreenInfo, 00554 IN PSMALL_RECT Region 00555 ) 00556 { 00557 COORD Window; 00558 int i,j; 00559 PATTR_PAIR Attr; 00560 RECT TextRect; 00561 SHORT RowIndex; 00562 SHORT CountOfAttr; 00563 PROW Row; 00564 BOOL OneLine, SimpleWrite; // one line && one attribute per line 00565 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 00566 PWCHAR TransBufferCharacter = NULL ; 00567 #ifdef WWSB_FE 00568 BOOL DoubleColorDbcs; 00569 SHORT CountOfAttrOriginal; 00570 SHORT RegionRight; 00571 BOOL LocalEUDCFlag; 00572 SMALL_RECT CaTextRect; 00573 PCONVERSIONAREA_INFORMATION ConvAreaInfo = ScreenInfo->ConvScreenInfo; 00574 #endif 00575 00576 DBGOUTPUT(("WriteRegionToScreen\n")); 00577 00578 #ifdef WWSB_FE 00579 if (ConvAreaInfo) { 00580 CaTextRect.Left = Region->Left - ScreenInfo->Console->CurrentScreenBuffer->Window.Left - ConvAreaInfo->CaInfo.coordConView.X; 00581 CaTextRect.Right = CaTextRect.Left + (Region->Right - Region->Left); 00582 CaTextRect.Top = Region->Top - ScreenInfo->Console->CurrentScreenBuffer->Window.Top - ConvAreaInfo->CaInfo.coordConView.Y; 00583 CaTextRect.Bottom = CaTextRect.Top + (Region->Bottom - Region->Top); 00584 } 00585 00586 if (Region->Left && (ScreenInfo->BisectFlag & BISECT_LEFT)) { 00587 Region->Left--; 00588 } 00589 if (Region->Right+1 < ScreenInfo->ScreenBufferSize.X && (ScreenInfo->BisectFlag & BISECT_RIGHT)) { 00590 Region->Right++; 00591 } 00592 ScreenInfo->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT); 00593 Console->ConsoleIme.ScrollWaitCountDown = Console->ConsoleIme.ScrollWaitTimeout; 00594 #endif 00595 00596 if (Console->FullScreenFlags == 0) { 00597 00598 // 00599 // if we have a selection, turn it off. 00600 // 00601 00602 InvertSelection(Console, TRUE); 00603 00604 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 00605 if (WWSB_PolyTextOutCandidate(ScreenInfo,Region)) { 00606 WWSB_ConsolePolyTextOut(ScreenInfo,Region); 00607 } 00608 else { 00609 00610 #ifdef WWSB_FE 00611 if (ConvAreaInfo) { 00612 Window.Y = Region->Top - Console->CurrentScreenBuffer->Window.Top; 00613 Window.X = Region->Left - Console->CurrentScreenBuffer->Window.Left; 00614 } 00615 else { 00616 #endif 00617 Window.Y = Region->Top - ScreenInfo->Window.Top; 00618 Window.X = Region->Left - ScreenInfo->Window.Left; 00619 #ifdef WWSB_FE 00620 } 00621 #endif 00622 00623 #ifdef WWSB_FE 00624 RowIndex = (ConvAreaInfo ? CaTextRect.Top : 00625 (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y 00626 ); 00627 RegionRight = Region->Right; 00628 #else 00629 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y; 00630 #endif 00631 OneLine = (Region->Top==Region->Bottom); 00632 00633 TransBufferCharacter = (PWCHAR)ConsoleHeapAlloc( 00634 MAKE_TAG( TMP_DBCS_TAG ), 00635 (ScreenInfo->ScreenBufferSize.X*sizeof(WCHAR))+sizeof(WCHAR)); 00636 if (TransBufferCharacter == NULL) 00637 { 00638 KdPrint(("CONSRV: WriteRegionToScreen cannot allocate memory\n")); 00639 return ; 00640 } 00641 00642 for (i=Region->Top;i<=Region->Bottom;i++,Window.Y++) { 00643 #ifdef WWSB_FE 00644 DoubleColorDbcs = FALSE; 00645 Region->Right = RegionRight; 00646 #endif 00647 00648 // 00649 // copy the chars and attrs from their respective arrays 00650 // 00651 00652 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 00653 00654 if (Row->AttrRow.Length == 1) { 00655 Attr = Row->AttrRow.Attrs; 00656 CountOfAttr = ScreenInfo->ScreenBufferSize.X; 00657 SimpleWrite = TRUE; 00658 } else { 00659 SimpleWrite = FALSE; 00660 FindAttrIndex(Row->AttrRow.Attrs, 00661 #ifdef WWSB_FE 00662 (SHORT)(ConvAreaInfo ? CaTextRect.Left : Region->Left), 00663 #else 00664 Region->Left, 00665 #endif 00666 &Attr, 00667 &CountOfAttr 00668 ); 00669 } 00670 if (Console->LastAttributes != Attr->Attr) { 00671 TEXTCOLOR_CALL; 00672 #ifdef WWSB_FE 00673 if (Attr->Attr & COMMON_LVB_REVERSE_VIDEO) 00674 { 00675 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); 00676 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); 00677 } 00678 else{ 00679 #endif 00680 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); 00681 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); 00682 #ifdef WWSB_FE 00683 } 00684 #endif 00685 Console->LastAttributes = Attr->Attr; 00686 } 00687 TextRect.top = Window.Y*SCR_FONTSIZE(ScreenInfo).Y; 00688 TextRect.bottom = TextRect.top + SCR_FONTSIZE(ScreenInfo).Y; 00689 for (j=Region->Left;j<=Region->Right;) { 00690 SHORT NumberOfChars; 00691 int TextLeft; 00692 SHORT LeftChar,RightChar; 00693 00694 if (CountOfAttr > (SHORT)(Region->Right - j + 1)) { 00695 CountOfAttr = (SHORT)(Region->Right - j + 1); 00696 } 00697 00698 #ifdef WWSB_FE 00699 CountOfAttrOriginal = CountOfAttr; 00700 00701 00702 LocalEUDCFlag = FALSE; 00703 if((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED && 00704 ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalVDMEudcMode)){ 00705 LocalEUDCFlag = CheckEudcRangeInString( 00706 Console, 00707 &Row->CharRow.Chars[ConvAreaInfo ? 00708 CaTextRect.Left + (j-Region->Left) : j], 00709 CountOfAttr, 00710 &CountOfAttr); 00711 } 00712 if (!(ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 00713 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) && 00714 ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalKeisenEudcMode 00715 ) { 00716 SHORT k; 00717 PWCHAR Char2; 00718 Char2 = &Row->CharRow.Chars[ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j]; 00719 for ( k = 0 ; k < CountOfAttr ; k++,Char2++){ 00720 if (*Char2 < UNICODE_SPACE){ 00721 CountOfAttr = k ; 00722 LocalEUDCFlag = TRUE; 00723 break; 00724 } 00725 } 00726 } 00727 #endif 00728 00729 // 00730 // make the bounding rect smaller, if we can. the TEXT_VALID_HINT 00731 // flag gets set each time we write to the screen buffer. it gets 00732 // turned off any time we get asked to redraw the screen 00733 // and we don't know exactly what needs to be redrawn 00734 // (i.e. paint messages). 00735 // 00736 // we have the left and right bounds of the text on the 00737 // line. the opaqueing rectangle and the number of 00738 // chars get set according to those values. 00739 // 00740 // if there's more than one attr per line (!SimpleWrite) 00741 // we bail on the opaqueing rect. 00742 // 00743 00744 if (ScreenInfo->BufferInfo.TextInfo.Flags & TEXT_VALID_HINT && SimpleWrite) { 00745 if (Row->CharRow.OldLeft != INVALID_OLD_LENGTH) { 00746 TextRect.left = (max(min(Row->CharRow.Left,Row->CharRow.OldLeft),j)-ScreenInfo->Window.Left) * 00747 SCR_FONTSIZE(ScreenInfo).X; 00748 } else { 00749 TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X; 00750 } 00751 00752 if (Row->CharRow.OldRight != INVALID_OLD_LENGTH) { 00753 TextRect.right = (min(max(Row->CharRow.Right,Row->CharRow.OldRight),j+CountOfAttr)-ScreenInfo->Window.Left) * 00754 SCR_FONTSIZE(ScreenInfo).X; 00755 } else { 00756 TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X; 00757 } 00758 LeftChar = max(Row->CharRow.Left,j); 00759 RightChar = min(Row->CharRow.Right,j+CountOfAttr); 00760 NumberOfChars = RightChar - LeftChar; 00761 TextLeft = (LeftChar-ScreenInfo->Window.Left)*SCR_FONTSIZE(ScreenInfo).X; 00762 } else { 00763 #ifdef WWSB_FE 00764 LeftChar = ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j; 00765 #else 00766 LeftChar = (SHORT)j; 00767 #endif 00768 TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X; 00769 TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X; 00770 #ifdef WWSB_FE 00771 if (ConvAreaInfo) 00772 NumberOfChars = (Row->CharRow.Right > (SHORT)((CaTextRect.Left+(j-Region->Left)) + CountOfAttr)) ? 00773 (CountOfAttr) : (SHORT)(Row->CharRow.Right-(CaTextRect.Left+(j-Region->Left))); 00774 else 00775 #endif 00776 NumberOfChars = (Row->CharRow.Right > (SHORT)(j + CountOfAttr)) ? (CountOfAttr) : (SHORT)(Row->CharRow.Right-j); 00777 TextLeft = TextRect.left; 00778 } 00779 00780 if (NumberOfChars < 0) 00781 { 00782 NumberOfChars = 0; 00783 #ifdef WWSB_FE 00784 TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X; 00785 TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X; 00786 #endif 00787 } 00788 TEXTOUT_CALL; 00789 #ifdef WWSB_FE 00790 /* 00791 * Text out everything (i.e. SBCS/DBCS, Common LVB attribute, Local EUDC) 00792 */ 00793 TextOutEverything(Console, 00794 ScreenInfo, 00795 (SHORT)j, 00796 &Region->Right, 00797 &CountOfAttr, 00798 CountOfAttrOriginal, 00799 &DoubleColorDbcs, 00800 LocalEUDCFlag, 00801 Row, 00802 Attr, 00803 LeftChar, 00804 RightChar, 00805 TextLeft, 00806 TextRect, 00807 NumberOfChars); 00808 #else 00809 NumberOfChars = 00810 (SHORT)RemoveDbcsMarkAll(ScreenInfo, 00811 Row, 00812 &LeftChar, 00813 &TextRect, 00814 &TextLeft, 00815 TransBufferCharacter, 00816 NumberOfChars); 00817 ExtTextOutW(Console->hDC, 00818 TextLeft, 00819 TextRect.top, 00820 ETO_OPAQUE, 00821 &TextRect, 00822 TransBufferCharacter, 00823 NumberOfChars, 00824 NULL 00825 ); 00826 #endif 00827 if (OneLine && SimpleWrite) { 00828 break; 00829 } 00830 j+=CountOfAttr; 00831 if (j <= Region->Right) { 00832 Window.X += CountOfAttr; 00833 #ifdef WWSB_FE 00834 if (CountOfAttr < CountOfAttrOriginal){ 00835 CountOfAttr = CountOfAttrOriginal - CountOfAttr; 00836 } 00837 else { 00838 #endif 00839 Attr++; 00840 CountOfAttr = Attr->Length; 00841 #ifdef WWSB_FE 00842 } 00843 #endif 00844 #ifdef WWSB_FE 00845 if (Attr->Attr & COMMON_LVB_REVERSE_VIDEO) 00846 { 00847 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); 00848 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); 00849 } 00850 else{ 00851 #endif 00852 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); 00853 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); 00854 #ifdef WWSB_FE 00855 } 00856 #endif 00857 Console->LastAttributes = Attr->Attr; 00858 } 00859 } 00860 Window.X = Region->Left - ScreenInfo->Window.Left; 00861 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 00862 RowIndex = 0; 00863 } 00864 } 00865 GdiFlush(); 00866 ConsoleHeapFree(TransBufferCharacter); 00867 } 00868 00869 // 00870 // if we have a selection, turn it on. 00871 // 00872 00873 InvertSelection(Console, FALSE); 00874 } 00875 #ifdef i386 00876 else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { 00877 #ifdef WWSB_FE 00878 if (! ScreenInfo->ConvScreenInfo) { 00879 if (ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo) { 00880 WWSB_WriteRegionToScreenHW(ScreenInfo,Region); 00881 } 00882 } 00883 else if (ScreenInfo->Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) 00884 #endif 00885 WWSB_WriteRegionToScreenHW(ScreenInfo,Region); 00886 } 00887 #endif 00888 00889 #ifdef WWSB_FE 00890 { 00891 SMALL_RECT TmpRegion; 00892 00893 if (ScreenInfo->BisectFlag & BISECT_TOP) { 00894 ScreenInfo->BisectFlag &= ~BISECT_TOP; 00895 if (Region->Top) { 00896 TmpRegion.Top = Region->Top-1; 00897 TmpRegion.Bottom = Region->Top-1; 00898 TmpRegion.Left = ScreenInfo->ScreenBufferSize.X-1; 00899 TmpRegion.Right = ScreenInfo->ScreenBufferSize.X-1; 00900 WWSB_WriteRegionToScreen(ScreenInfo,&TmpRegion); 00901 } 00902 } 00903 if (ScreenInfo->BisectFlag & BISECT_BOTTOM) { 00904 ScreenInfo->BisectFlag &= ~BISECT_BOTTOM; 00905 if (Region->Bottom+1 < ScreenInfo->ScreenBufferSize.Y) { 00906 TmpRegion.Top = Region->Bottom+1; 00907 TmpRegion.Bottom = Region->Bottom+1; 00908 TmpRegion.Left = 0; 00909 TmpRegion.Right = 0; 00910 WWSB_WriteRegionToScreen(ScreenInfo,&TmpRegion); 00911 } 00912 } 00913 } 00914 #endif 00915 } 00916 00917 VOID 00918 WWSB_WriteToScreen( 00919 IN PSCREEN_INFORMATION ScreenInfo, 00920 IN PSMALL_RECT Region 00921 ) 00922 /*++ 00923 00924 Routine Description: 00925 00926 This routine writes a screen buffer region to the screen. 00927 00928 Arguments: 00929 00930 ScreenInfo - Pointer to screen buffer information. 00931 00932 Region - Region to write in screen buffer coordinates. Region is 00933 inclusive 00934 00935 Return Value: 00936 00937 none. 00938 00939 --*/ 00940 00941 { 00942 SMALL_RECT ClippedRegion; 00943 00944 DBGOUTPUT(("WriteToScreen\n")); 00945 // 00946 // update to screen, if we're not iconic. we're marked as 00947 // iconic if we're fullscreen, so check for fullscreen. 00948 // 00949 00950 if (!ACTIVE_SCREEN_BUFFER(ScreenInfo) || 00951 (ScreenInfo->Console->Flags & (CONSOLE_IS_ICONIC | CONSOLE_NO_WINDOW) && 00952 ScreenInfo->Console->FullScreenFlags == 0)) { 00953 return; 00954 } 00955 00956 // clip region 00957 00958 ClippedRegion.Left = max(Region->Left, ScreenInfo->Window.Left); 00959 ClippedRegion.Top = max(Region->Top, ScreenInfo->Window.Top); 00960 ClippedRegion.Right = min(Region->Right, ScreenInfo->Window.Right); 00961 ClippedRegion.Bottom = min(Region->Bottom, ScreenInfo->Window.Bottom); 00962 if (ClippedRegion.Right < ClippedRegion.Left || 00963 ClippedRegion.Bottom < ClippedRegion.Top) { 00964 return; 00965 } 00966 00967 if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { 00968 if (ScreenInfo->Console->FullScreenFlags == 0) { 00969 WriteRegionToScreenBitMap(ScreenInfo, &ClippedRegion); 00970 } 00971 } else { 00972 ConsoleHideCursor(ScreenInfo); 00973 WWSB_WriteRegionToScreen(ScreenInfo, &ClippedRegion); 00974 #ifdef WWSB_FE 00975 if (!(ScreenInfo->Console->ConsoleIme.ScrollFlag & HIDE_FOR_SCROLL)) 00976 { 00977 PCONVERSIONAREA_INFORMATION ConvAreaInfo; 00978 00979 if (! ScreenInfo->Console->CurrentScreenBuffer->ConvScreenInfo) { 00980 WriteConvRegionToScreen(ScreenInfo, 00981 ScreenInfo->Console->ConsoleIme.ConvAreaRoot, 00982 Region); 00983 } 00984 else if (ConvAreaInfo = ScreenInfo->Console->ConsoleIme.ConvAreaRoot) { 00985 do { 00986 if (ConvAreaInfo->ScreenBuffer == ScreenInfo) 00987 break; 00988 } while (ConvAreaInfo = ConvAreaInfo->ConvAreaNext); 00989 if (ConvAreaInfo) { 00990 WriteConvRegionToScreen(ScreenInfo, 00991 ConvAreaInfo->ConvAreaNext, 00992 Region); 00993 } 00994 } 00995 } 00996 #endif 00997 ConsoleShowCursor(ScreenInfo); 00998 } 00999 } 01000 01001 NTSTATUS 01002 WWSB_WriteOutputString( 01003 IN PSCREEN_INFORMATION ScreenInfo, 01004 IN PVOID Buffer, 01005 IN COORD WriteCoord, 01006 IN ULONG StringType, 01007 IN OUT PULONG NumRecords, // this value is valid even for error cases 01008 OUT PULONG NumColumns OPTIONAL 01009 ) 01010 01011 /*++ 01012 01013 Routine Description: 01014 01015 This routine writes a string of characters or attributes to the 01016 screen buffer. 01017 01018 Arguments: 01019 01020 ScreenInfo - Pointer to screen buffer information. 01021 01022 Buffer - Buffer to write from. 01023 01024 WriteCoord - Screen buffer coordinate to begin writing to. 01025 01026 StringType 01027 One of the following: 01028 CONSOLE_ASCII - write a string of ascii characters. 01029 CONSOLE_REAL_UNICODE - write a string of real unicode characters. 01030 CONSOLE_FALSE_UNICODE - write a string of false unicode characters. 01031 CONSOLE_ATTRIBUTE - write a string of attributes. 01032 01033 NumRecords - On input, the number of elements to write. On output, 01034 the number of elements written. 01035 01036 NumColumns - receives the number of columns output, which could be more 01037 than NumRecords (FE fullwidth chars) 01038 Return Value: 01039 01040 01041 --*/ 01042 01043 { 01044 ULONG NumWritten; 01045 SHORT X,Y,LeftX; 01046 SMALL_RECT WriteRegion; 01047 PROW Row; 01048 PWCHAR Char; 01049 SHORT RowIndex; 01050 SHORT j; 01051 PWCHAR TransBuffer; 01052 #ifdef WWSB_NOFE 01053 WCHAR SingleChar; 01054 #endif 01055 UINT Codepage; 01056 #ifdef WWSB_FE 01057 PBYTE AttrP; 01058 PBYTE TransBufferA; 01059 PBYTE BufferA; 01060 ULONG NumRecordsSavedForUnicode; 01061 BOOL fLocalHeap = FALSE; 01062 #endif 01063 01064 DBGOUTPUT(("WriteOutputString\n")); 01065 #ifdef WWSB_FE 01066 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 01067 #endif 01068 01069 if (*NumRecords == 0) 01070 return STATUS_SUCCESS; 01071 01072 NumWritten = 0; 01073 X=WriteCoord.X; 01074 Y=WriteCoord.Y; 01075 if (X>=ScreenInfo->ScreenBufferSize.X || 01076 X<0 || 01077 Y>=ScreenInfo->ScreenBufferSize.Y || 01078 Y<0) { 01079 *NumRecords = 0; 01080 return STATUS_SUCCESS; 01081 } 01082 01083 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 01084 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+WriteCoord.Y) % ScreenInfo->ScreenBufferSize.Y; 01085 01086 if (StringType == CONSOLE_ASCII) { 01087 #ifdef WWSB_FE 01088 PCHAR TmpBuf; 01089 PWCHAR TmpTrans; 01090 ULONG i; 01091 PCHAR TmpTransA; 01092 #endif 01093 01094 if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 01095 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 01096 if (ScreenInfo->Console->OutputCP != WINDOWSCP) 01097 Codepage = USACP; 01098 else 01099 Codepage = WINDOWSCP; 01100 } else { 01101 Codepage = ScreenInfo->Console->OutputCP; 01102 } 01103 01104 #ifdef WWSB_FE 01105 if (*NumRecords > (ULONG)(ScreenInfo->ScreenBufferSize.X * ScreenInfo->ScreenBufferSize.Y)) { 01106 01107 TransBuffer = ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),*NumRecords * 2 * sizeof(WCHAR)); 01108 if (TransBuffer == NULL) { 01109 return STATUS_NO_MEMORY; 01110 } 01111 TransBufferA = ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),*NumRecords * 2 * sizeof(CHAR)); 01112 if (TransBufferA == NULL) { 01113 ConsoleHeapFree(TransBuffer); 01114 return STATUS_NO_MEMORY; 01115 } 01116 01117 fLocalHeap = TRUE; 01118 } 01119 else { 01120 TransBuffer = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter; 01121 TransBufferA = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute; 01122 } 01123 01124 TmpBuf = Buffer; 01125 TmpTrans = TransBuffer; 01126 TmpTransA = TransBufferA; // MSKK Apr.02.1993 V-HirotS For KAttr 01127 for (i=0; i < *NumRecords;) { 01128 if (IsDBCSLeadByteConsole(*TmpBuf,&ScreenInfo->Console->OutputCPInfo)) { 01129 if (i+1 >= *NumRecords) { 01130 *TmpTrans = UNICODE_SPACE; 01131 *TmpTransA = 0; 01132 i++; 01133 } 01134 else { 01135 ConvertOutputToUnicode(Codepage, 01136 TmpBuf, 01137 2, 01138 TmpTrans, 01139 2); 01140 *(TmpTrans+1) = *TmpTrans; 01141 TmpTrans += 2; 01142 TmpBuf += 2; 01143 *TmpTransA++ = ATTR_LEADING_BYTE; 01144 *TmpTransA++ = ATTR_TRAILING_BYTE; 01145 i += 2; 01146 } 01147 } 01148 else { 01149 ConvertOutputToUnicode(Codepage, 01150 TmpBuf, 01151 1, 01152 TmpTrans, 01153 1); 01154 TmpTrans++; 01155 TmpBuf++; 01156 *TmpTransA++ = 0; // MSKK APr.02.1993 V-HirotS For KAttr 01157 i++; 01158 } 01159 } 01160 BufferA = TransBufferA; 01161 Buffer = TransBuffer; 01162 #else 01163 if (*NumRecords == 1) { 01164 TransBuffer = NULL; 01165 SingleChar = SB_CharToWcharGlyph(Codepage, *((char *)Buffer)); 01166 Buffer = &SingleChar; 01167 } else { 01168 TransBuffer = (PWCHAR)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),*NumRecords * sizeof(WCHAR)); 01169 if (TransBuffer == NULL) { 01170 return STATUS_NO_MEMORY; 01171 } 01172 ConvertOutputToUnicode(Codepage, Buffer, *NumRecords, 01173 TransBuffer, *NumRecords); 01174 Buffer = TransBuffer; 01175 } 01176 #endif 01177 } else if (StringType == CONSOLE_REAL_UNICODE && 01178 (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 01179 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 01180 RealUnicodeToFalseUnicode(Buffer, 01181 *NumRecords, 01182 ScreenInfo->Console->OutputCP 01183 ); 01184 } 01185 01186 #ifdef WWSB_FE 01187 if ((StringType == CONSOLE_REAL_UNICODE) || (StringType == CONSOLE_FALSE_UNICODE)) { 01188 PWCHAR TmpBuf; 01189 PWCHAR TmpTrans; 01190 PCHAR TmpTransA; 01191 ULONG i,j; 01192 WCHAR c; 01193 01194 /* Avoid overflow into TransBufferCharacter , TransBufferAttribute 01195 * because, if hit by IsConsoleFullWidth() 01196 * then one unicde character needs two spaces on TransBuffer. 01197 */ 01198 if ((*NumRecords*2) > (ULONG)(ScreenInfo->ScreenBufferSize.X * ScreenInfo->ScreenBufferSize.Y)) { 01199 01200 TransBuffer = ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),*NumRecords * 2 * sizeof(WCHAR)); 01201 if (TransBuffer == NULL) { 01202 return STATUS_NO_MEMORY; 01203 } 01204 TransBufferA = ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),*NumRecords * 2 * sizeof(CHAR)); 01205 if (TransBufferA == NULL) { 01206 ConsoleHeapFree(TransBuffer); 01207 return STATUS_NO_MEMORY; 01208 } 01209 01210 fLocalHeap = TRUE; 01211 } 01212 else { 01213 TransBuffer = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter; 01214 TransBufferA = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute; 01215 } 01216 01217 TmpBuf = Buffer; 01218 TmpTrans = TransBuffer; 01219 TmpTransA = TransBufferA; 01220 for (i=0,j=0; i < *NumRecords; i++,j++) { 01221 *TmpTrans++ = c = *TmpBuf++; 01222 *TmpTransA = 0; 01223 if (IsConsoleFullWidth(ScreenInfo->Console->hDC, 01224 ScreenInfo->Console->OutputCP,c)) { 01225 *TmpTransA++ = ATTR_LEADING_BYTE; 01226 *TmpTrans++ = c; 01227 *TmpTransA = ATTR_TRAILING_BYTE; 01228 j++; 01229 } 01230 TmpTransA++; 01231 } 01232 NumRecordsSavedForUnicode = *NumRecords; 01233 *NumRecords = j; 01234 Buffer = TransBuffer; 01235 BufferA = TransBufferA; 01236 } 01237 #endif 01238 01239 if ((StringType == CONSOLE_REAL_UNICODE) || 01240 (StringType == CONSOLE_FALSE_UNICODE) || 01241 (StringType == CONSOLE_ASCII)) { 01242 while (TRUE) { 01243 01244 LeftX = X; 01245 01246 // 01247 // copy the chars into their arrays 01248 // 01249 01250 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01251 Char = &Row->CharRow.Chars[X]; 01252 #ifdef WWSB_FE 01253 AttrP = &Row->CharRow.KAttrs[X]; 01254 #endif 01255 if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*NumRecords - NumWritten)) { 01256 /* 01257 * The text will not hit the right hand edge, copy it all 01258 */ 01259 #ifdef WWSB_FE 01260 COORD TPoint; 01261 01262 TPoint.X = X; 01263 TPoint.Y = Y; 01264 BisectWrite((SHORT)(*NumRecords-NumWritten),TPoint,ScreenInfo); 01265 if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && 01266 (SHORT)(TPoint.X+*NumRecords-NumWritten) >= ScreenInfo->ScreenBufferSize.X && 01267 *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & ATTR_LEADING_BYTE 01268 ) { 01269 *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE; 01270 *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = 0; 01271 if ((SHORT)(*NumRecords-NumWritten) > (SHORT)(ScreenInfo->ScreenBufferSize.X-TPoint.X-1)) { 01272 *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE; 01273 *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X) = 0; 01274 } 01275 } 01276 RtlCopyMemory(AttrP,BufferA,(*NumRecords - NumWritten) * sizeof(CHAR)); 01277 #endif 01278 RtlCopyMemory(Char,Buffer,(*NumRecords - NumWritten) * sizeof(WCHAR)); 01279 X=(SHORT)(X+*NumRecords - NumWritten-1); 01280 NumWritten = *NumRecords; 01281 } 01282 else { 01283 /* 01284 * The text will hit the right hand edge, copy only that much 01285 */ 01286 #ifdef WWSB_FE 01287 COORD TPoint; 01288 01289 TPoint.X = X; 01290 TPoint.Y = Y; 01291 BisectWrite((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); 01292 if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && 01293 TPoint.X+ScreenInfo->ScreenBufferSize.X-X >= ScreenInfo->ScreenBufferSize.X && 01294 *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & ATTR_LEADING_BYTE 01295 ) { 01296 *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE; 01297 *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = 0; 01298 if (ScreenInfo->ScreenBufferSize.X-X > ScreenInfo->ScreenBufferSize.X-TPoint.X-1) { 01299 *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE; 01300 *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X) = 0; 01301 } 01302 } 01303 RtlCopyMemory(AttrP,BufferA,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR)); 01304 BufferA = (PVOID)((PBYTE)BufferA + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR))); 01305 #endif 01306 RtlCopyMemory(Char,Buffer,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR)); 01307 Buffer = (PVOID)((PBYTE)Buffer + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR))); 01308 NumWritten += ScreenInfo->ScreenBufferSize.X - X; 01309 X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 01310 } 01311 01312 // recalculate first and last non-space char 01313 01314 Row->CharRow.OldLeft = Row->CharRow.Left; 01315 if (LeftX < Row->CharRow.Left) { 01316 PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X]; 01317 01318 for (Char=&Row->CharRow.Chars[LeftX];Char < LastChar && *Char==(WCHAR)' ';Char++) 01319 ; 01320 Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars); 01321 } 01322 01323 Row->CharRow.OldRight = Row->CharRow.Right; 01324 if ((X+1) >= Row->CharRow.Right) { 01325 WORD LastNonSpace; 01326 PWCHAR FirstChar = Row->CharRow.Chars; 01327 01328 LastNonSpace = X; 01329 for (Char=&Row->CharRow.Chars[X];*Char==(WCHAR)' ' && Char >= FirstChar;Char--) 01330 LastNonSpace--; 01331 Row->CharRow.Right = (SHORT)(LastNonSpace+1); 01332 } 01333 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01334 RowIndex = 0; 01335 } 01336 if (NumWritten < *NumRecords) { 01337 /* 01338 * The string hit the right hand edge, so wrap around to the 01339 * next line by going back round the while loop, unless we 01340 * are at the end of the buffer - in which case we simply 01341 * abandon the remainder of the output string! 01342 */ 01343 X = 0; 01344 Y++; 01345 if (Y >= ScreenInfo->ScreenBufferSize.Y) { 01346 break; // abandon output, string is truncated 01347 } 01348 } else { 01349 break; 01350 } 01351 } 01352 } else if (StringType == CONSOLE_ATTRIBUTE) { 01353 PWORD SourcePtr=Buffer; 01354 PATTR_PAIR AttrBuf; 01355 ATTR_PAIR Attrs[80]; 01356 PATTR_PAIR Attr; 01357 SHORT AttrLength; 01358 01359 AttrBuf = Attrs; 01360 if (ScreenInfo->ScreenBufferSize.X > 80) { 01361 AttrBuf = (PATTR_PAIR)ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),ScreenInfo->ScreenBufferSize.X * sizeof(ATTR_PAIR)); 01362 if (AttrBuf == NULL) 01363 return STATUS_NO_MEMORY; 01364 } 01365 #ifdef WWSB_FE 01366 { 01367 COORD TPoint; 01368 TPoint.X = X; 01369 TPoint.Y = Y; 01370 if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*NumRecords - NumWritten)) { 01371 BisectWriteAttr((SHORT)(*NumRecords-NumWritten),TPoint,ScreenInfo); 01372 } 01373 else{ 01374 BisectWriteAttr((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); 01375 } 01376 } 01377 #endif 01378 while (TRUE) { 01379 01380 // 01381 // copy the attrs into the screen buffer arrays 01382 // 01383 01384 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01385 Attr = AttrBuf; 01386 Attr->Length = 0; 01387 #ifdef WWSB_FE 01388 Attr->Attr = *SourcePtr & ~COMMON_LVB_SBCSDBCS; 01389 #else 01390 Attr->Attr = *SourcePtr; 01391 #endif 01392 AttrLength = 1; 01393 for (j=X;j<ScreenInfo->ScreenBufferSize.X;j++,SourcePtr++) { 01394 #ifdef WWSB_FE 01395 if (Attr->Attr == (*SourcePtr & ~COMMON_LVB_SBCSDBCS)) 01396 #else 01397 if (Attr->Attr == *SourcePtr) 01398 #endif 01399 { 01400 Attr->Length += 1; 01401 } 01402 else { 01403 Attr++; 01404 Attr->Length = 1; 01405 #ifdef WWSB_FE 01406 Attr->Attr = *SourcePtr & ~COMMON_LVB_SBCSDBCS; 01407 #else 01408 Attr->Attr = *SourcePtr; 01409 #endif 01410 AttrLength += 1; 01411 } 01412 NumWritten++; 01413 X++; 01414 if (NumWritten == *NumRecords) { 01415 break; 01416 } 01417 } 01418 X--; 01419 01420 // recalculate last non-space char 01421 01422 // 01423 // see if attr string is different. if so, allocate a new 01424 // attr buffer and merge the two strings. 01425 // 01426 01427 if (AttrLength != Row->AttrRow.Length || 01428 memcmp(Row->AttrRow.Attrs,AttrBuf,AttrLength*sizeof(*Attr))) { 01429 PATTR_PAIR NewAttrs; 01430 WORD NewAttrsLength; 01431 01432 if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, 01433 Row->AttrRow.Length, 01434 AttrBuf, 01435 AttrLength, 01436 &NewAttrs, 01437 &NewAttrsLength, 01438 (SHORT)((Y == WriteCoord.Y) ? WriteCoord.X : 0), 01439 X, 01440 Row, 01441 ScreenInfo 01442 ))) { 01443 if (ScreenInfo->ScreenBufferSize.X > 80) { 01444 ConsoleHeapFree(AttrBuf); 01445 } 01446 ResetTextFlags(ScreenInfo,WriteCoord.Y,Y); 01447 return STATUS_NO_MEMORY; 01448 } 01449 if (Row->AttrRow.Length > 1) { 01450 ConsoleHeapFree(Row->AttrRow.Attrs); 01451 } 01452 else { 01453 ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); 01454 } 01455 Row->AttrRow.Attrs = NewAttrs; 01456 Row->AttrRow.Length = NewAttrsLength; 01457 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 01458 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 01459 } 01460 01461 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01462 RowIndex = 0; 01463 } 01464 if (NumWritten < *NumRecords) { 01465 X = 0; 01466 Y++; 01467 if (Y>=ScreenInfo->ScreenBufferSize.Y) { 01468 break; 01469 } 01470 } else { 01471 break; 01472 } 01473 } 01474 ResetTextFlags(ScreenInfo,WriteCoord.Y,Y); 01475 if (ScreenInfo->ScreenBufferSize.X > 80) { 01476 ConsoleHeapFree(AttrBuf); 01477 } 01478 } else { 01479 *NumRecords = 0; 01480 return STATUS_INVALID_PARAMETER; 01481 } 01482 if ((StringType == CONSOLE_ASCII) && (TransBuffer != NULL)) { 01483 #ifdef WWSB_FE 01484 if (fLocalHeap) { 01485 ConsoleHeapFree(TransBuffer); 01486 ConsoleHeapFree(TransBufferA); 01487 } 01488 #else 01489 ConsoleHeapFree(TransBuffer); 01490 #endif 01491 } 01492 #ifdef WWSB_FE 01493 else if ((StringType == CONSOLE_FALSE_UNICODE) || (StringType == CONSOLE_REAL_UNICODE)) { 01494 if (fLocalHeap) { 01495 ConsoleHeapFree(TransBuffer); 01496 ConsoleHeapFree(TransBufferA); 01497 } 01498 NumWritten = NumRecordsSavedForUnicode - (*NumRecords - NumWritten); 01499 } 01500 #endif 01501 01502 // 01503 // determine write region. if we're still on the same line we started 01504 // on, left X is the X we started with and right X is the one we're on 01505 // now. otherwise, left X is 0 and right X is the rightmost column of 01506 // the screen buffer. 01507 // 01508 // then update the screen. 01509 // 01510 01511 WriteRegion.Top = WriteCoord.Y; 01512 WriteRegion.Bottom = Y; 01513 if (Y != WriteCoord.Y) { 01514 WriteRegion.Left = 0; 01515 WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 01516 } 01517 else { 01518 WriteRegion.Left = WriteCoord.X; 01519 WriteRegion.Right = X; 01520 } 01521 WWSB_WriteToScreen(ScreenInfo,&WriteRegion); 01522 if (NumColumns) { 01523 *NumColumns = X + (WriteCoord.Y - Y) * ScreenInfo->ScreenBufferSize.X - WriteCoord.X + 1; 01524 } 01525 *NumRecords = NumWritten; 01526 return STATUS_SUCCESS; 01527 } 01528 01529 NTSTATUS 01530 WWSB_FillOutput( 01531 IN PSCREEN_INFORMATION ScreenInfo, 01532 IN WORD Element, 01533 IN COORD WriteCoord, 01534 IN ULONG ElementType, 01535 IN OUT PULONG Length // this value is valid even for error cases 01536 ) 01537 01538 /*++ 01539 01540 Routine Description: 01541 01542 This routine fills the screen buffer with the specified character or 01543 attribute. 01544 01545 Arguments: 01546 01547 ScreenInfo - Pointer to screen buffer information. 01548 01549 Element - Element to write. 01550 01551 WriteCoord - Screen buffer coordinate to begin writing to. 01552 01553 ElementType 01554 01555 CONSOLE_ASCII - element is an ascii character. 01556 CONSOLE_REAL_UNICODE - element is a real unicode character. These will 01557 get converted to False Unicode as required. 01558 CONSOLE_FALSE_UNICODE - element is a False Unicode character. 01559 CONSOLE_ATTRIBUTE - element is an attribute. 01560 01561 Length - On input, the number of elements to write. On output, 01562 the number of elements written. 01563 01564 Return Value: 01565 01566 01567 --*/ 01568 01569 { 01570 ULONG NumWritten; 01571 SHORT X,Y,LeftX; 01572 SMALL_RECT WriteRegion; 01573 PROW Row; 01574 PWCHAR Char; 01575 SHORT RowIndex; 01576 SHORT j; 01577 #ifdef WWSB_FE 01578 PCHAR AttrP; 01579 #endif 01580 01581 DBGOUTPUT(("FillOutput\n")); 01582 if (*Length == 0) 01583 return STATUS_SUCCESS; 01584 NumWritten = 0; 01585 X=WriteCoord.X; 01586 Y=WriteCoord.Y; 01587 if (X>=ScreenInfo->ScreenBufferSize.X || 01588 X<0 || 01589 Y>=ScreenInfo->ScreenBufferSize.Y || 01590 Y<0) { 01591 *Length = 0; 01592 return STATUS_SUCCESS; 01593 } 01594 01595 #ifdef WWSB_FE 01596 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 01597 #endif 01598 01599 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 01600 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+WriteCoord.Y) % ScreenInfo->ScreenBufferSize.Y; 01601 01602 if (ElementType == CONSOLE_ASCII) { 01603 UINT Codepage; 01604 if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 01605 ((ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { 01606 if (ScreenInfo->Console->OutputCP != WINDOWSCP) 01607 Codepage = USACP; 01608 else 01609 Codepage = WINDOWSCP; 01610 } else { 01611 Codepage = ScreenInfo->Console->OutputCP; 01612 } 01613 #ifdef WWSB_FE 01614 if (ScreenInfo->FillOutDbcsLeadChar == 0){ 01615 if (IsDBCSLeadByteConsole((CHAR)Element,&ScreenInfo->Console->OutputCPInfo)) { 01616 ScreenInfo->FillOutDbcsLeadChar = (CHAR)Element; 01617 *Length = 0; 01618 return STATUS_SUCCESS; 01619 }else{ 01620 CHAR Char=(CHAR)Element; 01621 ConvertOutputToUnicode(Codepage, 01622 &Char, 01623 1, 01624 &Element, 01625 1); 01626 } 01627 }else{ 01628 CHAR Char[2]; 01629 Char[0]=ScreenInfo->FillOutDbcsLeadChar; 01630 Char[1]=(BYTE)Element; 01631 ScreenInfo->FillOutDbcsLeadChar = 0; 01632 ConvertOutputToUnicode(Codepage, 01633 Char, 01634 2, 01635 &Element, 01636 2); 01637 } 01638 #else 01639 Element = SB_CharToWchar(Codepage, (CHAR)Element); 01640 #endif 01641 } else if (ElementType == CONSOLE_REAL_UNICODE && 01642 (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 01643 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 01644 RealUnicodeToFalseUnicode(&Element, 01645 1, 01646 ScreenInfo->Console->OutputCP 01647 ); 01648 } 01649 01650 if ((ElementType == CONSOLE_ASCII) || 01651 (ElementType == CONSOLE_REAL_UNICODE) || 01652 (ElementType == CONSOLE_FALSE_UNICODE)) { 01653 #ifdef WWSB_FE 01654 DWORD StartPosFlag ; 01655 StartPosFlag = 0; 01656 #endif 01657 while (TRUE) { 01658 01659 // 01660 // copy the chars into their arrays 01661 // 01662 01663 LeftX = X; 01664 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01665 Char = &Row->CharRow.Chars[X]; 01666 #ifdef WWSB_FE 01667 AttrP = &Row->CharRow.KAttrs[X]; 01668 #endif 01669 if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) { 01670 #ifdef WWSB_FE 01671 { 01672 COORD TPoint; 01673 01674 TPoint.X = X; 01675 TPoint.Y = Y; 01676 BisectWrite((SHORT)(*Length-NumWritten),TPoint,ScreenInfo); 01677 } 01678 #endif 01679 #ifdef WWSB_FE 01680 if (IsConsoleFullWidth(ScreenInfo->Console->hDC, 01681 ScreenInfo->Console->OutputCP,(WCHAR)Element)) { 01682 for (j=0;j<(SHORT)(*Length - NumWritten);j++) { 01683 *Char++ = (WCHAR)Element; 01684 *AttrP &= ~ATTR_DBCSSBCS_BYTE; 01685 if(StartPosFlag++ & 1) 01686 *AttrP++ |= ATTR_TRAILING_BYTE; 01687 else 01688 *AttrP++ |= ATTR_LEADING_BYTE; 01689 } 01690 if(StartPosFlag & 1){ 01691 *(Char-1) = UNICODE_SPACE; 01692 *(AttrP-1) &= ~ATTR_DBCSSBCS_BYTE; 01693 } 01694 } 01695 else { 01696 #endif 01697 for (j=0;j<(SHORT)(*Length - NumWritten);j++) { 01698 *Char++ = (WCHAR)Element; 01699 #ifdef WWSB_FE 01700 *AttrP++ &= ~ATTR_DBCSSBCS_BYTE; 01701 #endif 01702 } 01703 #ifdef WWSB_FE 01704 } 01705 #endif 01706 X=(SHORT)(X+*Length - NumWritten - 1); 01707 NumWritten = *Length; 01708 } 01709 else { 01710 #ifdef WWSB_FE 01711 { 01712 COORD TPoint; 01713 01714 TPoint.X = X; 01715 TPoint.Y = Y; 01716 BisectWrite((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); 01717 } 01718 #endif 01719 #ifdef WWSB_FE 01720 if (IsConsoleFullWidth(ScreenInfo->Console->hDC, 01721 ScreenInfo->Console->OutputCP,(WCHAR)Element)) { 01722 for (j=0;j<ScreenInfo->ScreenBufferSize.X - X;j++) { 01723 *Char++ = (WCHAR)Element; 01724 *AttrP &= ~ATTR_DBCSSBCS_BYTE; 01725 if(StartPosFlag++ & 1) 01726 *AttrP++ |= ATTR_TRAILING_BYTE; 01727 else 01728 *AttrP++ |= ATTR_LEADING_BYTE; 01729 } 01730 } 01731 else { 01732 #endif 01733 for (j=0;j<ScreenInfo->ScreenBufferSize.X - X;j++) { 01734 *Char++ = (WCHAR)Element; 01735 #ifdef WWSB_FE 01736 *AttrP++ &= ~ATTR_DBCSSBCS_BYTE; 01737 #endif 01738 } 01739 #ifdef WWSB_FE 01740 } 01741 #endif 01742 NumWritten += ScreenInfo->ScreenBufferSize.X - X; 01743 X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 01744 } 01745 01746 // recalculate first and last non-space char 01747 01748 Row->CharRow.OldLeft = Row->CharRow.Left; 01749 if (LeftX < Row->CharRow.Left) { 01750 if (Element == UNICODE_SPACE) { 01751 Row->CharRow.Left = X+1; 01752 } else { 01753 Row->CharRow.Left = LeftX; 01754 } 01755 } 01756 Row->CharRow.OldRight = Row->CharRow.Right; 01757 if ((X+1) >= Row->CharRow.Right) { 01758 if (Element == UNICODE_SPACE) { 01759 Row->CharRow.Right = LeftX; 01760 } else { 01761 Row->CharRow.Right = X+1; 01762 } 01763 } 01764 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01765 RowIndex = 0; 01766 } 01767 if (NumWritten < *Length) { 01768 X = 0; 01769 Y++; 01770 if (Y>=ScreenInfo->ScreenBufferSize.Y) { 01771 break; 01772 } 01773 } else { 01774 break; 01775 } 01776 } 01777 } else if (ElementType == CONSOLE_ATTRIBUTE) { 01778 ATTR_PAIR Attr; 01779 01780 #ifdef WWSB_FE 01781 COORD TPoint; 01782 TPoint.X = X; 01783 TPoint.Y = Y; 01784 01785 if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) { 01786 BisectWriteAttr((SHORT)(*Length-NumWritten),TPoint,ScreenInfo); 01787 } 01788 else{ 01789 BisectWriteAttr((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); 01790 } 01791 #endif 01792 01793 while (TRUE) { 01794 01795 // 01796 // copy the attrs into the screen buffer arrays 01797 // 01798 01799 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01800 if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) { 01801 X=(SHORT)(X+*Length - NumWritten - 1); 01802 NumWritten = *Length; 01803 } 01804 else { 01805 NumWritten += ScreenInfo->ScreenBufferSize.X - X; 01806 X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 01807 } 01808 01809 // recalculate last non-space char 01810 01811 // 01812 // merge the two attribute strings. 01813 // 01814 01815 Attr.Length = (SHORT)((Y == WriteCoord.Y) ? (X-WriteCoord.X+1) : (X+1)); 01816 #ifdef WWSB_FE 01817 Attr.Attr = Element & ~COMMON_LVB_SBCSDBCS; 01818 #else 01819 Attr.Attr = Element; 01820 #endif 01821 if (1 != Row->AttrRow.Length || 01822 memcmp(Row->AttrRow.Attrs,&Attr,sizeof(Attr))) { 01823 PATTR_PAIR NewAttrs; 01824 WORD NewAttrsLength; 01825 01826 if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, 01827 Row->AttrRow.Length, 01828 &Attr, 01829 1, 01830 &NewAttrs, 01831 &NewAttrsLength, 01832 (SHORT)(X-Attr.Length+1), 01833 X, 01834 Row, 01835 ScreenInfo 01836 ))) { 01837 ResetTextFlags(ScreenInfo,WriteCoord.Y,Y); 01838 return STATUS_NO_MEMORY; 01839 } 01840 if (Row->AttrRow.Length > 1) { 01841 ConsoleHeapFree(Row->AttrRow.Attrs); 01842 } 01843 else { 01844 ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); 01845 } 01846 Row->AttrRow.Attrs = NewAttrs; 01847 Row->AttrRow.Length = NewAttrsLength; 01848 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 01849 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 01850 } 01851 01852 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 01853 RowIndex = 0; 01854 } 01855 if (NumWritten < *Length) { 01856 X = 0; 01857 Y++; 01858 if (Y>=ScreenInfo->ScreenBufferSize.Y) { 01859 break; 01860 } 01861 } else { 01862 break; 01863 } 01864 } 01865 ResetTextFlags(ScreenInfo,WriteCoord.Y,Y); 01866 } else { 01867 *Length = 0; 01868 return STATUS_INVALID_PARAMETER; 01869 } 01870 01871 // 01872 // determine write region. if we're still on the same line we started 01873 // on, left X is the X we started with and right X is the one we're on 01874 // now. otherwise, left X is 0 and right X is the rightmost column of 01875 // the screen buffer. 01876 // 01877 // then update the screen. 01878 // 01879 01880 #ifdef WWSB_FE 01881 if (ScreenInfo->ConvScreenInfo) { 01882 WriteRegion.Top = WriteCoord.Y + ScreenInfo->Window.Left + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.Y; 01883 WriteRegion.Bottom = Y + ScreenInfo->Window.Left + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.Y; 01884 if (Y != WriteCoord.Y) { 01885 WriteRegion.Left = 0; 01886 WriteRegion.Right = (SHORT)(ScreenInfo->Console->CurrentScreenBuffer->ScreenBufferSize.X-1); 01887 } 01888 else { 01889 WriteRegion.Left = WriteCoord.X + ScreenInfo->Window.Top + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.X; 01890 WriteRegion.Right = X + ScreenInfo->Window.Top + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.X; 01891 } 01892 WriteConvRegionToScreen(ScreenInfo->Console->CurrentScreenBuffer, 01893 ScreenInfo->ConvScreenInfo, 01894 &WriteRegion 01895 ); 01896 ScreenInfo->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT | BISECT_TOP | BISECT_BOTTOM); 01897 *Length = NumWritten; 01898 return STATUS_SUCCESS; 01899 } 01900 #endif 01901 01902 WriteRegion.Top = WriteCoord.Y; 01903 WriteRegion.Bottom = Y; 01904 if (Y != WriteCoord.Y) { 01905 WriteRegion.Left = 0; 01906 WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); 01907 } 01908 else { 01909 WriteRegion.Left = WriteCoord.X; 01910 WriteRegion.Right = X; 01911 } 01912 WWSB_WriteToScreen(ScreenInfo,&WriteRegion); 01913 *Length = NumWritten; 01914 return STATUS_SUCCESS; 01915 } 01916 01917 VOID 01918 WWSB_FillRectangle( 01919 IN CHAR_INFO Fill, 01920 IN OUT PSCREEN_INFORMATION ScreenInfo, 01921 IN PSMALL_RECT TargetRect 01922 ) 01923 01924 /*++ 01925 01926 Routine Description: 01927 01928 This routine fills a rectangular region in the screen 01929 buffer. no clipping is done. 01930 01931 Arguments: 01932 01933 Fill - element to copy to each element in target rect 01934 01935 ScreenInfo - pointer to screen info 01936 01937 TargetRect - rectangle in screen buffer to fill 01938 01939 Return Value: 01940 01941 --*/ 01942 01943 { 01944 SHORT i,j; 01945 SHORT XSize; 01946 SHORT RowIndex; 01947 PROW Row; 01948 PWCHAR Char; 01949 ATTR_PAIR Attr; 01950 #ifdef WWSB_FE 01951 PCHAR AttrP; 01952 BOOL Width; 01953 #endif 01954 DBGOUTPUT(("FillRectangle\n")); 01955 #ifdef WWFE_SB 01956 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 01957 #endif 01958 01959 XSize = (SHORT)(TargetRect->Right - TargetRect->Left + 1); 01960 01961 ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 01962 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetRect->Top) % ScreenInfo->ScreenBufferSize.Y; 01963 for (i=TargetRect->Top;i<=TargetRect->Bottom;i++) { 01964 01965 // 01966 // copy the chars and attrs into their respective arrays 01967 // 01968 01969 #ifdef WWSB_FE 01970 { 01971 COORD TPoint; 01972 01973 TPoint.X = TargetRect->Left; 01974 TPoint.Y = i; 01975 BisectWrite(XSize,TPoint,ScreenInfo); 01976 Width = IsConsoleFullWidth(ScreenInfo->Console->hDC, 01977 ScreenInfo->Console->OutputCP,Fill.Char.UnicodeChar); 01978 } 01979 #endif 01980 01981 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 01982 Char = &Row->CharRow.Chars[TargetRect->Left]; 01983 #ifdef WWSB_FE 01984 AttrP = &Row->CharRow.KAttrs[TargetRect->Left]; 01985 #endif 01986 for (j=0;j<XSize;j++) { 01987 #ifdef WWSB_FE 01988 if (Width){ 01989 if (j < XSize-1){ 01990 *Char++ = Fill.Char.UnicodeChar; 01991 *Char++ = Fill.Char.UnicodeChar; 01992 *AttrP++ = ATTR_LEADING_BYTE; 01993 *AttrP++ = ATTR_TRAILING_BYTE; 01994 j++; 01995 } 01996 else{ 01997 *Char++ = UNICODE_SPACE; 01998 *AttrP++ = 0 ; 01999 } 02000 } 02001 else{ 02002 #endif 02003 *Char++ = Fill.Char.UnicodeChar; 02004 #ifdef WWSB_FE 02005 *AttrP++ = 0 ; 02006 } 02007 #endif 02008 } 02009 02010 // recalculate first and last non-space char 02011 02012 Row->CharRow.OldLeft = Row->CharRow.Left; 02013 if (TargetRect->Left < Row->CharRow.Left) { 02014 if (Fill.Char.UnicodeChar == UNICODE_SPACE) { 02015 Row->CharRow.Left = (SHORT)(TargetRect->Right+1); 02016 } 02017 else { 02018 Row->CharRow.Left = (SHORT)(TargetRect->Left); 02019 } 02020 } 02021 02022 Row->CharRow.OldRight = Row->CharRow.Right; 02023 if (TargetRect->Right >= Row->CharRow.Right) { 02024 if (Fill.Char.UnicodeChar == UNICODE_SPACE) { 02025 Row->CharRow.Right = (SHORT)(TargetRect->Left); 02026 } 02027 else { 02028 Row->CharRow.Right = (SHORT)(TargetRect->Right+1); 02029 } 02030 } 02031 02032 Attr.Length = XSize; 02033 Attr.Attr = Fill.Attributes; 02034 02035 // 02036 // merge the two attribute strings. 02037 // 02038 02039 if (1 != Row->AttrRow.Length || 02040 memcmp(Row->AttrRow.Attrs,&Attr,sizeof(Attr))) { 02041 PATTR_PAIR NewAttrs; 02042 WORD NewAttrsLength; 02043 02044 if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, 02045 Row->AttrRow.Length, 02046 &Attr, 02047 1, 02048 &NewAttrs, 02049 &NewAttrsLength, 02050 TargetRect->Left, 02051 TargetRect->Right, 02052 Row, 02053 ScreenInfo 02054 ))) { 02055 ResetTextFlags(ScreenInfo,TargetRect->Top,TargetRect->Bottom); 02056 return; 02057 } 02058 if (Row->AttrRow.Length > 1) { 02059 ConsoleHeapFree(Row->AttrRow.Attrs); 02060 } 02061 else { 02062 ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); 02063 } 02064 Row->AttrRow.Attrs = NewAttrs; 02065 Row->AttrRow.Length = NewAttrsLength; 02066 Row->CharRow.OldLeft = INVALID_OLD_LENGTH; 02067 Row->CharRow.OldRight = INVALID_OLD_LENGTH; 02068 } 02069 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 02070 RowIndex = 0; 02071 } 02072 } 02073 ResetTextFlags(ScreenInfo,TargetRect->Top,TargetRect->Bottom); 02074 } 02075 02076 BOOL 02077 WWSB_PolyTextOutCandidate( 02078 IN PSCREEN_INFORMATION ScreenInfo, 02079 IN PSMALL_RECT Region 02080 ) 02081 02082 /* 02083 02084 This function returns TRUE if the input region is reasonable to 02085 pass to ConsolePolyTextOut. The criteria are that there is only 02086 one attribute per line. 02087 02088 */ 02089 02090 { 02091 SHORT RowIndex; 02092 PROW Row; 02093 SHORT i; 02094 02095 #ifdef WWSB_FE 02096 if((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED && 02097 ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalVDMEudcMode)){ 02098 return FALSE; 02099 } 02100 if (!(ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && 02101 !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) && 02102 ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalKeisenEudcMode 02103 ) { 02104 return FALSE; 02105 } 02106 ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); 02107 if (ScreenInfo->BufferInfo.TextInfo.Flags & CONSOLE_CONVERSION_AREA_REDRAW) { 02108 return FALSE; 02109 } 02110 #endif 02111 02112 if (ScreenInfo->BufferInfo.TextInfo.Flags & SINGLE_ATTRIBUTES_PER_LINE) { 02113 return TRUE; 02114 } 02115 02116 // 02117 // make sure there is only one attr per line. 02118 // 02119 02120 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y; 02121 for (i=Region->Top;i<=Region->Bottom;i++) { 02122 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; 02123 if (Row->AttrRow.Length != 1) { 02124 return FALSE; 02125 } 02126 if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { 02127 RowIndex = 0; 02128 } 02129 } 02130 return TRUE; 02131 } 02132 02133 02134 #define MAX_POLY_LINES 80 02135 #define VERY_BIG_NUMBER 0x0FFFFFFF 02136 02137 #ifdef WWSB_FE 02138 typedef struct _KEISEN_INFORMATION { 02139 COORD Coord; 02140 WORD n; 02141 } KEISEN_INFORMATION, *PKEISEN_INFORMATION; 02142 #endif 02143 02144 VOID 02145 WWSB_ConsolePolyTextOut( 02146 IN PSCREEN_INFORMATION ScreenInfo, 02147 IN PSMALL_RECT Region 02148 ) 02149 02150 /* 02151 02152 This function calls PolyTextOut. The only restriction is that 02153 there can't be more than one attribute per line in the region. 02154 02155 */ 02156 02157 { 02158 PROW Row,LastRow; 02159 SHORT i,k; 02160 WORD Attr; 02161 POLYTEXTW TextInfo[MAX_POLY_LINES]; 02162 RECT TextRect; 02163 RECTL BoundingRect; 02164 int xSize = SCR_FONTSIZE(ScreenInfo).X; 02165 int ySize = SCR_FONTSIZE(ScreenInfo).Y; 02166 ULONG Flags = ScreenInfo->BufferInfo.TextInfo.Flags; 02167 int WindowLeft = ScreenInfo->Window.Left; 02168 int RegionLeft = Region->Left; 02169 int RegionRight = Region->Right + 1; 02170 int DefaultLeft = (RegionLeft - WindowLeft) * xSize; 02171 int DefaultRight = (RegionRight - WindowLeft) * xSize; 02172 PCONSOLE_INFORMATION Console = ScreenInfo->Console; 02173 PWCHAR TransPolyTextOut = NULL ; 02174 #ifdef WWSB_FE 02175 KEISEN_INFORMATION KeisenInfo[MAX_POLY_LINES]; 02176 SHORT j; 02177 WORD OldAttr; 02178 #endif 02179 02180 // 02181 // initialize the text rect and window position. 02182 // 02183 02184 TextRect.top = (Region->Top - ScreenInfo->Window.Top) * ySize; 02185 // TextRect.bottom is invalid. 02186 BoundingRect.top = TextRect.top; 02187 BoundingRect.left = VERY_BIG_NUMBER; 02188 BoundingRect.right = 0; 02189 02190 // 02191 // copy the chars and attrs from their respective arrays 02192 // 02193 02194 Row = &ScreenInfo->BufferInfo.TextInfo.Rows 02195 [ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top]; 02196 LastRow = &ScreenInfo->BufferInfo.TextInfo.Rows[ScreenInfo->ScreenBufferSize.Y]; 02197 if (Row >= LastRow) 02198 Row -= ScreenInfo->ScreenBufferSize.Y; 02199 02200 Attr = Row->AttrRow.AttrPair.Attr; 02201 if (Console->LastAttributes != Attr) { 02202 #ifdef WWSB_FE 02203 if (Attr & COMMON_LVB_REVERSE_VIDEO) 02204 { 02205 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); 02206 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); 02207 } 02208 else{ 02209 #endif 02210 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); 02211 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); 02212 #ifdef WWSB_FE 02213 } 02214 #endif 02215 Console->LastAttributes = Attr; 02216 } 02217 02218 /* 02219 * Temporarly use the process heap to isolate the heap trash problem 02220 * TransPolyTextOut = (PWCHAR)ConsoleHeapAlloc( 02221 * MAKE_TAG( TMP_DBCS_TAG ), 02222 * ScreenInfo->ScreenBufferSize.X*MAX_POLY_LINES*sizeof(WCHAR)); 02223 */ 02224 TransPolyTextOut = (PWCHAR)LocalAlloc(LPTR, ScreenInfo->ScreenBufferSize.X*MAX_POLY_LINES*sizeof(WCHAR)); 02225 if (TransPolyTextOut == NULL) 02226 { 02227 KdPrint(("CONSRV: ConsoleTextOut cannot allocate memory\n")); 02228 return ; 02229 } 02230 02231 for (i=Region->Top;i<=Region->Bottom;) { 02232 PWCHAR TmpChar; 02233 TmpChar = TransPolyTextOut; 02234 for(k=0;i<=Region->Bottom&&k<MAX_POLY_LINES;i++) { 02235 SHORT NumberOfChars; 02236 SHORT LeftChar,RightChar; 02237 02238 // 02239 // make the bounding rect smaller, if we can. the TEXT_VALID_HINT 02240 // flag gets set each time we write to the screen buffer. it gets 02241 // turned off any time we get asked to redraw the screen 02242 // and we don't know exactly what needs to be redrawn 02243 // (i.e. paint messages). 02244 // 02245 // we have the left and right bounds of the text on the 02246 // line. the opaqueing rectangle and the number of 02247 // chars get set according to those values. 02248 // 02249 02250 TextRect.left = DefaultLeft; 02251 TextRect.right = DefaultRight; 02252 02253 if (Flags & TEXT_VALID_HINT) 02254 { 02255 // We compute an opaquing interval. If A is the old interval of text, 02256 // B is the new interval, and R is the Region, then the opaquing interval 02257 // must be R*(A+B), where * represents intersection and + represents union. 02258 02259 if (Row->CharRow.OldLeft != INVALID_OLD_LENGTH) 02260 { 02261 // The min determines the left of (A+B). The max intersects that with 02262 // the left of the region. 02263 02264 TextRect.left = ( 02265 max 02266 ( 02267 min 02268 ( 02269 Row->CharRow.Left, 02270 Row->CharRow.OldLeft 02271 ), 02272 RegionLeft 02273 ) 02274 -WindowLeft 02275 ) * xSize; 02276 } 02277 02278 if (Row->CharRow.OldRight != INVALID_OLD_LENGTH) 02279 { 02280 // The max determines the right of (A+B). The min intersects that with 02281 // the right of the region. 02282 02283 TextRect.right = ( 02284 min 02285 ( 02286 max 02287 ( 02288 Row->CharRow.Right, 02289 Row->CharRow.OldRight 02290 ), 02291 RegionRight 02292 ) 02293 -WindowLeft 02294 ) * xSize; 02295 } 02296 } 02297 02298 // 02299 // We've got to draw any new text that appears in the region, so we just 02300 // intersect the new text interval with the region. 02301 // 02302 02303 LeftChar = max(Row->CharRow.Left,RegionLeft); 02304 RightChar = min(Row->CharRow.Right,RegionRight); 02305 NumberOfChars = RightChar - LeftChar; 02306 #ifdef WWSB_FE 02307 if (Row->CharRow.KAttrs[RightChar-1] & ATTR_LEADING_BYTE){ 02308 if(TextRect.right <= ScreenInfo->Window.Right*xSize) { 02309 TextRect.right += xSize; 02310 } 02311 } 02312 #endif 02313 02314 // 02315 // Empty rows are represented by CharRow.Right=0, CharRow.Left=MAX, so we 02316 // may have NumberOfChars<0 at this point if there is no text that needs 02317 // drawing. (I.e. the intersection was empty.) 02318 // 02319 02320 if (NumberOfChars < 0) { 02321 NumberOfChars = 0; 02322 LeftChar = 0; 02323 RightChar = 0; 02324 } 02325 02326 // 02327 // We may also have TextRect.right<TextRect.left if the screen 02328 // is already cleared, and we really don't need to do anything at all. 02329 // 02330 02331 if (TextRect.right > TextRect.left) 02332 { 02333 NumberOfChars = (SHORT)RemoveDbcsMarkAll(ScreenInfo,Row,&LeftChar,&TextRect,NULL,TmpChar,NumberOfChars); 02334 TextInfo[k].x = (LeftChar-WindowLeft) * xSize; 02335 TextInfo[k].y = TextRect.top; 02336 TextRect.bottom = TextRect.top + ySize; 02337 TextInfo[k].n = NumberOfChars; 02338 TextInfo[k].lpstr = TmpChar; 02339 #ifdef WWSB_FE 02340 if (CheckBisectStringW(ScreenInfo, 02341 Console->OutputCP, 02342 TmpChar, 02343 NumberOfChars, 02344 (TextRect.right-max(TextRect.left,TextInfo[k].x))/xSize 02345 ) 02346 ) { 02347 TextRect.right += xSize; 02348 } 02349 #endif 02350 TmpChar += NumberOfChars; 02351 TextInfo[k].rcl = TextRect; 02352 TextInfo[k].pdx = NULL; 02353 TextInfo[k].uiFlags = ETO_OPAQUE; 02354 #ifdef WWSB_FE 02355 KeisenInfo[k].n = DefaultRight-DefaultLeft ; 02356 KeisenInfo[k].Coord.Y = (WORD)TextRect.top; 02357 KeisenInfo[k].Coord.X = (WORD)DefaultLeft; 02358 #endif 02359 k++; 02360 02361 if (BoundingRect.left > TextRect.left) { 02362 BoundingRect.left = TextRect.left; 02363 } 02364 if (BoundingRect.right < TextRect.right) { 02365 BoundingRect.right = TextRect.right; 02366 } 02367 } 02368 02369 // Advance the high res bounds. 02370 02371 TextRect.top += ySize; 02372 02373 // Advance the row pointer. 02374 02375 if (++Row >= LastRow) 02376 Row = ScreenInfo->BufferInfo.TextInfo.Rows; 02377 02378 // Draw now if the attributes are about to change. 02379 02380 #ifdef WWSB_FE 02381 OldAttr = Attr ; 02382 #endif 02383 if (Attr != Row->AttrRow.AttrPair.Attr) { 02384 Attr = Row->AttrRow.AttrPair.Attr; 02385 i++; 02386 break; 02387 } 02388 } 02389 02390 if (k) 02391 { 02392 BoundingRect.bottom = TextRect.top; 02393 ASSERT(BoundingRect.left != VERY_BIG_NUMBER); 02394 ASSERT(BoundingRect.left <= BoundingRect.right); 02395 ASSERT(BoundingRect.top <= BoundingRect.bottom); 02396 GdiConsoleTextOut(Console->hDC, 02397 TextInfo, 02398 k, 02399 &BoundingRect); 02400 #ifdef WWSB_FE 02401 for ( j = 0 ; j < k ; j++){ 02402 RECT TextRect; 02403 02404 TextRect.left = KeisenInfo[j].Coord.X; 02405 TextRect.top = KeisenInfo[j].Coord.Y; 02406 TextRect.right = KeisenInfo[j].n + TextRect.left; 02407 TextRect.bottom = KeisenInfo[j].Coord.Y + ySize; 02408 TextOutCommonLVB(ScreenInfo->Console, OldAttr, TextRect); 02409 } 02410 #endif 02411 } 02412 if (Console->LastAttributes != Attr) { 02413 #ifdef WWSB_FE 02414 if (Attr & COMMON_LVB_REVERSE_VIDEO) 02415 { 02416 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); 02417 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); 02418 } 02419 else{ 02420 #endif 02421 SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); 02422 SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); 02423 #ifdef WWSB_FE 02424 } 02425 #endif 02426 Console->LastAttributes = Attr; 02427 BoundingRect.top = TextRect.top; 02428 BoundingRect.left = VERY_BIG_NUMBER; 02429 BoundingRect.right = 0; 02430 } 02431 } 02432 GdiFlush(); 02433 /* 02434 * ConsoleHeapFree(TransPolyTextOut); 02435 */ 02436 LocalFree(TransPolyTextOut); 02437 }

Generated on Sat May 15 19:39:12 2004 for test by doxygen 1.3.7