|
|
/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
_output.h
Abstract:
Performance critical routine for Single Binary
Each function will be created with two flavors FE and non FE
Author:
KazuM Jun.11.1997
Revision History:
--*/
#define WWSB_NEUTRAL_FILE 1
#if !defined(FE_SB)
#error This header file should be included with FE_SB
#endif
#if !defined(WWSB_FE) && !defined(WWSB_NOFE)
#error Either WWSB_FE and WWSB_NOFE must be defined.
#endif
#if defined(WWSB_FE) && defined(WWSB_NOFE)
#error Both WWSB_FE and WWSB_NOFE defined.
#endif
#include "dispatch.h"
#if defined(WWSB_FE)
#pragma alloc_text(FE_TEXT, FE_StreamWriteToScreenBuffer)
#pragma alloc_text(FE_TEXT, FE_WriteRectToScreenBuffer)
#pragma alloc_text(FE_TEXT, FE_WriteRegionToScreen)
#pragma alloc_text(FE_TEXT, FE_WriteToScreen)
#pragma alloc_text(FE_TEXT, FE_WriteOutputString)
#pragma alloc_text(FE_TEXT, FE_FillOutput)
#pragma alloc_text(FE_TEXT, FE_FillRectangle)
#pragma alloc_text(FE_TEXT, FE_PolyTextOutCandidate)
#pragma alloc_text(FE_TEXT, FE_ConsolePolyTextOut)
#endif
#if defined(WWSB_NOFE)
VOID SB_StreamWriteToScreenBuffer( IN PWCHAR String, IN SHORT StringLength, IN PSCREEN_INFORMATION ScreenInfo ) #else
VOID FE_StreamWriteToScreenBuffer( IN PWCHAR String, IN SHORT StringLength, IN PSCREEN_INFORMATION ScreenInfo, IN PCHAR StringA ) #endif
{ SHORT RowIndex; PROW Row; PWCHAR Char; COORD TargetPoint;
DBGOUTPUT(("StreamWriteToScreenBuffer\n")); #ifdef WWSB_FE
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); #endif
ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; TargetPoint = ScreenInfo->BufferInfo.TextInfo.CursorPosition; RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y; Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; DBGOUTPUT(("RowIndex = %x, Row = %x, TargetPoint = (%x,%x)\n", RowIndex, Row, TargetPoint.X, TargetPoint.Y));
//
// copy chars
//
#ifdef WWSB_FE
BisectWrite(StringLength,TargetPoint,ScreenInfo); if (TargetPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && TargetPoint.X+StringLength >= ScreenInfo->ScreenBufferSize.X && *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) & ATTR_LEADING_BYTE ) { *(String+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) = UNICODE_SPACE; *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) = 0; if (StringLength > ScreenInfo->ScreenBufferSize.X-TargetPoint.X-1) { *(String+ScreenInfo->ScreenBufferSize.X-TargetPoint.X) = UNICODE_SPACE; *(StringA+ScreenInfo->ScreenBufferSize.X-TargetPoint.X) = 0; } }
RtlCopyMemory(&Row->CharRow.KAttrs[TargetPoint.X],StringA,StringLength*sizeof(CHAR)); #endif
RtlCopyMemory(&Row->CharRow.Chars[TargetPoint.X],String,StringLength*sizeof(WCHAR));
// recalculate first and last non-space char
Row->CharRow.OldLeft = Row->CharRow.Left; if (TargetPoint.X < Row->CharRow.Left) { PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X];
for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++) ; Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars); }
Row->CharRow.OldRight = Row->CharRow.Right; if ((TargetPoint.X+StringLength) >= Row->CharRow.Right) { PWCHAR FirstChar = Row->CharRow.Chars;
for (Char=&Row->CharRow.Chars[TargetPoint.X+StringLength-1];*Char==(WCHAR)' ' && Char >= FirstChar;Char--) ; Row->CharRow.Right = (SHORT)(Char+1-FirstChar); }
//
// see if attr string is different. if so, allocate a new
// attr buffer and merge the two strings.
//
if (Row->AttrRow.Length != 1 || Row->AttrRow.Attrs->Attr != ScreenInfo->Attributes) { PATTR_PAIR NewAttrs; WORD NewAttrsLength; ATTR_PAIR Attrs;
Attrs.Length = StringLength; Attrs.Attr = ScreenInfo->Attributes; if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, &Attrs, 1, &NewAttrs, &NewAttrsLength, TargetPoint.X, (SHORT)(TargetPoint.X+StringLength-1), Row, ScreenInfo ))) { return; } if (Row->AttrRow.Length > 1) { ConsoleHeapFree(Row->AttrRow.Attrs); } else { ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); } Row->AttrRow.Attrs = NewAttrs; Row->AttrRow.Length = NewAttrsLength; Row->CharRow.OldLeft = INVALID_OLD_LENGTH; Row->CharRow.OldRight = INVALID_OLD_LENGTH; } ResetTextFlags(ScreenInfo, TargetPoint.X, TargetPoint.Y, TargetPoint.X + StringLength - 1, TargetPoint.Y); }
#define CHAR_OF_PCI(p) (((PCHAR_INFO)(p))->Char.AsciiChar)
#define WCHAR_OF_PCI(p) (((PCHAR_INFO)(p))->Char.UnicodeChar)
#define ATTR_OF_PCI(p) (((PCHAR_INFO)(p))->Attributes)
#define SIZEOF_CI_CELL sizeof(CHAR_INFO)
#define CHAR_OF_VGA(p) (p[0])
#define ATTR_OF_VGA(p) (p[1])
#ifdef i386
#define SIZEOF_VGA_CELL 2
#else // risc
#define SIZEOF_VGA_CELL 4
#endif
#define COMMON_LVB_MASK 0x33
#define ATTR_OF_COMMON_LVB(p) (ATTR_OF_VGA(p) + (((p[2] & ~COMMON_LVB_MASK)) << 8))
#define SIZEOF_COMMON_LVB_CELL 4
VOID WWSB_WriteRectToScreenBuffer( PBYTE Source, COORD SourceSize, PSMALL_RECT SourceRect, PSCREEN_INFORMATION ScreenInfo, COORD TargetPoint, IN UINT Codepage )
/*++
Routine Description:
This routine copies a rectangular region to the screen buffer. no clipping is done.
The source should contain Unicode or UnicodeOem chars.
Arguments:
Source - pointer to source buffer (a real VGA buffer or CHAR_INFO[])
SourceSize - dimensions of source buffer
SourceRect - rectangle in source buffer to copy
ScreenInfo - pointer to screen info
TargetPoint - upper left coordinates of target rectangle
Codepage - codepage to translate real VGA buffer from, 0xFFFFFFF if Source is CHAR_INFO[] (not requiring translation) Return Value:
none.
--*/
{
PBYTE SourcePtr; SHORT i,j; SHORT XSize,YSize; BOOLEAN WholeSource; SHORT RowIndex; PROW Row; PWCHAR Char; ATTR_PAIR Attrs[80]; PATTR_PAIR AttrBuf; PATTR_PAIR Attr; SHORT AttrLength; BOOL bVGABuffer; ULONG ulCellSize; #ifdef WWSB_FE
PCHAR AttrP; #endif
DBGOUTPUT(("WriteRectToScreenBuffer\n")); #ifdef WWSB_FE
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); #endif
ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; XSize = (SHORT)(SourceRect->Right - SourceRect->Left + 1); YSize = (SHORT)(SourceRect->Bottom - SourceRect->Top + 1);
AttrBuf = Attrs; if (XSize > 80) { AttrBuf = ConsoleHeapAlloc(TMP_TAG, XSize * sizeof(ATTR_PAIR)); if (AttrBuf == NULL) { return; } }
bVGABuffer = (Codepage != 0xFFFFFFFF); if (bVGABuffer) { #ifdef WWSB_FE
ulCellSize = (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL; #else
ulCellSize = SIZEOF_VGA_CELL; #endif
} else { ulCellSize = SIZEOF_CI_CELL; }
SourcePtr = Source;
WholeSource = FALSE; if (XSize == SourceSize.X) { ASSERT (SourceRect->Left == 0); if (SourceRect->Top != 0) { SourcePtr += SCREEN_BUFFER_POINTER(SourceRect->Left, SourceRect->Top, SourceSize.X, ulCellSize); } WholeSource = TRUE; } RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y; for (i=0;i<YSize;i++) { if (!WholeSource) { SourcePtr = Source + SCREEN_BUFFER_POINTER(SourceRect->Left, SourceRect->Top+i, SourceSize.X, ulCellSize); }
//
// copy the chars and attrs into their respective arrays
//
#ifdef WWSB_FE
if (! bVGABuffer) { COORD TPoint;
TPoint.X = TargetPoint.X; TPoint.Y = TargetPoint.Y + i; BisectWrite(XSize,TPoint,ScreenInfo); if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && TPoint.X+XSize-1 >= ScreenInfo->ScreenBufferSize.X && ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & COMMON_LVB_LEADING_BYTE) { WCHAR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE; ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) &= ~COMMON_LVB_SBCSDBCS; if (XSize-1 > ScreenInfo->ScreenBufferSize.X-TPoint.X-1) { WCHAR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE; ATTR_OF_PCI(SourcePtr+ScreenInfo->ScreenBufferSize.X-TPoint.X) &= ~COMMON_LVB_SBCSDBCS; } } } #endif
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; Char = &Row->CharRow.Chars[TargetPoint.X]; #ifdef WWSB_FE
AttrP = &Row->CharRow.KAttrs[TargetPoint.X]; #endif
Attr = AttrBuf; Attr->Length = 0; AttrLength = 1;
/*
* Two version of the following loop to keep it fast: * one for VGA buffers, one for CHAR_INFO buffers. */ if (bVGABuffer) { #ifdef WWSB_FE
Attr->Attr = (ScreenInfo->Console->fVDMVideoMode) ? ATTR_OF_COMMON_LVB(SourcePtr) : ATTR_OF_VGA(SourcePtr); #else
Attr->Attr = ATTR_OF_VGA(SourcePtr); #endif
for (j = SourceRect->Left; j <= SourceRect->Right; j++, #ifdef WWSB_FE
SourcePtr += (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL #else
SourcePtr += SIZEOF_VGA_CELL #endif
) {
#ifdef WWSB_FE
UCHAR TmpBuff[2];
if (IsDBCSLeadByteConsole(CHAR_OF_VGA(SourcePtr),&ScreenInfo->Console->OutputCPInfo)) { if (j+1 > SourceRect->Right) { *Char = UNICODE_SPACE; *AttrP = 0; } else { TmpBuff[0] = CHAR_OF_VGA(SourcePtr); TmpBuff[1] = CHAR_OF_VGA((SourcePtr + ((ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL))); ConvertOutputToUnicode(Codepage, TmpBuff, 2, Char, 2); Char++; j++; *AttrP++ = ATTR_LEADING_BYTE; *Char++ = *(Char-1); *AttrP++ = ATTR_TRAILING_BYTE;
if (ScreenInfo->Console->fVDMVideoMode) { if (Attr->Attr == ATTR_OF_COMMON_LVB(SourcePtr)) { Attr->Length += 1; } else { Attr++; Attr->Length = 1; Attr->Attr = ATTR_OF_COMMON_LVB(SourcePtr); AttrLength += 1; } } else { if (Attr->Attr == ATTR_OF_VGA(SourcePtr)) { Attr->Length += 1; } else { Attr++; Attr->Length = 1; Attr->Attr = ATTR_OF_VGA(SourcePtr); AttrLength += 1; } }
SourcePtr += (ScreenInfo->Console->fVDMVideoMode) ? SIZEOF_COMMON_LVB_CELL : SIZEOF_VGA_CELL; } } else { ConvertOutputToUnicode(Codepage, &CHAR_OF_VGA(SourcePtr), 1, Char, 1); Char++; *AttrP++ = 0; } #else
*Char++ = SB_CharToWcharGlyph(Codepage, CHAR_OF_VGA(SourcePtr)); #endif
#ifdef WWSB_FE
if (ScreenInfo->Console->fVDMVideoMode) { if (Attr->Attr == ATTR_OF_COMMON_LVB(SourcePtr)) { Attr->Length += 1; } else { Attr++; Attr->Length = 1; Attr->Attr = ATTR_OF_COMMON_LVB(SourcePtr); AttrLength += 1; } } else #endif
if (Attr->Attr == ATTR_OF_VGA(SourcePtr)) { Attr->Length += 1; } else { Attr++; Attr->Length = 1; Attr->Attr = ATTR_OF_VGA(SourcePtr); AttrLength += 1; } } } else { #ifdef WWSB_FE
Attr->Attr = ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS; #else
Attr->Attr = ATTR_OF_PCI(SourcePtr); #endif
for (j = SourceRect->Left; j <= SourceRect->Right; j++, SourcePtr += SIZEOF_CI_CELL) {
*Char++ = WCHAR_OF_PCI(SourcePtr); #ifdef WWSB_FE
// MSKK Apr.02.1993 V-HirotS For KAttr
*AttrP++ = (CHAR)((ATTR_OF_PCI(SourcePtr) & COMMON_LVB_SBCSDBCS) >>8); #endif
#ifdef WWSB_FE
if (Attr->Attr == (ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS)) #else
if (Attr->Attr == ATTR_OF_PCI(SourcePtr)) #endif
{ Attr->Length += 1; } else { Attr++; Attr->Length = 1; #ifdef WWSB_FE
// MSKK Apr.02.1993 V-HirotS For KAttr
Attr->Attr = ATTR_OF_PCI(SourcePtr) & ~COMMON_LVB_SBCSDBCS; #else
Attr->Attr = ATTR_OF_PCI(SourcePtr); #endif
AttrLength += 1; } } }
// recalculate first and last non-space char
Row->CharRow.OldLeft = Row->CharRow.Left; if (TargetPoint.X < Row->CharRow.Left) { PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X];
for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++) ; Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars); }
Row->CharRow.OldRight = Row->CharRow.Right; if ((TargetPoint.X+XSize) >= Row->CharRow.Right) { SHORT LastNonSpace; PWCHAR FirstChar = Row->CharRow.Chars;
LastNonSpace = (SHORT)(TargetPoint.X+XSize-1); for (Char=&Row->CharRow.Chars[(TargetPoint.X+XSize-1)];*Char==(WCHAR)' ' && Char >= FirstChar;Char--) LastNonSpace--;
//
// if the attributes change after the last non-space, make the
// index of the last attribute change + 1 the length. otherwise
// make the length one more than the last non-space.
//
Row->CharRow.Right = (SHORT)(LastNonSpace+1); }
//
// see if attr string is different. if so, allocate a new
// attr buffer and merge the two strings.
//
if (AttrLength != Row->AttrRow.Length || memcmp(Row->AttrRow.Attrs,AttrBuf,AttrLength*sizeof(*Attr))) { PATTR_PAIR NewAttrs; WORD NewAttrsLength;
if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, AttrBuf, AttrLength, &NewAttrs, &NewAttrsLength, TargetPoint.X, (SHORT)(TargetPoint.X+XSize-1), Row, ScreenInfo ))) { if (XSize > 80) { ConsoleHeapFree(AttrBuf); } ResetTextFlags(ScreenInfo, TargetPoint.X, TargetPoint.Y, (SHORT)(TargetPoint.X + XSize - 1), (SHORT)(TargetPoint.Y + YSize - 1)); return; } if (Row->AttrRow.Length > 1) { ConsoleHeapFree(Row->AttrRow.Attrs); } else { ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); } Row->AttrRow.Attrs = NewAttrs; Row->AttrRow.Length = NewAttrsLength; Row->CharRow.OldLeft = INVALID_OLD_LENGTH; Row->CharRow.OldRight = INVALID_OLD_LENGTH; } if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } } ResetTextFlags(ScreenInfo, TargetPoint.X, TargetPoint.Y, (SHORT)(TargetPoint.X + XSize - 1), (SHORT)(TargetPoint.Y + YSize - 1));
if (XSize > 80) { ConsoleHeapFree(AttrBuf); } }
VOID WWSB_WriteRegionToScreen( IN PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT Region ) { COORD Window; int i,j; PATTR_PAIR Attr; RECT TextRect; SHORT RowIndex; SHORT CountOfAttr; PROW Row; BOOL OneLine, SimpleWrite; // one line && one attribute per line
PCONSOLE_INFORMATION Console = ScreenInfo->Console; PWCHAR TransBufferCharacter = NULL ; #ifdef WWSB_FE
BOOL DoubleColorDbcs; SHORT CountOfAttrOriginal; SHORT RegionRight; BOOL LocalEUDCFlag; SMALL_RECT CaTextRect; PCONVERSIONAREA_INFORMATION ConvAreaInfo = ScreenInfo->ConvScreenInfo; #endif
DBGOUTPUT(("WriteRegionToScreen\n"));
#ifdef WWSB_FE
if (ConvAreaInfo) { CaTextRect.Left = Region->Left - ScreenInfo->Console->CurrentScreenBuffer->Window.Left - ConvAreaInfo->CaInfo.coordConView.X; CaTextRect.Right = CaTextRect.Left + (Region->Right - Region->Left); CaTextRect.Top = Region->Top - ScreenInfo->Console->CurrentScreenBuffer->Window.Top - ConvAreaInfo->CaInfo.coordConView.Y; CaTextRect.Bottom = CaTextRect.Top + (Region->Bottom - Region->Top); }
if (Region->Left && (ScreenInfo->BisectFlag & BISECT_LEFT)) { Region->Left--; } if (Region->Right+1 < ScreenInfo->ScreenBufferSize.X && (ScreenInfo->BisectFlag & BISECT_RIGHT)) { Region->Right++; } ScreenInfo->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT); Console->ConsoleIme.ScrollWaitCountDown = Console->ConsoleIme.ScrollWaitTimeout; #endif
if (Console->FullScreenFlags == 0) {
//
// if we have a selection, turn it off.
//
InvertSelection(Console, TRUE);
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); if (WWSB_PolyTextOutCandidate(ScreenInfo,Region)) { WWSB_ConsolePolyTextOut(ScreenInfo,Region); } else {
#ifdef WWSB_FE
if (ConvAreaInfo) { Window.Y = Region->Top - Console->CurrentScreenBuffer->Window.Top; Window.X = Region->Left - Console->CurrentScreenBuffer->Window.Left; } else { #endif
Window.Y = Region->Top - ScreenInfo->Window.Top; Window.X = Region->Left - ScreenInfo->Window.Left; #ifdef WWSB_FE
} #endif
#ifdef WWSB_FE
RowIndex = (ConvAreaInfo ? CaTextRect.Top : (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y ); RegionRight = Region->Right; #else
RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y; #endif
OneLine = (Region->Top==Region->Bottom);
TransBufferCharacter = ConsoleHeapAlloc(TMP_DBCS_TAG, (ScreenInfo->ScreenBufferSize.X * sizeof(WCHAR)) + sizeof(WCHAR)); if (TransBufferCharacter == NULL) { RIPMSG0(RIP_WARNING, "WriteRegionToScreen cannot allocate memory"); return; }
for (i=Region->Top;i<=Region->Bottom;i++,Window.Y++) { #ifdef WWSB_FE
DoubleColorDbcs = FALSE; Region->Right = RegionRight; #endif
//
// copy the chars and attrs from their respective arrays
//
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
if (Row->AttrRow.Length == 1) { Attr = Row->AttrRow.Attrs; CountOfAttr = ScreenInfo->ScreenBufferSize.X; SimpleWrite = TRUE; } else { SimpleWrite = FALSE; FindAttrIndex(Row->AttrRow.Attrs, #ifdef WWSB_FE
(SHORT)(ConvAreaInfo ? CaTextRect.Left : Region->Left), #else
Region->Left, #endif
&Attr, &CountOfAttr ); } if (Console->LastAttributes != Attr->Attr) { TEXTCOLOR_CALL; #ifdef WWSB_FE
if (Attr->Attr & COMMON_LVB_REVERSE_VIDEO) { SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); } else{ #endif
SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); #ifdef WWSB_FE
} #endif
Console->LastAttributes = Attr->Attr; } TextRect.top = Window.Y*SCR_FONTSIZE(ScreenInfo).Y; TextRect.bottom = TextRect.top + SCR_FONTSIZE(ScreenInfo).Y; for (j=Region->Left;j<=Region->Right;) { SHORT NumberOfChars; int TextLeft; SHORT LeftChar,RightChar;
if (CountOfAttr > (SHORT)(Region->Right - j + 1)) { CountOfAttr = (SHORT)(Region->Right - j + 1); }
#ifdef WWSB_FE
CountOfAttrOriginal = CountOfAttr;
LocalEUDCFlag = FALSE; if((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED && ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalVDMEudcMode)){ LocalEUDCFlag = CheckEudcRangeInString( Console, &Row->CharRow.Chars[ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j], CountOfAttr, &CountOfAttr); } if (!(ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) && ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalKeisenEudcMode ) { SHORT k; PWCHAR Char2; Char2 = &Row->CharRow.Chars[ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j]; for ( k = 0 ; k < CountOfAttr ; k++,Char2++){ if (*Char2 < UNICODE_SPACE){ CountOfAttr = k ; LocalEUDCFlag = TRUE; break; } } } #endif
//
// make the bounding rect smaller, if we can. the TEXT_VALID_HINT
// flag gets set each time we write to the screen buffer. it gets
// turned off any time we get asked to redraw the screen
// and we don't know exactly what needs to be redrawn
// (i.e. paint messages).
//
// we have the left and right bounds of the text on the
// line. the opaqueing rectangle and the number of
// chars get set according to those values.
//
// if there's more than one attr per line (!SimpleWrite)
// we bail on the opaqueing rect.
//
if (ScreenInfo->BufferInfo.TextInfo.Flags & TEXT_VALID_HINT && SimpleWrite) { if (Row->CharRow.OldLeft != INVALID_OLD_LENGTH) { TextRect.left = (max(min(Row->CharRow.Left,Row->CharRow.OldLeft),j)-ScreenInfo->Window.Left) * SCR_FONTSIZE(ScreenInfo).X; } else { TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X; }
if (Row->CharRow.OldRight != INVALID_OLD_LENGTH) { TextRect.right = (min(max(Row->CharRow.Right,Row->CharRow.OldRight),j+CountOfAttr)-ScreenInfo->Window.Left) * SCR_FONTSIZE(ScreenInfo).X; } else { TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X; } LeftChar = max(Row->CharRow.Left,j); RightChar = min(Row->CharRow.Right,j+CountOfAttr); NumberOfChars = RightChar - LeftChar; TextLeft = (LeftChar-ScreenInfo->Window.Left)*SCR_FONTSIZE(ScreenInfo).X; } else { #ifdef WWSB_FE
LeftChar = ConvAreaInfo ? CaTextRect.Left + (j-Region->Left) : j; #else
LeftChar = (SHORT)j; #endif
TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X; TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X; #ifdef WWSB_FE
if (ConvAreaInfo) NumberOfChars = (Row->CharRow.Right > (SHORT)((CaTextRect.Left+(j-Region->Left)) + CountOfAttr)) ? (CountOfAttr) : (SHORT)(Row->CharRow.Right-(CaTextRect.Left+(j-Region->Left))); else #endif
NumberOfChars = (Row->CharRow.Right > (SHORT)(j + CountOfAttr)) ? (CountOfAttr) : (SHORT)(Row->CharRow.Right-j); TextLeft = TextRect.left; }
if (NumberOfChars < 0) { NumberOfChars = 0; #ifdef WWSB_FE
TextRect.left = Window.X*SCR_FONTSIZE(ScreenInfo).X; TextRect.right = TextRect.left + CountOfAttr*SCR_FONTSIZE(ScreenInfo).X; #endif
} TEXTOUT_CALL; #ifdef WWSB_FE
/*
* Text out everything (i.e. SBCS/DBCS, Common LVB attribute, Local EUDC) */ TextOutEverything(Console, ScreenInfo, (SHORT)j, &Region->Right, &CountOfAttr, CountOfAttrOriginal, &DoubleColorDbcs, LocalEUDCFlag, Row, Attr, LeftChar, RightChar, TextLeft, TextRect, NumberOfChars); #else
NumberOfChars = (SHORT)RemoveDbcsMarkAll(ScreenInfo, Row, &LeftChar, &TextRect, &TextLeft, TransBufferCharacter, NumberOfChars); ExtTextOutW(Console->hDC, TextLeft, TextRect.top, ETO_OPAQUE, &TextRect, TransBufferCharacter, NumberOfChars, NULL ); #endif
if (OneLine && SimpleWrite) { break; } j+=CountOfAttr; if (j <= Region->Right) { Window.X += CountOfAttr; #ifdef WWSB_FE
if (CountOfAttr < CountOfAttrOriginal){ CountOfAttr = CountOfAttrOriginal - CountOfAttr; } else { #endif
Attr++; CountOfAttr = Attr->Length; #ifdef WWSB_FE
} #endif
#ifdef WWSB_FE
if (Attr->Attr & COMMON_LVB_REVERSE_VIDEO) { SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); } else{ #endif
SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr))); SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr->Attr >> 4))); #ifdef WWSB_FE
} #endif
Console->LastAttributes = Attr->Attr; } } Window.X = Region->Left - ScreenInfo->Window.Left; if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } } GdiFlush(); ConsoleHeapFree(TransBufferCharacter); }
//
// if we have a selection, turn it on.
//
InvertSelection(Console, FALSE); } #ifdef i386
else if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) { #ifdef WWSB_FE
if (! ScreenInfo->ConvScreenInfo) { if (ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo) { WWSB_WriteRegionToScreenHW(ScreenInfo,Region); } } else if (ScreenInfo->Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) #endif
WWSB_WriteRegionToScreenHW(ScreenInfo,Region); } #endif
#ifdef WWSB_FE
{ SMALL_RECT TmpRegion;
if (ScreenInfo->BisectFlag & BISECT_TOP) { ScreenInfo->BisectFlag &= ~BISECT_TOP; if (Region->Top) { TmpRegion.Top = Region->Top-1; TmpRegion.Bottom = Region->Top-1; TmpRegion.Left = ScreenInfo->ScreenBufferSize.X-1; TmpRegion.Right = ScreenInfo->ScreenBufferSize.X-1; WWSB_WriteRegionToScreen(ScreenInfo,&TmpRegion); } } if (ScreenInfo->BisectFlag & BISECT_BOTTOM) { ScreenInfo->BisectFlag &= ~BISECT_BOTTOM; if (Region->Bottom+1 < ScreenInfo->ScreenBufferSize.Y) { TmpRegion.Top = Region->Bottom+1; TmpRegion.Bottom = Region->Bottom+1; TmpRegion.Left = 0; TmpRegion.Right = 0; WWSB_WriteRegionToScreen(ScreenInfo,&TmpRegion); } } } #endif
}
VOID WWSB_WriteToScreen( IN PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT Region ) /*++
Routine Description:
This routine writes a screen buffer region to the screen.
Arguments:
ScreenInfo - Pointer to screen buffer information.
Region - Region to write in screen buffer coordinates. Region is inclusive
Return Value:
none.
--*/
{ SMALL_RECT ClippedRegion;
DBGOUTPUT(("WriteToScreen\n")); //
// update to screen, if we're not iconic. we're marked as
// iconic if we're fullscreen, so check for fullscreen.
//
if (!ACTIVE_SCREEN_BUFFER(ScreenInfo) || (ScreenInfo->Console->Flags & (CONSOLE_IS_ICONIC | CONSOLE_NO_WINDOW) && ScreenInfo->Console->FullScreenFlags == 0)) { return; }
// clip region
ClippedRegion.Left = max(Region->Left, ScreenInfo->Window.Left); ClippedRegion.Top = max(Region->Top, ScreenInfo->Window.Top); ClippedRegion.Right = min(Region->Right, ScreenInfo->Window.Right); ClippedRegion.Bottom = min(Region->Bottom, ScreenInfo->Window.Bottom); if (ClippedRegion.Right < ClippedRegion.Left || ClippedRegion.Bottom < ClippedRegion.Top) { return; }
if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { if (ScreenInfo->Console->FullScreenFlags == 0) { WriteRegionToScreenBitMap(ScreenInfo, &ClippedRegion); } } else { ConsoleHideCursor(ScreenInfo); WWSB_WriteRegionToScreen(ScreenInfo, &ClippedRegion); #ifdef WWSB_FE
if (!(ScreenInfo->Console->ConsoleIme.ScrollFlag & HIDE_FOR_SCROLL)) { PCONVERSIONAREA_INFORMATION ConvAreaInfo;
if (! ScreenInfo->Console->CurrentScreenBuffer->ConvScreenInfo) { WriteConvRegionToScreen(ScreenInfo, ScreenInfo->Console->ConsoleIme.ConvAreaRoot, Region); } else if (ConvAreaInfo = ScreenInfo->Console->ConsoleIme.ConvAreaRoot) { do { if (ConvAreaInfo->ScreenBuffer == ScreenInfo) break; } while (ConvAreaInfo = ConvAreaInfo->ConvAreaNext); if (ConvAreaInfo) { WriteConvRegionToScreen(ScreenInfo, ConvAreaInfo->ConvAreaNext, Region); } } } #endif
ConsoleShowCursor(ScreenInfo); } }
NTSTATUS WWSB_WriteOutputString( IN PSCREEN_INFORMATION ScreenInfo, IN PVOID Buffer, IN COORD WriteCoord, IN ULONG StringType, IN OUT PULONG NumRecords, // this value is valid even for error cases
OUT PULONG NumColumns OPTIONAL )
/*++
Routine Description:
This routine writes a string of characters or attributes to the screen buffer.
Arguments:
ScreenInfo - Pointer to screen buffer information.
Buffer - Buffer to write from.
WriteCoord - Screen buffer coordinate to begin writing to.
StringType One of the following: CONSOLE_ASCII - write a string of ascii characters. CONSOLE_REAL_UNICODE - write a string of real unicode characters. CONSOLE_FALSE_UNICODE - write a string of false unicode characters. CONSOLE_ATTRIBUTE - write a string of attributes.
NumRecords - On input, the number of elements to write. On output, the number of elements written.
NumColumns - receives the number of columns output, which could be more than NumRecords (FE fullwidth chars) Return Value:
--*/
{ ULONG NumWritten; SHORT X,Y,LeftX; SMALL_RECT WriteRegion; PROW Row; PWCHAR Char; SHORT RowIndex; SHORT j; PWCHAR TransBuffer; #ifdef WWSB_NOFE
WCHAR SingleChar; #endif
UINT Codepage; #ifdef WWSB_FE
PBYTE AttrP; PBYTE TransBufferA; PBYTE BufferA; ULONG NumRecordsSavedForUnicode; BOOL fLocalHeap = FALSE; #endif
DBGOUTPUT(("WriteOutputString\n")); #ifdef WWSB_FE
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); #endif
if (*NumRecords == 0) return STATUS_SUCCESS;
NumWritten = 0; X=WriteCoord.X; Y=WriteCoord.Y; if (X>=ScreenInfo->ScreenBufferSize.X || X<0 || Y>=ScreenInfo->ScreenBufferSize.Y || Y<0) { *NumRecords = 0; return STATUS_SUCCESS; }
ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+WriteCoord.Y) % ScreenInfo->ScreenBufferSize.Y;
if (StringType == CONSOLE_ASCII) { #ifdef WWSB_FE
PCHAR TmpBuf; PWCHAR TmpTrans; ULONG i; PCHAR TmpTransA; #endif
if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { if (ScreenInfo->Console->OutputCP != WINDOWSCP) Codepage = USACP; else Codepage = WINDOWSCP; } else { Codepage = ScreenInfo->Console->OutputCP; }
#ifdef WWSB_FE
if (*NumRecords > (ULONG)(ScreenInfo->ScreenBufferSize.X * ScreenInfo->ScreenBufferSize.Y)) {
TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(WCHAR)); if (TransBuffer == NULL) { return STATUS_NO_MEMORY; } TransBufferA = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(CHAR)); if (TransBufferA == NULL) { ConsoleHeapFree(TransBuffer); return STATUS_NO_MEMORY; }
fLocalHeap = TRUE; } else { TransBuffer = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter; TransBufferA = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute; }
TmpBuf = Buffer; TmpTrans = TransBuffer; TmpTransA = TransBufferA; // MSKK Apr.02.1993 V-HirotS For KAttr
for (i=0; i < *NumRecords;) { if (IsDBCSLeadByteConsole(*TmpBuf,&ScreenInfo->Console->OutputCPInfo)) { if (i+1 >= *NumRecords) { *TmpTrans = UNICODE_SPACE; *TmpTransA = 0; i++; } else { ConvertOutputToUnicode(Codepage, TmpBuf, 2, TmpTrans, 2); *(TmpTrans+1) = *TmpTrans; TmpTrans += 2; TmpBuf += 2; *TmpTransA++ = ATTR_LEADING_BYTE; *TmpTransA++ = ATTR_TRAILING_BYTE; i += 2; } } else { ConvertOutputToUnicode(Codepage, TmpBuf, 1, TmpTrans, 1); TmpTrans++; TmpBuf++; *TmpTransA++ = 0; // MSKK APr.02.1993 V-HirotS For KAttr
i++; } } BufferA = TransBufferA; Buffer = TransBuffer; #else
if (*NumRecords == 1) { TransBuffer = NULL; SingleChar = SB_CharToWcharGlyph(Codepage, *((char *)Buffer)); Buffer = &SingleChar; } else { TransBuffer = ConsoleHeapAlloc(TMP_TAG, *NumRecords * sizeof(WCHAR)); if (TransBuffer == NULL) { return STATUS_NO_MEMORY; } ConvertOutputToUnicode(Codepage, Buffer, *NumRecords, TransBuffer, *NumRecords); Buffer = TransBuffer; } #endif
} else if (StringType == CONSOLE_REAL_UNICODE && (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { RealUnicodeToFalseUnicode(Buffer, *NumRecords, ScreenInfo->Console->OutputCP ); }
#ifdef WWSB_FE
if ((StringType == CONSOLE_REAL_UNICODE) || (StringType == CONSOLE_FALSE_UNICODE)) { PWCHAR TmpBuf; PWCHAR TmpTrans; PCHAR TmpTransA; ULONG i,j; WCHAR c;
/* Avoid overflow into TransBufferCharacter , TransBufferAttribute
* because, if hit by IsConsoleFullWidth() * then one unicde character needs two spaces on TransBuffer. */ if ((*NumRecords*2) > (ULONG)(ScreenInfo->ScreenBufferSize.X * ScreenInfo->ScreenBufferSize.Y)) {
TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(WCHAR)); if (TransBuffer == NULL) { return STATUS_NO_MEMORY; } TransBufferA = ConsoleHeapAlloc(TMP_DBCS_TAG, *NumRecords * 2 * sizeof(CHAR)); if (TransBufferA == NULL) { ConsoleHeapFree(TransBuffer); return STATUS_NO_MEMORY; }
fLocalHeap = TRUE; } else { TransBuffer = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferCharacter; TransBufferA = ScreenInfo->BufferInfo.TextInfo.DbcsScreenBuffer.TransBufferAttribute; }
TmpBuf = Buffer; TmpTrans = TransBuffer; TmpTransA = TransBufferA; for (i=0,j=0; i < *NumRecords; i++,j++) { *TmpTrans++ = c = *TmpBuf++; *TmpTransA = 0; if (IsConsoleFullWidth(ScreenInfo->Console->hDC, ScreenInfo->Console->OutputCP,c)) { *TmpTransA++ = ATTR_LEADING_BYTE; *TmpTrans++ = c; *TmpTransA = ATTR_TRAILING_BYTE; j++; } TmpTransA++; } NumRecordsSavedForUnicode = *NumRecords; *NumRecords = j; Buffer = TransBuffer; BufferA = TransBufferA; } #endif
if ((StringType == CONSOLE_REAL_UNICODE) || (StringType == CONSOLE_FALSE_UNICODE) || (StringType == CONSOLE_ASCII)) { while (TRUE) {
LeftX = X;
//
// copy the chars into their arrays
//
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; Char = &Row->CharRow.Chars[X]; #ifdef WWSB_FE
AttrP = &Row->CharRow.KAttrs[X]; #endif
if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*NumRecords - NumWritten)) { /*
* The text will not hit the right hand edge, copy it all */ #ifdef WWSB_FE
COORD TPoint;
TPoint.X = X; TPoint.Y = Y; BisectWrite((SHORT)(*NumRecords-NumWritten),TPoint,ScreenInfo); if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && (SHORT)(TPoint.X+*NumRecords-NumWritten) >= ScreenInfo->ScreenBufferSize.X && *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & ATTR_LEADING_BYTE ) { *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE; *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = 0; if ((SHORT)(*NumRecords-NumWritten) > (SHORT)(ScreenInfo->ScreenBufferSize.X-TPoint.X-1)) { *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE; *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X) = 0; } } RtlCopyMemory(AttrP,BufferA,(*NumRecords - NumWritten) * sizeof(CHAR)); #endif
RtlCopyMemory(Char,Buffer,(*NumRecords - NumWritten) * sizeof(WCHAR)); X=(SHORT)(X+*NumRecords - NumWritten-1); NumWritten = *NumRecords; } else { /*
* The text will hit the right hand edge, copy only that much */ #ifdef WWSB_FE
COORD TPoint;
TPoint.X = X; TPoint.Y = Y; BisectWrite((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); if (TPoint.Y == ScreenInfo->ScreenBufferSize.Y-1 && TPoint.X+ScreenInfo->ScreenBufferSize.X-X >= ScreenInfo->ScreenBufferSize.X && *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) & ATTR_LEADING_BYTE ) { *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = UNICODE_SPACE; *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X-1) = 0; if (ScreenInfo->ScreenBufferSize.X-X > ScreenInfo->ScreenBufferSize.X-TPoint.X-1) { *((PWCHAR)Buffer+ScreenInfo->ScreenBufferSize.X-TPoint.X) = UNICODE_SPACE; *((PCHAR)BufferA+ScreenInfo->ScreenBufferSize.X-TPoint.X) = 0; } } RtlCopyMemory(AttrP,BufferA,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR)); BufferA = (PVOID)((PBYTE)BufferA + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(CHAR))); #endif
RtlCopyMemory(Char,Buffer,(ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR)); Buffer = (PVOID)((PBYTE)Buffer + ((ScreenInfo->ScreenBufferSize.X - X) * sizeof(WCHAR))); NumWritten += ScreenInfo->ScreenBufferSize.X - X; X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); }
// recalculate first and last non-space char
Row->CharRow.OldLeft = Row->CharRow.Left; if (LeftX < Row->CharRow.Left) { PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X];
for (Char=&Row->CharRow.Chars[LeftX];Char < LastChar && *Char==(WCHAR)' ';Char++) ; Row->CharRow.Left = (SHORT)(Char-Row->CharRow.Chars); }
Row->CharRow.OldRight = Row->CharRow.Right; if ((X+1) >= Row->CharRow.Right) { WORD LastNonSpace; PWCHAR FirstChar = Row->CharRow.Chars;
LastNonSpace = X; for (Char=&Row->CharRow.Chars[X];*Char==(WCHAR)' ' && Char >= FirstChar;Char--) LastNonSpace--; Row->CharRow.Right = (SHORT)(LastNonSpace+1); } if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } if (NumWritten < *NumRecords) { /*
* The string hit the right hand edge, so wrap around to the * next line by going back round the while loop, unless we * are at the end of the buffer - in which case we simply * abandon the remainder of the output string! */ X = 0; Y++; if (Y >= ScreenInfo->ScreenBufferSize.Y) { break; // abandon output, string is truncated
} } else { break; } } } else if (StringType == CONSOLE_ATTRIBUTE) { PWORD SourcePtr=Buffer; PATTR_PAIR AttrBuf; ATTR_PAIR Attrs[80]; PATTR_PAIR Attr; SHORT AttrLength;
AttrBuf = Attrs; if (ScreenInfo->ScreenBufferSize.X > 80) { AttrBuf = ConsoleHeapAlloc(TMP_TAG, ScreenInfo->ScreenBufferSize.X * sizeof(ATTR_PAIR)); if (AttrBuf == NULL) return STATUS_NO_MEMORY; } #ifdef WWSB_FE
{ COORD TPoint; TPoint.X = X; TPoint.Y = Y; if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*NumRecords - NumWritten)) { BisectWriteAttr((SHORT)(*NumRecords-NumWritten),TPoint,ScreenInfo); } else{ BisectWriteAttr((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); } } #endif
while (TRUE) {
//
// copy the attrs into the screen buffer arrays
//
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; Attr = AttrBuf; Attr->Length = 0; #ifdef WWSB_FE
Attr->Attr = *SourcePtr & ~COMMON_LVB_SBCSDBCS; #else
Attr->Attr = *SourcePtr; #endif
AttrLength = 1; for (j=X;j<ScreenInfo->ScreenBufferSize.X;j++,SourcePtr++) { #ifdef WWSB_FE
if (Attr->Attr == (*SourcePtr & ~COMMON_LVB_SBCSDBCS)) #else
if (Attr->Attr == *SourcePtr) #endif
{ Attr->Length += 1; } else { Attr++; Attr->Length = 1; #ifdef WWSB_FE
Attr->Attr = *SourcePtr & ~COMMON_LVB_SBCSDBCS; #else
Attr->Attr = *SourcePtr; #endif
AttrLength += 1; } NumWritten++; X++; if (NumWritten == *NumRecords) { break; } } X--;
// recalculate last non-space char
//
// see if attr string is different. if so, allocate a new
// attr buffer and merge the two strings.
//
if (AttrLength != Row->AttrRow.Length || memcmp(Row->AttrRow.Attrs,AttrBuf,AttrLength*sizeof(*Attr))) { PATTR_PAIR NewAttrs; WORD NewAttrsLength;
if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, AttrBuf, AttrLength, &NewAttrs, &NewAttrsLength, (SHORT)((Y == WriteCoord.Y) ? WriteCoord.X : 0), X, Row, ScreenInfo ))) { if (ScreenInfo->ScreenBufferSize.X > 80) { ConsoleHeapFree(AttrBuf); } ResetTextFlags(ScreenInfo, WriteCoord.X, WriteCoord.Y, X, Y); return STATUS_NO_MEMORY; } if (Row->AttrRow.Length > 1) { ConsoleHeapFree(Row->AttrRow.Attrs); } else { ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); } Row->AttrRow.Attrs = NewAttrs; Row->AttrRow.Length = NewAttrsLength; Row->CharRow.OldLeft = INVALID_OLD_LENGTH; Row->CharRow.OldRight = INVALID_OLD_LENGTH; }
if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } if (NumWritten < *NumRecords) { X = 0; Y++; if (Y>=ScreenInfo->ScreenBufferSize.Y) { break; } } else { break; } } ResetTextFlags(ScreenInfo, WriteCoord.X, WriteCoord.Y, X, Y); if (ScreenInfo->ScreenBufferSize.X > 80) { ConsoleHeapFree(AttrBuf); } } else { *NumRecords = 0; return STATUS_INVALID_PARAMETER; } if ((StringType == CONSOLE_ASCII) && (TransBuffer != NULL)) { #ifdef WWSB_FE
if (fLocalHeap) { ConsoleHeapFree(TransBuffer); ConsoleHeapFree(TransBufferA); } #else
ConsoleHeapFree(TransBuffer); #endif
} #ifdef WWSB_FE
else if ((StringType == CONSOLE_FALSE_UNICODE) || (StringType == CONSOLE_REAL_UNICODE)) { if (fLocalHeap) { ConsoleHeapFree(TransBuffer); ConsoleHeapFree(TransBufferA); } NumWritten = NumRecordsSavedForUnicode - (*NumRecords - NumWritten); } #endif
//
// determine write region. if we're still on the same line we started
// on, left X is the X we started with and right X is the one we're on
// now. otherwise, left X is 0 and right X is the rightmost column of
// the screen buffer.
//
// then update the screen.
//
WriteRegion.Top = WriteCoord.Y; WriteRegion.Bottom = Y; if (Y != WriteCoord.Y) { WriteRegion.Left = 0; WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); } else { WriteRegion.Left = WriteCoord.X; WriteRegion.Right = X; } WWSB_WriteToScreen(ScreenInfo,&WriteRegion); if (NumColumns) { *NumColumns = X + (WriteCoord.Y - Y) * ScreenInfo->ScreenBufferSize.X - WriteCoord.X + 1; } *NumRecords = NumWritten; return STATUS_SUCCESS; }
NTSTATUS WWSB_FillOutput( IN PSCREEN_INFORMATION ScreenInfo, IN WORD Element, IN COORD WriteCoord, IN ULONG ElementType, IN OUT PULONG Length // this value is valid even for error cases
)
/*++
Routine Description:
This routine fills the screen buffer with the specified character or attribute.
Arguments:
ScreenInfo - Pointer to screen buffer information.
Element - Element to write.
WriteCoord - Screen buffer coordinate to begin writing to.
ElementType
CONSOLE_ASCII - element is an ascii character. CONSOLE_REAL_UNICODE - element is a real unicode character. These will get converted to False Unicode as required. CONSOLE_FALSE_UNICODE - element is a False Unicode character. CONSOLE_ATTRIBUTE - element is an attribute.
Length - On input, the number of elements to write. On output, the number of elements written.
Return Value:
--*/
{ ULONG NumWritten; SHORT X,Y,LeftX; SMALL_RECT WriteRegion; PROW Row; PWCHAR Char; SHORT RowIndex; SHORT j; #ifdef WWSB_FE
PCHAR AttrP; #endif
DBGOUTPUT(("FillOutput\n")); if (*Length == 0) return STATUS_SUCCESS; NumWritten = 0; X=WriteCoord.X; Y=WriteCoord.Y; if (X>=ScreenInfo->ScreenBufferSize.X || X<0 || Y>=ScreenInfo->ScreenBufferSize.Y || Y<0) { *Length = 0; return STATUS_SUCCESS; }
#ifdef WWSB_FE
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); #endif
ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+WriteCoord.Y) % ScreenInfo->ScreenBufferSize.Y;
if (ElementType == CONSOLE_ASCII) { UINT Codepage; if ((ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && ((ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { if (ScreenInfo->Console->OutputCP != WINDOWSCP) Codepage = USACP; else Codepage = WINDOWSCP; } else { Codepage = ScreenInfo->Console->OutputCP; } #ifdef WWSB_FE
if (ScreenInfo->FillOutDbcsLeadChar == 0){ if (IsDBCSLeadByteConsole((CHAR)Element,&ScreenInfo->Console->OutputCPInfo)) { ScreenInfo->FillOutDbcsLeadChar = (CHAR)Element; *Length = 0; return STATUS_SUCCESS; }else{ CHAR Char=(CHAR)Element; ConvertOutputToUnicode(Codepage, &Char, 1, &Element, 1); } }else{ CHAR Char[2]; Char[0]=ScreenInfo->FillOutDbcsLeadChar; Char[1]=(BYTE)Element; ScreenInfo->FillOutDbcsLeadChar = 0; ConvertOutputToUnicode(Codepage, Char, 2, &Element, 2); } #else
Element = SB_CharToWchar(Codepage, (CHAR)Element); #endif
} else if (ElementType == CONSOLE_REAL_UNICODE && (ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { RealUnicodeToFalseUnicode(&Element, 1, ScreenInfo->Console->OutputCP ); }
if ((ElementType == CONSOLE_ASCII) || (ElementType == CONSOLE_REAL_UNICODE) || (ElementType == CONSOLE_FALSE_UNICODE)) { #ifdef WWSB_FE
DWORD StartPosFlag ; StartPosFlag = 0; #endif
while (TRUE) {
//
// copy the chars into their arrays
//
LeftX = X; Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; Char = &Row->CharRow.Chars[X]; #ifdef WWSB_FE
AttrP = &Row->CharRow.KAttrs[X]; #endif
if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) { #ifdef WWSB_FE
{ COORD TPoint;
TPoint.X = X; TPoint.Y = Y; BisectWrite((SHORT)(*Length-NumWritten),TPoint,ScreenInfo); } #endif
#ifdef WWSB_FE
if (IsConsoleFullWidth(ScreenInfo->Console->hDC, ScreenInfo->Console->OutputCP,(WCHAR)Element)) { for (j=0;j<(SHORT)(*Length - NumWritten);j++) { *Char++ = (WCHAR)Element; *AttrP &= ~ATTR_DBCSSBCS_BYTE; if(StartPosFlag++ & 1) *AttrP++ |= ATTR_TRAILING_BYTE; else *AttrP++ |= ATTR_LEADING_BYTE; } if(StartPosFlag & 1){ *(Char-1) = UNICODE_SPACE; *(AttrP-1) &= ~ATTR_DBCSSBCS_BYTE; } } else { #endif
for (j=0;j<(SHORT)(*Length - NumWritten);j++) { *Char++ = (WCHAR)Element; #ifdef WWSB_FE
*AttrP++ &= ~ATTR_DBCSSBCS_BYTE; #endif
} #ifdef WWSB_FE
} #endif
X=(SHORT)(X+*Length - NumWritten - 1); NumWritten = *Length; } else { #ifdef WWSB_FE
{ COORD TPoint;
TPoint.X = X; TPoint.Y = Y; BisectWrite((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); } #endif
#ifdef WWSB_FE
if (IsConsoleFullWidth(ScreenInfo->Console->hDC, ScreenInfo->Console->OutputCP,(WCHAR)Element)) { for (j=0;j<ScreenInfo->ScreenBufferSize.X - X;j++) { *Char++ = (WCHAR)Element; *AttrP &= ~ATTR_DBCSSBCS_BYTE; if(StartPosFlag++ & 1) *AttrP++ |= ATTR_TRAILING_BYTE; else *AttrP++ |= ATTR_LEADING_BYTE; } } else { #endif
for (j=0;j<ScreenInfo->ScreenBufferSize.X - X;j++) { *Char++ = (WCHAR)Element; #ifdef WWSB_FE
*AttrP++ &= ~ATTR_DBCSSBCS_BYTE; #endif
} #ifdef WWSB_FE
} #endif
NumWritten += ScreenInfo->ScreenBufferSize.X - X; X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); }
// recalculate first and last non-space char
Row->CharRow.OldLeft = Row->CharRow.Left; if (LeftX < Row->CharRow.Left) { if (Element == UNICODE_SPACE) { Row->CharRow.Left = X+1; } else { Row->CharRow.Left = LeftX; } } Row->CharRow.OldRight = Row->CharRow.Right; if ((X+1) >= Row->CharRow.Right) { if (Element == UNICODE_SPACE) { Row->CharRow.Right = LeftX; } else { Row->CharRow.Right = X+1; } } if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } if (NumWritten < *Length) { X = 0; Y++; if (Y>=ScreenInfo->ScreenBufferSize.Y) { break; } } else { break; } } } else if (ElementType == CONSOLE_ATTRIBUTE) { ATTR_PAIR Attr;
#ifdef WWSB_FE
COORD TPoint; TPoint.X = X; TPoint.Y = Y;
if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) { BisectWriteAttr((SHORT)(*Length-NumWritten),TPoint,ScreenInfo); } else{ BisectWriteAttr((SHORT)(ScreenInfo->ScreenBufferSize.X-X),TPoint,ScreenInfo); } #endif
while (TRUE) {
//
// copy the attrs into the screen buffer arrays
//
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; if ((ULONG)(ScreenInfo->ScreenBufferSize.X - X) >= (*Length - NumWritten)) { X=(SHORT)(X+*Length - NumWritten - 1); NumWritten = *Length; } else { NumWritten += ScreenInfo->ScreenBufferSize.X - X; X = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); }
// recalculate last non-space char
//
// merge the two attribute strings.
//
Attr.Length = (SHORT)((Y == WriteCoord.Y) ? (X-WriteCoord.X+1) : (X+1)); #ifdef WWSB_FE
Attr.Attr = Element & ~COMMON_LVB_SBCSDBCS; #else
Attr.Attr = Element; #endif
if (1 != Row->AttrRow.Length || memcmp(Row->AttrRow.Attrs,&Attr,sizeof(Attr))) { PATTR_PAIR NewAttrs; WORD NewAttrsLength;
if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, &Attr, 1, &NewAttrs, &NewAttrsLength, (SHORT)(X-Attr.Length+1), X, Row, ScreenInfo ))) { ResetTextFlags(ScreenInfo, WriteCoord.X, WriteCoord.Y, X, Y); return STATUS_NO_MEMORY; } if (Row->AttrRow.Length > 1) { ConsoleHeapFree(Row->AttrRow.Attrs); } else { ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); } Row->AttrRow.Attrs = NewAttrs; Row->AttrRow.Length = NewAttrsLength; Row->CharRow.OldLeft = INVALID_OLD_LENGTH; Row->CharRow.OldRight = INVALID_OLD_LENGTH; }
if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } if (NumWritten < *Length) { X = 0; Y++; if (Y>=ScreenInfo->ScreenBufferSize.Y) { break; } } else { break; } } ResetTextFlags(ScreenInfo, WriteCoord.X, WriteCoord.Y, X, Y); } else { *Length = 0; return STATUS_INVALID_PARAMETER; }
//
// determine write region. if we're still on the same line we started
// on, left X is the X we started with and right X is the one we're on
// now. otherwise, left X is 0 and right X is the rightmost column of
// the screen buffer.
//
// then update the screen.
//
#ifdef WWSB_FE
if (ScreenInfo->ConvScreenInfo) { WriteRegion.Top = WriteCoord.Y + ScreenInfo->Window.Left + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.Y; WriteRegion.Bottom = Y + ScreenInfo->Window.Left + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.Y; if (Y != WriteCoord.Y) { WriteRegion.Left = 0; WriteRegion.Right = (SHORT)(ScreenInfo->Console->CurrentScreenBuffer->ScreenBufferSize.X-1); } else { WriteRegion.Left = WriteCoord.X + ScreenInfo->Window.Top + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.X; WriteRegion.Right = X + ScreenInfo->Window.Top + ScreenInfo->ConvScreenInfo->CaInfo.coordConView.X; } WriteConvRegionToScreen(ScreenInfo->Console->CurrentScreenBuffer, ScreenInfo->ConvScreenInfo, &WriteRegion ); ScreenInfo->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT | BISECT_TOP | BISECT_BOTTOM); *Length = NumWritten; return STATUS_SUCCESS; } #endif
WriteRegion.Top = WriteCoord.Y; WriteRegion.Bottom = Y; if (Y != WriteCoord.Y) { WriteRegion.Left = 0; WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); } else { WriteRegion.Left = WriteCoord.X; WriteRegion.Right = X; } WWSB_WriteToScreen(ScreenInfo,&WriteRegion); *Length = NumWritten; return STATUS_SUCCESS; }
VOID WWSB_FillRectangle( IN CHAR_INFO Fill, IN OUT PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT TargetRect )
/*++
Routine Description:
This routine fills a rectangular region in the screen buffer. no clipping is done.
Arguments:
Fill - element to copy to each element in target rect
ScreenInfo - pointer to screen info
TargetRect - rectangle in screen buffer to fill
Return Value:
--*/
{ SHORT i,j; SHORT XSize; SHORT RowIndex; PROW Row; PWCHAR Char; ATTR_PAIR Attr; #ifdef WWSB_FE
PCHAR AttrP; BOOL Width; #endif
DBGOUTPUT(("FillRectangle\n")); #ifdef WWFE_SB
ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); #endif
XSize = (SHORT)(TargetRect->Right - TargetRect->Left + 1);
ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetRect->Top) % ScreenInfo->ScreenBufferSize.Y; for (i=TargetRect->Top;i<=TargetRect->Bottom;i++) {
//
// copy the chars and attrs into their respective arrays
//
#ifdef WWSB_FE
{ COORD TPoint;
TPoint.X = TargetRect->Left; TPoint.Y = i; BisectWrite(XSize,TPoint,ScreenInfo); Width = IsConsoleFullWidth(ScreenInfo->Console->hDC, ScreenInfo->Console->OutputCP,Fill.Char.UnicodeChar); } #endif
Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; Char = &Row->CharRow.Chars[TargetRect->Left]; #ifdef WWSB_FE
AttrP = &Row->CharRow.KAttrs[TargetRect->Left]; #endif
for (j=0;j<XSize;j++) { #ifdef WWSB_FE
if (Width){ if (j < XSize-1){ *Char++ = Fill.Char.UnicodeChar; *Char++ = Fill.Char.UnicodeChar; *AttrP++ = ATTR_LEADING_BYTE; *AttrP++ = ATTR_TRAILING_BYTE; j++; } else{ *Char++ = UNICODE_SPACE; *AttrP++ = 0 ; } } else{ #endif
*Char++ = Fill.Char.UnicodeChar; #ifdef WWSB_FE
*AttrP++ = 0 ; } #endif
}
// recalculate first and last non-space char
Row->CharRow.OldLeft = Row->CharRow.Left; if (TargetRect->Left < Row->CharRow.Left) { if (Fill.Char.UnicodeChar == UNICODE_SPACE) { Row->CharRow.Left = (SHORT)(TargetRect->Right+1); } else { Row->CharRow.Left = (SHORT)(TargetRect->Left); } }
Row->CharRow.OldRight = Row->CharRow.Right; if (TargetRect->Right >= Row->CharRow.Right) { if (Fill.Char.UnicodeChar == UNICODE_SPACE) { Row->CharRow.Right = (SHORT)(TargetRect->Left); } else { Row->CharRow.Right = (SHORT)(TargetRect->Right+1); } }
Attr.Length = XSize; Attr.Attr = Fill.Attributes;
//
// merge the two attribute strings.
//
if (1 != Row->AttrRow.Length || memcmp(Row->AttrRow.Attrs,&Attr,sizeof(Attr))) { PATTR_PAIR NewAttrs; WORD NewAttrsLength;
if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, &Attr, 1, &NewAttrs, &NewAttrsLength, TargetRect->Left, TargetRect->Right, Row, ScreenInfo ))) { ResetTextFlags(ScreenInfo, TargetRect->Left, TargetRect->Top, TargetRect->Right, TargetRect->Bottom); return; } if (Row->AttrRow.Length > 1) { ConsoleHeapFree(Row->AttrRow.Attrs); } else { ASSERT(Row->AttrRow.Attrs == &Row->AttrRow.AttrPair); } Row->AttrRow.Attrs = NewAttrs; Row->AttrRow.Length = NewAttrsLength; Row->CharRow.OldLeft = INVALID_OLD_LENGTH; Row->CharRow.OldRight = INVALID_OLD_LENGTH; } if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } } ResetTextFlags(ScreenInfo, TargetRect->Left, TargetRect->Top, TargetRect->Right, TargetRect->Bottom); }
BOOL WWSB_PolyTextOutCandidate( IN PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT Region )
/*
This function returns TRUE if the input region is reasonable to pass to ConsolePolyTextOut. The criteria are that there is only one attribute per line.
*/
{ SHORT RowIndex; PROW Row; SHORT i;
#ifdef WWSB_FE
if((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED && ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalVDMEudcMode)){ return FALSE; } if (!(ScreenInfo->Flags & CONSOLE_OEMFONT_DISPLAY) && !(ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN) && ((PEUDC_INFORMATION)(ScreenInfo->Console->EudcInformation))->LocalKeisenEudcMode ) { return FALSE; } ASSERT(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER); if (ScreenInfo->BufferInfo.TextInfo.Flags & CONSOLE_CONVERSION_AREA_REDRAW) { return FALSE; } #endif
if (ScreenInfo->BufferInfo.TextInfo.Flags & SINGLE_ATTRIBUTES_PER_LINE) { return TRUE; }
//
// make sure there is only one attr per line.
//
RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top) % ScreenInfo->ScreenBufferSize.Y; for (i=Region->Top;i<=Region->Bottom;i++) { Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex]; if (Row->AttrRow.Length != 1) { return FALSE; } if (++RowIndex == ScreenInfo->ScreenBufferSize.Y) { RowIndex = 0; } } return TRUE; }
#define MAX_POLY_LINES 80
#define VERY_BIG_NUMBER 0x0FFFFFFF
#ifdef WWSB_FE
typedef struct _KEISEN_INFORMATION { COORD Coord; WORD n; } KEISEN_INFORMATION, *PKEISEN_INFORMATION; #endif
VOID WWSB_ConsolePolyTextOut( IN PSCREEN_INFORMATION ScreenInfo, IN PSMALL_RECT Region )
/*
This function calls PolyTextOut. The only restriction is that there can't be more than one attribute per line in the region.
*/
{ PROW Row,LastRow; SHORT i,k; WORD Attr; POLYTEXTW TextInfo[MAX_POLY_LINES]; RECT TextRect; RECTL BoundingRect; int xSize = SCR_FONTSIZE(ScreenInfo).X; int ySize = SCR_FONTSIZE(ScreenInfo).Y; ULONG Flags = ScreenInfo->BufferInfo.TextInfo.Flags; int WindowLeft = ScreenInfo->Window.Left; int RegionLeft = Region->Left; int RegionRight = Region->Right + 1; int DefaultLeft = (RegionLeft - WindowLeft) * xSize; int DefaultRight = (RegionRight - WindowLeft) * xSize; PCONSOLE_INFORMATION Console = ScreenInfo->Console; PWCHAR TransPolyTextOut = NULL ; #ifdef WWSB_FE
KEISEN_INFORMATION KeisenInfo[MAX_POLY_LINES]; SHORT j; WORD OldAttr; #endif
//
// initialize the text rect and window position.
//
TextRect.top = (Region->Top - ScreenInfo->Window.Top) * ySize; // TextRect.bottom is invalid.
BoundingRect.top = TextRect.top; BoundingRect.left = VERY_BIG_NUMBER; BoundingRect.right = 0;
//
// copy the chars and attrs from their respective arrays
//
Row = &ScreenInfo->BufferInfo.TextInfo.Rows [ScreenInfo->BufferInfo.TextInfo.FirstRow+Region->Top]; LastRow = &ScreenInfo->BufferInfo.TextInfo.Rows[ScreenInfo->ScreenBufferSize.Y]; if (Row >= LastRow) Row -= ScreenInfo->ScreenBufferSize.Y;
Attr = Row->AttrRow.AttrPair.Attr; if (Console->LastAttributes != Attr) { #ifdef WWSB_FE
if (Attr & COMMON_LVB_REVERSE_VIDEO) { SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); } else{ #endif
SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); #ifdef WWSB_FE
} #endif
Console->LastAttributes = Attr; }
TransPolyTextOut = ConsoleHeapAlloc(TMP_DBCS_TAG, ScreenInfo->ScreenBufferSize.X * MAX_POLY_LINES * sizeof(WCHAR)); if (TransPolyTextOut == NULL) { RIPMSG0(RIP_WARNING, "ConsoleTextOut cannot allocate memory"); return; }
for (i=Region->Top;i<=Region->Bottom;) { PWCHAR TmpChar; TmpChar = TransPolyTextOut; for(k=0;i<=Region->Bottom&&k<MAX_POLY_LINES;i++) { SHORT NumberOfChars; SHORT LeftChar,RightChar;
//
// make the bounding rect smaller, if we can. the TEXT_VALID_HINT
// flag gets set each time we write to the screen buffer. it gets
// turned off any time we get asked to redraw the screen
// and we don't know exactly what needs to be redrawn
// (i.e. paint messages).
//
// we have the left and right bounds of the text on the
// line. the opaqueing rectangle and the number of
// chars get set according to those values.
//
TextRect.left = DefaultLeft; TextRect.right = DefaultRight;
if (Flags & TEXT_VALID_HINT) { // We compute an opaquing interval. If A is the old interval of text,
// B is the new interval, and R is the Region, then the opaquing interval
// must be R*(A+B), where * represents intersection and + represents union.
if (Row->CharRow.OldLeft != INVALID_OLD_LENGTH) { // The min determines the left of (A+B). The max intersects that with
// the left of the region.
TextRect.left = ( max ( min ( Row->CharRow.Left, Row->CharRow.OldLeft ), RegionLeft ) -WindowLeft ) * xSize; }
if (Row->CharRow.OldRight != INVALID_OLD_LENGTH) { // The max determines the right of (A+B). The min intersects that with
// the right of the region.
TextRect.right = ( min ( max ( Row->CharRow.Right, Row->CharRow.OldRight ), RegionRight ) -WindowLeft ) * xSize; } }
//
// We've got to draw any new text that appears in the region, so we just
// intersect the new text interval with the region.
//
LeftChar = max(Row->CharRow.Left,RegionLeft); RightChar = min(Row->CharRow.Right,RegionRight); NumberOfChars = RightChar - LeftChar; #ifdef WWSB_FE
if (Row->CharRow.KAttrs[RightChar-1] & ATTR_LEADING_BYTE){ if(TextRect.right <= ScreenInfo->Window.Right*xSize) { TextRect.right += xSize; } } #endif
//
// Empty rows are represented by CharRow.Right=0, CharRow.Left=MAX, so we
// may have NumberOfChars<0 at this point if there is no text that needs
// drawing. (I.e. the intersection was empty.)
//
if (NumberOfChars < 0) { NumberOfChars = 0; LeftChar = 0; RightChar = 0; }
//
// We may also have TextRect.right<TextRect.left if the screen
// is already cleared, and we really don't need to do anything at all.
//
if (TextRect.right > TextRect.left) { NumberOfChars = (SHORT)RemoveDbcsMarkAll(ScreenInfo,Row,&LeftChar,&TextRect,NULL,TmpChar,NumberOfChars); TextInfo[k].x = (LeftChar-WindowLeft) * xSize; TextInfo[k].y = TextRect.top; TextRect.bottom = TextRect.top + ySize; TextInfo[k].n = NumberOfChars; TextInfo[k].lpstr = TmpChar; #ifdef WWSB_FE
if (CheckBisectStringW(ScreenInfo, Console->OutputCP, TmpChar, NumberOfChars, (TextRect.right-max(TextRect.left,TextInfo[k].x))/xSize ) ) { TextRect.right += xSize; } #endif
TmpChar += NumberOfChars; TextInfo[k].rcl = TextRect; TextInfo[k].pdx = NULL; TextInfo[k].uiFlags = ETO_OPAQUE; #ifdef WWSB_FE
KeisenInfo[k].n = DefaultRight-DefaultLeft ; KeisenInfo[k].Coord.Y = (WORD)TextRect.top; KeisenInfo[k].Coord.X = (WORD)DefaultLeft; #endif
k++;
if (BoundingRect.left > TextRect.left) { BoundingRect.left = TextRect.left; } if (BoundingRect.right < TextRect.right) { BoundingRect.right = TextRect.right; } }
// Advance the high res bounds.
TextRect.top += ySize;
// Advance the row pointer.
if (++Row >= LastRow) Row = ScreenInfo->BufferInfo.TextInfo.Rows;
// Draw now if the attributes are about to change.
#ifdef WWSB_FE
OldAttr = Attr ; #endif
if (Attr != Row->AttrRow.AttrPair.Attr) { Attr = Row->AttrRow.AttrPair.Attr; i++; break; } }
if (k) { BoundingRect.bottom = TextRect.top; ASSERT(BoundingRect.left != VERY_BIG_NUMBER); ASSERT(BoundingRect.left <= BoundingRect.right); ASSERT(BoundingRect.top <= BoundingRect.bottom); GdiConsoleTextOut(Console->hDC, TextInfo, k, &BoundingRect); #ifdef WWSB_FE
for ( j = 0 ; j < k ; j++){ RECT TextRect;
TextRect.left = KeisenInfo[j].Coord.X; TextRect.top = KeisenInfo[j].Coord.Y; TextRect.right = KeisenInfo[j].n + TextRect.left; TextRect.bottom = KeisenInfo[j].Coord.Y + ySize; TextOutCommonLVB(ScreenInfo->Console, OldAttr, TextRect); } #endif
} if (Console->LastAttributes != Attr) { #ifdef WWSB_FE
if (Attr & COMMON_LVB_REVERSE_VIDEO) { SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); } else{ #endif
SetTextColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr))); SetBkColor(Console->hDC, ConvertAttrToRGB(Console, LOBYTE(Attr >> 4))); #ifdef WWSB_FE
} #endif
Console->LastAttributes = Attr; BoundingRect.top = TextRect.top; BoundingRect.left = VERY_BIG_NUMBER; BoundingRect.right = 0; } } GdiFlush(); ConsoleHeapFree(TransPolyTextOut); }
|