Skip to content
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

Merged
9 commits merged into from
Aug 19, 2019
Merged

Add support for HTML copy #1224

9 commits merged into from
Aug 19, 2019

Conversation

carlos-zamora
Copy link
Member

@carlos-zamora carlos-zamora commented Jun 12, 2019

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:
    • moved from Clipboard to TextBuffer
    • added iFontHeightPoints and fontFaceName so that I don't depend on the ServiceLocator
  • TermControl: have CopyToClipboardEventArgs have space for both data types
  • TerminalApp: just extract the data from the event and put it into the clipboard

References

#1146 (HTML portion)

PR Checklist

  • Closes half of Feature Request: HTML Copy #1146
  • CLA signed. If not, go over here and sign the CLA
  • Tests added/passed
  • Requires documentation to be updated
  • 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.

Detailed Description of the Pull Request / Additional comments

I do have a few things I'm not sure of:

  • As of now, HTML copy is always enabled. I can easily add make it optional but idk what the design should look like (i.e.: new keybinding copies only HTML?)
  • I don't think we can/should add tests to this because (1) it resuses old code and (2) we definitely don't want to actually copy stuff to the clipboard during a test. The only thing to test would be what GenHTML does but that was already here.
  • Not sure if the iFontHeightPointsis right (or even described properly for that matter) in GenHTML().
    • for Clipboard we do int const iFontHeightPoints = fontData.GetUnscaledSize().Y * 72 / ServiceLocator::LocateGlobals().dpi;
    • for TermControl I did fontData.GetUnscaledSize().Y
    • I don't really know how to verify if this is correct. But I also don't know if we actually even need the DPI here. Thoughts?

Validation Steps Performed

Copy selections and paste to MSWord (regular text vs formatted text)


try
{
std::string const szHtmlClipFormat =
Copy link
Contributor

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

// measure clip header
size_t const cbHeader = 157; // when formats are expanded, there will be 157 bytes in the header.

std::string const szHtmlHeader =
Copy link
Contributor

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

size_t const cbHtmlHeader = szHtmlHeader.size();

std::string const szHtmlFragStart = "<!--StartFragment -->";
std::string const szHtmlFragEnd = "<!--EndFragment -->";
Copy link
Contributor

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("...");

"<!DOCTYPE><HTML><HEAD><TITLE>Windows Console Host</TITLE></HEAD><BODY>";
size_t const cbHtmlHeader = szHtmlHeader.size();

std::string const szHtmlFragStart = "<!--StartFragment -->";
Copy link
Contributor

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

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
Copy link
Contributor

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.

// - 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
Copy link
Contributor

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 Show resolved Hide resolved

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.
Copy link
Contributor

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.

Copy link
Member

@zadjii-msft zadjii-msft left a 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.

src/cascadia/TerminalControl/TermControl.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControl.cpp Outdated Show resolved Hide resolved
src/interactivity/win32/Clipboard.cpp Show resolved Hide resolved
@ghost ghost added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jun 13, 2019
@zadjii-msft zadjii-msft added Area-TerminalControl Issues pertaining to the terminal control (input, selection, keybindings, mouse interaction, etc.) Product-Terminal The new Windows Terminal. labels Jun 13, 2019
@oising
Copy link
Collaborator

oising commented Jun 13, 2019

Oh, HTML copy :)

CSI Pm i  Media Copy (MC).
            Ps = 0  -> Print screen (default).
            Ps = 4  -> Turn off printer controller mode.
            Ps = 5  -> Turn on printer controller mode.
            Ps = 1 0  -> HTML screen dump, xterm.
            Ps = 1 1  -> SVG screen dump, xterm.

@carlos-zamora carlos-zamora self-assigned this Jun 18, 2019
@ghost ghost removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jun 18, 2019
Refactor RetrieveSelectedTextFromBuffer
Modify CopyToClipboardEventArgs to include HTML data
NOTE: refactoring text buffer code is a separate task. New issue to be created.
@carlos-zamora carlos-zamora added the Needs-Second It's a PR that needs another sign-off label Aug 16, 2019
src/cascadia/TerminalApp/App.cpp Outdated Show resolved Hide resolved
@@ -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;
Copy link
Contributor

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.

Copy link
Member Author

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. :(

@DHowett-MSFT
Copy link
Contributor

nit: name. something like add support for HTML copy or whatever

@carlos-zamora carlos-zamora changed the title HTML Copy Add support for HTML copy Aug 19, 2019
@carlos-zamora carlos-zamora added AutoMerge Marked for automatic merge by the bot when requirements are met and removed Needs-Second It's a PR that needs another sign-off labels Aug 19, 2019
@ghost
Copy link

ghost commented Aug 19, 2019

Hello @carlos-zamora!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

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 (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 71eaf62 into master Aug 19, 2019
@ghost ghost deleted the dev/cazamor/html-copy branch August 19, 2019 22:59
@ghost
Copy link

ghost commented Aug 27, 2019

🎉Windows Terminal Preview v0.4.2382.0 has been released which incorporates this pull request.:tada:

Handy links:

@anirudhrb anirudhrb mentioned this pull request Nov 12, 2019
5 tasks
zadjii-msft pushed a commit that referenced this pull request Nov 13, 2019
## 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
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-TerminalControl Issues pertaining to the terminal control (input, selection, keybindings, mouse interaction, etc.) AutoMerge Marked for automatic merge by the bot when requirements are met Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants