- Notifications
You must be signed in to change notification settings - Fork 8.5k
/
Copy pathrenderData.cpp
383 lines (344 loc) · 14.1 KB
/
renderData.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include"precomp.h"
#include"renderData.hpp"
#include"dbcs.h"
#include"handle.h"
#include"../interactivity/inc/ServiceLocator.hpp"
#pragma hdrstop
usingnamespaceMicrosoft::Console::Types;
usingnamespaceMicrosoft::Console::Interactivity;
using Microsoft::Console::Interactivity::ServiceLocator;
// Routine Description:
// - Retrieves the viewport that applies over the data available in the GetTextBuffer() call
// Return Value:
// - Viewport describing rectangular region of TextBuffer that should be displayed.
Microsoft::Console::Types::Viewport RenderData::GetViewport() noexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().GetViewport();
}
// Routine Description:
// - Retrieves the end position of the text buffer. We use
// the cursor position as the text buffer end position
// Return Value:
// - til::point of the end position of the text buffer
til::point RenderData::GetTextBufferEndPosition() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto bufferSize = gci.GetActiveOutputBuffer().GetBufferSize();
return { bufferSize.Width() - 1, bufferSize.BottomInclusive() };
}
// Routine Description:
// - Provides access to the text data that can be presented. Check GetViewport() for
// the appropriate windowing.
// Return Value:
// - Text buffer with cell information for display
TextBuffer& RenderData::GetTextBuffer() constnoexcept
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().GetTextBuffer();
}
// Routine Description:
// - Describes which font should be used for presenting text
// Return Value:
// - Font description structure
const FontInfo& RenderData::GetFontInfo() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().GetCurrentFont();
}
// Method Description:
// - Retrieves one span per line describing the area of the viewport
// that should be highlighted in some way to represent a user-interactive selection
std::span<const til::point_span> RenderData::GetSelectionSpans() constnoexcept
{
returnSelection::Instance().GetSelectionSpans();
}
// Method Description:
// - Retrieves one rectangle per line describing the area of the viewport
// that should be highlighted
// Return Value:
// - Vector of rects describing the highlighted area
std::span<const til::point_span> RenderData::GetSearchHighlights() constnoexcept
{
return {};
}
// Method Description:
// - Lock the console for reading the contents of the buffer. Ensures that the
// contents of the console won't be changed in the middle of a paint
// operation.
// Callers should make sure to also call RenderData::UnlockConsole once
// they're done with any querying they need to do.
voidRenderData::LockConsole() noexcept
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.LockConsole();
}
// Method Description:
// - Unlocks the console after a call to RenderData::LockConsole.
voidRenderData::UnlockConsole() noexcept
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.UnlockConsole();
}
// Method Description:
// - Gets the cursor's position in the buffer, relative to the buffer origin.
// Arguments:
// - <none>
// Return Value:
// - the cursor's position in the buffer relative to the buffer origin.
til::point RenderData::GetCursorPosition() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
constauto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
return cursor.GetPosition();
}
// Method Description:
// - Returns whether the cursor is currently visible or not. If the cursor is
// visible and blinking, this is true, even if the cursor has currently
// blinked to the "off" state.
// Arguments:
// - <none>
// Return Value:
// - true if the cursor is set to the visible state, regardless of blink state
boolRenderData::IsCursorVisible() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
constauto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
return cursor.IsVisible();
}
// Method Description:
// - Returns whether the cursor is currently visually visible or not. If the
// cursor is visible, and blinking, this will alternate between true and
// false as the cursor blinks.
// Arguments:
// - <none>
// Return Value:
// - true if the cursor is currently visually visible, depending upon blink state
boolRenderData::IsCursorOn() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
constauto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
return cursor.IsVisible() && cursor.IsOn();
}
// Method Description:
// - The height of the cursor, out of 100, where 100 indicates the cursor should
// be the full height of the cell.
// Arguments:
// - <none>
// Return Value:
// - height of the cursor, out of 100
ULONG RenderData::GetCursorHeight() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
constauto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
// Determine cursor height
auto ulHeight = cursor.GetSize();
// Now adjust the height for the overwrite/insert mode. If we're in overwrite mode, IsDouble will be set.
// When IsDouble is set, we either need to double the height of the cursor, or if it's already too big,
// then we need to shrink it by half.
if (cursor.IsDouble())
{
if (ulHeight > 50) // 50 because 50 percent is half of 100 percent which is the max size.
{
ulHeight >>= 1;
}
else
{
ulHeight <<= 1;
}
}
return ulHeight;
}
// Method Description:
// - The CursorType of the cursor. The CursorType is used to determine what
// shape the cursor should be.
// Arguments:
// - <none>
// Return Value:
// - the CursorType of the cursor.
CursorType RenderData::GetCursorStyle() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
constauto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
return cursor.GetType();
}
// Method Description:
// - Retrieves the operating system preference from Ease of Access for the pixel
// width of the cursor. Useful for a bar-style cursor.
// Arguments:
// - <none>
// Return Value:
// - The suggested width of the cursor in pixels.
ULONG RenderData::GetCursorPixelWidth() constnoexcept
{
returnServiceLocator::LocateGlobals().cursorPixelWidth;
}
// Method Description:
// - Returns true if the cursor should be drawn twice as wide as usual because
// the cursor is currently over a cell with a double-wide character in it.
// Arguments:
// - <none>
// Return Value:
// - true if the cursor should be drawn twice as wide as usual
boolRenderData::IsCursorDoubleWidth() const
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().CursorIsDoubleWidth();
}
// Routine Description:
// - Checks the user preference as to whether grid line drawing is allowed around the edges of each cell.
// - This is for backwards compatibility with old behaviors in the legacy console.
// Return Value:
// - If true, line drawing information retrieved from the text buffer can/should be displayed.
// - If false, it should be ignored and never drawn
constboolRenderData::IsGridLineDrawingAllowed() noexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
constauto outputMode = gci.GetActiveOutputBuffer().OutputMode;
// If virtual terminal output is set, grid line drawing is a must. It is also enabled
// if someone explicitly asked for worldwide line drawing.
if (WI_IsAnyFlagSet(outputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_LVB_GRID_WORLDWIDE))
{
returntrue;
}
else
{
// Otherwise, for compatibility reasons with legacy applications that used the additional CHAR_INFO bits by accident or for their own purposes,
// we must enable grid line drawing only in a DBCS output codepage. (Line drawing historically only worked in DBCS codepages.)
// The only known instance of this is Image for Windows by TeraByte, Inc. (TeraByte Unlimited) which used the bits accidentally and for no purpose
// (according to the app developer) in conjunction with the Borland Turbo C cgscrn library.
return !!IsAvailableEastAsianCodePage(gci.OutputCP);
}
}
// Routine Description:
// - Retrieves the title information to be displayed in the frame/edge of the window
// Return Value:
// - String with title information
const std::wstring_view RenderData::GetConsoleTitle() constnoexcept
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetTitleAndPrefix();
}
// Method Description:
// - Get the hyperlink URI associated with a hyperlink ID
// Arguments:
// - The hyperlink ID
// Return Value:
// - The URI
const std::wstring RenderData::GetHyperlinkUri(uint16_t id) const
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().GetTextBuffer().GetHyperlinkUriFromId(id);
}
// Method Description:
// - Get the custom ID associated with a hyperlink ID
// Arguments:
// - The hyperlink ID
// Return Value:
// - The custom ID if there was one, empty string otherwise
const std::wstring RenderData::GetHyperlinkCustomId(uint16_t id) const
{
constauto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().GetTextBuffer().GetCustomIdFromId(id);
}
// For now, we ignore regex patterns in conhost
const std::vector<size_t> RenderData::GetPatternId(const til::point /*location*/) const
{
return {};
}
// Routine Description:
// - Converts a text attribute into the RGB values that should be presented, applying
// relevant table translation information and preferences.
// Return Value:
// - ARGB color values for the foreground and background
std::pair<COLORREF, COLORREF> RenderData::GetAttributeColors(const TextAttribute& attr) constnoexcept
{
constauto& renderSettings = ServiceLocator::LocateGlobals().getConsoleInformation().GetRenderSettings();
return renderSettings.GetAttributeColors(attr);
}
// Routine Description:
// - Determines whether the selection area is empty.
// Arguments:
// - <none>
// Return Value:
// - True if the selection variables contain valid selection data. False otherwise.
constboolRenderData::IsSelectionActive() const
{
returnSelection::Instance().IsAreaSelected();
}
constboolRenderData::IsBlockSelection() constnoexcept
{
return !Selection::Instance().IsLineSelection();
}
// Routine Description:
// - If a selection exists, clears it and restores the state.
// Will also unblock a blocked write if one exists.
// Arguments:
// - <none> (Uses global state)
// Return Value:
// - <none>
voidRenderData::ClearSelection()
{
Selection::Instance().ClearSelection();
}
// Routine Description:
// - Resets the current selection and selects a new region from the start to end coordinates
// Arguments:
// - coordStart - Position to start selection area from
// - coordEnd - Position to select up to
// Return Value:
// - <none>
voidRenderData::SelectNewRegion(const til::point coordStart, const til::point coordEnd)
{
Selection::Instance().SelectNewRegion(coordStart, coordEnd);
}
const til::point_span* RenderData::GetSearchHighlightFocused() constnoexcept
{
returnnullptr;
}
// Routine Description:
// - Gets the current selection anchor position
// Arguments:
// - none
// Return Value:
// - current selection anchor
const til::point RenderData::GetSelectionAnchor() constnoexcept
{
returnSelection::Instance().GetSelectionAnchor();
}
// Routine Description:
// - Gets the current end selection anchor position
// Arguments:
// - none
// Return Value:
// - current selection anchor
const til::point RenderData::GetSelectionEnd() constnoexcept
{
// The selection area in ConHost is encoded as two things...
// - SelectionAnchor: the initial position where the selection was started
// - SelectionRect: the rectangular region denoting a portion of the buffer that is selected
// The following is an excerpt from Selection::GetSelectionSpans
// if the anchor (start of select) was in the top right or bottom left of the box,
// we need to remove rectangular overlap in the middle.
// e.g.
// For selections with the anchor in the top left (A) or bottom right (B),
// it is valid to maintain the inner rectangle (+) as part of the selection
// A+++++++================
// ==============++++++++B
// + and = are valid highlights in this scenario.
// For selections with the anchor in in the top right (A) or bottom left (B),
// we must remove a portion of the first/last line that lies within the rectangle (+)
// +++++++A=================
// ==============B+++++++
// Only = is valid for highlight in this scenario.
// This is only needed for line selection. Box selection doesn't need to account for this.
constauto selectionRect = Selection::Instance().GetSelectionRectangle();
// To extract the end anchor from this rect, we need to know which corner of the rect is the SelectionAnchor
// Then choose the opposite corner.
constauto anchor = Selection::Instance().GetSelectionAnchor();
constauto x_pos = (selectionRect.left == anchor.x) ? selectionRect.right : selectionRect.left;
constauto y_pos = (selectionRect.top == anchor.y) ? selectionRect.bottom : selectionRect.top;
return { x_pos, y_pos };
}