2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/frontends/gui/text.c
5 * PURPOSE: GUI Terminal Front-End - Support for text-mode screen-buffers
6 * PROGRAMMERS: Gé van Geldorp
9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
12 /* INCLUDES *******************************************************************/
21 /* FUNCTIONS ******************************************************************/
23 COLORREF
PaletteRGBFromAttrib(PCONSOLE Console
, WORD Attribute
)
25 HPALETTE hPalette
= Console
->ActiveBuffer
->PaletteHandle
;
28 if (hPalette
== NULL
) return RGBFromAttrib(Console
, Attribute
);
30 GetPaletteEntries(hPalette
, Attribute
, 1, &pe
);
31 return PALETTERGB(pe
.peRed
, pe
.peGreen
, pe
.peBlue
);
35 GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer
,
36 PGUI_CONSOLE_DATA GuiData
)
39 * This function supposes that the system clipboard was opened.
43 * Pressing the Shift key while copying text, allows us to copy
44 * text without newline characters (inline-text copy mode).
46 BOOL InlineCopyMode
= (GetKeyState(VK_SHIFT
) & 0x8000);
51 ULONG selWidth
, selHeight
;
52 ULONG xPos
, yPos
, size
;
54 selWidth
= GuiData
->Selection
.srSelection
.Right
- GuiData
->Selection
.srSelection
.Left
+ 1;
55 selHeight
= GuiData
->Selection
.srSelection
.Bottom
- GuiData
->Selection
.srSelection
.Top
+ 1;
56 DPRINT("Selection is (%d|%d) to (%d|%d)\n",
57 GuiData
->Selection
.srSelection
.Left
,
58 GuiData
->Selection
.srSelection
.Top
,
59 GuiData
->Selection
.srSelection
.Right
,
60 GuiData
->Selection
.srSelection
.Bottom
);
65 #define IS_WHITESPACE(c) ((c) == L'\0' || (c) == L' ' || (c) == L'\t')
67 /* Basic size for one line... */
69 /* ... and for the other lines, add newline characters if needed. */
73 * If we are not in inline-text copy mode, each selected line must
74 * finish with \r\n . Otherwise, the lines will be just concatenated.
76 size
+= (selWidth
+ (!InlineCopyMode
? 2 : 0)) * (selHeight
- 1);
78 size
+= 1; /* Null-termination */
79 size
*= sizeof(WCHAR
);
81 /* Allocate some memory area to be given to the clipboard, so it will not be freed here */
82 hData
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
83 if (hData
== NULL
) return;
85 data
= GlobalLock(hData
);
92 DPRINT("Copying %dx%d selection\n", selWidth
, selHeight
);
95 for (yPos
= 0; yPos
< selHeight
; yPos
++)
97 ULONG length
= selWidth
;
99 ptr
= ConioCoordToPointer(Buffer
,
100 GuiData
->Selection
.srSelection
.Left
,
101 GuiData
->Selection
.srSelection
.Top
+ yPos
);
103 /* Trim whitespace from the right */
106 if (IS_WHITESPACE(ptr
[length
-1].Char
.UnicodeChar
))
112 /* Copy only the characters, leave attributes alone */
113 for (xPos
= 0; xPos
< length
; xPos
++)
116 * Sometimes, applications can put NULL chars into the screen-buffer
117 * (this behaviour is allowed). Detect this and replace by a space.
119 dstPos
[xPos
] = (ptr
[xPos
].Char
.UnicodeChar
? ptr
[xPos
].Char
.UnicodeChar
: L
' ');
123 /* Add newline characters if we are not in inline-text copy mode */
126 if (yPos
!= (selHeight
- 1))
128 wcscat(data
, L
"\r\n");
134 DPRINT("Setting data <%S> to clipboard\n", data
);
138 SetClipboardData(CF_UNICODETEXT
, hData
);
142 GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer
,
143 PGUI_CONSOLE_DATA GuiData
)
146 * This function supposes that the system clipboard was opened.
149 PCONSOLE Console
= Buffer
->Header
.Console
;
155 USHORT VkKey
; // MAKEWORD(low = vkey_code, high = shift_state);
158 hData
= GetClipboardData(CF_UNICODETEXT
);
159 if (hData
== NULL
) return;
161 str
= GlobalLock(hData
);
162 if (str
== NULL
) return;
164 DPRINT("Got data <%S> from clipboard\n", str
);
166 er
.EventType
= KEY_EVENT
;
167 er
.Event
.KeyEvent
.wRepeatCount
= 1;
170 /* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
171 if (CurChar
== L
'\r' && *str
== L
'\n')
178 /* Get the key code (+ shift state) corresponding to the character */
179 VkKey
= VkKeyScanW(CurChar
);
182 DPRINT1("VkKeyScanW failed - Should simulate the key...\n");
186 /* Pressing some control keys */
188 /* Pressing the character key, with the control keys maintained pressed */
189 er
.Event
.KeyEvent
.bKeyDown
= TRUE
;
190 er
.Event
.KeyEvent
.wVirtualKeyCode
= LOBYTE(VkKey
);
191 er
.Event
.KeyEvent
.wVirtualScanCode
= MapVirtualKeyW(LOBYTE(VkKey
), MAPVK_VK_TO_CHAR
);
192 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= CurChar
;
193 er
.Event
.KeyEvent
.dwControlKeyState
= 0;
194 if (HIBYTE(VkKey
) & 1)
195 er
.Event
.KeyEvent
.dwControlKeyState
|= SHIFT_PRESSED
;
196 if (HIBYTE(VkKey
) & 2)
197 er
.Event
.KeyEvent
.dwControlKeyState
|= LEFT_CTRL_PRESSED
; // RIGHT_CTRL_PRESSED;
198 if (HIBYTE(VkKey
) & 4)
199 er
.Event
.KeyEvent
.dwControlKeyState
|= LEFT_ALT_PRESSED
; // RIGHT_ALT_PRESSED;
201 ConioProcessInputEvent(Console
, &er
);
203 /* Up all the character and control keys */
204 er
.Event
.KeyEvent
.bKeyDown
= FALSE
;
205 ConioProcessInputEvent(Console
, &er
);
212 GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer
,
213 PGUI_CONSOLE_DATA GuiData
,
217 PCONSOLE Console
= Buffer
->Header
.Console
;
218 // ASSERT(Console == GuiData->Console);
220 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
221 ULONG Line
, Char
, Start
;
224 WORD LastAttribute
, Attribute
;
225 ULONG CursorX
, CursorY
, CursorHeight
;
226 HBRUSH CursorBrush
, OldBrush
;
229 if (Buffer
->Buffer
== NULL
) return;
231 if (!ConDrvValidateConsoleUnsafe(Console
, CONSOLE_RUNNING
, TRUE
)) return;
233 rcFramebuffer
->left
= Buffer
->ViewOrigin
.X
* GuiData
->CharWidth
+ rcView
->left
;
234 rcFramebuffer
->top
= Buffer
->ViewOrigin
.Y
* GuiData
->CharHeight
+ rcView
->top
;
235 rcFramebuffer
->right
= Buffer
->ViewOrigin
.X
* GuiData
->CharWidth
+ rcView
->right
;
236 rcFramebuffer
->bottom
= Buffer
->ViewOrigin
.Y
* GuiData
->CharHeight
+ rcView
->bottom
;
238 LeftChar
= rcFramebuffer
->left
/ GuiData
->CharWidth
;
239 TopLine
= rcFramebuffer
->top
/ GuiData
->CharHeight
;
240 RightChar
= rcFramebuffer
->right
/ GuiData
->CharWidth
;
241 BottomLine
= rcFramebuffer
->bottom
/ GuiData
->CharHeight
;
243 if (RightChar
>= Buffer
->ScreenBufferSize
.X
) RightChar
= Buffer
->ScreenBufferSize
.X
- 1;
244 if (BottomLine
>= Buffer
->ScreenBufferSize
.Y
) BottomLine
= Buffer
->ScreenBufferSize
.Y
- 1;
246 LastAttribute
= ConioCoordToPointer(Buffer
, LeftChar
, TopLine
)->Attributes
;
248 SetTextColor(GuiData
->hMemDC
, PaletteRGBFromAttrib(Console
, TextAttribFromAttrib(LastAttribute
)));
249 SetBkColor(GuiData
->hMemDC
, PaletteRGBFromAttrib(Console
, BkgdAttribFromAttrib(LastAttribute
)));
251 OldFont
= SelectObject(GuiData
->hMemDC
, GuiData
->Font
);
253 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
255 WCHAR LineBuffer
[80]; // Buffer containing a part or all the line to be displayed
256 From
= ConioCoordToPointer(Buffer
, LeftChar
, Line
); // Get the first code of the line
260 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
263 * We flush the buffer if the new attribute is different
264 * from the current one, or if the buffer is full.
266 if (From
->Attributes
!= LastAttribute
|| (Char
- Start
== sizeof(LineBuffer
) / sizeof(WCHAR
)))
268 TextOutW(GuiData
->hMemDC
,
269 Start
* GuiData
->CharWidth
,
270 Line
* GuiData
->CharHeight
,
275 Attribute
= From
->Attributes
;
276 if (Attribute
!= LastAttribute
)
278 SetTextColor(GuiData
->hMemDC
, PaletteRGBFromAttrib(Console
, TextAttribFromAttrib(Attribute
)));
279 SetBkColor(GuiData
->hMemDC
, PaletteRGBFromAttrib(Console
, BkgdAttribFromAttrib(Attribute
)));
280 LastAttribute
= Attribute
;
284 *(To
++) = (From
++)->Char
.UnicodeChar
;
287 TextOutW(GuiData
->hMemDC
,
288 Start
* GuiData
->CharWidth
,
289 Line
* GuiData
->CharHeight
,
291 RightChar
- Start
+ 1);
297 if (Buffer
->CursorInfo
.bVisible
&&
298 Buffer
->CursorBlinkOn
&&
299 !Buffer
->ForceCursorOff
)
301 CursorX
= Buffer
->CursorPosition
.X
;
302 CursorY
= Buffer
->CursorPosition
.Y
;
303 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
304 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
306 CursorHeight
= ConioEffectiveCursorSize(Console
, GuiData
->CharHeight
);
308 Attribute
= ConioCoordToPointer(Buffer
, Buffer
->CursorPosition
.X
, Buffer
->CursorPosition
.Y
)->Attributes
;
309 if (Attribute
== DEFAULT_SCREEN_ATTRIB
) Attribute
= Buffer
->ScreenDefaultAttrib
;
311 CursorBrush
= CreateSolidBrush(PaletteRGBFromAttrib(Console
, TextAttribFromAttrib(Attribute
)));
312 OldBrush
= SelectObject(GuiData
->hMemDC
, CursorBrush
);
314 PatBlt(GuiData
->hMemDC
,
315 CursorX
* GuiData
->CharWidth
,
316 CursorY
* GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
320 SelectObject(GuiData
->hMemDC
, OldBrush
);
321 DeleteObject(CursorBrush
);
325 SelectObject(GuiData
->hMemDC
, OldFont
);
327 LeaveCriticalSection(&Console
->Lock
);