/*++ Copyright (c) 1985 - 1999, Microsoft Corporation Module Name: convarea.c Abstract: Author: KazuM Mar.8,1993 Revision History: --*/ #include "precomp.h" #pragma hdrstop #if defined(FE_IME) VOID LinkConversionArea( IN PCONSOLE_INFORMATION Console, IN PCONVERSIONAREA_INFORMATION ConvAreaInfo ) { PCONVERSIONAREA_INFORMATION PrevConvAreaInfo; if (Console->ConsoleIme.ConvAreaRoot == NULL) { Console->ConsoleIme.ConvAreaRoot = ConvAreaInfo; } else { PrevConvAreaInfo = Console->ConsoleIme.ConvAreaRoot; while (PrevConvAreaInfo->ConvAreaNext) PrevConvAreaInfo = PrevConvAreaInfo->ConvAreaNext; PrevConvAreaInfo->ConvAreaNext = ConvAreaInfo; } } NTSTATUS FreeConvAreaScreenBuffer( IN PSCREEN_INFORMATION ScreenInfo ) /*++ Routine Description: This routine frees the memory associated with a screen buffer. Arguments: ScreenInfo - screen buffer data to free. Return Value: Note: console handle table lock must be held when calling this routine --*/ { return FreeScreenBuffer(ScreenInfo); } NTSTATUS AllocateConversionArea( IN PCONSOLE_INFORMATION Console, IN COORD dwScreenBufferSize, OUT PCONVERSIONAREA_INFORMATION *ConvAreaInfo ) { COORD dwWindowSize; CHAR_INFO Fill, PopupFill; PCONVERSIONAREA_INFORMATION ca; int FontIndex; NTSTATUS Status; // // allocate console data // if (Console->CurrentScreenBuffer == NULL) { return STATUS_UNSUCCESSFUL; } ca = ConsoleHeapAlloc(CONVAREA_TAG, sizeof(CONVERSIONAREA_INFORMATION)); if (ca == NULL) { return STATUS_NO_MEMORY; } dwWindowSize.X = CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer); dwWindowSize.Y = CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer); Fill.Attributes = Console->CurrentScreenBuffer->Attributes; PopupFill.Attributes = Console->CurrentScreenBuffer->PopupAttributes; FontIndex = FindCreateFont(CON_FAMILY(Console), CON_FACENAME(Console), CON_FONTSIZE(Console), CON_FONTWEIGHT(Console), CON_FONTCODEPAGE(Console) ); Status = CreateScreenBuffer(&ca->ScreenBuffer, dwWindowSize, FontIndex, dwScreenBufferSize, Fill, PopupFill, Console, CONSOLE_TEXTMODE_BUFFER, NULL, NULL, NULL, CURSOR_SMALL_SIZE, NULL ); if (!NT_SUCCESS(Status)) { ConsoleHeapFree(ca); return Status; } *ConvAreaInfo = ca; return STATUS_SUCCESS; } NTSTATUS SetUpConversionArea( IN PCONSOLE_INFORMATION Console, IN COORD coordCaBuffer, IN SMALL_RECT rcViewCaWindow, IN COORD coordConView, IN DWORD dwOption, OUT PCONVERSIONAREA_INFORMATION *ConvAreaInfo ) { NTSTATUS Status; PCONVERSIONAREA_INFORMATION ca; Status = AllocateConversionArea(Console, coordCaBuffer, &ca); if (!NT_SUCCESS(Status)) { return Status; } ca->ConversionAreaMode = dwOption; ca->CaInfo.coordCaBuffer = coordCaBuffer; ca->CaInfo.rcViewCaWindow = rcViewCaWindow; ca->CaInfo.coordConView = coordConView; ca->ConvAreaNext = NULL; ca->ScreenBuffer->ConvScreenInfo = ca; LinkConversionArea(Console, ca); SetUndetermineAttribute(Console); *ConvAreaInfo = ca; return STATUS_SUCCESS; } VOID WriteConvRegionToScreen( IN PSCREEN_INFORMATION ScreenInfo, IN PCONVERSIONAREA_INFORMATION ConvAreaInfo, IN PSMALL_RECT ConvRegion ) /*++ Routine Description: Arguments: ClippedRegion - Rectangle of region by screen coordinate. Return Value: --*/ { SMALL_RECT Region; SMALL_RECT ClippedRegion; if (ScreenInfo->Console->CurrentScreenBuffer->Flags & CONSOLE_GRAPHICS_BUFFER) return; while (ConvAreaInfo) { if ((ConvAreaInfo->ConversionAreaMode & (CA_HIDDEN+CA_HIDE_FOR_SCROLL))==0) { // // Do clipping region // Region.Left = ScreenInfo->Window.Left + ConvAreaInfo->CaInfo.rcViewCaWindow.Left + ConvAreaInfo->CaInfo.coordConView.X; Region.Right = Region.Left + (ConvAreaInfo->CaInfo.rcViewCaWindow.Right - ConvAreaInfo->CaInfo.rcViewCaWindow.Left); Region.Top = ScreenInfo->Window.Top + ConvAreaInfo->CaInfo.rcViewCaWindow.Top + ConvAreaInfo->CaInfo.coordConView.Y; Region.Bottom = Region.Top + (ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom - ConvAreaInfo->CaInfo.rcViewCaWindow.Top); 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) { /* TODO: Fix this. */; } else { Region = ClippedRegion; ClippedRegion.Left = max(Region.Left, ConvRegion->Left); ClippedRegion.Top = max(Region.Top, ConvRegion->Top); ClippedRegion.Right = min(Region.Right, ConvRegion->Right); ClippedRegion.Bottom = min(Region.Bottom, ConvRegion->Bottom); if (ClippedRegion.Right < ClippedRegion.Left || ClippedRegion.Bottom < ClippedRegion.Top) { /* TODO: Fix this */; } else { ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; WriteRegionToScreen(ConvAreaInfo->ScreenBuffer, &ClippedRegion ); ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.Flags &= ~CONSOLE_CONVERSION_AREA_REDRAW; } } } ConvAreaInfo = ConvAreaInfo->ConvAreaNext; } } BOOL ConsoleImeBottomLineUse( IN PSCREEN_INFORMATION ScreenInfo, IN SHORT ScrollOffset ) /*++ Routine Description: Arguments: ScreenInfo - ScrollOffset - Return Value: --*/ { SMALL_RECT ScrollRectangle; COORD DestinationOrigin; CHAR_INFO Fill; PCONVERSIONAREA_INFORMATION ConvAreaInfo; SMALL_RECT WriteRegion; BOOL fRedraw = FALSE; if (!(ScreenInfo->Console->ConsoleIme.ScrollFlag & HIDE_FOR_SCROLL)) { ScreenInfo->Console->ConsoleIme.ScrollFlag |= HIDE_FOR_SCROLL; if (ConvAreaInfo = ScreenInfo->Console->ConsoleIme.ConvAreaRoot) { do { if ((ConvAreaInfo->ConversionAreaMode & (CA_STATUS_LINE))==0) { ConvAreaInfo->ConversionAreaMode |= CA_HIDE_FOR_SCROLL; fRedraw = TRUE; } } while (ConvAreaInfo = ConvAreaInfo->ConvAreaNext); if (fRedraw) { // Check code for must CONSOLE_TEXTMODE_BUFFER !! if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { ASSERT(FALSE); } else { WriteRegion = ScreenInfo->Window; WriteRegion.Bottom--; ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; ScreenInfo->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; WriteToScreen(ScreenInfo,&WriteRegion); ScreenInfo->BufferInfo.TextInfo.Flags &= ~CONSOLE_CONVERSION_AREA_REDRAW; } } } } if (ScrollOffset) { ScrollRectangle.Top = 1; ScrollRectangle.Left = 0; ScrollRectangle.Right = ScreenInfo->ScreenBufferSize.X-1; ScrollRectangle.Bottom = ScreenInfo->ScreenBufferSize.Y-1; ScrollRectangle.Bottom -= (ScrollOffset-1); DestinationOrigin.X = ScrollRectangle.Left; DestinationOrigin.Y = ScrollRectangle.Top-1; Fill.Char.UnicodeChar = '\0'; Fill.Attributes = 0; ScrollRegion(ScreenInfo, &ScrollRectangle, NULL, DestinationOrigin, Fill ); #if defined(FE_SB) #if defined(FE_IME) if ( ! (ScreenInfo->Console->InputBuffer.ImeMode.Disable) && ! (ScreenInfo->Console->InputBuffer.ImeMode.Unavailable) && (ScreenInfo->Console->InputBuffer.ImeMode.Open) && (ScrollRectangle.Left == ScreenInfo->Window.Left) && (ScrollRectangle.Right == ScreenInfo->Window.Right) ) { ScrollRectangle.Top = ScreenInfo->Window.Bottom; ScrollRectangle.Bottom = ScreenInfo->Window.Bottom; WriteToScreen(ScreenInfo,&ScrollRectangle); WriteConvRegionToScreen(ScreenInfo, ScreenInfo->Console->ConsoleIme.ConvAreaRoot, &ScrollRectangle); } #endif #endif } else { ScreenInfo->Console->ConsoleIme.ScrollWaitCountDown = ScreenInfo->Console->ConsoleIme.ScrollWaitTimeout; } return TRUE; } VOID ConsoleImeBottomLineInUse( IN PSCREEN_INFORMATION ScreenInfo ) /*++ Routine Description: Arguments: ScreenInfo - Return Value: --*/ { PCONVERSIONAREA_INFORMATION ConvAreaInfo; SMALL_RECT WriteRegion; BOOL fRedraw = FALSE; COORD CursorPosition; ScreenInfo->Console->ConsoleIme.ScrollFlag &= ~HIDE_FOR_SCROLL; if (ConvAreaInfo = ScreenInfo->Console->ConsoleIme.ConvAreaRoot) { do { if (ConvAreaInfo->ConversionAreaMode & CA_HIDE_FOR_SCROLL) { ConvAreaInfo->ConversionAreaMode &= ~CA_HIDE_FOR_SCROLL; fRedraw = TRUE; } } while (ConvAreaInfo = ConvAreaInfo->ConvAreaNext); if (fRedraw) { // Check code for must CONSOLE_TEXTMODE_BUFFER !! if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { ASSERT(FALSE); } else { if (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y == (ScreenInfo->ScreenBufferSize.Y-1)) { ConsoleHideCursor(ScreenInfo); ConsoleImeBottomLineUse(ScreenInfo,1); CursorPosition = ScreenInfo->BufferInfo.TextInfo.CursorPosition; CursorPosition.Y--; SetCursorPosition(ScreenInfo,CursorPosition,TRUE); if (ScreenInfo->Console->lpCookedReadData) { ((PCOOKED_READ_DATA)(ScreenInfo->Console->lpCookedReadData))->OriginalCursorPosition.Y--; } ConsoleShowCursor(ScreenInfo); } else if (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y == ScreenInfo->Window.Bottom) { /* TODO: Fix this. */; } WriteRegion.Top = 0; WriteRegion.Bottom = (SHORT)(ScreenInfo->ScreenBufferSize.Y-1); WriteRegion.Left = 0; WriteRegion.Right = (SHORT)(ScreenInfo->ScreenBufferSize.X-1); ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; ScreenInfo->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; WriteToScreen(ScreenInfo,&WriteRegion); ScreenInfo->BufferInfo.TextInfo.Flags &= ~CONSOLE_CONVERSION_AREA_REDRAW; } } } } NTSTATUS CreateConvAreaUndetermine( PCONSOLE_INFORMATION Console ) { PCONSOLE_IME_INFORMATION ConsoleIme = &Console->ConsoleIme; NTSTATUS Status; COORD coordCaBuffer; SMALL_RECT rcViewCaWindow; COORD coordConView; PCONVERSIONAREA_INFORMATION ConvAreaInfo; if (ConsoleIme->ConvAreaCompStr) { ConsoleIme->ConvAreaCompStr = ConsoleHeapReAlloc( 0, ConsoleIme->ConvAreaCompStr, ConsoleHeapSize( ConsoleIme->ConvAreaCompStr)+sizeof(PCONVERSIONAREA_INFORMATION)); if (ConsoleIme->ConvAreaCompStr == NULL) return STATUS_NO_MEMORY; } else { ConsoleIme->ConvAreaCompStr = ConsoleHeapAlloc( CONVAREA_TAG, sizeof(PCONVERSIONAREA_INFORMATION)); if (ConsoleIme->ConvAreaCompStr == NULL) return STATUS_NO_MEMORY; } coordCaBuffer = Console->CurrentScreenBuffer->ScreenBufferSize; coordCaBuffer.Y = 1; rcViewCaWindow.Top = 0; rcViewCaWindow.Left = 0; rcViewCaWindow.Bottom = 0; rcViewCaWindow.Right = 0; coordConView.X = 0; coordConView.Y = 0; Status = SetUpConversionArea(Console, coordCaBuffer, rcViewCaWindow, coordConView, (Console->ConsoleIme.ScrollFlag & HIDE_FOR_SCROLL) ? CA_HIDE_FOR_SCROLL : CA_HIDDEN, &ConvAreaInfo ); if (!NT_SUCCESS(Status)) { return Status; } ConsoleIme->ConvAreaCompStr[ConsoleIme->NumberOfConvAreaCompStr] = ConvAreaInfo; ConsoleIme->NumberOfConvAreaCompStr++; return Status; } NTSTATUS CreateConvAreaModeSystem( PCONSOLE_INFORMATION Console ) { PCONSOLE_IME_INFORMATION ConsoleIme = &Console->ConsoleIme; NTSTATUS Status; COORD coordCaBuffer; SMALL_RECT rcViewCaWindow; COORD coordConView; PCONVERSIONAREA_INFORMATION ConvAreaInfo; if (Console->CurrentScreenBuffer == NULL) { return STATUS_UNSUCCESSFUL; } /* * Create mode text buffer */ coordCaBuffer = Console->CurrentScreenBuffer->ScreenBufferSize; coordCaBuffer.Y = 1; rcViewCaWindow.Top = 0; rcViewCaWindow.Left = 0; rcViewCaWindow.Bottom = 0; rcViewCaWindow.Right = 0; coordConView.X = 0; coordConView.Y = 0; Status = SetUpConversionArea(Console, coordCaBuffer, rcViewCaWindow, coordConView, CA_HIDDEN+CA_STATUS_LINE, &ConvAreaInfo ); if (!NT_SUCCESS(Status)) { return Status; } ConsoleIme->ConvAreaMode = ConvAreaInfo; /* * Create system text buffer */ Status = SetUpConversionArea(Console, coordCaBuffer, rcViewCaWindow, coordConView, CA_HIDDEN+CA_STATUS_LINE, &ConvAreaInfo ); if (!NT_SUCCESS(Status)) { return Status; } ConsoleIme->ConvAreaSystem = ConvAreaInfo; return Status; } #define LOCAL_BUFFER_SIZE 100 NTSTATUS WriteUndetermineChars( PCONSOLE_INFORMATION Console, LPWSTR lpString, PBYTE lpAtr, PWORD lpAtrIdx, DWORD NumChars // character count ) { PSCREEN_INFORMATION ScreenInfo; PSCREEN_INFORMATION ConvScreenInfo; WCHAR LocalBuffer[LOCAL_BUFFER_SIZE]; BYTE LocalBufferA[LOCAL_BUFFER_SIZE]; PWCHAR LocalBufPtr; PBYTE LocalBufPtrA; DWORD BufferSize; COORD Position; ULONG i; SMALL_RECT Region; COORD CursorPosition; WCHAR Char; WORD Attr; PCONSOLE_IME_INFORMATION ConsoleIme; PCONVERSIONAREA_INFORMATION ConvAreaInfo; DWORD ConvAreaIndex; NTSTATUS Status; ULONG NumStr; int WholeLen; int WholeRow; SHORT PosY; BOOL UndetAreaUp = FALSE; ConsoleIme = &Console->ConsoleIme; ScreenInfo = Console->CurrentScreenBuffer; // Check code for must CONSOLE_TEXTMODE_BUFFER !! ASSERT(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)); Position = ScreenInfo->BufferInfo.TextInfo.CursorPosition; if ((ScreenInfo->Window.Left <= Position.X && Position.X <= ScreenInfo->Window.Right) && (ScreenInfo->Window.Top <= Position.Y && Position.Y <= ScreenInfo->Window.Bottom) ) { Position.X = ScreenInfo->BufferInfo.TextInfo.CursorPosition.X - ScreenInfo->Window.Left; Position.Y = ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y - ScreenInfo->Window.Top; } else { Position.X = 0; Position.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo) - 2; } PosY = Position.Y; RtlUnicodeToMultiByteSize(&NumStr, lpString, NumChars*sizeof(WCHAR)); WholeLen = (int)Position.X + (int)NumStr; WholeRow = WholeLen / CONSOLE_WINDOW_SIZE_X(ScreenInfo); if ( ( PosY + WholeRow ) > ( CONSOLE_WINDOW_SIZE_Y(ScreenInfo) - 2) ) { PosY = CONSOLE_WINDOW_SIZE_Y(ScreenInfo) - 2 - WholeRow; if (PosY < 0) { PosY = ScreenInfo->Window.Top; } } if (PosY != Position.Y) { Position.Y = PosY; UndetAreaUp = TRUE; } ConvAreaIndex = 0; BufferSize = NumChars; NumChars = 0; for (ConvAreaIndex = 0; NumChars < BufferSize; ConvAreaIndex++) { if (ConvAreaIndex+1 > ConsoleIme->NumberOfConvAreaCompStr) { Status = CreateConvAreaUndetermine(Console); if (!NT_SUCCESS(Status)) { return Status; } } ConvAreaInfo = ConsoleIme->ConvAreaCompStr[ConvAreaIndex]; ConvScreenInfo = ConvAreaInfo->ScreenBuffer; ConvScreenInfo->BufferInfo.TextInfo.CursorPosition.X = Position.X; if ((ConvAreaInfo->ConversionAreaMode & CA_HIDDEN) || (UndetAreaUp)) { /* * This conversion area need positioning onto cursor position. */ CursorPosition.X = 0; CursorPosition.Y = (SHORT)(Position.Y + ConvAreaIndex); ConsoleImeViewInfo(Console,ConvAreaInfo,CursorPosition); } Region.Left = ConvScreenInfo->BufferInfo.TextInfo.CursorPosition.X; Region.Top = 0; Region.Bottom = 0; while (NumChars < BufferSize) { i=0; LocalBufPtr = LocalBuffer; LocalBufPtrA = LocalBufferA; while (NumChars < BufferSize && i < LOCAL_BUFFER_SIZE && Position.X < CONSOLE_WINDOW_SIZE_X(ScreenInfo)) { Char = *lpString; Attr = *lpAtr; if (Char >= (WCHAR)' ') { if (IsConsoleFullWidth(Console->hDC,Console->OutputCP,Char)) { if (i < (LOCAL_BUFFER_SIZE-1) && Position.X < CONSOLE_WINDOW_SIZE_X(ScreenInfo)-1) { *LocalBufPtr++ = Char; *LocalBufPtrA++ = ATTR_LEADING_BYTE; *LocalBufPtr++ = Char; *LocalBufPtrA++ = ATTR_TRAILING_BYTE; Position.X+=2; i+=2; } else { Position.X++; break; } } else { *LocalBufPtr++ = Char; *LocalBufPtrA++ = 0; Position.X++; i++; } } lpString++; lpAtr++; NumChars++; if (NumChars < BufferSize && Attr != *lpAtr) break; } if (i != 0) { ConvScreenInfo->Attributes = lpAtrIdx[Attr & 0x07]; if (Attr & 0x10) { ConvScreenInfo->Attributes |= (COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_RVERTICAL); } else if (Attr & 0x20) { ConvScreenInfo->Attributes |= (COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_LVERTICAL); } StreamWriteToScreenBufferIME(LocalBuffer, (SHORT)i, ConvScreenInfo, LocalBufferA); ConvScreenInfo->BufferInfo.TextInfo.CursorPosition.X += (SHORT)i; if (NumChars == BufferSize || Position.X >= CONSOLE_WINDOW_SIZE_X(ScreenInfo) || ( (Char >= (WCHAR)' ' && IsConsoleFullWidth(Console->hDC,Console->OutputCP,Char) && Position.X >= CONSOLE_WINDOW_SIZE_X(ScreenInfo)-1) ) ) { Region.Right = (SHORT)(ConvScreenInfo->BufferInfo.TextInfo.CursorPosition.X - 1); ConsoleImeWindowInfo(Console,ConvAreaInfo,Region); ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); Position.X = 0; break; } if (NumChars == BufferSize) { return STATUS_SUCCESS; } continue; } else if (NumChars == BufferSize) { return STATUS_SUCCESS; } if (!NT_SUCCESS(Status)) { return Status; } if (Position.X >= CONSOLE_WINDOW_SIZE_X(ScreenInfo)) { Position.X = 0; break; } } } for (; ConvAreaIndex < ConsoleIme->NumberOfConvAreaCompStr; ConvAreaIndex++) { ConvAreaInfo = ConsoleIme->ConvAreaCompStr[ConvAreaIndex]; if (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN)) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); } } return STATUS_SUCCESS; } VOID WriteModeSystemChars( PCONSOLE_INFORMATION Console, PCONVERSIONAREA_INFORMATION ConvAreaInfo, PCHAR_INFO Buffer, DWORD NumberOfChars, DWORD ViewPosition ) { SMALL_RECT CharRegion; COORD CursorPosition; if (Buffer) { CharRegion.Left = 0; CharRegion.Top = 0; CharRegion.Right = CalcWideCharToColumn(Console,Buffer,NumberOfChars); CharRegion.Right = (CharRegion.Right ? CharRegion.Right-1 : 0); CharRegion.Bottom = 0; } else { CharRegion = ConvAreaInfo->CaInfo.rcViewCaWindow; } if (ConvAreaInfo) { if (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN)) { if (CharRegion.Left != ConvAreaInfo->CaInfo.rcViewCaWindow.Left || CharRegion.Top != ConvAreaInfo->CaInfo.rcViewCaWindow.Top || CharRegion.Right != ConvAreaInfo->CaInfo.rcViewCaWindow.Right || CharRegion.Bottom != ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom) { switch (ViewPosition) { case VIEW_LEFT: CursorPosition.X = 0; break; case VIEW_RIGHT: CursorPosition.X = CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer) - (CharRegion.Right + 1); break; } CursorPosition.Y = CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer) - 1; ConsoleImeViewInfo(Console,ConvAreaInfo,CursorPosition); ConsoleImeWindowInfo(Console,ConvAreaInfo,CharRegion); } } else { /* * This conversion area need positioning onto cursor position. */ switch (ViewPosition) { case VIEW_LEFT: CursorPosition.X = 0; break; case VIEW_RIGHT: CursorPosition.X = CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer) - (CharRegion.Right + 1); break; } CursorPosition.Y = CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer) - 1; ConsoleImeViewInfo(Console,ConvAreaInfo,CursorPosition); ConsoleImeWindowInfo(Console,ConvAreaInfo,CharRegion); } if (Buffer) { ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; ConsoleImeWriteOutput(Console,ConvAreaInfo,Buffer,CharRegion,TRUE); } else { ConsoleImePaint(Console,ConvAreaInfo); } } } NTSTATUS FillUndetermineChars( PCONSOLE_INFORMATION Console, PCONVERSIONAREA_INFORMATION ConvAreaInfo ) { COORD Coord; DWORD CharsToWrite; ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; Coord.X = 0; Coord.Y = 0; CharsToWrite = ConvAreaInfo->ScreenBuffer->ScreenBufferSize.X; FillOutput(ConvAreaInfo->ScreenBuffer, (WCHAR)' ', Coord, CONSOLE_FALSE_UNICODE, // faster than real unicode &CharsToWrite ); CharsToWrite = ConvAreaInfo->ScreenBuffer->ScreenBufferSize.X; FillOutput(ConvAreaInfo->ScreenBuffer, Console->CurrentScreenBuffer->Attributes, Coord, CONSOLE_ATTRIBUTE, &CharsToWrite ); ConsoleImePaint(Console,ConvAreaInfo); return STATUS_SUCCESS; } NTSTATUS ConsoleImeCompStr( IN PCONSOLE_INFORMATION Console, IN LPCONIME_UICOMPMESSAGE CompStr ) { UINT i; PCONVERSIONAREA_INFORMATION ConvAreaInfo; if (CompStr->dwCompStrLen == 0 || CompStr->dwResultStrLen != 0 ) { // Cursor turn ON. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) && Console->ConsoleIme.SavedCursorVisible ) { Console->ConsoleIme.SavedCursorVisible = FALSE; SetCursorInformation(Console->CurrentScreenBuffer, Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorSize, TRUE); } /* * Determine string. */ for (i=0; iConsoleIme.NumberOfConvAreaCompStr; i++) { ConvAreaInfo = Console->ConsoleIme.ConvAreaCompStr[i]; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { FillUndetermineChars(Console,ConvAreaInfo); } } if (CompStr->dwResultStrLen != 0) { if (!InsertConverTedString(Console, (LPWSTR)((PBYTE)CompStr + CompStr->dwResultStrOffset))) { return STATUS_INVALID_HANDLE; } } if (Console->ConsoleIme.CompStrData) { ConsoleHeapFree(Console->ConsoleIme.CompStrData); Console->ConsoleIme.CompStrData = NULL; } } else { LPWSTR lpStr; PBYTE lpAtr; PWORD lpAtrIdx; // Cursor turn OFF. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) && Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorVisible ) { Console->ConsoleIme.SavedCursorVisible = TRUE; SetCursorInformation(Console->CurrentScreenBuffer, Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorSize, FALSE); } /* * Composition string. */ for (i=0; iConsoleIme.NumberOfConvAreaCompStr; i++) { ConvAreaInfo = Console->ConsoleIme.ConvAreaCompStr[i]; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { FillUndetermineChars(Console,ConvAreaInfo); } } lpStr = (LPWSTR)((PBYTE)CompStr + CompStr->dwCompStrOffset); lpAtr = (PBYTE)CompStr + CompStr->dwCompAttrOffset; lpAtrIdx = (PWORD)CompStr->CompAttrColor; WriteUndetermineChars(Console, lpStr, lpAtr, lpAtrIdx, CompStr->dwCompStrLen / sizeof(WCHAR)); } return STATUS_SUCCESS; } NTSTATUS ConsoleImeResizeModeSystemView( PCONSOLE_INFORMATION Console, SMALL_RECT WindowRect ) { PCONVERSIONAREA_INFORMATION ConvAreaInfo; SMALL_RECT CharRegion; COORD CursorPosition; /* * Mode string */ ConvAreaInfo = Console->ConsoleIme.ConvAreaMode; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); CharRegion = ConvAreaInfo->CaInfo.rcViewCaWindow; if (Console->ConsoleIme.ConvAreaModePosition == VIEW_LEFT){ CursorPosition.X = 0; } else{ CursorPosition.X = CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer) - (CharRegion.Right + 1); } CursorPosition.Y = CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer) - 1; ConsoleImeViewInfo(Console,ConvAreaInfo,CursorPosition); ConsoleImeWindowInfo(Console,ConvAreaInfo,CharRegion); ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; WriteModeSystemChars(Console, Console->ConsoleIme.ConvAreaMode, NULL, 0, Console->ConsoleIme.ConvAreaModePosition); } /* * System string */ ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); CharRegion = ConvAreaInfo->CaInfo.rcViewCaWindow; CursorPosition.X = 0; CursorPosition.Y = CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer) - 1; ConsoleImeViewInfo(Console,ConvAreaInfo,CursorPosition); ConsoleImeWindowInfo(Console,ConvAreaInfo,CharRegion); ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; WriteModeSystemChars(Console, Console->ConsoleIme.ConvAreaSystem, NULL, 0, VIEW_LEFT); } return STATUS_SUCCESS; UNREFERENCED_PARAMETER(WindowRect); } NTSTATUS ConsoleImeResizeCompStrView( PCONSOLE_INFORMATION Console, SMALL_RECT WindowRect ) { UINT i; PCONVERSIONAREA_INFORMATION ConvAreaInfo; LPCONIME_UICOMPMESSAGE CompStr; LPWSTR lpStr; PBYTE lpAtr; PWORD lpAtrIdx; /* * Compositon string */ CompStr = Console->ConsoleIme.CompStrData; if (CompStr) { for (i=0; iConsoleIme.NumberOfConvAreaCompStr; i++) { ConvAreaInfo = Console->ConsoleIme.ConvAreaCompStr[i]; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { FillUndetermineChars(Console,ConvAreaInfo); } } lpStr = (LPWSTR)((PBYTE)CompStr + CompStr->dwCompStrOffset); lpAtr = (PBYTE)CompStr + CompStr->dwCompAttrOffset; lpAtrIdx = (PWORD)CompStr->CompAttrColor; WriteUndetermineChars(Console, lpStr, lpAtr, lpAtrIdx, CompStr->dwCompStrLen / sizeof(WCHAR)); } return STATUS_SUCCESS; UNREFERENCED_PARAMETER(WindowRect); } NTSTATUS ConsoleImeResizeModeSystemScreenBuffer( PCONSOLE_INFORMATION Console, COORD NewScreenSize ) { NTSTATUS Status; PCONVERSIONAREA_INFORMATION ConvAreaInfo; /* * Mode string */ ConvAreaInfo = Console->ConsoleIme.ConvAreaMode; if (ConvAreaInfo) { if (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN)) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; } Status = ConsoleImeResizeScreenBuffer(ConvAreaInfo->ScreenBuffer,NewScreenSize,ConvAreaInfo); if (! NT_SUCCESS(Status)) return Status; } /* * System string */ ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem; if (ConvAreaInfo) { if (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN)) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; } Status = ConsoleImeResizeScreenBuffer(ConvAreaInfo->ScreenBuffer,NewScreenSize,ConvAreaInfo); if (! NT_SUCCESS(Status)) return Status; } return STATUS_SUCCESS; } NTSTATUS ConsoleImeResizeCompStrScreenBuffer( PCONSOLE_INFORMATION Console, COORD NewScreenSize ) { NTSTATUS Status; UINT i; PCONVERSIONAREA_INFORMATION ConvAreaInfo; /* * Compositon string */ for (i=0; iConsoleIme.NumberOfConvAreaCompStr; i++) { ConvAreaInfo = Console->ConsoleIme.ConvAreaCompStr[i]; if (ConvAreaInfo) { if (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN)) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); } Status = ConsoleImeResizeScreenBuffer(ConvAreaInfo->ScreenBuffer,NewScreenSize,ConvAreaInfo); if (! NT_SUCCESS(Status)) return Status; } } return STATUS_SUCCESS; } SHORT CalcWideCharToColumn( IN PCONSOLE_INFORMATION Console, IN PCHAR_INFO Buffer, IN DWORD NumberOfChars ) { SHORT Column = 0; while (NumberOfChars--) { if (IsConsoleFullWidth(Console->hDC,Console->OutputCP,Buffer->Char.UnicodeChar)) Column += 2; else Column++; Buffer++; } return Column; } LONG ConsoleImePaint( IN PCONSOLE_INFORMATION Console, IN PCONVERSIONAREA_INFORMATION ConvAreaInfo ) /*++ This routine --*/ { PSCREEN_INFORMATION ScreenInfo; SMALL_RECT WriteRegion; COORD CursorPosition; if (!ConvAreaInfo) return FALSE; ScreenInfo = Console->CurrentScreenBuffer; if (!ScreenInfo) return FALSE; // Check code for must CONSOLE_TEXTMODE_BUFFER !! ASSERT(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)); WriteRegion.Left = ScreenInfo->Window.Left + ConvAreaInfo->CaInfo.coordConView.X + ConvAreaInfo->CaInfo.rcViewCaWindow.Left; WriteRegion.Right = WriteRegion.Left + (ConvAreaInfo->CaInfo.rcViewCaWindow.Right - ConvAreaInfo->CaInfo.rcViewCaWindow.Left); WriteRegion.Top = ScreenInfo->Window.Top + ConvAreaInfo->CaInfo.coordConView.Y + ConvAreaInfo->CaInfo.rcViewCaWindow.Top; WriteRegion.Bottom = WriteRegion.Top + (ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom - ConvAreaInfo->CaInfo.rcViewCaWindow.Top); if ((ConvAreaInfo->ConversionAreaMode & (CA_HIDDEN+CA_STATUS_LINE))==(CA_STATUS_LINE)) { if (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y == (ScreenInfo->ScreenBufferSize.Y-1)) { ConsoleHideCursor(ScreenInfo); ConsoleImeBottomLineUse(ScreenInfo,1); CursorPosition = ScreenInfo->BufferInfo.TextInfo.CursorPosition; CursorPosition.Y--; SetCursorPosition(ScreenInfo,CursorPosition,TRUE); if (ScreenInfo->Console->lpCookedReadData) { ((PCOOKED_READ_DATA)(ScreenInfo->Console->lpCookedReadData))->OriginalCursorPosition.Y--; } ConsoleShowCursor(ScreenInfo); } else if (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y == ScreenInfo->Window.Bottom) { WriteRegion.Top = ScreenInfo->Window.Top + ConvAreaInfo->CaInfo.coordConView.Y + ConvAreaInfo->CaInfo.rcViewCaWindow.Top; WriteRegion.Bottom = WriteRegion.Top + (ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom - ConvAreaInfo->CaInfo.rcViewCaWindow.Top); } } ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; ScreenInfo->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; if (!(ConvAreaInfo->ConversionAreaMode & (CA_HIDDEN | CA_HIDE_FOR_SCROLL))) { WriteConvRegionToScreen(ScreenInfo, ConvAreaInfo, &WriteRegion ); } else { WriteToScreen(ScreenInfo,&WriteRegion); } ScreenInfo->BufferInfo.TextInfo.Flags &= ~CONSOLE_CONVERSION_AREA_REDRAW; return TRUE; } VOID ConsoleImeViewInfo( IN PCONSOLE_INFORMATION Console, IN PCONVERSIONAREA_INFORMATION ConvAreaInfo, IN COORD coordConView ) { SMALL_RECT OldRegion; SMALL_RECT NewRegion; if (ConvAreaInfo->ConversionAreaMode & CA_HIDDEN) { ConvAreaInfo->CaInfo.coordConView = coordConView; NewRegion = ConvAreaInfo->CaInfo.rcViewCaWindow; NewRegion.Left += ConvAreaInfo->CaInfo.coordConView.X; NewRegion.Right += ConvAreaInfo->CaInfo.coordConView.X; NewRegion.Top += ConvAreaInfo->CaInfo.coordConView.Y; NewRegion.Bottom += ConvAreaInfo->CaInfo.coordConView.Y; } else { OldRegion = ConvAreaInfo->CaInfo.rcViewCaWindow; OldRegion.Left += ConvAreaInfo->CaInfo.coordConView.X; OldRegion.Right += ConvAreaInfo->CaInfo.coordConView.X; OldRegion.Top += ConvAreaInfo->CaInfo.coordConView.Y; OldRegion.Bottom += ConvAreaInfo->CaInfo.coordConView.Y; ConvAreaInfo->CaInfo.coordConView = coordConView; // Check code for must CONSOLE_TEXTMODE_BUFFER !! ASSERT(!(Console->CurrentScreenBuffer->Flags & CONSOLE_GRAPHICS_BUFFER)); Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags |= CONSOLE_CONVERSION_AREA_REDRAW; WriteToScreen(Console->CurrentScreenBuffer,&OldRegion); NewRegion = ConvAreaInfo->CaInfo.rcViewCaWindow; NewRegion.Left += ConvAreaInfo->CaInfo.coordConView.X; NewRegion.Right += ConvAreaInfo->CaInfo.coordConView.X; NewRegion.Top += ConvAreaInfo->CaInfo.coordConView.Y; NewRegion.Bottom += ConvAreaInfo->CaInfo.coordConView.Y; Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; WriteToScreen(Console->CurrentScreenBuffer,&NewRegion); Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~CONSOLE_CONVERSION_AREA_REDRAW; } } VOID ConsoleImeWindowInfo( IN PCONSOLE_INFORMATION Console, IN PCONVERSIONAREA_INFORMATION ConvAreaInfo, IN SMALL_RECT rcViewCaWindow ) { if (rcViewCaWindow.Left != ConvAreaInfo->CaInfo.rcViewCaWindow.Left || rcViewCaWindow.Top != ConvAreaInfo->CaInfo.rcViewCaWindow.Top || rcViewCaWindow.Right != ConvAreaInfo->CaInfo.rcViewCaWindow.Right || rcViewCaWindow.Bottom != ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom) { if (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN)) { ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImePaint(Console,ConvAreaInfo); ConvAreaInfo->CaInfo.rcViewCaWindow = rcViewCaWindow; ConvAreaInfo->ConversionAreaMode &= ~CA_HIDDEN; ConvAreaInfo->ScreenBuffer->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT | BISECT_TOP | BISECT_BOTTOM); ConsoleImePaint(Console,ConvAreaInfo); } else ConvAreaInfo->CaInfo.rcViewCaWindow = rcViewCaWindow; } } NTSTATUS ConsoleImeResizeScreenBuffer( IN PSCREEN_INFORMATION ScreenInfo, IN COORD NewScreenSize, PCONVERSIONAREA_INFORMATION ConvAreaInfo ) { NTSTATUS Status; Status = ResizeScreenBuffer(ScreenInfo, NewScreenSize, FALSE); if (NT_SUCCESS(Status)) { ConvAreaInfo->CaInfo.coordCaBuffer = NewScreenSize; if (ConvAreaInfo->CaInfo.rcViewCaWindow.Left > NewScreenSize.X-1) ConvAreaInfo->CaInfo.rcViewCaWindow.Left = NewScreenSize.X-1; if (ConvAreaInfo->CaInfo.rcViewCaWindow.Right > NewScreenSize.X-1) ConvAreaInfo->CaInfo.rcViewCaWindow.Right = NewScreenSize.X-1; if (ConvAreaInfo->CaInfo.rcViewCaWindow.Top > NewScreenSize.Y-1) ConvAreaInfo->CaInfo.rcViewCaWindow.Top = NewScreenSize.Y-1; if (ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom > NewScreenSize.Y-1) ConvAreaInfo->CaInfo.rcViewCaWindow.Bottom = NewScreenSize.Y-1; } return Status; } NTSTATUS ConsoleImeWriteOutput( IN PCONSOLE_INFORMATION Console, IN PCONVERSIONAREA_INFORMATION ConvAreaInfo, IN PCHAR_INFO Buffer, IN SMALL_RECT CharRegion, IN BOOL fUnicode ) { NTSTATUS Status; PSCREEN_INFORMATION ScreenInfo; COORD BufferSize; SMALL_RECT ConvRegion; COORD CursorPosition; BufferSize.X = (SHORT)(CharRegion.Right - CharRegion.Left + 1); BufferSize.Y = (SHORT)(CharRegion.Bottom - CharRegion.Top + 1); ConvRegion = CharRegion; ScreenInfo = ConvAreaInfo->ScreenBuffer; if (!fUnicode) { TranslateOutputToUnicode(Console, Buffer, BufferSize ); Status = WriteScreenBuffer(ScreenInfo, Buffer, &ConvRegion ); } else { CHAR_INFO StackBuffer[STACK_BUFFER_SIZE * 2]; PCHAR_INFO TransBuffer; BOOL StackBufferF = FALSE; if (BufferSize.Y * BufferSize.X <= STACK_BUFFER_SIZE) { TransBuffer = StackBuffer; StackBufferF = TRUE; } else { TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, (BufferSize.Y * BufferSize.X) * 2 * sizeof(CHAR_INFO)); if (TransBuffer == NULL) { return STATUS_NO_MEMORY; } } if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { TranslateOutputToAnsiUnicode(Console, Buffer, BufferSize, &TransBuffer[0] ); } else { TranslateOutputToPaddingUnicode(Console, Buffer, BufferSize, &TransBuffer[0] ); } Status = WriteScreenBuffer(ScreenInfo, &TransBuffer[0], &ConvRegion ); if (!StackBufferF) ConsoleHeapFree(TransBuffer); } if (NT_SUCCESS(Status)) { ScreenInfo = Console->CurrentScreenBuffer; // Check code for must CONSOLE_TEXTMODE_BUFFER !! if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { ASSERT(FALSE); } else if ((ConvAreaInfo->ConversionAreaMode & (CA_HIDDEN+CA_STATUS_LINE))==(CA_STATUS_LINE)) { if (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y == (ScreenInfo->ScreenBufferSize.Y-1) ) { ConsoleHideCursor(ScreenInfo); ConsoleImeBottomLineUse(ScreenInfo,1); CursorPosition = ScreenInfo->BufferInfo.TextInfo.CursorPosition; CursorPosition.Y--; SetCursorPosition(ScreenInfo,CursorPosition,TRUE); if (ScreenInfo->Console->lpCookedReadData) { ((PCOOKED_READ_DATA)(ScreenInfo->Console->lpCookedReadData))->OriginalCursorPosition.Y--; } ConsoleShowCursor(ScreenInfo); } else if (ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y == ScreenInfo->Window.Bottom) { COORD WindowOrigin; WindowOrigin.X = ScreenInfo->Window.Left; WindowOrigin.Y = ScreenInfo->Window.Top+1; SetWindowOrigin(ScreenInfo, TRUE, WindowOrigin); if ( ! (ScreenInfo->Console->InputBuffer.ImeMode.Disable) && ! (ScreenInfo->Console->InputBuffer.ImeMode.Unavailable) && (ScreenInfo->Console->InputBuffer.ImeMode.Open) ) { SMALL_RECT Rectangle; Rectangle.Left = ScreenInfo->Window.Left; Rectangle.Right = ScreenInfo->Window.Right; Rectangle.Top = ScreenInfo->Window.Bottom; Rectangle.Bottom = ScreenInfo->Window.Bottom; ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; WriteToScreen(ScreenInfo,&Rectangle); ScreenInfo->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; WriteConvRegionToScreen(ScreenInfo, ScreenInfo->Console->ConsoleIme.ConvAreaRoot, &Rectangle); } } } // // cause screen to be updated // ConvRegion.Left += (ScreenInfo->Window.Left + ConvAreaInfo->CaInfo.coordConView.X); ConvRegion.Right += (ScreenInfo->Window.Left + ConvAreaInfo->CaInfo.coordConView.X); ConvRegion.Top += (ScreenInfo->Window.Top + ConvAreaInfo->CaInfo.coordConView.Y); ConvRegion.Bottom += (ScreenInfo->Window.Top + ConvAreaInfo->CaInfo.coordConView.Y); // Check code for must CONSOLE_TEXTMODE_BUFFER !! if (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER) { ASSERT(FALSE); } else ScreenInfo->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; WriteConvRegionToScreen(ScreenInfo, ConvAreaInfo, &ConvRegion ); ConvAreaInfo->ScreenBuffer->BisectFlag &= ~(BISECT_LEFT | BISECT_RIGHT | BISECT_TOP | BISECT_BOTTOM); } return Status; } NTSTATUS ImeControl( IN PCONSOLE_INFORMATION Console, IN HWND hWndConsoleIME, IN PCOPYDATASTRUCT lParam ) /*++ Routine Description: This routine handle WM_COPYDATA message. Arguments: Console - Pointer to console information structure. wParam - lParam - Return Value: --*/ { PSCREEN_INFORMATION ScreenInfo; PCONVERSIONAREA_INFORMATION ConvAreaInfo; PCHAR_INFO SystemString; DWORD i, j; if (lParam == NULL) { // fail safe. return STATUS_SUCCESS; } ScreenInfo = Console->CurrentScreenBuffer; switch ((LONG)lParam->dwData) { case CI_CONIMECOMPOSITION: if (lParam->cbData >= sizeof(CONIME_UICOMPMESSAGE)) { LPCONIME_UICOMPMESSAGE CompStr; DBGPRINT(("CONSRV: Get IR_CONIMECOMPOSITION Message\n")); CompStr = (LPCONIME_UICOMPMESSAGE)lParam->lpData; if (CompStr && CompStr->dwSize == lParam->cbData) { if (Console->ConsoleIme.CompStrData) ConsoleHeapFree(Console->ConsoleIme.CompStrData); Console->ConsoleIme.CompStrData = ConsoleHeapAlloc( IME_TAG, CompStr->dwSize); if (Console->ConsoleIme.CompStrData == NULL) break; memmove(Console->ConsoleIme.CompStrData,CompStr,CompStr->dwSize); ConsoleImeCompStr(Console, Console->ConsoleIme.CompStrData); } } break; case CI_CONIMEMODEINFO: if (lParam->cbData == sizeof(CONIME_UIMODEINFO)) { LPCONIME_UIMODEINFO lpModeInfo; DBGPRINT(("CONSRV: Get IR_CONIMEMODEINFO Message\n")); lpModeInfo = (LPCONIME_UIMODEINFO)lParam->lpData; if (lpModeInfo != NULL) { if (! Console->InputBuffer.ImeMode.Disable) { if (lpModeInfo->ModeStringLen != 0){ for (j = 0; j < lpModeInfo->ModeStringLen; j++ ) lpModeInfo->ModeString[j].Attributes = Console->CurrentScreenBuffer->Attributes; Console->ConsoleIme.ConvAreaModePosition = lpModeInfo->Position; WriteModeSystemChars(Console, Console->ConsoleIme.ConvAreaMode, (PCHAR_INFO)&lpModeInfo->ModeString, lpModeInfo->ModeStringLen, Console->ConsoleIme.ConvAreaModePosition); } else{ ConvAreaInfo = Console->ConsoleIme.ConvAreaMode; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { FillUndetermineChars(Console,ConvAreaInfo); } ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { FillUndetermineChars(Console,ConvAreaInfo); } } } } } break; case CI_CONIMESYSINFO: { PWCHAR SourceString; DBGPRINT(("CONSRV: Get IR_CONIMESYSINFO Message\n")); if ((lParam->cbData != 0) && (lParam->lpData != NULL) && (! Console->InputBuffer.ImeMode.Disable)) { i = (lParam->cbData / sizeof(WCHAR))-1; SourceString = ((LPCONIME_UIMESSAGE)(lParam->lpData))->String; SystemString = ConsoleHeapAlloc(IME_TAG, sizeof(CHAR_INFO) * i); if (SystemString == NULL) { break; } for (j = 0; j < i; j++ ) { SystemString[j].Char.UnicodeChar = *SourceString; SystemString[j].Attributes = Console->CurrentScreenBuffer->Attributes; SourceString++; } WriteModeSystemChars(Console, Console->ConsoleIme.ConvAreaSystem, (PCHAR_INFO)SystemString, i, VIEW_LEFT); ConsoleHeapFree(SystemString); } else { ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem; if (ConvAreaInfo && (!(ConvAreaInfo->ConversionAreaMode & CA_HIDDEN))) { FillUndetermineChars(Console,ConvAreaInfo); } } break; } case CI_CONIMECANDINFO:{ PWCHAR SourceString; PUCHAR SourceAttr; DWORD LengthToWrite; LPCONIME_CANDMESSAGE CandInfo = (LPCONIME_CANDMESSAGE)(lParam->lpData); DBGPRINT(("CONSRV: Get IR_CONIMESYSINFO Message\n")); if ((lParam->cbData != 0) && (CandInfo != NULL) ){ SourceString = CandInfo->String; SourceAttr = (PUCHAR)((PBYTE)CandInfo + CandInfo->AttrOff); LengthToWrite = lstrlenW(SourceString); SystemString = ConsoleHeapAlloc(IME_TAG, sizeof(CHAR_INFO) * LengthToWrite); if (SystemString == NULL) { break; } for (j = 0; j < LengthToWrite; j++ ) { SystemString[j].Char.UnicodeChar = *SourceString; if (*SourceAttr == 1 && Console->ConsoleIme.CompStrData != NULL) { SystemString[j].Attributes = Console->ConsoleIme.CompStrData->CompAttrColor[1]; } else { SystemString[j].Attributes = Console->CurrentScreenBuffer->Attributes; } SourceString++; SourceAttr++; } WriteModeSystemChars(Console, Console->ConsoleIme.ConvAreaSystem, (PCHAR_INFO)SystemString, LengthToWrite, VIEW_LEFT); ConsoleHeapFree(SystemString); } else { ConvAreaInfo = Console->ConsoleIme.ConvAreaSystem; if (ConvAreaInfo) { SMALL_RECT rcViewCaWindow = {0, 0, 0, 0}; FillUndetermineChars(Console,ConvAreaInfo); ConvAreaInfo->ConversionAreaMode |= CA_HIDDEN; ConsoleImeWindowInfo(Console,ConvAreaInfo,rcViewCaWindow); } } break; } case CI_CONIMEPROPERTYINFO:{ WPARAM* wParam = (WPARAM*)(lParam->lpData); if ((lParam->cbData != 0) && (wParam != NULL) ){ switch (*wParam) { case IMS_OPENPROPERTYWINDOW: Console->InputBuffer.hWndConsoleIME = hWndConsoleIME; break; case IMS_CLOSEPROPERTYWINDOW: Console->InputBuffer.hWndConsoleIME = NULL; SetFocus(Console->hWnd); break; } } break; } } return STATUS_SUCCESS; } BOOL InsertConverTedString( IN PCONSOLE_INFORMATION Console, LPWSTR lpStr ) { ULONG EventsWritten; PINPUT_RECORD InputEvent,TmpInputEvent; DWORD dwControlKeyState; DWORD dwLen; DWORD dwConversion; BOOL fResult = FALSE; // Check code for must CONSOLE_TEXTMODE_BUFFER !! if (Console->CurrentScreenBuffer->Flags & CONSOLE_GRAPHICS_BUFFER) { ASSERT(FALSE); } else if(Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorOn){ CursorTimerRoutine(Console->CurrentScreenBuffer); } dwLen = wcslen(lpStr)+1; InputEvent = ConsoleHeapAlloc(IME_TAG, sizeof(INPUT_RECORD)*dwLen); if (InputEvent == NULL) { return FALSE; } TmpInputEvent = InputEvent; dwControlKeyState = GetControlKeyState(0); if (!NT_SUCCESS(GetImeKeyState(Console, &dwConversion))) { goto skip_and_return; } dwControlKeyState |= ImmConversionToConsole(dwConversion); while (*lpStr) { TmpInputEvent->EventType = KEY_EVENT; TmpInputEvent->Event.KeyEvent.bKeyDown = TRUE; TmpInputEvent->Event.KeyEvent.wVirtualKeyCode = 0; TmpInputEvent->Event.KeyEvent.wVirtualScanCode = 0; TmpInputEvent->Event.KeyEvent.dwControlKeyState = dwControlKeyState; TmpInputEvent->Event.KeyEvent.uChar.UnicodeChar = *lpStr++; TmpInputEvent->Event.KeyEvent.wRepeatCount = 1; TmpInputEvent++; } EventsWritten = WriteInputBuffer( Console, &Console->InputBuffer, InputEvent, dwLen-1 ); fResult = TRUE; skip_and_return: ConsoleHeapFree(InputEvent); return fResult; } VOID SetUndetermineAttribute( IN PCONSOLE_INFORMATION Console ) { PSCREEN_INFORMATION ScreenInfo; PCONVERSIONAREA_INFORMATION ConvAreaInfo; ScreenInfo = Console->CurrentScreenBuffer; ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot; if (ConvAreaInfo != NULL) { do { ConvAreaInfo->ScreenBuffer->Attributes = ScreenInfo->Attributes; ConvAreaInfo = ConvAreaInfo->ConvAreaNext; } while (ConvAreaInfo != NULL); } if (Console->ConsoleIme.ConvAreaMode != NULL) { Console->ConsoleIme.ConvAreaMode->ScreenBuffer->Attributes = ScreenInfo->Attributes; } if (Console->ConsoleIme.ConvAreaSystem != NULL) { Console->ConsoleIme.ConvAreaSystem->ScreenBuffer->Attributes = ScreenInfo->Attributes; } } VOID StreamWriteToScreenBufferIME( IN PWCHAR String, IN SHORT StringLength, IN PSCREEN_INFORMATION ScreenInfo, IN PCHAR StringA ) { SHORT RowIndex; PROW Row; PWCHAR Char; COORD TargetPoint; DBGOUTPUT(("StreamWriteToScreenBuffer\n")); // Check code for must CONSOLE_TEXTMODE_BUFFER !! ASSERT(!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)); 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 = %lx, Row = %lx, TargetPoint = (%d,%d)\n", RowIndex, Row, TargetPoint.X, TargetPoint.Y)); // // copy chars // //#if defined(FE_SB) 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; } } //#endif RtlCopyMemory(&Row->CharRow.Chars[TargetPoint.X],String,StringLength*sizeof(WCHAR)); //#if defined(FE_SB) RtlCopyMemory(&Row->CharRow.KAttrs[TargetPoint.X],StringA,StringLength*sizeof(CHAR)); //#endif // recalculate first and last non-space char Row->CharRow.OldLeft = Row->CharRow.Left; if (TargetPoint.X < Row->CharRow.Left) { //#if defined(FE_SB) /* * CharRow.Left is leftmost bound of chars in Chars array (array will be full width) * i.e. type is COORD */ PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X-1]; //#else // PWCHAR LastChar = &Row->CharRow.Chars[ScreenInfo->ScreenBufferSize.X]; //#endif for (Char=&Row->CharRow.Chars[TargetPoint.X];Char < LastChar && *Char==(WCHAR)' ';Char++) { /* do nothing*/; } 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--) { /* do nothing */; } 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; //#if defined(FE_SB) && defined(FE_IME) if ((ScreenInfo->Attributes & (COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_RVERTICAL)) == (COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_RVERTICAL)){ SHORT i; for (i = 0; i < StringLength; i++ ) { Attrs.Length = 1; if (*(StringA + i) & ATTR_LEADING_BYTE) { Attrs.Attr = ScreenInfo->Attributes & ~(COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_RVERTICAL); } else { Attrs.Attr = ScreenInfo->Attributes & ~COMMON_LVB_GRID_SINGLEFLAG; } if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, &Attrs, 1, &NewAttrs, &NewAttrsLength, (SHORT)(TargetPoint.X+i), (SHORT)(TargetPoint.X+i), 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; } else if ((ScreenInfo->Attributes & (COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_LVERTICAL)) == (COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_LVERTICAL)){ SHORT i; for (i = 0; i < StringLength; i++ ) { Attrs.Length = 1; if (*(StringA + i) & ATTR_TRAILING_BYTE) { Attrs.Attr = ScreenInfo->Attributes & ~(COMMON_LVB_GRID_SINGLEFLAG + COMMON_LVB_GRID_LVERTICAL); } else { Attrs.Attr = ScreenInfo->Attributes & ~COMMON_LVB_GRID_SINGLEFLAG; } if (!NT_SUCCESS(MergeAttrStrings(Row->AttrRow.Attrs, Row->AttrRow.Length, &Attrs, 1, &NewAttrs, &NewAttrsLength, (SHORT)(TargetPoint.X+i), (SHORT)(TargetPoint.X+i), 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; } else{ //#endif 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; //#if defined(FE_SB) && defined(FE_IME) } //#endif } ResetTextFlags(ScreenInfo, TargetPoint.X, TargetPoint.Y, TargetPoint.X + StringLength - 1, TargetPoint.Y); } #endif // FE_IME