Terminal: support for underline color and styles
the text is now printed above the underline. Change-Id: I1a3a7713bf514830106532e1534793e0fe158bc2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6706 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
c5abd6a796
commit
18d6122240
@ -167,6 +167,16 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
// Underline style
|
||||
enum {
|
||||
SINGLE_UNDERLINE = 1,
|
||||
DOUBLE_UNDERLINE,
|
||||
CURLY_UNDERLINE,
|
||||
DOTTED_UNDERLINE,
|
||||
DASHED_UNDERLINE
|
||||
};
|
||||
|
||||
|
||||
// Preference Folder and setting path
|
||||
|
||||
static const int32 DEFAULT = -1;
|
||||
@ -206,9 +216,10 @@ enum {
|
||||
#define FONT 0x0100
|
||||
#define RESERVE 0x0080
|
||||
#define DUMPCR 0x0040
|
||||
#define UNDERSET 0x0020
|
||||
#define FORECOLOR 0xFF0000
|
||||
#define BACKCOLOR 0xFF000000
|
||||
#define CHAR_ATTRIBUTES 0xFFFF7700
|
||||
#define CHAR_ATTRIBUTES 0xFFFF7720
|
||||
|
||||
#define FORECOLORED(x) ((x) << 16)
|
||||
#define BACKCOLORED(x) ((x) << 24)
|
||||
|
@ -795,19 +795,49 @@ TermParse::EscParse()
|
||||
break;
|
||||
|
||||
case 4: /* Underline */
|
||||
attributes |= UNDERLINE;
|
||||
if ((row + 1) < nparam) {
|
||||
row++;
|
||||
switch (param[row]) {
|
||||
case 0:
|
||||
attributes.UnsetUnder();
|
||||
break;
|
||||
case 1:
|
||||
attributes.SetUnder(SINGLE_UNDERLINE);
|
||||
break;
|
||||
case 2:
|
||||
attributes.SetUnder(DOUBLE_UNDERLINE);
|
||||
break;
|
||||
case 3:
|
||||
attributes.SetUnder(CURLY_UNDERLINE);
|
||||
break;
|
||||
case 4:
|
||||
attributes.SetUnder(DOTTED_UNDERLINE);
|
||||
break;
|
||||
case 5:
|
||||
attributes.SetUnder(DASHED_UNDERLINE);
|
||||
break;
|
||||
default:
|
||||
row = nparam; // force exit of the parsing
|
||||
break;
|
||||
}
|
||||
} else
|
||||
attributes.SetUnder(SINGLE_UNDERLINE);
|
||||
break;
|
||||
|
||||
case 7: /* Inverse */
|
||||
attributes |= INVERSE;
|
||||
break;
|
||||
|
||||
case 21: /* Double Underline */
|
||||
attributes.SetUnder(DOUBLE_UNDERLINE);
|
||||
break;
|
||||
|
||||
case 22: /* Not Bold */
|
||||
attributes &= ~BOLD;
|
||||
break;
|
||||
|
||||
case 24: /* Not Underline */
|
||||
attributes &= ~UNDERLINE;
|
||||
attributes.UnsetUnder();
|
||||
break;
|
||||
|
||||
case 27: /* Not Inverse */
|
||||
@ -891,6 +921,25 @@ TermParse::EscParse()
|
||||
case 49:
|
||||
attributes.UnsetBackground();
|
||||
break;
|
||||
|
||||
case 58:
|
||||
{
|
||||
if (nparam >= 3 && param[row+1] == 5) {
|
||||
attributes.SetIndexedUnderline(param[row+2]);
|
||||
row += 2;
|
||||
} else if (nparam >= 5 && param[row+1] == 2) {
|
||||
attributes.SetDirectUnderline(param[row+2], param[row+3], param[row+4]);
|
||||
row += 4;
|
||||
} else {
|
||||
row = nparam; // force exit of the parsing
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 59:
|
||||
attributes.UnsetUnderline();
|
||||
break;
|
||||
}
|
||||
}
|
||||
fBuffer->SetAttributes(attributes);
|
||||
|
@ -1050,12 +1050,15 @@ TermView::_DrawLinePart(float x1, float y1, Attributes attr,
|
||||
|
||||
rgb_color rgb_fore = fTextForeColor;
|
||||
rgb_color rgb_back = fTextBackColor;
|
||||
rgb_color rgb_under = fTextForeColor;
|
||||
|
||||
// color attribute
|
||||
if (attr.IsForeSet())
|
||||
rgb_fore = attr.ForegroundColor(fTextBuffer->Palette());
|
||||
if (attr.IsBackSet())
|
||||
rgb_back = attr.BackgroundColor(fTextBuffer->Palette());
|
||||
if (attr.IsUnderSet())
|
||||
rgb_under = attr.UnderlineColor(fTextBuffer->Palette());
|
||||
|
||||
// Selection check.
|
||||
if (cursor) {
|
||||
@ -1077,6 +1080,58 @@ TermView::_DrawLinePart(float x1, float y1, Attributes attr,
|
||||
inView->SetHighColor(rgb_back);
|
||||
inView->FillRect(BRect(x1, y1, x2 - 1, y2 - 1));
|
||||
inView->SetLowColor(rgb_back);
|
||||
|
||||
// underline attribute
|
||||
if (attr.IsUnder()) {
|
||||
inView->SetHighColor(rgb_under);
|
||||
switch (attr.UnderlineStyle()) {
|
||||
default:
|
||||
case SINGLE_UNDERLINE:
|
||||
inView->MovePenTo(x1, y1 + fFontAscent + 1);
|
||||
inView->StrokeLine(BPoint(x1 , y1 + fFontAscent + 1),
|
||||
BPoint(x2 , y1 + fFontAscent + 1));
|
||||
break;
|
||||
case DOUBLE_UNDERLINE:
|
||||
inView->MovePenTo(x1, y1 + fFontAscent);
|
||||
inView->StrokeLine(BPoint(x1 , y1 + fFontAscent),
|
||||
BPoint(x2 , y1 + fFontAscent));
|
||||
inView->MovePenTo(x1, y1 + fFontAscent + 2);
|
||||
inView->StrokeLine(BPoint(x1 , y1 + fFontAscent + 2),
|
||||
BPoint(x2 , y1 + fFontAscent + 2));
|
||||
break;
|
||||
case CURLY_UNDERLINE:
|
||||
{
|
||||
inView->MovePenTo(x1, y1 + fFontAscent + 1);
|
||||
bool up = true;
|
||||
for (float x = x1; x < x2; x += 3) {
|
||||
inView->StrokeLine(BPoint(x, y1 + fFontAscent + (up ? 0 : 2)),
|
||||
BPoint(std::min(x + 2, x2), y1 + fFontAscent + (up ? 2 : 0)));
|
||||
up = !up;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOTTED_UNDERLINE:
|
||||
{
|
||||
inView->MovePenTo(x1, y1 + fFontAscent + 1);
|
||||
for (float x = x1; x < x2; x += 4) {
|
||||
inView->StrokeLine(BPoint(x, y1 + fFontAscent + 1),
|
||||
BPoint(std::min(x, x2), y1 + fFontAscent + 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DASHED_UNDERLINE:
|
||||
{
|
||||
inView->MovePenTo(x1, y1 + fFontAscent + 1);
|
||||
for (float x = x1; x < x2; x += 5) {
|
||||
inView->StrokeLine(BPoint(x, y1 + fFontAscent + 1),
|
||||
BPoint(std::min(x + 2, x2), y1 + fFontAscent + 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inView->SetHighColor(rgb_fore);
|
||||
|
||||
// Draw character.
|
||||
@ -1100,12 +1155,6 @@ TermView::_DrawLinePart(float x1, float y1, Attributes attr,
|
||||
inView->DrawString((char *)buf);
|
||||
inView->SetDrawingMode(B_OP_COPY);
|
||||
|
||||
// underline attribute
|
||||
if (attr.IsUnder()) {
|
||||
inView->MovePenTo(x1, y1 + fFontAscent);
|
||||
inView->StrokeLine(BPoint(x1 , y1 + fFontAscent),
|
||||
BPoint(x2 , y1 + fFontAscent));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,10 +22,19 @@ struct Attributes {
|
||||
uint32 state;
|
||||
uint32 foreground;
|
||||
uint32 background;
|
||||
uint32 underline;
|
||||
int underlineStyle;
|
||||
|
||||
Attributes() : state(0), foreground(0), background(0) {}
|
||||
Attributes() : state(0), foreground(0), background(0), underline(0), underlineStyle(0) {}
|
||||
|
||||
inline void Reset() { state = 0; foreground = 0; background = 0; }
|
||||
inline void Reset()
|
||||
{
|
||||
state = 0;
|
||||
foreground = 0;
|
||||
background = 0;
|
||||
underline = 0;
|
||||
underlineStyle = 0;
|
||||
}
|
||||
|
||||
inline bool IsWidth() const { return (state & A_WIDTH) == A_WIDTH; }
|
||||
inline bool IsBold() const { return (state & BOLD) == BOLD; }
|
||||
@ -34,6 +43,7 @@ struct Attributes {
|
||||
inline bool IsMouse() const { return (state & MOUSE) == MOUSE; }
|
||||
inline bool IsForeSet() const { return (state & FORESET) == FORESET; }
|
||||
inline bool IsBackSet() const { return (state & BACKSET) == BACKSET; }
|
||||
inline bool IsUnderSet() const { return (state & UNDERSET) == UNDERSET; }
|
||||
inline bool IsFont() const { return (state & FONT) == FONT; }
|
||||
inline bool IsCR() const { return (state & DUMPCR) == DUMPCR; }
|
||||
|
||||
@ -51,6 +61,12 @@ struct Attributes {
|
||||
state |= BACKSET;
|
||||
}
|
||||
|
||||
inline void SetDirectUnderline(uint8 red, uint8 green, uint8 blue)
|
||||
{
|
||||
underline = 0x80000000 | (red << 16) | (green << 8) | blue;
|
||||
state |= UNDERSET;
|
||||
}
|
||||
|
||||
inline void SetIndexedForeground(uint32 index)
|
||||
{
|
||||
state &= ~FORECOLOR;
|
||||
@ -67,6 +83,18 @@ struct Attributes {
|
||||
background = 0;
|
||||
}
|
||||
|
||||
inline void SetIndexedUnderline(uint32 index)
|
||||
{
|
||||
state |= UNDERSET;
|
||||
underline = index;
|
||||
}
|
||||
|
||||
inline void SetUnder(int style)
|
||||
{
|
||||
underlineStyle = style;
|
||||
state |= UNDERLINE;
|
||||
}
|
||||
|
||||
inline void UnsetForeground()
|
||||
{
|
||||
state &= ~FORESET;
|
||||
@ -79,6 +107,18 @@ struct Attributes {
|
||||
background = 0;
|
||||
}
|
||||
|
||||
inline void UnsetUnderline()
|
||||
{
|
||||
state &= ~UNDERSET;
|
||||
underline = 0;
|
||||
}
|
||||
|
||||
inline void UnsetUnder()
|
||||
{
|
||||
underlineStyle = 0;
|
||||
state &= ~UNDERLINE;
|
||||
}
|
||||
|
||||
inline rgb_color
|
||||
ForegroundColor(const rgb_color* indexedColors) const
|
||||
{
|
||||
@ -101,6 +141,23 @@ struct Attributes {
|
||||
return indexedColors[(state & BACKCOLOR) >> 24];
|
||||
}
|
||||
|
||||
inline rgb_color
|
||||
UnderlineColor(const rgb_color* indexedColors) const
|
||||
{
|
||||
if ((underline & 0x80000000) != 0)
|
||||
return make_color((underline >> 16) & 0xFF,
|
||||
(underline >> 8) & 0xFF,
|
||||
underline & 0xFF);
|
||||
else
|
||||
return indexedColors[underline];
|
||||
}
|
||||
|
||||
inline int
|
||||
UnderlineStyle() const
|
||||
{
|
||||
return underlineStyle;
|
||||
}
|
||||
|
||||
inline Attributes&
|
||||
operator&=(uint32 value) { state &= value; return *this; }
|
||||
|
||||
@ -118,7 +175,9 @@ struct Attributes {
|
||||
{
|
||||
return state == other.state
|
||||
&& foreground == other.foreground
|
||||
&& background == other.background;
|
||||
&& background == other.background
|
||||
&& underline == other.underline
|
||||
&& underlineStyle == other.underlineStyle;
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -126,7 +185,9 @@ struct Attributes {
|
||||
{
|
||||
return state != other.state
|
||||
|| foreground != other.foreground
|
||||
|| background != other.background;
|
||||
|| background != other.background
|
||||
|| underline != other.underline
|
||||
|| underlineStyle != other.underlineStyle;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1069,7 +1069,7 @@ CASE_ESC_DIGIT,
|
||||
/* 8 9 : ; */
|
||||
CASE_ESC_DIGIT,
|
||||
CASE_ESC_DIGIT,
|
||||
CASE_IGNORE,
|
||||
CASE_ESC_SEMI,
|
||||
CASE_ESC_SEMI,
|
||||
/* < = > ? */
|
||||
CASE_IGNORE,
|
||||
|
Loading…
Reference in New Issue
Block a user