-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for HTML copy #1224
Conversation
src/buffer/out/textBuffer.cpp
Outdated
|
||
try | ||
{ | ||
std::string const szHtmlClipFormat = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe constexpr std::wstring_view
is better
src/buffer/out/textBuffer.cpp
Outdated
// measure clip header | ||
size_t const cbHeader = 157; // when formats are expanded, there will be 157 bytes in the header. | ||
|
||
std::string const szHtmlHeader = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe constexpr std::wstring_view is better
src/buffer/out/textBuffer.cpp
Outdated
size_t const cbHtmlHeader = szHtmlHeader.size(); | ||
|
||
std::string const szHtmlFragStart = "<!--StartFragment -->"; | ||
std::string const szHtmlFragEnd = "<!--EndFragment -->"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This constant is only used once (in line 1239), its definition should be moved to that location and the constant should be changed to constexpr std::string_view
:
// copy HTML end fragment
constexpr std::string_view szHtmlFragEnd = "...";
szClipboard.append(szHtmlFragEnd);
Given that the constant is only used once and the point of use even has a comment stating what is being done (append end fragment) you can even consider removing the constant altogether, as this code is not less readable than the above:
// copy HTML end fragment
szClipboard.append("...");
src/buffer/out/textBuffer.cpp
Outdated
"<!DOCTYPE><HTML><HEAD><TITLE>Windows Console Host</TITLE></HEAD><BODY>"; | ||
size_t const cbHtmlHeader = szHtmlHeader.size(); | ||
|
||
std::string const szHtmlFragStart = "<!--StartFragment -->"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to point of first use
src/buffer/out/textBuffer.cpp
Outdated
std::string szSpanFontSize; | ||
szSpanFontSize.resize(cbSpanFontSize + 1); // reserve space for null after string for sprintf | ||
sprintf_s(szSpanFontSize.data(), cbSpanFontSize + 1, szSpanFontSizePattern.data(), iFontHeightPoints); | ||
szSpanFontSize.resize(cbSpanFontSize); //chop off null at end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: This might be the only way to do formatting, but the resize, format, resize again seems cumbersome.
I know everybody hates C++ streams but it seems that they would work relatively well for this function at least.
src/buffer/out/textBuffer.cpp
Outdated
// - string containing the generated HTML | ||
std::string TextBuffer::GenHTML(const TextAndColor& rows, const int iFontHeightPoints, const PCWCHAR fontFaceName) | ||
{ | ||
std::string szClipboard; // we will build the data going back in this string buffer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to point of first use
src/buffer/out/textBuffer.cpp
Outdated
|
||
std::string const szSpanStartPattern = R"X(<SPAN STYLE="color:#%02x%02x%02x;background-color:#%02x%02x%02x">)X"; | ||
|
||
size_t const cbSpanStart = 53; // when format is expanded, there will be 53 bytes per color pattern. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we still using Hungarian Notation? According to NL.5: Avoid encoding type information in names explicitly not recommended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I'm fine with this, save for the _actualFont
thing. I don't think it's your responsibility to update GenHTML
to be more stylistically modern, since you're just lifting that function. We could always file a follow-up issue to modernize that function.
Oh, HTML copy :)
|
Refactor RetrieveSelectedTextFromBuffer Modify CopyToClipboardEventArgs to include HTML data
NOTE: refactoring text buffer code is a separate task. New issue to be created.
40a8d8e
to
514d007
Compare
@@ -515,7 +275,9 @@ void Clipboard::CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, | |||
|
|||
if (fAlsoCopyHtml) | |||
{ | |||
std::string HTMLToPlaceOnClip = GenHTML(rows); | |||
const auto& fontData = ServiceLocator::LocateGlobals().getConsoleInformation().GetActiveOutputBuffer().GetCurrentFont(); | |||
int const iFontHeightPoints = fontData.GetUnscaledSize().Y * 72 / ServiceLocator::LocateGlobals().dpi; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wonder if there's an existing constant for this 72
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hate to say it but I couldn't find anything on where the value came from or what constant we could use for it. :(
nit: name. something like |
Hello @carlos-zamora! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
🎉 Handy links: |
## Summary of the Pull Request RTF data is now copied to the clipboard. Tested by copy pasting text from terminal to WordPad. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #2487 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Requires documentation to be updated * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #2487 <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments Mostly similar to PR #1224. Added a new static method `GenRTF` in `TextBuffer` that is responsible for generating the RTF representation of a given text. The generated RTF is added to the `DataPackage` that is ultimately passed to the clipboard. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Validated by copy pasting text from the terminal to WordPad. Validated with different colors to make sure that is working. (MS Word seems to prefer HTML data from the clipboard instead of RTF.) <hr> * Copy RTF data to the clipboard * Added comment explaining various parts of the header * Fixed static code analysis issues and added noexcept to GenRTF() * Removed noexcept
Summary of the Pull Request
HTML data is now copied to the clipboard. I tried reusing the old clipboard method so I had to move some stuff around. The design is pretty straightforward. Instead of sending just text data up on a
CopyToClipboard
event, send the HTML data up too in the same winrt object.Here's some specifics:
Clipboard::GenHTML()
Changes:Clipboard
toTextBuffer
iFontHeightPoints
andfontFaceName
so that I don't depend on theServiceLocator
TermControl
: haveCopyToClipboardEventArgs
have space for both data typesTerminalApp
: just extract the data from the event and put it into the clipboardReferences
#1146 (HTML portion)
PR Checklist
Detailed Description of the Pull Request / Additional comments
I do have a few things I'm not sure of:
GenHTML
does but that was already here.iFontHeightPoints
is right (or even described properly for that matter) inGenHTML()
.Clipboard
we doint const iFontHeightPoints = fontData.GetUnscaledSize().Y * 72 / ServiceLocator::LocateGlobals().dpi;
TermControl
I didfontData.GetUnscaledSize().Y
Validation Steps Performed
Copy selections and paste to MSWord (regular text vs formatted text)