ReactOS  0.4.14-dev-50-g13bb5e2
text.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Console Server DLL
4  * FILE: win32ss/user/winsrv/consrv_new/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 /* FUNCTIONS ******************************************************************/
24 
25 VOID
27 {
28  /*
29  * This function supposes that the system clipboard was opened.
30  */
31 
32  PCONSOLE Console = Buffer->Header.Console;
33 
34  /*
35  * Pressing the Shift key while copying text, allows us to copy
36  * text without newline characters (inline-text copy mode).
37  */
38  BOOL InlineCopyMode = (GetKeyState(VK_SHIFT) & 0x8000);
39 
40  HANDLE hData;
42  LPWSTR data, dstPos;
43  ULONG selWidth, selHeight;
44  ULONG xPos, yPos, size;
45 
46  selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
47  selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
48  DPRINT("Selection is (%d|%d) to (%d|%d)\n",
49  Console->Selection.srSelection.Left,
50  Console->Selection.srSelection.Top,
51  Console->Selection.srSelection.Right,
52  Console->Selection.srSelection.Bottom);
53 
54  /* Basic size for one line... */
55  size = selWidth;
56  /* ... and for the other lines, add newline characters if needed. */
57  if (selHeight > 0)
58  {
59  /*
60  * If we are not in inline-text copy mode, each selected line must
61  * finish with \r\n . Otherwise, the lines will be just concatenated.
62  */
63  size += (selWidth + (!InlineCopyMode ? 2 : 0)) * (selHeight - 1);
64  }
65  size += 1; /* Null-termination */
66  size *= sizeof(WCHAR);
67 
68  /* Allocate memory, it will be passed to the system and may not be freed here */
70  if (hData == NULL) return;
71 
72  data = GlobalLock(hData);
73  if (data == NULL) return;
74 
75  DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
76  dstPos = data;
77 
78  for (yPos = 0; yPos < selHeight; yPos++)
79  {
81  Console->Selection.srSelection.Left,
82  yPos + Console->Selection.srSelection.Top);
83  /* Copy only the characters, leave attributes alone */
84  for (xPos = 0; xPos < selWidth; xPos++)
85  {
86  /*
87  * Sometimes, applications can put NULL chars into the screen-buffer
88  * (this behaviour is allowed). Detect this and replace by a space.
89  * FIXME - HACK: Improve the way we're doing that (i.e., put spaces
90  * instead of NULLs (or even, nothing) only if it exists a non-null
91  * char *after* those NULLs, before the end-of-line of the selection.
92  * Do the same concerning spaces -- i.e. trailing spaces --).
93  */
94  dstPos[xPos] = (ptr[xPos].Char.UnicodeChar ? ptr[xPos].Char.UnicodeChar : L' ');
95  }
96  dstPos += selWidth;
97 
98  /* Add newline characters if we are not in inline-text copy mode */
99  if (!InlineCopyMode)
100  {
101  if (yPos != (selHeight - 1))
102  {
103  wcscat(data, L"\r\n");
104  dstPos += 2;
105  }
106  }
107  }
108 
109  DPRINT("Setting data <%S> to clipboard\n", data);
110  GlobalUnlock(hData);
111 
112  EmptyClipboard();
114 }
115 
116 VOID
118 {
119  /*
120  * This function supposes that the system clipboard was opened.
121  */
122 
123  PCONSOLE Console = Buffer->Header.Console;
124 
125  HANDLE hData;
126  LPWSTR str;
127  WCHAR CurChar = 0;
128 
129  SHORT VkKey; // MAKEWORD(low = vkey_code, high = shift_state);
130  INPUT_RECORD er;
131 
133  if (hData == NULL) return;
134 
135  str = GlobalLock(hData);
136  if (str == NULL) return;
137 
138  DPRINT("Got data <%S> from clipboard\n", str);
139 
140  er.EventType = KEY_EVENT;
141  er.Event.KeyEvent.wRepeatCount = 1;
142  while (*str)
143  {
144  /* \r or \n characters. Go to the line only if we get "\r\n" sequence. */
145  if (CurChar == L'\r' && *str == L'\n')
146  {
147  str++;
148  continue;
149  }
150  CurChar = *str++;
151 
152  /* Get the key code (+ shift state) corresponding to the character */
153  VkKey = VkKeyScanW(CurChar);
154  if (VkKey == 0xFFFF)
155  {
156  DPRINT1("VkKeyScanW failed - Should simulate the key...\n");
157  continue;
158  }
159 
160  /* Pressing some control keys */
161 
162  /* Pressing the character key, with the control keys maintained pressed */
164  er.Event.KeyEvent.wVirtualKeyCode = LOBYTE(VkKey);
168  if (HIBYTE(VkKey) & 1)
170  if (HIBYTE(VkKey) & 2)
171  er.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; // RIGHT_CTRL_PRESSED;
172  if (HIBYTE(VkKey) & 4)
173  er.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; // RIGHT_ALT_PRESSED;
174 
176 
177  /* Up all the character and control keys */
180  }
181 
182  GlobalUnlock(hData);
183 }
184 
185 VOID
187  PGUI_CONSOLE_DATA GuiData,
188  HDC hDC,
189  PRECT rc)
190 {
191  PCONSOLE Console = Buffer->Header.Console;
192  // ASSERT(Console == GuiData->Console);
193 
194  ULONG TopLine, BottomLine, LeftChar, RightChar;
195  ULONG Line, Char, Start;
196  PCHAR_INFO From;
197  PWCHAR To;
198  WORD LastAttribute, Attribute;
199  ULONG CursorX, CursorY, CursorHeight;
200  HBRUSH CursorBrush, OldBrush;
201  HFONT OldFont;
202 
203  if (Buffer->Buffer == NULL) return;
204 
205  TopLine = rc->top / GuiData->CharHeight + Buffer->ViewOrigin.Y;
206  BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buffer->ViewOrigin.Y;
207  LeftChar = rc->left / GuiData->CharWidth + Buffer->ViewOrigin.X;
208  RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buffer->ViewOrigin.X;
209 
210  LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)->Attributes;
211 
214 
215  if (BottomLine >= Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1;
216  if (RightChar >= Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1;
217 
218  OldFont = SelectObject(hDC, GuiData->Font);
219 
220  for (Line = TopLine; Line <= BottomLine; Line++)
221  {
222  WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed
223  From = ConioCoordToPointer(Buffer, LeftChar, Line); // Get the first code of the line
224  Start = LeftChar;
225  To = LineBuffer;
226 
227  for (Char = LeftChar; Char <= RightChar; Char++)
228  {
229  /*
230  * We flush the buffer if the new attribute is different
231  * from the current one, or if the buffer is full.
232  */
233  if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
234  {
235  TextOutW(hDC,
236  (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth ,
237  (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
238  LineBuffer,
239  Char - Start);
240  Start = Char;
241  To = LineBuffer;
242  Attribute = From->Attributes;
243  if (Attribute != LastAttribute)
244  {
247  LastAttribute = Attribute;
248  }
249  }
250 
251  *(To++) = (From++)->Char.UnicodeChar;
252  }
253 
254  TextOutW(hDC,
255  (Start - Buffer->ViewOrigin.X) * GuiData->CharWidth ,
256  (Line - Buffer->ViewOrigin.Y) * GuiData->CharHeight,
257  LineBuffer,
258  RightChar - Start + 1);
259  }
260 
261  /*
262  * Draw the caret
263  */
264  if (Buffer->CursorInfo.bVisible &&
265  Buffer->CursorBlinkOn &&
266  !Buffer->ForceCursorOff)
267  {
268  CursorX = Buffer->CursorPosition.X;
269  CursorY = Buffer->CursorPosition.Y;
270  if (LeftChar <= CursorX && CursorX <= RightChar &&
271  TopLine <= CursorY && CursorY <= BottomLine)
272  {
273  CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
274  Attribute = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y)->Attributes;
275 
276  if (Attribute != DEFAULT_SCREEN_ATTRIB)
277  {
278  CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Attribute));
279  }
280  else
281  {
282  CursorBrush = CreateSolidBrush(RGBFromAttrib(Console, Buffer->ScreenDefaultAttrib));
283  }
284 
285  OldBrush = SelectObject(hDC, CursorBrush);
286  PatBlt(hDC,
287  (CursorX - Buffer->ViewOrigin.X) * GuiData->CharWidth,
288  (CursorY - Buffer->ViewOrigin.Y) * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
289  GuiData->CharWidth,
290  CursorHeight,
291  PATCOPY);
292  SelectObject(hDC, OldBrush);
293  DeleteObject(CursorBrush);
294  }
295  }
296 
298 }
299 
300 /* EOF */
#define DEFAULT_SCREEN_ATTRIB
Definition: settings.c:29
#define TRUE
Definition: types.h:120
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
WCHAR UnicodeChar
Definition: wincon.h:230
WORD wVirtualScanCode
Definition: wincon.h:228
BOOL WINAPI TextOutW(_In_ HDC hdc, _In_ INT nXStart, _In_ INT nYStart, _In_reads_(cchString) LPCWSTR lpString, _In_ INT cchString)
Definition: text.c:66
#define LOBYTE(W)
Definition: jmemdos.c:487
PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y)
Definition: text.c:140
static ULONG CursorY
Definition: display.c:137
static HDC
Definition: imagelist.c:92
DWORD dwControlKeyState
Definition: wincon.h:233
#define HIBYTE(W)
Definition: jmemdos.c:486
LONG top
Definition: windef.h:292
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
uint16_t * PWCHAR
Definition: typedefs.h:54
LONG left
Definition: windef.h:291
#define SHIFT_PRESSED
Definition: wincon.h:135
LONG right
Definition: windef.h:293
HANDLE WINAPI SetClipboardData(_In_ UINT, _In_opt_ HANDLE)
WORD wVirtualKeyCode
Definition: wincon.h:227
union _INPUT_RECORD::@3154 Event
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
BOOL WINAPI PatBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
UINT CharHeight
Definition: conwnd.h:87
WORD wRepeatCount
Definition: wincon.h:226
unsigned int BOOL
Definition: ntddk_ex.h:94
short SHORT
Definition: pedump.c:59
char Char
Definition: bzip2.c:161
#define KEY_EVENT
Definition: wincon.h:122
static PVOID ptr
Definition: dispmode.c:27
#define VK_SHIFT
Definition: winuser.h:2177
#define CF_UNICODETEXT
Definition: constants.h:408
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
UINT WINAPI MapVirtualKeyW(_In_ UINT, _In_ UINT)
HFONT Font[FONT_MAXNO]
Definition: conwnd.h:85
#define BkgdAttribFromAttrib(Attribute)
Definition: settings.h:73
SHORT WINAPI GetKeyState(_In_ int)
#define LEFT_ALT_PRESSED
Definition: wincon.h:132
VOID GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer, PGUI_CONSOLE_DATA GuiData)
Definition: text.c:330
union _KEY_EVENT_RECORD::@3153 uChar
BOOL WINAPI EmptyClipboard(void)
Definition: ntwrapper.h:190
GLsizeiptr size
Definition: glext.h:5919
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define RGBFromAttrib(Console, Attribute)
Definition: settings.h:71
WORD Attributes
Definition: wincon.h:172
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
unsigned short WORD
Definition: ntddk_ex.h:93
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: partlist.h:33
Definition: ncftp.h:79
static ULONG CursorX
Definition: display.c:136
#define LEFT_CTRL_PRESSED
Definition: wincon.h:134
static const WCHAR L[]
Definition: oid.c:1250
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
#define TextAttribFromAttrib(Attribute)
Definition: settings.h:72
#define PATCOPY
Definition: wingdi.h:334
#define MAPVK_VK_TO_CHAR
Definition: winuser.h:2332
VOID GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer, PGUI_CONSOLE_DATA GuiData, PRECT rcView, PRECT rcFramebuffer)
Definition: text.c:355
static HDC hDC
Definition: 3dtext.c:33
static TCHAR CurChar
Definition: parser.c:52
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
UINT CharWidth
Definition: conwnd.h:86
HANDLE WINAPI GetClipboardData(_In_ UINT)
DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale)
Definition: text.c:303
CConsole Console
WORD EventType
Definition: wincon.h:261
#define DPRINT1
Definition: precomp.h:8
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
SHORT WINAPI VkKeyScanW(_In_ WCHAR)
unsigned int ULONG
Definition: retypes.h:1
LONG bottom
Definition: windef.h:294
VOID GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer, PGUI_CONSOLE_DATA GuiData)
Definition: text.c:297
COLORREF WINAPI SetTextColor(_In_ HDC hdc, _In_ COLORREF crColor)
Definition: text.c:888
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define GMEM_MOVEABLE
Definition: winbase.h:291
#define GMEM_ZEROINIT
Definition: winbase.h:303
struct Line Line
NTSTATUS ConioProcessInputEvent(PCONSRV_CONSOLE Console, PINPUT_RECORD InputEvent)
Definition: coninput.c:195