Add support for Underlined independent of LVB_UNDERSCORE #4078

Closed
opened 2026-01-30 23:37:28 +00:00 by claunia · 6 comments
Owner

Originally created by @zadjii-msft on GitHub (Sep 26, 2019).

Discussed with @DHowett-MSFT, as a follow up of #2554.

We've been using LVB_UNDERSCORE for underlines in the console since Windows 10 was released. However, LVB_UNDERSCORE is more of a box-drawing feature, it draws the underline fully under the text.

We should more correctly have a separate Underline state, that draws the underline at the baseline of the text, not just under it.

In VT, underline is in a trinary state: [No Underline, Underlined, Doubly Underlined]. We should make sure to store this in the buffer appropriately.

Technically, we believe characters could have both Underlined and LVB_UNDERSCORE.

Open Questions:

  • should Underline be read from the API as LVB_UNDERSCORE? Currently it is, but I think that it shouldn't. If you round-trip the attributes, then that would pollute the state.
Originally created by @zadjii-msft on GitHub (Sep 26, 2019). Discussed with @DHowett-MSFT, as a follow up of #2554. We've been using LVB_UNDERSCORE for underlines in the console since Windows 10 was released. However, LVB_UNDERSCORE is more of a box-drawing feature, it draws the underline fully under the text. We should more correctly have a separate Underline state, that draws the underline at the baseline of the text, not just under it. In VT, underline is in a trinary state: [No Underline, Underlined, Doubly Underlined]. We should make sure to store this in the buffer appropriately. Technically, we believe characters could have both Underlined and LVB_UNDERSCORE. Open Questions: * [ ] should Underline be read from the API as LVB_UNDERSCORE? Currently it is, but I think that it _shouldn't_. If you round-trip the attributes, then that would pollute the state.
claunia added the Product-ConhostResolution-Fix-CommittedIssue-TaskArea-VT labels 2026-01-30 23:37:28 +00:00
Author
Owner

@DHowett commented on GitHub (Aug 1, 2020):

The diff to do this directly is pretty minimal (and it looks nicer now that @j4james has done #7107).

Should underline read back as LVB_UNDERSCORE

Nope, for the exact reason you mentioned.

Trinary

There was an open discussion about how underline types stack in #2916.

James asserts, about double/single underline being a trinary state,

Yes and no. There aren't many terminals that support double-underline for real (most treat it as a synonym for single underline) so there's no obvious consensus. In VTE it's a trinary state, where the last choice (single or double) takes precedence. However in XTerm, underline and double-underline are actually separate attributes, and double-underline takes precedence when both are set, regardless of the order they were applied.

I'm not sure it matters that much, but I'd probably be inclined to follow the XTerm approach.

I'm inclined to agree with this.

If we don't have to worry about making underlined/doubly underlined trinary, we can close 2915 with 2 files changed, 7 insertions(+), 4 deletions(-).

@DHowett commented on GitHub (Aug 1, 2020): The diff to do this directly is pretty minimal (and it looks nicer now that @j4james has done #7107). > Should underline read back as LVB_UNDERSCORE Nope, for the exact reason you mentioned. > Trinary There was an open discussion about how underline types stack in #2916. James asserts, about double/single underline being a trinary state, > Yes and no. There aren't many terminals that support double-underline for real (most treat it as a synonym for single underline) so there's no obvious consensus. In VTE it's a trinary state, where the last choice (single or double) takes precedence. However in XTerm, underline and double-underline are actually separate attributes, and double-underline takes precedence when both are set, regardless of the order they were applied. > > I'm not sure it matters that much, but I'd probably be inclined to follow the XTerm approach. I'm inclined to agree with this. If we don't have to worry about making underlined/doubly underlined trinary, we can close 2915 with `2 files changed, 7 insertions(+), 4 deletions(-)`.
Author
Owner

@DHowett commented on GitHub (Aug 1, 2020):

Before

image

After

image

@DHowett commented on GitHub (Aug 1, 2020): Before ![image](https://user-images.githubusercontent.com/189190/89090965-1a015100-d35b-11ea-9cda-1545d784c6e1.png) After ![image](https://user-images.githubusercontent.com/189190/89090959-15d53380-d35b-11ea-8f4e-de0f89c52c9c.png)
Author
Owner

@j4james commented on GitHub (Aug 1, 2020):

@DHowett I was just putting together a PR for this, but it looks like you've done it already. Should I leave this with you?

As for the doubly underlined attribute, I was going to suggest we simply render that as a single underline for now, since that's what many some other terminals seem to do. We should still parse and store it separately, though, so we can pass on the correct SGR value to the conpty pipe for clients that do actually render it differently.

Edit: I've just done some retesting, and there aren't as many terminals treating single and double underlines the same as I thought. It's not always obvious that a double underline is being used (at least on a hidpi screen) until you zoom in. I still think it might be a reasonable temporary solution, though.

@j4james commented on GitHub (Aug 1, 2020): @DHowett I was just putting together a PR for this, but it looks like you've done it already. Should I leave this with you? As for the doubly underlined attribute, I was going to suggest we simply render that as a single underline for now, since that's what <s>many</s> some other terminals seem to do. We should still parse and store it separately, though, so we can pass on the correct SGR value to the conpty pipe for clients that do actually render it differently. Edit: I've just done some retesting, and there aren't as many terminals treating single and double underlines the same as I thought. It's not always obvious that a double underline is being used (at least on a hidpi screen) until you zoom in. I still think it might be a reasonable temporary solution, though.
Author
Owner

@DHowett commented on GitHub (Aug 1, 2020):

I wasn’t going to do the Doubly Underlined bits, so I imagine you’re farther along than I am :) I’ll leave it to you

Agree on equating doubly with singly during render for now

Thanks!

@DHowett commented on GitHub (Aug 1, 2020): I wasn’t going to do the Doubly Underlined bits, so I imagine you’re farther along than I am :) I’ll leave it to you Agree on equating doubly with singly during render for now Thanks!
Author
Owner

@j4james commented on GitHub (Aug 1, 2020):

OK so I started with rendering the doubly underlined attribute as a simple alias for the single underline, but it occurred to me that it might not be that difficult to add a proper renderer for it with the framework we now have in place. And you can see below some examples of what I've got so far.

I'm still tweaking the look, and there are some issues with the conpty pass-through that I'm not completely happy with, so in the meantime I thought it would be best if I just submit a PR with the basic underline functionality to start with. Then we can continue the doubly-underline discussion in #2916 and add a separate PR for that later.

image

@j4james commented on GitHub (Aug 1, 2020): OK so I started with rendering the doubly underlined attribute as a simple alias for the single underline, but it occurred to me that it might not be that difficult to add a proper renderer for it with the framework we now have in place. And you can see below some examples of what I've got so far. I'm still tweaking the look, and there are some issues with the conpty pass-through that I'm not completely happy with, so in the meantime I thought it would be best if I just submit a PR with the basic underline functionality to start with. Then we can continue the doubly-underline discussion in #2916 and add a separate PR for that later. ![image](https://user-images.githubusercontent.com/4181424/89110000-21e5f180-d43e-11ea-8a7d-587c09ff04d5.png)
Author
Owner

@ghost commented on GitHub (Aug 26, 2020):

:tada:This issue was addressed in #7148, which has now been successfully released as Windows Terminal Preview v1.3.2382.0.🎉

Handy links:

@ghost commented on GitHub (Aug 26, 2020): :tada:This issue was addressed in #7148, which has now been successfully released as `Windows Terminal Preview v1.3.2382.0`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.3.2382.0) * [Store Download](https://www.microsoft.com/store/apps/9n8g5rfz9xk3?cid=storebadge&ocid=badge)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#4078