Terminal: support for hyperlinks (#18827)
* support for invisible text * support for DECSTR - soft terminal reset Change-Id: I5cc333c7409a16fb41bcd57c5ebf2f277bd31370 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9661 Reviewed-by: Adrien Destugues <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
cfd2df0eba
commit
1a163d0ce9
@@ -15,7 +15,9 @@
|
|||||||
HyperLink::HyperLink()
|
HyperLink::HyperLink()
|
||||||
:
|
:
|
||||||
fAddress(),
|
fAddress(),
|
||||||
fType(TYPE_URL)
|
fType(TYPE_URL),
|
||||||
|
fOSCRef(0),
|
||||||
|
fOSCID(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +26,9 @@ HyperLink::HyperLink(const BString& address, Type type)
|
|||||||
:
|
:
|
||||||
fText(address),
|
fText(address),
|
||||||
fAddress(address),
|
fAddress(address),
|
||||||
fType(type)
|
fType(type),
|
||||||
|
fOSCRef(0),
|
||||||
|
fOSCID(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +37,20 @@ HyperLink::HyperLink(const BString& text, const BString& address, Type type)
|
|||||||
:
|
:
|
||||||
fText(text),
|
fText(text),
|
||||||
fAddress(address),
|
fAddress(address),
|
||||||
fType(type)
|
fType(type),
|
||||||
|
fOSCRef(0),
|
||||||
|
fOSCID(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HyperLink::HyperLink(const BString& address, uint32 ref, const BString& id)
|
||||||
|
:
|
||||||
|
fText(NULL),
|
||||||
|
fAddress(address),
|
||||||
|
fType(TYPE_OSC_URL),
|
||||||
|
fOSCRef(ref),
|
||||||
|
fOSCID(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ public:
|
|||||||
TYPE_URL,
|
TYPE_URL,
|
||||||
TYPE_PATH,
|
TYPE_PATH,
|
||||||
TYPE_PATH_WITH_LINE,
|
TYPE_PATH_WITH_LINE,
|
||||||
TYPE_PATH_WITH_LINE_AND_COLUMN
|
TYPE_PATH_WITH_LINE_AND_COLUMN,
|
||||||
|
TYPE_OSC_URL
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -23,12 +24,15 @@ public:
|
|||||||
HyperLink(const BString& address, Type type);
|
HyperLink(const BString& address, Type type);
|
||||||
HyperLink(const BString& text,
|
HyperLink(const BString& text,
|
||||||
const BString& address, Type type);
|
const BString& address, Type type);
|
||||||
|
HyperLink(const BString& address, uint32 ref, const BString& id);
|
||||||
|
|
||||||
bool IsValid() const { return !fAddress.IsEmpty(); }
|
bool IsValid() const { return !fAddress.IsEmpty(); }
|
||||||
|
|
||||||
const BString& Text() const { return fText; }
|
const BString& Text() const { return fText; }
|
||||||
const BString& Address() const { return fAddress; }
|
const BString& Address() const { return fAddress; }
|
||||||
Type GetType() const { return fType; }
|
Type GetType() const { return fType; }
|
||||||
|
const BString& OSCID() const { return fOSCID; }
|
||||||
|
const uint32& OSCRef() const { return fOSCRef; }
|
||||||
|
|
||||||
status_t Open();
|
status_t Open();
|
||||||
|
|
||||||
@@ -36,6 +40,8 @@ private:
|
|||||||
BString fText;
|
BString fText;
|
||||||
BString fAddress;
|
BString fAddress;
|
||||||
Type fType;
|
Type fType;
|
||||||
|
uint32 fOSCRef;
|
||||||
|
BString fOSCID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -220,9 +220,10 @@ enum {
|
|||||||
#define DUMPCR 0x0040
|
#define DUMPCR 0x0040
|
||||||
#define UNDERSET 0x0020
|
#define UNDERSET 0x0020
|
||||||
#define OVERLINE 0x0010
|
#define OVERLINE 0x0010
|
||||||
|
#define HIDDEN 0x0008
|
||||||
#define FORECOLOR 0xFF0000
|
#define FORECOLOR 0xFF0000
|
||||||
#define BACKCOLOR 0xFF000000
|
#define BACKCOLOR 0xFF000000
|
||||||
#define CHAR_ATTRIBUTES 0xFFFF7730
|
#define CHAR_ATTRIBUTES 0xFFFF7738
|
||||||
|
|
||||||
#define FORECOLORED(x) ((x) << 16)
|
#define FORECOLORED(x) ((x) << 16)
|
||||||
#define BACKCOLORED(x) ((x) << 24)
|
#define BACKCOLORED(x) ((x) << 24)
|
||||||
|
|||||||
@@ -646,6 +646,12 @@ TermParse::EscParse()
|
|||||||
param[nparam++] = ' ';
|
param[nparam++] = ' ';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CASE_CSI_EXCL: // ESC [N p
|
||||||
|
// part of soft reset DECSTR
|
||||||
|
if (nparam < NPARAM)
|
||||||
|
param[nparam++] = '!';
|
||||||
|
break;
|
||||||
|
|
||||||
case CASE_DEC_DOL: // ESC [? N p
|
case CASE_DEC_DOL: // ESC [? N p
|
||||||
// part of change cursor style DECRQM
|
// part of change cursor style DECRQM
|
||||||
if (nparam < NPARAM)
|
if (nparam < NPARAM)
|
||||||
@@ -838,6 +844,10 @@ TermParse::EscParse()
|
|||||||
attributes |= INVERSE;
|
attributes |= INVERSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 8: /* Hidden */
|
||||||
|
attributes |= HIDDEN;
|
||||||
|
break;
|
||||||
|
|
||||||
case 21: /* Double Underline */
|
case 21: /* Double Underline */
|
||||||
attributes.SetUnder(DOUBLE_UNDERLINE);
|
attributes.SetUnder(DOUBLE_UNDERLINE);
|
||||||
break;
|
break;
|
||||||
@@ -854,6 +864,10 @@ TermParse::EscParse()
|
|||||||
attributes &= ~INVERSE;
|
attributes &= ~INVERSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 28: /* Not Hidden */
|
||||||
|
attributes &= ~HIDDEN;
|
||||||
|
break;
|
||||||
|
|
||||||
case 53: /* Overline */
|
case 53: /* Overline */
|
||||||
attributes |= OVERLINE;
|
attributes |= OVERLINE;
|
||||||
break;
|
break;
|
||||||
@@ -1298,6 +1312,14 @@ TermParse::EscParse()
|
|||||||
parsestate = groundtable;
|
parsestate = groundtable;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CASE_DECSTR: // DECSTR - soft terminal reset
|
||||||
|
if (nparam == 2 && param[1] == '!') {
|
||||||
|
Attributes attributes;
|
||||||
|
fBuffer->SetAttributes(attributes);
|
||||||
|
}
|
||||||
|
parsestate = groundtable;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1710,6 +1732,34 @@ TermParse::_ProcessOperatingSystemControls(uchar* params)
|
|||||||
fBuffer->ResetColors(indexes, 1, true);
|
fBuffer->ResetColors(indexes, 1, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// handle hyperlinks
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
char* id = NULL;
|
||||||
|
char* start = (char*)params;
|
||||||
|
char* end = strpbrk(start, ";:");
|
||||||
|
for (; end != NULL; start = end + 1) {
|
||||||
|
end = strpbrk(start, ";:");
|
||||||
|
if (end == NULL)
|
||||||
|
break;
|
||||||
|
if (end - start > 3 && strncmp(start, "id=", 3) == 0)
|
||||||
|
id = strndup(start + 3, end - start + 3);
|
||||||
|
if (*end == ';')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (end == NULL)
|
||||||
|
break;
|
||||||
|
BString uri(end + 1);
|
||||||
|
Attributes attributes = fBuffer->GetAttributes();
|
||||||
|
if (uri.IsEmpty()) {
|
||||||
|
attributes.SetHyperlink(0);
|
||||||
|
} else {
|
||||||
|
attributes.SetHyperlink(fBuffer->PutHyperLink(id, uri));
|
||||||
|
}
|
||||||
|
free(id);
|
||||||
|
fBuffer->SetAttributes(attributes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// printf("%d -> %s\n", mode, params);
|
// printf("%d -> %s\n", mode, params);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -452,7 +452,7 @@ TermView::BackgroundColor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline int32
|
int32
|
||||||
TermView::_LineAt(float y) const
|
TermView::_LineAt(float y) const
|
||||||
{
|
{
|
||||||
int32 location = int32(y + fScrollOffset);
|
int32 location = int32(y + fScrollOffset);
|
||||||
@@ -1061,6 +1061,9 @@ void
|
|||||||
TermView::_DrawLinePart(float x1, float y1, Attributes attr,
|
TermView::_DrawLinePart(float x1, float y1, Attributes attr,
|
||||||
char *buf, int32 width, Highlight* highlight, bool cursor, BView *inView)
|
char *buf, int32 width, Highlight* highlight, bool cursor, BView *inView)
|
||||||
{
|
{
|
||||||
|
if (attr.IsHidden())
|
||||||
|
return;
|
||||||
|
|
||||||
if (highlight != NULL)
|
if (highlight != NULL)
|
||||||
attr.state = highlight->Highlighter()->AdjustTextAttributes(attr.state);
|
attr.state = highlight->Highlighter()->AdjustTextAttributes(attr.state);
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// point and text offset conversion
|
// point and text offset conversion
|
||||||
inline int32 _LineAt(float y) const;
|
int32 _LineAt(float y) const;
|
||||||
inline float _LineOffset(int32 index) const;
|
inline float _LineOffset(int32 index) const;
|
||||||
TermPos _ConvertToTerminal(const BPoint& point) const;
|
TermPos _ConvertToTerminal(const BPoint& point) const;
|
||||||
inline BPoint _ConvertFromTerminal(const TermPos& pos) const;
|
inline BPoint _ConvertFromTerminal(const TermPos& pos) const;
|
||||||
|
|||||||
@@ -833,10 +833,19 @@ TermView::HyperLinkState::_GetHyperLinkAt(BPoint where, bool pathPrefixOnly,
|
|||||||
HyperLink& _link, TermPos& _start, TermPos& _end)
|
HyperLink& _link, TermPos& _start, TermPos& _end)
|
||||||
{
|
{
|
||||||
TerminalBuffer* textBuffer = fView->fTextBuffer;
|
TerminalBuffer* textBuffer = fView->fTextBuffer;
|
||||||
|
BasicTerminalBuffer* visibleTextBuffer = fView->fVisibleTextBuffer;
|
||||||
BAutolock textBufferLocker(textBuffer);
|
BAutolock textBufferLocker(textBuffer);
|
||||||
|
int32 firstVisible = fView->_LineAt(0);
|
||||||
|
|
||||||
TermPos pos = fView->_ConvertToTerminal(where);
|
TermPos pos = fView->_ConvertToTerminal(where);
|
||||||
|
|
||||||
|
UTF8Char character;
|
||||||
|
Attributes attr;
|
||||||
|
if (visibleTextBuffer->GetChar(pos.y - firstVisible, pos.x, character, attr) == A_CHAR
|
||||||
|
&& attr.Hyperlink() != 0) {
|
||||||
|
return textBuffer->GetHyperLink(attr.Hyperlink(), _link);
|
||||||
|
}
|
||||||
|
|
||||||
// try to get a URL first
|
// try to get a URL first
|
||||||
BString text;
|
BString text;
|
||||||
if (!textBuffer->FindWord(pos, &fURLCharClassifier, false, _start, _end))
|
if (!textBuffer->FindWord(pos, &fURLCharClassifier, false, _start, _end))
|
||||||
@@ -1120,6 +1129,7 @@ TermView::HyperLinkMenuState::Prepare(BPoint point, const HyperLink& link)
|
|||||||
BLayoutBuilder::Menu<> menuBuilder(menu);
|
BLayoutBuilder::Menu<> menuBuilder(menu);
|
||||||
switch (link.GetType()) {
|
switch (link.GetType()) {
|
||||||
case HyperLink::TYPE_URL:
|
case HyperLink::TYPE_URL:
|
||||||
|
case HyperLink::TYPE_OSC_URL:
|
||||||
menuBuilder
|
menuBuilder
|
||||||
.AddItem(B_TRANSLATE("Open link"), kMessageOpenLink)
|
.AddItem(B_TRANSLATE("Open link"), kMessageOpenLink)
|
||||||
.AddItem(B_TRANSLATE("Copy link location"), kMessageCopyLink);
|
.AddItem(B_TRANSLATE("Copy link location"), kMessageCopyLink);
|
||||||
@@ -1161,8 +1171,7 @@ TermView::HyperLinkMenuState::MessageReceived(BMessage* message)
|
|||||||
case kMessageCopyAbsolutePath:
|
case kMessageCopyAbsolutePath:
|
||||||
{
|
{
|
||||||
if (fLink.IsValid()) {
|
if (fLink.IsValid()) {
|
||||||
BString toCopy = message->what == kMessageCopyLink
|
BString toCopy = fLink.Address();
|
||||||
? fLink.Text() : fLink.Address();
|
|
||||||
|
|
||||||
if (!be_clipboard->Lock())
|
if (!be_clipboard->Lock())
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ TerminalBuffer::TerminalBuffer()
|
|||||||
fColorsPalette(NULL),
|
fColorsPalette(NULL),
|
||||||
fListenerValid(false),
|
fListenerValid(false),
|
||||||
fMode(MODE_INTERPRET_META_KEY | MODE_META_KEY_SENDS_ESCAPE | MODE_CURSOR_BLINKING),
|
fMode(MODE_INTERPRET_META_KEY | MODE_META_KEY_SENDS_ESCAPE | MODE_CURSOR_BLINKING),
|
||||||
fCursorStyle(BLOCK_CURSOR)
|
fCursorStyle(BLOCK_CURSOR),
|
||||||
|
fNextOSCRef(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +45,14 @@ TerminalBuffer::~TerminalBuffer()
|
|||||||
free(fAlternateScreen);
|
free(fAlternateScreen);
|
||||||
delete fAlternateHistory;
|
delete fAlternateHistory;
|
||||||
delete[] fColorsPalette;
|
delete[] fColorsPalette;
|
||||||
|
|
||||||
|
HyperLinkRefMap::Iterator iterator = fHyperLinkForRef.GetIterator();
|
||||||
|
while (iterator.HasNext()) {
|
||||||
|
HyperLinkRefMap::Entry entry = iterator.Next();
|
||||||
|
delete entry.value;
|
||||||
|
}
|
||||||
|
fHyperLinkForID.Clear();
|
||||||
|
fHyperLinkForRef.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -321,3 +330,33 @@ TerminalBuffer::_SwitchScreenBuffer()
|
|||||||
std::swap(fAttributes, fAlternateAttributes);
|
std::swap(fAttributes, fAlternateAttributes);
|
||||||
fAlternateScreenActive = !fAlternateScreenActive;
|
fAlternateScreenActive = !fAlternateScreenActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
TerminalBuffer::PutHyperLink(const char* id, BString& uri)
|
||||||
|
{
|
||||||
|
HyperLink* hyperLink = NULL;
|
||||||
|
if (id != NULL)
|
||||||
|
hyperLink = fHyperLinkForID.Get(id);
|
||||||
|
if (hyperLink == NULL) {
|
||||||
|
hyperLink = new (std::nothrow) HyperLink(uri, fNextOSCRef++, id);
|
||||||
|
if (id != NULL)
|
||||||
|
fHyperLinkForID.Put(id, hyperLink);
|
||||||
|
HyperLink* oldHyperLink = fHyperLinkForRef.Get(hyperLink->OSCRef());
|
||||||
|
fHyperLinkForRef.Put(hyperLink->OSCRef(), hyperLink);
|
||||||
|
delete oldHyperLink;
|
||||||
|
}
|
||||||
|
return hyperLink->OSCRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
TerminalBuffer::GetHyperLink(uint32 ref, HyperLink &_link)
|
||||||
|
{
|
||||||
|
HyperLink* hyperLink = fHyperLinkForRef.Get(ref);
|
||||||
|
if (hyperLink == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_link = *hyperLink;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,11 @@
|
|||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
#include <Messenger.h>
|
#include <Messenger.h>
|
||||||
|
|
||||||
|
#include <HashMap.h>
|
||||||
|
#include <HashString.h>
|
||||||
|
|
||||||
#include "BasicTerminalBuffer.h"
|
#include "BasicTerminalBuffer.h"
|
||||||
|
#include "HyperLink.h"
|
||||||
|
|
||||||
|
|
||||||
class TerminalBuffer : public BasicTerminalBuffer, public BLocker {
|
class TerminalBuffer : public BasicTerminalBuffer, public BLocker {
|
||||||
@@ -57,6 +61,9 @@ public:
|
|||||||
void SetMode(uint32 mode);
|
void SetMode(uint32 mode);
|
||||||
void ResetMode(uint32 mode);
|
void ResetMode(uint32 mode);
|
||||||
|
|
||||||
|
uint32 PutHyperLink(const char* id, BString& uri);
|
||||||
|
bool GetHyperLink(uint32 ref, HyperLink& _link);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void NotifyListener();
|
virtual void NotifyListener();
|
||||||
|
|
||||||
@@ -78,6 +85,12 @@ private:
|
|||||||
|
|
||||||
uint32 fMode;
|
uint32 fMode;
|
||||||
int fCursorStyle;
|
int fCursorStyle;
|
||||||
|
|
||||||
|
typedef HashMap<HashKey32<int32>, HyperLink*> HyperLinkRefMap;
|
||||||
|
HyperLinkRefMap fHyperLinkForRef;
|
||||||
|
typedef HashMap<HashString, HyperLink*> HyperLinkIDMap;
|
||||||
|
HyperLinkIDMap fHyperLinkForID;
|
||||||
|
uint32 fNextOSCRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ struct Attributes {
|
|||||||
uint32 background;
|
uint32 background;
|
||||||
uint32 underline;
|
uint32 underline;
|
||||||
int underlineStyle;
|
int underlineStyle;
|
||||||
|
uint32 hyperlink;
|
||||||
|
|
||||||
Attributes() : state(0), foreground(0), background(0), underline(0), underlineStyle(0) {}
|
Attributes() : state(0), foreground(0), background(0), underline(0), underlineStyle(0),
|
||||||
|
hyperlink(0) {}
|
||||||
|
|
||||||
inline void Reset()
|
inline void Reset()
|
||||||
{
|
{
|
||||||
@@ -41,6 +43,7 @@ struct Attributes {
|
|||||||
inline bool IsUnder() const { return (state & UNDERLINE) == UNDERLINE; }
|
inline bool IsUnder() const { return (state & UNDERLINE) == UNDERLINE; }
|
||||||
inline bool IsInverse() const { return (state & INVERSE) == INVERSE; }
|
inline bool IsInverse() const { return (state & INVERSE) == INVERSE; }
|
||||||
inline bool IsOver() const { return (state & OVERLINE) == OVERLINE; }
|
inline bool IsOver() const { return (state & OVERLINE) == OVERLINE; }
|
||||||
|
inline bool IsHidden() const { return (state & HIDDEN) == HIDDEN; }
|
||||||
inline bool IsMouse() const { return (state & MOUSE) == MOUSE; }
|
inline bool IsMouse() const { return (state & MOUSE) == MOUSE; }
|
||||||
inline bool IsForeSet() const { return (state & FORESET) == FORESET; }
|
inline bool IsForeSet() const { return (state & FORESET) == FORESET; }
|
||||||
inline bool IsBackSet() const { return (state & BACKSET) == BACKSET; }
|
inline bool IsBackSet() const { return (state & BACKSET) == BACKSET; }
|
||||||
@@ -96,6 +99,11 @@ struct Attributes {
|
|||||||
state |= UNDERLINE;
|
state |= UNDERLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SetHyperlink(uint32 id)
|
||||||
|
{
|
||||||
|
hyperlink = id;
|
||||||
|
}
|
||||||
|
|
||||||
inline void UnsetForeground()
|
inline void UnsetForeground()
|
||||||
{
|
{
|
||||||
state &= ~FORESET;
|
state &= ~FORESET;
|
||||||
@@ -159,6 +167,12 @@ struct Attributes {
|
|||||||
return underlineStyle;
|
return underlineStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline uint32
|
||||||
|
Hyperlink() const
|
||||||
|
{
|
||||||
|
return hyperlink;
|
||||||
|
}
|
||||||
|
|
||||||
inline Attributes&
|
inline Attributes&
|
||||||
operator&=(uint32 value) { state &= value; return *this; }
|
operator&=(uint32 value) { state &= value; return *this; }
|
||||||
|
|
||||||
@@ -178,7 +192,8 @@ struct Attributes {
|
|||||||
&& foreground == other.foreground
|
&& foreground == other.foreground
|
||||||
&& background == other.background
|
&& background == other.background
|
||||||
&& underline == other.underline
|
&& underline == other.underline
|
||||||
&& underlineStyle == other.underlineStyle;
|
&& underlineStyle == other.underlineStyle
|
||||||
|
&& hyperlink == other.hyperlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@@ -188,7 +203,8 @@ struct Attributes {
|
|||||||
|| foreground != other.foreground
|
|| foreground != other.foreground
|
||||||
|| background != other.background
|
|| background != other.background
|
||||||
|| underline != other.underline
|
|| underline != other.underline
|
||||||
|| underlineStyle != other.underlineStyle;
|
|| underlineStyle != other.underlineStyle
|
||||||
|
|| hyperlink != other.hyperlink;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -203,7 +219,8 @@ struct TerminalCell {
|
|||||||
return (attributes.state & CHAR_ATTRIBUTES)
|
return (attributes.state & CHAR_ATTRIBUTES)
|
||||||
!= (other.state & CHAR_ATTRIBUTES)
|
!= (other.state & CHAR_ATTRIBUTES)
|
||||||
|| attributes.foreground != other.foreground
|
|| attributes.foreground != other.foreground
|
||||||
|| attributes.background != other.background;
|
|| attributes.background != other.background
|
||||||
|
|| attributes.hyperlink != other.hyperlink;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1038,7 +1038,7 @@ CASE_IGNORE,
|
|||||||
CASE_IGNORE,
|
CASE_IGNORE,
|
||||||
/* SP ! " # */
|
/* SP ! " # */
|
||||||
CASE_CSI_SP,
|
CASE_CSI_SP,
|
||||||
CASE_ESC_IGNORE,
|
CASE_CSI_EXCL,
|
||||||
CASE_ESC_IGNORE,
|
CASE_ESC_IGNORE,
|
||||||
CASE_ESC_IGNORE,
|
CASE_ESC_IGNORE,
|
||||||
/* $ % & ' */
|
/* $ % & ' */
|
||||||
@@ -1137,7 +1137,7 @@ CASE_SGR,
|
|||||||
CASE_CPR,
|
CASE_CPR,
|
||||||
CASE_GROUND_STATE,
|
CASE_GROUND_STATE,
|
||||||
/* p q r s */
|
/* p q r s */
|
||||||
CASE_GROUND_STATE,
|
CASE_DECSTR,
|
||||||
CASE_DECSCUSR_ETC,
|
CASE_DECSCUSR_ETC,
|
||||||
CASE_DECSTBM,
|
CASE_DECSTBM,
|
||||||
CASE_GROUND_STATE,
|
CASE_GROUND_STATE,
|
||||||
|
|||||||
@@ -104,4 +104,6 @@
|
|||||||
#define CASE_REP 101
|
#define CASE_REP 101
|
||||||
#define CASE_DEC_DOL 102
|
#define CASE_DEC_DOL 102
|
||||||
#define CASE_DECRQM 103
|
#define CASE_DECRQM 103
|
||||||
|
#define CASE_CSI_EXCL 104
|
||||||
|
#define CASE_DECSTR 105
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user