/*++ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: - selection.hpp Abstract: - This module is used for managing the selection region Author(s): - Michael Niksa (MiNiksa) 4-Jun-2014 - Paul Campbell (PaulCam) 4-Jun-2014 Revision History: - From components of clipbrd.h/.c and input.h/.c of v1 console. --*/ #pragma once #include "input.h" #include "../interactivity/inc/IAccessibilityNotifier.hpp" #include "../interactivity/inc/IConsoleWindow.hpp" class Selection { public: ~Selection() = default; std::vector GetSelectionRects() const; void ShowSelection(); void HideSelection(); static Selection& Instance(); // Key selection generally refers to "mark mode" selection where // the cursor is present and used to navigate 100% with the // keyboard. // // Mouse selection means either the block or line mode selection // usually initiated by the mouse. // // However, Mouse mode can also mean initiated with our // shift+directional commands as no block cursor is required for // navigation. void InitializeMarkSelection(); void InitializeMouseSelection(const COORD coordBufferPos); void SelectNewRegion(const COORD coordStart, const COORD coordEnd); void SelectAll(); void ExtendSelection(_In_ COORD coordBufferPos); void AdjustSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd); void ClearSelection(); void ClearSelection(const bool fStartingNewSelection); void ColorSelection(const SMALL_RECT& srRect, const TextAttribute attr); void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr); // delete these or we can accidentally get copies of the singleton Selection(Selection const&) = delete; void operator=(Selection const&) = delete; protected: Selection(); private: void _SetSelectionVisibility(const bool fMakeVisible); void _PaintSelection() const; void _CancelMarkSelection(); void _CancelMouseSelection(); // ------------------------------------------------------------------------------------------------------- // input handling (selectionInput.cpp) public: // key handling // N.B.: This enumeration helps push up calling clipboard functions into // the caller. This way, all of the selection code is independent of // the clipboard and thus more easily shareable with Windows editions // that do not have a clipboard (i.e. OneCore). enum class KeySelectionEventResult { EventHandled, EventNotHandled, CopyToClipboard }; KeySelectionEventResult HandleKeySelectionEvent(const INPUT_KEY_INFO* const pInputKeyInfo); static bool s_IsValidKeyboardLineSelection(const INPUT_KEY_INFO* const pInputKeyInfo); bool HandleKeyboardLineSelectionEvent(const INPUT_KEY_INFO* const pInputKeyInfo); void CheckAndSetAlternateSelection(); // calculation functions [[nodiscard]] static bool s_GetInputLineBoundaries(_Out_opt_ COORD* const pcoordInputStart, _Out_opt_ COORD* const pcoordInputEnd); void GetValidAreaBoundaries(_Out_opt_ COORD* const pcoordValidStart, _Out_opt_ COORD* const pcoordValidEnd) const; static bool s_IsWithinBoundaries(const COORD coordPosition, const COORD coordStart, const COORD coordEnd); private: // key handling bool _HandleColorSelection(const INPUT_KEY_INFO* const pInputKeyInfo); bool _HandleMarkModeSelectionNav(const INPUT_KEY_INFO* const pInputKeyInfo); COORD WordByWordSelection(const bool fPrevious, const Microsoft::Console::Types::Viewport& bufferSize, const COORD coordAnchor, const COORD coordSelPoint) const; // ------------------------------------------------------------------------------------------------------- // selection state (selectionState.cpp) public: bool IsKeyboardMarkSelection() const; bool IsMouseInitiatedSelection() const; bool IsLineSelection() const; bool IsInSelectingState() const; bool IsInQuickEditMode() const; bool IsAreaSelected() const; bool IsMouseButtonDown() const; DWORD GetPublicSelectionFlags() const noexcept; COORD GetSelectionAnchor() const noexcept; SMALL_RECT GetSelectionRectangle() const noexcept; void SetLineSelection(const bool fLineSelectionOn); bool ShouldAllowMouseDragSelection(const COORD mousePosition) const noexcept; // TODO: these states likely belong somewhere else void MouseDown(); void MouseUp(); private: void _SaveCursorData(const Cursor& cursor) noexcept; void _RestoreDataToCursor(Cursor& cursor) noexcept; void _AlignAlternateSelection(const bool fAlignToLineSelect); void _SetSelectingState(const bool fSelectingOn); // TODO: extended edit key should probably be in here (remaining code is in cmdline.cpp) // TODO: trim leading zeros should probably be in here (pending move of reactive code from input.cpp to selectionInput.cpp) // TODO: enable color selection should be in here // TODO: quick edit mode should be in here // TODO: console selection mode should be in here // TODO: consider putting word delims in here // -- State/Flags -- // This replaces/deprecates CONSOLE_SELECTION_INVERTED on gci->SelectionFlags bool _fSelectionVisible; bool _fLineSelection; // whether to use line selection or block selection bool _fUseAlternateSelection; // whether the user has triggered the alternate selection method bool _allowMouseDragSelection; // true if the dragging the mouse should change the selection // Flags for this DWORD are defined in wincon.h. Search for def:CONSOLE_SELECTION_IN_PROGRESS, etc. DWORD _dwSelectionFlags; // -- Current Selection Data -- // Anchor is the point the selection was started from (and will be one of the corners of the rectangle). COORD _coordSelectionAnchor; // Rectangle is the area inscribing the selection. It is extended to screen edges in a particular way for line selection. SMALL_RECT _srSelectionRect; // -- Saved Cursor Data -- // Saved when a selection is started for restoration later. Position is in character coordinates, not pixels. COORD _coordSavedCursorPosition; ULONG _ulSavedCursorSize; bool _fSavedCursorVisible; COLORREF _savedCursorColor; CursorType _savedCursorType; #ifdef UNIT_TESTING friend class SelectionTests; friend class SelectionInputTests; friend class ClipboardTests; #endif };