terminal/src/host/CopyToCharPopup.cpp

85 lines
2.7 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "CopyToCharPopup.hpp"
#include "stream.h"
#include "_stream.h"
#include "resource.h"
static constexpr size_t COPY_TO_CHAR_PROMPT_LENGTH = 26;
CopyToCharPopup::CopyToCharPopup(SCREEN_INFORMATION& screenInfo) :
Popup(screenInfo, { COPY_TO_CHAR_PROMPT_LENGTH + 2, 1 })
{
}
// Routine Description:
// - copies text from the previous command into the current prompt line, up to but not including the first
// instance of wch after the current cookedReadData's cursor position. if wch is not found, nothing is copied.
// Arguments:
// - cookedReadData - the read data to operate on
// - LastCommand - the most recent command run
// - wch - the wchar to copy up to
void CopyToCharPopup::_copyToChar(COOKED_READ_DATA& cookedReadData, const std::wstring_view LastCommand, const wchar_t wch)
{
// make sure that there it is possible to copy any found text over
if (cookedReadData.InsertionPoint() >= LastCommand.size())
{
return;
}
const auto searchStart = std::next(LastCommand.cbegin(), cookedReadData.InsertionPoint() + 1);
auto location = std::find(searchStart, LastCommand.cend(), wch);
// didn't find wch so copy nothing
if (location == LastCommand.cend())
{
return;
}
const auto startIt = std::next(LastCommand.cbegin(), cookedReadData.InsertionPoint());
const auto endIt = location;
cookedReadData.Write({ &*startIt, gsl::narrow<size_t>(std::distance(startIt, endIt)) });
}
// Routine Description:
// - This routine handles the delete char popup. It returns when we're out of input or the user has entered a char.
// Return Value:
// - CONSOLE_STATUS_WAIT - we ran out of input, so a wait block was created
// - CONSOLE_STATUS_READ_COMPLETE - user hit return
[[nodiscard]] NTSTATUS CopyToCharPopup::Process(COOKED_READ_DATA& cookedReadData) noexcept
{
wchar_t wch = UNICODE_NULL;
bool popupKey = false;
DWORD modifiers = 0;
NTSTATUS Status = _getUserInput(cookedReadData, popupKey, modifiers, wch);
if (!NT_SUCCESS(Status))
{
return Status;
}
CommandLine::Instance().EndCurrentPopup();
if (popupKey && wch == VK_ESCAPE)
{
return CONSOLE_STATUS_WAIT_NO_BLOCK;
}
// copy up to specified char
const auto lastCommand = cookedReadData.History().GetLastCommand();
if (!lastCommand.empty())
{
_copyToChar(cookedReadData, lastCommand, wch);
}
return CONSOLE_STATUS_WAIT_NO_BLOCK;
}
void CopyToCharPopup::_DrawContent()
{
_DrawPrompt(ID_CONSOLE_MSGCMDLINEF2);
}