/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
- * FILE: consrv/frontends/gui/text.c
+ * FILE: win32ss/user/winsrv/consrv/frontends/gui/text.c
* PURPOSE: GUI Terminal Front-End - Support for text-mode screen-buffers
* PROGRAMMERS: Gé van Geldorp
* Johannes Anderwald
* Pressing the Shift key while copying text, allows us to copy
* text without newline characters (inline-text copy mode).
*/
- BOOL InlineCopyMode = !!(GetKeyState(VK_SHIFT) & 0x8000);
+ BOOL InlineCopyMode = !!(GetKeyState(VK_SHIFT) & KEY_PRESSED);
HANDLE hData;
PCHAR_INFO ptr;
DPRINT1("This case must never happen, because selHeight is at least == 1\n");
}
- size += 1; /* Null-termination */
+ size++; /* Null-termination */
size *= sizeof(WCHAR);
/* Allocate some memory area to be given to the clipboard, so it will not be freed here */
* array, because of the way things are stored inside it. The downside is
* that it makes the code more complicated.
*/
- for (yPos = Begin->Y; (yPos <= End->Y) && (NumChars > 0); yPos++)
+ for (yPos = Begin->Y; (yPos <= (ULONG)End->Y) && (NumChars > 0); yPos++)
{
xBeg = (yPos == Begin->Y ? Begin->X : 0);
xEnd = (yPos == End->Y ? End->X : Buffer->ScreenBufferSize.X - 1);
}
+VOID
+PasteText(
+ IN PCONSRV_CONSOLE Console,
+ IN PWCHAR Buffer,
+ IN SIZE_T cchSize)
+{
+ USHORT VkKey; // MAKEWORD(low = vkey_code, high = shift_state);
+ INPUT_RECORD er;
+ WCHAR CurChar = 0;
+
+ /* Do nothing if we have nothing to paste */
+ if (!Buffer || (cchSize <= 0))
+ return;
+
+ er.EventType = KEY_EVENT;
+ er.Event.KeyEvent.wRepeatCount = 1;
+ while (cchSize--)
+ {
+ /* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
+ if (CurChar == L'\r' && *Buffer == L'\n')
+ {
+ ++Buffer;
+ continue;
+ }
+ CurChar = *Buffer++;
+
+ /* Get the key code (+ shift state) corresponding to the character */
+ VkKey = VkKeyScanW(CurChar);
+ if (VkKey == 0xFFFF)
+ {
+ DPRINT1("FIXME: TODO: VkKeyScanW failed - Should simulate the key!\n");
+ /*
+ * We don't really need the scan/key code because we actually only
+ * use the UnicodeChar for output purposes. It may pose few problems
+ * later on but it's not of big importance. One trick would be to
+ * convert the character to OEM / multibyte and use MapVirtualKey()
+ * on each byte (simulating an Alt-0xxx OEM keyboard press).
+ */
+ }
+
+ /* Pressing some control keys */
+
+ /* Pressing the character key, with the control keys maintained pressed */
+ er.Event.KeyEvent.bKeyDown = TRUE;
+ er.Event.KeyEvent.wVirtualKeyCode = LOBYTE(VkKey);
+ er.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyW(LOBYTE(VkKey), MAPVK_VK_TO_VSC);
+ er.Event.KeyEvent.uChar.UnicodeChar = CurChar;
+ er.Event.KeyEvent.dwControlKeyState = 0;
+ if (HIBYTE(VkKey) & 1)
+ er.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
+ if (HIBYTE(VkKey) & 2)
+ er.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; // RIGHT_CTRL_PRESSED;
+ if (HIBYTE(VkKey) & 4)
+ er.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; // RIGHT_ALT_PRESSED;
+
+ ConioProcessInputEvent(Console, &er);
+
+ /* Up all the character and control keys */
+ er.Event.KeyEvent.bKeyDown = FALSE;
+ ConioProcessInputEvent(Console, &er);
+ }
+}
+
VOID
GetSelectionBeginEnd(PCOORD Begin, PCOORD End,
PCOORD SelectionAnchor,
PCONSRV_CONSOLE Console = Buffer->Header.Console;
HANDLE hData;
- LPWSTR str;
- WCHAR CurChar = 0;
-
- USHORT VkKey; // MAKEWORD(low = vkey_code, high = shift_state);
- INPUT_RECORD er;
+ LPWSTR pszText;
hData = GetClipboardData(CF_UNICODETEXT);
if (hData == NULL) return;
- str = GlobalLock(hData);
- if (str == NULL) return;
-
- DPRINT("Got data <%S> from clipboard\n", str);
-
- er.EventType = KEY_EVENT;
- er.Event.KeyEvent.wRepeatCount = 1;
- while (*str)
- {
- /* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
- if (CurChar == L'\r' && *str == L'\n')
- {
- str++;
- continue;
- }
- CurChar = *str++;
-
- /* Get the key code (+ shift state) corresponding to the character */
- VkKey = VkKeyScanW(CurChar);
- if (VkKey == 0xFFFF)
- {
- DPRINT1("VkKeyScanW failed - Should simulate the key...\n");
- continue;
- }
-
- /* Pressing some control keys */
+ pszText = GlobalLock(hData);
+ if (pszText == NULL) return;
- /* Pressing the character key, with the control keys maintained pressed */
- er.Event.KeyEvent.bKeyDown = TRUE;
- er.Event.KeyEvent.wVirtualKeyCode = LOBYTE(VkKey);
- er.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyW(LOBYTE(VkKey), MAPVK_VK_TO_CHAR);
- er.Event.KeyEvent.uChar.UnicodeChar = CurChar;
- er.Event.KeyEvent.dwControlKeyState = 0;
- if (HIBYTE(VkKey) & 1)
- er.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
- if (HIBYTE(VkKey) & 2)
- er.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; // RIGHT_CTRL_PRESSED;
- if (HIBYTE(VkKey) & 4)
- er.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; // RIGHT_ALT_PRESSED;
-
- ConioProcessInputEvent(Console, &er);
-
- /* Up all the character and control keys */
- er.Event.KeyEvent.bKeyDown = FALSE;
- ConioProcessInputEvent(Console, &er);
- }
+ DPRINT("Got data <%S> from clipboard\n", pszText);
+ PasteText(Console, pszText, wcslen(pszText));
GlobalUnlock(hData);
}
PRECT rcFramebuffer)
{
PCONSRV_CONSOLE Console = Buffer->Header.Console;
- // ASSERT(Console == GuiData->Console);
-
- ULONG TopLine, BottomLine, LeftChar, RightChar;
+ ULONG TopLine, BottomLine, LeftColumn, RightColumn;
ULONG Line, Char, Start;
PCHAR_INFO From;
PWCHAR To;
HFONT OldFont, NewFont;
BOOLEAN IsUnderline;
- if (Buffer->Buffer == NULL) return;
+ // ASSERT(Console == GuiData->Console);
- if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return;
+ ConioInitLongRect(rcFramebuffer, 0, 0, 0, 0);
- rcFramebuffer->left = Buffer->ViewOrigin.X * GuiData->CharWidth + rcView->left;
- rcFramebuffer->top = Buffer->ViewOrigin.Y * GuiData->CharHeight + rcView->top;
- rcFramebuffer->right = Buffer->ViewOrigin.X * GuiData->CharWidth + rcView->right;
- rcFramebuffer->bottom = Buffer->ViewOrigin.Y * GuiData->CharHeight + rcView->bottom;
+ if (Buffer->Buffer == NULL)
+ return;
+
+ if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE))
+ return;
+
+ ConioInitLongRect(rcFramebuffer,
+ Buffer->ViewOrigin.Y * GuiData->CharHeight + rcView->top,
+ Buffer->ViewOrigin.X * GuiData->CharWidth + rcView->left,
+ Buffer->ViewOrigin.Y * GuiData->CharHeight + rcView->bottom,
+ Buffer->ViewOrigin.X * GuiData->CharWidth + rcView->right);
+
+ LeftColumn = rcFramebuffer->left / GuiData->CharWidth;
+ RightColumn = rcFramebuffer->right / GuiData->CharWidth;
+ if (RightColumn >= (ULONG)Buffer->ScreenBufferSize.X)
+ RightColumn = Buffer->ScreenBufferSize.X - 1;
- LeftChar = rcFramebuffer->left / GuiData->CharWidth;
TopLine = rcFramebuffer->top / GuiData->CharHeight;
- RightChar = rcFramebuffer->right / GuiData->CharWidth;
BottomLine = rcFramebuffer->bottom / GuiData->CharHeight;
+ if (BottomLine >= (ULONG)Buffer->ScreenBufferSize.Y)
+ BottomLine = Buffer->ScreenBufferSize.Y - 1;
- if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1;
- if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1;
-
- LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)->Attributes;
+ LastAttribute = ConioCoordToPointer(Buffer, LeftColumn, TopLine)->Attributes;
SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
OldFont = SelectObject(GuiData->hMemDC, NewFont);
- for (Line = TopLine; Line <= BottomLine; Line++)
+ if (Console->IsCJK)
{
- WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
- From = ConioCoordToPointer(Buffer, LeftChar, Line); // Get the first code of the line
- Start = LeftChar;
- To = LineBuffer;
-
- for (Char = LeftChar; Char <= RightChar; Char++)
+ for (Line = TopLine; Line <= BottomLine; Line++)
{
- /*
- * We flush the buffer if the new attribute is different
- * from the current one, or if the buffer is full.
- */
- if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
+ for (Char = LeftColumn; Char <= RightColumn; Char++)
{
- TextOutW(GuiData->hMemDC,
- Start * GuiData->CharWidth,
- Line * GuiData->CharHeight,
- LineBuffer,
- Char - Start);
- Start = Char;
- To = LineBuffer;
+ From = ConioCoordToPointer(Buffer, Char, Line);
Attribute = From->Attributes;
- if (Attribute != LastAttribute)
+ SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
+ SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
+
+ /* Change underline state if needed */
+ if (!!(Attribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
{
- LastAttribute = Attribute;
- SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
- SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
+ IsUnderline = !!(Attribute & COMMON_LVB_UNDERSCORE);
+
+ /* Select the new font */
+ NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
+ SelectObject(GuiData->hMemDC, NewFont);
+ }
+
+ if (Attribute & COMMON_LVB_TRAILING_BYTE)
+ continue;
+
+ TextOutW(GuiData->hMemDC,
+ Char * GuiData->CharWidth,
+ Line * GuiData->CharHeight,
+ &From->Char.UnicodeChar, 1);
+ }
+ }
+ }
+ else
+ {
+ for (Line = TopLine; Line <= BottomLine; Line++)
+ {
+ WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
+ From = ConioCoordToPointer(Buffer, LeftColumn, Line); // Get the first code of the line
+ Start = LeftColumn;
+ To = LineBuffer;
- /* Change underline state if needed */
- if (!!(LastAttribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
+ for (Char = LeftColumn; Char <= RightColumn; Char++)
+ {
+ /*
+ * We flush the buffer if the new attribute is different
+ * from the current one, or if the buffer is full.
+ */
+ if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
+ {
+ TextOutW(GuiData->hMemDC,
+ Start * GuiData->CharWidth,
+ Line * GuiData->CharHeight,
+ LineBuffer,
+ Char - Start);
+ Start = Char;
+ To = LineBuffer;
+ Attribute = From->Attributes;
+ if (Attribute != LastAttribute)
{
- IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
- /* Select the new font */
- NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
- /* OldFont = */ SelectObject(GuiData->hMemDC, NewFont);
+ LastAttribute = Attribute;
+ SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
+ SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
+
+ /* Change underline state if needed */
+ if (!!(LastAttribute & COMMON_LVB_UNDERSCORE) != IsUnderline)
+ {
+ IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE);
+ /* Select the new font */
+ NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL];
+ SelectObject(GuiData->hMemDC, NewFont);
+ }
}
}
+
+ *(To++) = (From++)->Char.UnicodeChar;
}
- *(To++) = (From++)->Char.UnicodeChar;
+ TextOutW(GuiData->hMemDC,
+ Start * GuiData->CharWidth,
+ Line * GuiData->CharHeight,
+ LineBuffer,
+ RightColumn - Start + 1);
}
-
- TextOutW(GuiData->hMemDC,
- Start * GuiData->CharWidth,
- Line * GuiData->CharHeight,
- LineBuffer,
- RightChar - Start + 1);
}
/* Restore the old font */
{
CursorX = Buffer->CursorPosition.X;
CursorY = Buffer->CursorPosition.Y;
- if (LeftChar <= CursorX && CursorX <= RightChar &&
- TopLine <= CursorY && CursorY <= BottomLine)
+ if (LeftColumn <= CursorX && CursorX <= RightColumn &&
+ TopLine <= CursorY && CursorY <= BottomLine)
{
CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
Attribute = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y)->Attributes;
- if (Attribute == DEFAULT_SCREEN_ATTRIB) Attribute = Buffer->ScreenDefaultAttrib;
+ if (Attribute == DEFAULT_SCREEN_ATTRIB)
+ Attribute = Buffer->ScreenDefaultAttrib;
CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
OldBrush = SelectObject(GuiData->hMemDC, CursorBrush);
- PatBlt(GuiData->hMemDC,
- CursorX * GuiData->CharWidth,
- CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
- GuiData->CharWidth,
- CursorHeight,
- PATCOPY);
+ if (Attribute & COMMON_LVB_LEADING_BYTE)
+ {
+ /* The caret is on the leading byte */
+ PatBlt(GuiData->hMemDC,
+ CursorX * GuiData->CharWidth,
+ CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+ GuiData->CharWidth * 2,
+ CursorHeight,
+ PATCOPY);
+ }
+ else if (Attribute & COMMON_LVB_TRAILING_BYTE)
+ {
+ /* The caret is on the trailing byte */
+ PatBlt(GuiData->hMemDC,
+ (CursorX - 1) * GuiData->CharWidth,
+ CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+ GuiData->CharWidth * 2,
+ CursorHeight,
+ PATCOPY);
+ }
+ else
+ {
+ PatBlt(GuiData->hMemDC,
+ CursorX * GuiData->CharWidth,
+ CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
+ GuiData->CharWidth,
+ CursorHeight,
+ PATCOPY);
+ }
SelectObject(GuiData->hMemDC, OldBrush);
DeleteObject(CursorBrush);