[CONSOLE.CPL-KERNEL32]
[reactos.git] / reactos / win32ss / user / consrv / frontends / gui / text.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/frontends/gui/text.c
5 * PURPOSE: GUI Terminal Front-End - Support for text-mode screen-buffers
6 * PROGRAMMERS: Gé van Geldorp
7 * Johannes Anderwald
8 * Jeffrey Morlan
9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 */
11
12 /* INCLUDES *******************************************************************/
13
14 #include "consrv.h"
15 #include "include/conio.h"
16 #include "include/settings.h"
17 #include "guisettings.h"
18
19 #define NDEBUG
20 #include <debug.h>
21
22
23 /* GLOBALS ********************************************************************/
24
25 /* Copied from consrv/text.c */
26 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
27 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
28
29
30 /* FUNCTIONS ******************************************************************/
31
32 VOID
33 GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
34 {
35 /*
36 * This function supposes that the system clipboard was opened.
37 */
38
39 PCONSOLE Console = Buffer->Header.Console;
40
41 HANDLE hData;
42 PBYTE ptr;
43 LPWSTR data, dstPos;
44 ULONG selWidth, selHeight;
45 ULONG xPos, yPos, size;
46
47 selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
48 selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
49 DPRINT("Selection is (%d|%d) to (%d|%d)\n",
50 Console->Selection.srSelection.Left,
51 Console->Selection.srSelection.Top,
52 Console->Selection.srSelection.Right,
53 Console->Selection.srSelection.Bottom);
54
55 /* Basic size for one line and termination */
56 size = selWidth + 1;
57 if (selHeight > 0)
58 {
59 /* Multiple line selections have to get \r\n appended */
60 size += ((selWidth + 2) * (selHeight - 1));
61 }
62 size *= sizeof(WCHAR);
63
64 /* Allocate memory, it will be passed to the system and may not be freed here */
65 hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
66 if (hData == NULL) return;
67
68 data = GlobalLock(hData);
69 if (data == NULL) return;
70
71 DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
72 dstPos = data;
73
74 for (yPos = 0; yPos < selHeight; yPos++)
75 {
76 ptr = ConioCoordToPointer(Buffer,
77 Console->Selection.srSelection.Left,
78 yPos + Console->Selection.srSelection.Top);
79 /* Copy only the characters, leave attributes alone */
80 for (xPos = 0; xPos < selWidth; xPos++)
81 {
82 ConsoleAnsiCharToUnicodeChar(Console, &dstPos[xPos], (LPCSTR)&ptr[xPos * 2]);
83 }
84 dstPos += selWidth;
85 if (yPos != (selHeight - 1))
86 {
87 wcscat(data, L"\r\n");
88 dstPos += 2;
89 }
90 }
91
92 DPRINT("Setting data <%S> to clipboard\n", data);
93 GlobalUnlock(hData);
94
95 EmptyClipboard();
96 SetClipboardData(CF_UNICODETEXT, hData);
97 }
98
99 VOID
100 GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
101 {
102 /*
103 * This function supposes that the system clipboard was opened.
104 */
105
106 PCONSOLE Console = Buffer->Header.Console;
107
108 HANDLE hData;
109 LPWSTR str;
110 WCHAR CurChar = 0;
111
112 SHORT VkKey; // MAKEWORD(low = vkey_code, high = shift_state);
113 INPUT_RECORD er;
114
115 hData = GetClipboardData(CF_UNICODETEXT);
116 if (hData == NULL) return;
117
118 str = GlobalLock(hData);
119 if (str == NULL) return;
120
121 DPRINT("Got data <%S> from clipboard\n", str);
122
123 er.EventType = KEY_EVENT;
124 er.Event.KeyEvent.wRepeatCount = 1;
125 while (*str)
126 {
127 /* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
128 if (CurChar == L'\r' && *str == L'\n')
129 {
130 str++;
131 continue;
132 }
133 CurChar = *str++;
134
135 /* Get the key code (+ shift state) corresponding to the character */
136 VkKey = VkKeyScanW(CurChar);
137 if (VkKey == 0xFFFF)
138 {
139 DPRINT1("VkKeyScanW failed - Should simulate the key...\n");
140 continue;
141 }
142
143 /* Pressing some control keys */
144
145 /* Pressing the character key, with the control keys maintained pressed */
146 er.Event.KeyEvent.bKeyDown = TRUE;
147 er.Event.KeyEvent.wVirtualKeyCode = LOBYTE(VkKey);
148 er.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyW(LOBYTE(VkKey), MAPVK_VK_TO_CHAR);
149 er.Event.KeyEvent.uChar.UnicodeChar = CurChar;
150 er.Event.KeyEvent.dwControlKeyState = 0;
151 if (HIBYTE(VkKey) & 1)
152 er.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
153 if (HIBYTE(VkKey) & 2)
154 er.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; // RIGHT_CTRL_PRESSED;
155 if (HIBYTE(VkKey) & 4)
156 er.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; // RIGHT_ALT_PRESSED;
157
158 ConioProcessInputEvent(Console, &er);
159
160 /* Up all the character and control keys */
161 er.Event.KeyEvent.bKeyDown = FALSE;
162 ConioProcessInputEvent(Console, &er);
163 }
164
165 GlobalUnlock(hData);
166 }
167
168 VOID
169 GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
170 PGUI_CONSOLE_DATA GuiData,
171 HDC hDC,
172 PRECT rc)
173 {
174 PCONSOLE Console = Buffer->Header.Console;
175 // ASSERT(Console == GuiData->Console);
176
177 ULONG TopLine, BottomLine, LeftChar, RightChar;
178 ULONG Line, Char, Start;
179 PBYTE From;
180 PWCHAR To;
181 BYTE LastAttribute, Attribute;
182 ULONG CursorX, CursorY, CursorHeight;
183 HBRUSH CursorBrush, OldBrush;
184 HFONT OldFont;
185
186 if (Buffer->Buffer == NULL) return;
187
188 TopLine = rc->top / GuiData->CharHeight + Buffer->ViewOrigin.Y;
189 BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buffer->ViewOrigin.Y;
190 LeftChar = rc->left / GuiData->CharWidth + Buffer->ViewOrigin.X;
191 RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buffer->ViewOrigin.X;
192 LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)[1];
193
194 SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute)));
195 SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute)));
196
197 if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1;
198 if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1;
199
200 OldFont = SelectObject(hDC, GuiData->Font);
201
202 for (Line = TopLine; Line <= BottomLine; Line++)
203 {
204 WCHAR LineBuffer[80];
205 From = ConioCoordToPointer(Buffer, LeftChar, Line);
206 Start = LeftChar;
207 To = LineBuffer;
208
209 for (Char = LeftChar; Char <= RightChar; Char++)
210 {
211 if (*(From + 1) != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
212 {
213 TextOutW(hDC,
214 (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth,
215 (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
216 LineBuffer,
217 Char - Start);
218 Start = Char;
219 To = LineBuffer;
220 Attribute = *(From + 1);
221 if (Attribute != LastAttribute)
222 {
223 SetTextColor(hDC, RGBFromAttrib(Console, TextAttribFromAttrib(Attribute)));
224 SetBkColor(hDC, RGBFromAttrib(Console, BkgdAttribFromAttrib(Attribute)));
225 LastAttribute = Attribute;
226 }
227 }
228
229 MultiByteToWideChar(Console->OutputCodePage,
230 0, (PCHAR)From, 1, To, 1);
231 To++;
232 From += 2;
233 }
234
235 TextOutW(hDC,
236 (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth,
237 (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
238 LineBuffer,
239 RightChar - Start + 1);
240 }
241
242 /*
243 * Draw the caret
244 */
245 if (Buffer->CursorInfo.bVisible &&
246 Buffer->CursorBlinkOn &&
247 !Buffer->ForceCursorOff)
248 {
249 CursorX = Buffer->CursorPosition.X;
250 CursorY = Buffer->CursorPosition.Y;
251 if (LeftChar <= CursorX && CursorX <= RightChar &&
252 TopLine <= CursorY && CursorY <= BottomLine)
253 {
254 CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
255 From = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y) + 1;
256
257 if (*From != DEFAULT_SCREEN_ATTRIB)
258 {
259 CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, *From));
260 }
261 else
262 {
263 CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Buffer->ScreenDefaultAttrib));
264 }
265
266 OldBrush = SelectObject(hDC, CursorBrush);
267 PatBlt(hDC,
268 (CursorX - Buffer->ViewOrigin.X) * GuiData->CharWidth,
269 (CursorY - Buffer->ViewOrigin.Y) * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
270 GuiData->CharWidth,
271 CursorHeight,
272 PATCOPY);
273 SelectObject(hDC, OldBrush);
274 DeleteObject(CursorBrush);
275 }
276 }
277
278 SelectObject(hDC, OldFont);
279 }
280
281 /* EOF */