/*++ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: - cmdline.h Abstract: - This file contains the internal structures and definitions used by command line input and editing. Author: - Therese Stowell (ThereseS) 15-Nov-1991 Revision History: - Mike Griese (migrie) Jan 2018: Refactored the history and alias functionality into their own files. - Michael Niksa (miniksa) May 2018: Split apart popup information. Started encapsulating command line things. Removed 0 length buffers. Notes: The input model for the command line editing popups is complex. Here is the relevant pseudocode: CookedReadWaitRoutine if (CookedRead->Popup) Status = (*CookedRead->Popup->Callback)(); if (Status == CONSOLE_STATUS_READ_COMPLETE) return STATUS_SUCCESS; return Status; CookedRead if (Command Line Editing Key) ProcessCommandLine else process regular key ProcessCommandLine if F7 return Popup Popup draw popup return ProcessCommandListInput ProcessCommandListInput while (TRUE) GetChar if (wait) return wait switch (char) . . . --*/ #pragma once #include "input.h" #include "screenInfo.hpp" #include "server.h" #include "history.h" #include "alias.h" #include "readDataCooked.hpp" #include "popup.h" class CommandLine { public: ~CommandLine(); static CommandLine& Instance(); bool IsEditLineEmpty() const; void Hide(const bool fUpdateFields); void Show(); bool IsVisible() const noexcept; [[nodiscard]] NTSTATUS ProcessCommandLine(COOKED_READ_DATA& cookedReadData, _In_ WCHAR wch, const DWORD dwKeyState); [[nodiscard]] HRESULT StartCommandNumberPopup(COOKED_READ_DATA& cookedReadData); bool HasPopup() const noexcept; Popup& GetPopup(); void EndCurrentPopup(); void EndAllPopups(); void DeletePromptAfterCursor(COOKED_READ_DATA& cookedReadData) noexcept; COORD DeleteFromRightOfCursor(COOKED_READ_DATA& cookedReadData) noexcept; protected: CommandLine(); // delete these because we don't want to accidentally get copies of the singleton CommandLine(CommandLine const&) = delete; CommandLine& operator=(CommandLine const&) = delete; [[nodiscard]] NTSTATUS _startCommandListPopup(COOKED_READ_DATA& cookedReadData); [[nodiscard]] NTSTATUS _startCopyFromCharPopup(COOKED_READ_DATA& cookedReadData); [[nodiscard]] NTSTATUS _startCopyToCharPopup(COOKED_READ_DATA& cookedReadData); void _processHistoryCycling(COOKED_READ_DATA& cookedReadData, const CommandHistory::SearchDirection searchDirection); void _setPromptToOldestCommand(COOKED_READ_DATA& cookedReadData); void _setPromptToNewestCommand(COOKED_READ_DATA& cookedReadData); COORD _deletePromptBeforeCursor(COOKED_READ_DATA& cookedReadData) noexcept; COORD _moveCursorToEndOfPrompt(COOKED_READ_DATA& cookedReadData) noexcept; COORD _moveCursorToStartOfPrompt(COOKED_READ_DATA& cookedReadData) noexcept; COORD _moveCursorLeftByWord(COOKED_READ_DATA& cookedReadData) noexcept; COORD _moveCursorLeft(COOKED_READ_DATA& cookedReadData); COORD _moveCursorRightByWord(COOKED_READ_DATA& cookedReadData) noexcept; COORD _moveCursorRight(COOKED_READ_DATA& cookedReadData) noexcept; void _insertCtrlZ(COOKED_READ_DATA& cookedReadData) noexcept; void _deleteCommandHistory(COOKED_READ_DATA& cookedReadData) noexcept; void _fillPromptWithPreviousCommandFragment(COOKED_READ_DATA& cookedReadData) noexcept; COORD _cycleMatchingCommandHistoryToPrompt(COOKED_READ_DATA& cookedReadData); #ifdef UNIT_TESTING friend class CommandLineTests; friend class CommandNumberPopupTests; #endif private: std::deque> _popups; bool _isVisible; }; void DeleteCommandLine(COOKED_READ_DATA& cookedReadData, const bool fUpdateFields); void RedrawCommandLine(COOKED_READ_DATA& cookedReadData); // Values for WriteChars(), WriteCharsLegacy() dwFlags #define WC_DESTRUCTIVE_BACKSPACE 0x01 #define WC_KEEP_CURSOR_VISIBLE 0x02 #define WC_PRINTABLE_CONTROL_CHARS 0x04 // This is no longer necessary. The buffer will always be Unicode. We don't need to perform special work to check if we're in a raster font // and convert the entire buffer to match (and all insertions). //#define WC_FALSIFY_UNICODE 0x08 #define WC_LIMIT_BACKSPACE 0x10 //#define WC_NONDESTRUCTIVE_TAB 0x20 - This is not needed anymore, because the VT code handles tabs internally now. //#define WC_NEWLINE_SAVE_X 0x40 - This has been replaced with an output mode flag instead as it's line discipline behavior that may not necessarily be coupled with VT. #define WC_DELAY_EOL_WRAP 0x80 // Word delimiters bool IsWordDelim(const wchar_t wch); bool IsWordDelim(const std::wstring_view charData); [[nodiscard]] HRESULT DoSrvSetConsoleTitleW(const std::wstring_view title) noexcept; bool IsValidStringBuffer(_In_ bool Unicode, _In_reads_bytes_(Size) PVOID Buffer, _In_ ULONG Size, _In_ ULONG Count, ...); void SetCurrentCommandLine(COOKED_READ_DATA& cookedReadData, _In_ SHORT Index);