Terminal: implement 24-bit colour.

* Changes `TERM` to `xterm`, as we're now a full colour capable terminal
* Removes now-obsolete GuessPaletteColor from an RGB triple
* Since it's using a struct instead of uint32 for attributes, add a bunch
  of helpers for a cleaner implementation
* Pass the TerminalBuffer's palette to the foreground/background get
  helpers, for when an indexed colour is returned

Change-Id: I33bd3bb1407b87a237a8bc355093fe549e05b43a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5195
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
Jessica Hamilton
2022-04-12 09:31:56 +00:00
committed by Adrien Destugues
parent d45a65c88d
commit c0b591c58f
11 changed files with 232 additions and 167 deletions
+29 -27
View File
@@ -113,7 +113,7 @@ BasicTerminalBuffer::BasicTerminalBuffer()
fScreen(NULL), fScreen(NULL),
fScreenOffset(0), fScreenOffset(0),
fHistory(NULL), fHistory(NULL),
fAttributes(0), fAttributes(),
fSoftWrappedCursor(false), fSoftWrappedCursor(false),
fOverwriteMode(false), fOverwriteMode(false),
fAlternateScreenActive(false), fAlternateScreenActive(false),
@@ -287,13 +287,13 @@ BasicTerminalBuffer::IsFullWidthChar(int32 row, int32 column) const
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
TerminalLine* line = _HistoryLineAt(row, lineBuffer); TerminalLine* line = _HistoryLineAt(row, lineBuffer);
return line != NULL && column > 0 && column < line->length return line != NULL && column > 0 && column < line->length
&& (line->cells[column - 1].attributes & A_WIDTH) != 0; && line->cells[column - 1].attributes.IsWidth();
} }
int int
BasicTerminalBuffer::GetChar(int32 row, int32 column, UTF8Char& character, BasicTerminalBuffer::GetChar(int32 row, int32 column, UTF8Char& character,
uint32& attributes) const Attributes& attributes) const
{ {
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
TerminalLine* line = _HistoryLineAt(row, lineBuffer); TerminalLine* line = _HistoryLineAt(row, lineBuffer);
@@ -303,7 +303,7 @@ BasicTerminalBuffer::GetChar(int32 row, int32 column, UTF8Char& character,
if (column < 0 || column >= line->length) if (column < 0 || column >= line->length)
return NO_CHAR; return NO_CHAR;
if (column > 0 && (line->cells[column - 1].attributes & A_WIDTH) != 0) if (column > 0 && line->cells[column - 1].attributes.IsWidth())
return IN_STRING; return IN_STRING;
TerminalCell& cell = line->cells[column]; TerminalCell& cell = line->cells[column];
@@ -315,7 +315,7 @@ BasicTerminalBuffer::GetChar(int32 row, int32 column, UTF8Char& character,
void void
BasicTerminalBuffer::GetCellAttributes(int32 row, int32 column, BasicTerminalBuffer::GetCellAttributes(int32 row, int32 column,
uint32& attributes, uint32& count) const Attributes& attributes, uint32& count) const
{ {
count = 0; count = 0;
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
@@ -336,7 +336,7 @@ BasicTerminalBuffer::GetCellAttributes(int32 row, int32 column,
int32 int32
BasicTerminalBuffer::GetString(int32 row, int32 firstColumn, int32 lastColumn, BasicTerminalBuffer::GetString(int32 row, int32 firstColumn, int32 lastColumn,
char* buffer, uint32& attributes) const char* buffer, Attributes& attributes) const
{ {
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
TerminalLine* line = _HistoryLineAt(row, lineBuffer); TerminalLine* line = _HistoryLineAt(row, lineBuffer);
@@ -419,7 +419,7 @@ BasicTerminalBuffer::FindWord(const TermPos& pos,
return true; return true;
} }
if (x > 0 && IS_WIDTH(line->cells[x - 1].attributes)) if (x > 0 && line->cells[x - 1].attributes.IsWidth())
x--; x--;
// get the char type at the given position // get the char type at the given position
@@ -431,7 +431,7 @@ BasicTerminalBuffer::FindWord(const TermPos& pos,
// find the beginning // find the beginning
TermPos start(x, y); TermPos start(x, y);
TermPos end(x + (IS_WIDTH(line->cells[x].attributes) TermPos end(x + (line->cells[x].attributes.IsWidth()
? FULL_WIDTH : HALF_WIDTH), y); ? FULL_WIDTH : HALF_WIDTH), y);
for (;;) { for (;;) {
TermPos previousPos = start; TermPos previousPos = start;
@@ -455,7 +455,7 @@ BasicTerminalBuffer::FindWord(const TermPos& pos,
if (classifier->Classify(line->cells[nextPos.x].character) != type) if (classifier->Classify(line->cells[nextPos.x].character) != type)
break; break;
nextPos.x += IS_WIDTH(line->cells[nextPos.x].attributes) nextPos.x += line->cells[nextPos.x].attributes.IsWidth()
? FULL_WIDTH : HALF_WIDTH; ? FULL_WIDTH : HALF_WIDTH;
end = nextPos; end = nextPos;
} }
@@ -489,7 +489,7 @@ BasicTerminalBuffer::NextLinePos(TermPos& pos, bool normalize) const
if (!_NormalizeLinePos(lineBuffer, line, pos)) if (!_NormalizeLinePos(lineBuffer, line, pos))
return false; return false;
pos.x += IS_WIDTH(line->cells[pos.x].attributes) ? FULL_WIDTH : HALF_WIDTH; pos.x += line->cells[pos.x].attributes.IsWidth() ? FULL_WIDTH : HALF_WIDTH;
return !normalize || _NormalizeLinePos(lineBuffer, line, pos); return !normalize || _NormalizeLinePos(lineBuffer, line, pos);
} }
@@ -503,12 +503,15 @@ BasicTerminalBuffer::LineLength(int32 index) const
} }
int32 void
BasicTerminalBuffer::GetLineColor(int32 index) const BasicTerminalBuffer::GetLineColor(int32 index, Attributes& attr) const
{ {
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
TerminalLine* line = _HistoryLineAt(index, lineBuffer); TerminalLine* line = _HistoryLineAt(index, lineBuffer);
return line != NULL ? line->attributes : 0; if (line != NULL)
attr = line->attributes;
else
attr.Reset();
} }
@@ -641,8 +644,8 @@ BasicTerminalBuffer::InsertChar(UTF8Char c)
TerminalLine* line = _LineAt(fCursor.y); TerminalLine* line = _LineAt(fCursor.y);
line->cells[fCursor.x].character = c; line->cells[fCursor.x].character = c;
line->cells[fCursor.x].attributes line->cells[fCursor.x].attributes = fAttributes;
= fAttributes | (width == FULL_WIDTH ? A_WIDTH : 0); line->cells[fCursor.x].attributes.state |= (width == FULL_WIDTH ? A_WIDTH : 0);
if (line->length < fCursor.x + width) if (line->length < fCursor.x + width)
line->length = fCursor.x + width; line->length = fCursor.x + width;
@@ -662,7 +665,7 @@ BasicTerminalBuffer::InsertChar(UTF8Char c)
void void
BasicTerminalBuffer::FillScreen(UTF8Char c, uint32 attributes) BasicTerminalBuffer::FillScreen(UTF8Char c, Attributes &attributes)
{ {
uint32 width = HALF_WIDTH; uint32 width = HALF_WIDTH;
if (c.IsFullWidth()) { if (c.IsFullWidth()) {
@@ -838,9 +841,9 @@ BasicTerminalBuffer::EraseCharsFrom(int32 first, int32 numChars)
fSoftWrappedCursor = false; fSoftWrappedCursor = false;
end = min_c(first + numChars, line->length); end = min_c(first + numChars, line->length);
if (first > 0 && IS_WIDTH(line->cells[first - 1].attributes)) if (first > 0 && line->cells[first - 1].attributes.IsWidth())
first--; first--;
if (end > 0 && IS_WIDTH(line->cells[end - 1].attributes)) if (end > 0 && line->cells[end - 1].attributes.IsWidth())
end++; end++;
for (int32 i = first; i < end; i++) { for (int32 i = first; i < end; i++) {
@@ -865,7 +868,7 @@ BasicTerminalBuffer::EraseAbove()
TerminalLine* line = _LineAt(fCursor.y); TerminalLine* line = _LineAt(fCursor.y);
if (fCursor.x < line->length) { if (fCursor.x < line->length) {
int32 to = fCursor.x; int32 to = fCursor.x;
if (IS_WIDTH(line->cells[fCursor.x].attributes)) if (line->cells[fCursor.x].attributes.IsWidth())
to++; to++;
for (int32 i = 0; i <= to; i++) { for (int32 i = 0; i <= to; i++) {
line->cells[i].attributes = fAttributes; line->cells[i].attributes = fAttributes;
@@ -1090,7 +1093,7 @@ BasicTerminalBuffer::_AllocateLines(int32 width, int32 count)
_FreeLines(lines, i); _FreeLines(lines, i);
return NULL; return NULL;
} }
lines[i]->Clear(0, width); lines[i]->Clear(width);
} }
return lines; return lines;
@@ -1337,8 +1340,7 @@ BasicTerminalBuffer::_ResizeRewrap(int32 width, int32 height,
int32 toCopy = min_c(sourceLeft, destLeft); int32 toCopy = min_c(sourceLeft, destLeft);
// If the last cell to copy is the first cell of a // If the last cell to copy is the first cell of a
// full-width char, don't copy it yet. // full-width char, don't copy it yet.
if (toCopy > 0 && IS_WIDTH( if (toCopy > 0 && sourceLine->cells[sourceX + toCopy - 1].attributes.IsWidth()) {
sourceLine->cells[sourceX + toCopy - 1].attributes)) {
//debug_printf(" -> last char is full-width -- don't copy it\n"); //debug_printf(" -> last char is full-width -- don't copy it\n");
toCopy--; toCopy--;
} }
@@ -1620,7 +1622,7 @@ BasicTerminalBuffer::_TruncateLine(TerminalLine* line, int32 length)
if (line->length <= length) if (line->length <= length)
return; return;
if (length > 0 && IS_WIDTH(line->cells[length - 1].attributes)) if (length > 0 && line->cells[length - 1].attributes.IsWidth())
length--; length--;
line->length = length; line->length = length;
@@ -1661,7 +1663,7 @@ BasicTerminalBuffer::_GetPartialLineString(BString& string, int32 row,
const TerminalCell& cell = line->cells[x]; const TerminalCell& cell = line->cells[x];
string.Append(cell.character.bytes, cell.character.ByteCount()); string.Append(cell.character.bytes, cell.character.ByteCount());
if (IS_WIDTH(cell.attributes)) if (cell.attributes.IsWidth())
x++; x++;
} }
@@ -1745,7 +1747,7 @@ BasicTerminalBuffer::_PreviousLinePos(TerminalLine* lineBuffer,
} }
pos.x = line->length - 1; pos.x = line->length - 1;
} }
if (pos.x > 0 && IS_WIDTH(line->cells[pos.x - 1].attributes)) if (pos.x > 0 && line->cells[pos.x - 1].attributes.IsWidth())
pos.x--; pos.x--;
return true; return true;
@@ -1805,7 +1807,7 @@ BasicTerminalBuffer::MakeLinesSnapshots(time_t timeStamp, const char* fileName)
} }
fprintf(fileOut, "%02" B_PRId16 ":%02" B_PRId16 ":%08" B_PRIx32 ":\n", fprintf(fileOut, "%02" B_PRId16 ":%02" B_PRId16 ":%08" B_PRIx32 ":\n",
i, line->length, line->attributes); i, line->length, line->attributes.state);
for (int j = 0; j < line->length; j++) for (int j = 0; j < line->length; j++)
if (line->cells[j].character.bytes[0] != 0) if (line->cells[j].character.bytes[0] != 0)
fwrite(line->cells[j].character.bytes, 1, fwrite(line->cells[j].character.bytes, 1,
@@ -1815,7 +1817,7 @@ BasicTerminalBuffer::MakeLinesSnapshots(time_t timeStamp, const char* fileName)
for (int s = 28; s >= 0; s -= 4) { for (int s = 28; s >= 0; s -= 4) {
for (int j = 0; j < fWidth; j++) for (int j = 0; j < fWidth; j++)
fprintf(fileOut, "%01" B_PRIx32, fprintf(fileOut, "%01" B_PRIx32,
(line->cells[j].attributes >> s) & 0x0F); (line->cells[j].attributes.state >> s) & 0x0F);
fprintf(fileOut, "\n"); fprintf(fileOut, "\n");
} }
+10 -10
View File
@@ -91,12 +91,12 @@ public:
bool IsFullWidthChar(int32 row, int32 column) const; bool IsFullWidthChar(int32 row, int32 column) const;
int GetChar(int32 row, int32 column, int GetChar(int32 row, int32 column,
UTF8Char& character, UTF8Char& character,
uint32& attributes) const; Attributes& attributes) const;
void GetCellAttributes(int32 row, int32 column, void GetCellAttributes(int32 row, int32 column,
uint32& attributes, uint32& count) const; Attributes& attributes, uint32& count) const;
int32 GetString(int32 row, int32 firstColumn, int32 GetString(int32 row, int32 firstColumn,
int32 lastColumn, char* buffer, int32 lastColumn, char* buffer,
uint32& attributes) const; Attributes& attributes) const;
void GetStringFromRegion(BString& string, void GetStringFromRegion(BString& string,
const TermPos& start, const TermPos& start,
const TermPos& end) const; const TermPos& end) const;
@@ -105,7 +105,7 @@ public:
bool findNonWords, TermPos& start, bool findNonWords, TermPos& start,
TermPos& end) const; TermPos& end) const;
int32 LineLength(int32 index) const; int32 LineLength(int32 index) const;
int32 GetLineColor(int32 index) const; void GetLineColor(int32 index, Attributes& attr) const;
bool PreviousLinePos(TermPos& pos) const; bool PreviousLinePos(TermPos& pos) const;
bool NextLinePos(TermPos& pos, bool normalize) const; bool NextLinePos(TermPos& pos, bool normalize) const;
@@ -120,8 +120,8 @@ public:
bool matchWord, TermPos& matchStart, bool matchWord, TermPos& matchStart,
TermPos& matchEnd) const; TermPos& matchEnd) const;
inline uint32 GetAttributes(); inline Attributes GetAttributes();
inline void SetAttributes(uint32 attributes); inline void SetAttributes(const Attributes& attributes);
// snapshots and data capture for debugging // snapshots and data capture for debugging
void MakeLinesSnapshots(time_t timeStamp, void MakeLinesSnapshots(time_t timeStamp,
@@ -131,7 +131,7 @@ public:
// insert chars/lines // insert chars/lines
void InsertChar(UTF8Char c); void InsertChar(UTF8Char c);
void FillScreen(UTF8Char c, uint32 attr); void FillScreen(UTF8Char c, Attributes &attr);
void InsertCR(); void InsertCR();
void InsertLF(); void InsertLF();
@@ -235,7 +235,7 @@ protected:
int32 fScreenOffset; // index of screen line 0 int32 fScreenOffset; // index of screen line 0
HistoryBuffer* fHistory; HistoryBuffer* fHistory;
uint32 fAttributes; Attributes fAttributes;
// cursor position (origin: (0, 0)) // cursor position (origin: (0, 0))
TermPos fCursor; TermPos fCursor;
@@ -272,7 +272,7 @@ BasicTerminalBuffer::HistoryCapacity() const
} }
uint32 Attributes
BasicTerminalBuffer::GetAttributes() BasicTerminalBuffer::GetAttributes()
{ {
return fAttributes; return fAttributes;
@@ -280,7 +280,7 @@ BasicTerminalBuffer::GetAttributes()
void void
BasicTerminalBuffer::SetAttributes(uint32 attributes) BasicTerminalBuffer::SetAttributes(const Attributes& attributes)
{ {
fAttributes = attributes; fAttributes = attributes;
} }
+17 -17
View File
@@ -84,7 +84,7 @@ HistoryBuffer::GetTerminalLineAt(int32 index, TerminalLine* buffer) const
int32 charCount = 0; int32 charCount = 0;
const char* chars = line->Chars(); const char* chars = line->Chars();
buffer->length = 0; buffer->length = 0;
uint32 attributes = 0; Attributes attributes;
AttributesRun* attributesRun = line->AttributesRuns(); AttributesRun* attributesRun = line->AttributesRuns();
int32 attributesRunCount = line->attributesRunCount; int32 attributesRunCount = line->attributesRunCount;
int32 nextAttributesAt = attributesRunCount > 0 int32 nextAttributesAt = attributesRunCount > 0
@@ -95,7 +95,7 @@ HistoryBuffer::GetTerminalLineAt(int32 index, TerminalLine* buffer) const
if (charCount == nextAttributesAt) { if (charCount == nextAttributesAt) {
if (charCount < attributesRun->offset) { if (charCount < attributesRun->offset) {
// the "hole" in attributes run // the "hole" in attributes run
attributes = 0; attributes.Reset();
nextAttributesAt = attributesRun->offset; nextAttributesAt = attributesRun->offset;
} else if (attributesRunCount > 0) { } else if (attributesRunCount > 0) {
attributes = attributesRun->attributes; attributes = attributesRun->attributes;
@@ -104,7 +104,7 @@ HistoryBuffer::GetTerminalLineAt(int32 index, TerminalLine* buffer) const
attributesRun++; attributesRun++;
attributesRunCount--; attributesRunCount--;
} else { } else {
attributes = 0; attributes.Reset();
nextAttributesAt = INT_MAX; nextAttributesAt = INT_MAX;
} }
} }
@@ -120,10 +120,10 @@ HistoryBuffer::GetTerminalLineAt(int32 index, TerminalLine* buffer) const
// full width char? // full width char?
if (cell.character.IsFullWidth()) { if (cell.character.IsFullWidth()) {
cell.attributes |= A_WIDTH; cell.attributes.state |= A_WIDTH;
// attributes of the second, "invisible" cell must be // attributes of the second, "invisible" cell must be
// cleared to let full-width chars detection work properly // cleared to let full-width chars detection work properly
buffer->cells[charCount++].attributes = 0; buffer->cells[charCount++].attributes.Reset();
} }
} }
@@ -140,18 +140,18 @@ HistoryBuffer::AddLine(const TerminalLine* line)
{ {
//debug_printf("HistoryBuffer::AddLine(%p): length: %d\n", line, line->length); //debug_printf("HistoryBuffer::AddLine(%p): length: %d\n", line, line->length);
// determine the amount of memory we need for the line // determine the amount of memory we need for the line
uint32 attributes = 0; Attributes attributes;
int32 attributesRuns = 0; int32 attributesRuns = 0;
int32 byteLength = 0; int32 byteLength = 0;
for (int32 i = 0; i < line->length; i++) { for (int32 i = 0; i < line->length; i++) {
const TerminalCell& cell = line->cells[i]; const TerminalCell& cell = line->cells[i];
byteLength += cell.character.ByteCount(); byteLength += cell.character.ByteCount();
if ((cell.attributes & CHAR_ATTRIBUTES) != attributes) { if ((cell.attributes.state & CHAR_ATTRIBUTES) != attributes.state) {
attributes = cell.attributes & CHAR_ATTRIBUTES; attributes.state = cell.attributes.state & CHAR_ATTRIBUTES;
if (attributes != 0) if (attributes.state != 0)
attributesRuns++; attributesRuns++;
} }
if (IS_WIDTH(cell.attributes)) if (cell.attributes.IsWidth())
i++; i++;
} }
@@ -160,7 +160,7 @@ HistoryBuffer::AddLine(const TerminalLine* line)
// allocate and translate the line // allocate and translate the line
HistoryLine* historyLine = _AllocateLine(attributesRuns, byteLength); HistoryLine* historyLine = _AllocateLine(attributesRuns, byteLength);
attributes = 0; attributes.Reset();
AttributesRun* attributesRun = historyLine->AttributesRuns(); AttributesRun* attributesRun = historyLine->AttributesRuns();
char* chars = historyLine->Chars(); char* chars = historyLine->Chars();
@@ -173,28 +173,28 @@ HistoryBuffer::AddLine(const TerminalLine* line)
chars += charLength; chars += charLength;
// deal with attributes // deal with attributes
if ((cell.attributes & CHAR_ATTRIBUTES) != attributes) { if ((cell.attributes.state & CHAR_ATTRIBUTES) != attributes.state) {
// terminate the previous attributes run // terminate the previous attributes run
if (attributes != 0) { if (attributes.state != 0) {
attributesRun->length = i - attributesRun->offset; attributesRun->length = i - attributesRun->offset;
attributesRun++; attributesRun++;
} }
attributes = cell.attributes & CHAR_ATTRIBUTES; attributes.state = cell.attributes.state & CHAR_ATTRIBUTES;
// init the new one // init the new one
if (attributes != 0) { if (attributes.state != 0) {
attributesRun->attributes = attributes; attributesRun->attributes = attributes;
attributesRun->offset = i; attributesRun->offset = i;
} }
} }
if (IS_WIDTH(cell.attributes)) if (cell.attributes.IsWidth())
i++; i++;
} }
// set the last attributes run's length // set the last attributes run's length
if (attributes != 0) if (attributes.state != 0)
attributesRun->length = line->length - attributesRun->offset; attributesRun->length = line->length - attributesRun->offset;
historyLine->softBreak = line->softBreak; historyLine->softBreak = line->softBreak;
+1 -1
View File
@@ -74,7 +74,7 @@
// TODO: should extract from /etc/passwd instead??? // TODO: should extract from /etc/passwd instead???
const char *kDefaultShell = "/bin/sh"; const char *kDefaultShell = "/bin/sh";
const char *kTerminalType = "xterm-256color"; const char *kTerminalType = "xterm";
/* /*
* Set environment variable. * Set environment variable.
-12
View File
@@ -206,18 +206,6 @@ enum {
#define BACKCOLOR 0xFF000000 #define BACKCOLOR 0xFF000000
#define CHAR_ATTRIBUTES 0xFFFF7700 #define CHAR_ATTRIBUTES 0xFFFF7700
#define IS_WIDTH(x) (((x) & A_WIDTH) )
#define IS_BOLD(x) (((x) & BOLD) )
#define IS_UNDER(x) (((x) & UNDERLINE) )
#define IS_INVERSE(x) (((x) & INVERSE) )
#define IS_MOUSE(x) (((x) & MOUSE) )
#define IS_FORESET(x) (((x) & FORESET) )
#define IS_BACKSET(x) (((x) & BACKSET) )
#define IS_FONT(x) (((x) & FONT) )
#define IS_CR(x) (((x) & DUMPCR) )
#define IS_FORECOLOR(x) (((x) & FORECOLOR) >> 16)
#define IS_BACKCOLOR(x) (((x) & BACKCOLOR) >> 24)
#define FORECOLORED(x) ((x) << 16) #define FORECOLORED(x) ((x) << 16)
#define BACKCOLORED(x) ((x) << 24) #define BACKCOLORED(x) ((x) << 24)
+15 -32
View File
@@ -781,12 +781,12 @@ TermParse::EscParse()
case CASE_SGR: case CASE_SGR:
{ {
/* SGR */ /* SGR */
uint32 attributes = fBuffer->GetAttributes(); Attributes attributes = fBuffer->GetAttributes();
for (row = 0; row < nparam; ++row) { for (row = 0; row < nparam; ++row) {
switch (param[row]) { switch (param[row]) {
case DEFAULT: case DEFAULT:
case 0: /* Reset attribute */ case 0: /* Reset attribute */
attributes = 0; attributes.Reset();
break; break;
case 1: /* Bold */ case 1: /* Bold */
@@ -831,32 +831,22 @@ TermParse::EscParse()
case 35: case 35:
case 36: case 36:
case 37: case 37:
attributes &= ~FORECOLOR; attributes.SetIndexedForeground(param[row] - 30);
attributes |= FORECOLORED(param[row] - 30);
attributes |= FORESET;
break; break;
case 38: case 38:
{ {
int color = -1;
if (nparam == 3 && param[1] == 5) if (nparam == 3 && param[1] == 5)
color = param[2]; attributes.SetIndexedForeground(param[2]);
else if (nparam == 5 && param[1] == 2) else if (nparam == 5 && param[1] == 2)
color = fBuffer->GuessPaletteColor( attributes.SetDirectForeground(param[2], param[3], param[4]);
param[2], param[3], param[4]);
if (color >= 0) {
attributes &= ~FORECOLOR;
attributes |= FORECOLORED(color);
attributes |= FORESET;
}
row = nparam; // force exit of the parsing row = nparam; // force exit of the parsing
break; break;
} }
case 39: case 39:
attributes &= ~FORESET; attributes.UnsetForeground();
break; break;
case 100: case 100:
@@ -876,32 +866,22 @@ TermParse::EscParse()
case 45: case 45:
case 46: case 46:
case 47: case 47:
attributes &= ~BACKCOLOR; attributes.SetIndexedBackground(param[row] - 40);
attributes |= BACKCOLORED(param[row] - 40);
attributes |= BACKSET;
break; break;
case 48: case 48:
{ {
int color = -1;
if (nparam == 3 && param[1] == 5) if (nparam == 3 && param[1] == 5)
color = param[2]; attributes.SetIndexedBackground(param[2]);
else if (nparam == 5 && param[1] == 2) else if (nparam == 5 && param[1] == 2)
color = fBuffer->GuessPaletteColor( attributes.SetDirectBackground(param[2], param[3], param[4]);
param[2], param[3], param[4]);
if (color >= 0) {
attributes &= ~BACKCOLOR;
attributes |= BACKCOLORED(color);
attributes |= BACKSET;
}
row = nparam; // force exit of the parsing row = nparam; // force exit of the parsing
break; break;
} }
case 49: case 49:
attributes &= ~BACKSET; attributes.UnsetBackground();
break; break;
} }
} }
@@ -996,8 +976,11 @@ TermParse::EscParse()
case CASE_DECALN: case CASE_DECALN:
/* DECALN */ /* DECALN */
fBuffer->FillScreen(UTF8Char('E'), 0); {
parsestate = groundtable; Attributes attr;
fBuffer->FillScreen(UTF8Char('E'), attr);
parsestate = groundtable;
}
break; break;
// case CASE_GSETS: // case CASE_GSETS:
+23 -28
View File
@@ -1028,13 +1028,13 @@ TermView::_Deactivate()
//! Draw part of a line in the given view. //! Draw part of a line in the given view.
void void
TermView::_DrawLinePart(float x1, float y1, uint32 attr, char *buf, TermView::_DrawLinePart(float x1, float y1, Attributes attr,
int32 width, Highlight* highlight, bool cursor, BView *inView) char *buf, int32 width, Highlight* highlight, bool cursor, BView *inView)
{ {
if (highlight != NULL) if (highlight != NULL)
attr = highlight->Highlighter()->AdjustTextAttributes(attr); attr.state = highlight->Highlighter()->AdjustTextAttributes(attr.state);
inView->SetFont(IS_BOLD(attr) && !fEmulateBold && fAllowBold inView->SetFont(attr.IsBold() && !fEmulateBold && fAllowBold
? &fBoldFont : &fHalfFont); ? &fBoldFont : &fHalfFont);
// Set pen point // Set pen point
@@ -1045,13 +1045,10 @@ TermView::_DrawLinePart(float x1, float y1, uint32 attr, char *buf,
rgb_color rgb_back = fTextBackColor; rgb_color rgb_back = fTextBackColor;
// color attribute // color attribute
int forecolor = IS_FORECOLOR(attr); if (attr.IsForeSet())
int backcolor = IS_BACKCOLOR(attr); rgb_fore = attr.ForegroundColor(fTextBuffer->Palette());
if (attr.IsBackSet())
if (IS_FORESET(attr)) rgb_back = attr.BackgroundColor(fTextBuffer->Palette());
rgb_fore = fTextBuffer->PaletteColor(forecolor);
if (IS_BACKSET(attr))
rgb_back = fTextBuffer->PaletteColor(backcolor);
// Selection check. // Selection check.
if (cursor) { if (cursor) {
@@ -1062,7 +1059,7 @@ TermView::_DrawLinePart(float x1, float y1, uint32 attr, char *buf,
rgb_back = highlight->Highlighter()->BackgroundColor(); rgb_back = highlight->Highlighter()->BackgroundColor();
} else { } else {
// Reverse attribute(If selected area, don't reverse color). // Reverse attribute(If selected area, don't reverse color).
if (IS_INVERSE(attr)) { if (attr.IsInverse()) {
rgb_color rgb_tmp = rgb_fore; rgb_color rgb_tmp = rgb_fore;
rgb_fore = rgb_back; rgb_fore = rgb_back;
rgb_back = rgb_tmp; rgb_back = rgb_tmp;
@@ -1076,7 +1073,7 @@ TermView::_DrawLinePart(float x1, float y1, uint32 attr, char *buf,
inView->SetHighColor(rgb_fore); inView->SetHighColor(rgb_fore);
// Draw character. // Draw character.
if (IS_BOLD(attr)) { if (attr.IsBold()) {
if (fEmulateBold) { if (fEmulateBold) {
inView->MovePenTo(x1 - 1, y1 + fFontAscent - 1); inView->MovePenTo(x1 - 1, y1 + fFontAscent - 1);
inView->DrawString((char *)buf); inView->DrawString((char *)buf);
@@ -1097,7 +1094,7 @@ TermView::_DrawLinePart(float x1, float y1, uint32 attr, char *buf,
inView->SetDrawingMode(B_OP_COPY); inView->SetDrawingMode(B_OP_COPY);
// underline attribute // underline attribute
if (IS_UNDER(attr)) { if (attr.IsUnder()) {
inView->MovePenTo(x1, y1 + fFontAscent); inView->MovePenTo(x1, y1 + fFontAscent);
inView->StrokeLine(BPoint(x1 , y1 + fFontAscent), inView->StrokeLine(BPoint(x1 , y1 + fFontAscent),
BPoint(x2 , y1 + fFontAscent)); BPoint(x2 , y1 + fFontAscent));
@@ -1116,7 +1113,7 @@ TermView::_DrawCursor()
int32 firstVisible = _LineAt(0); int32 firstVisible = _LineAt(0);
UTF8Char character; UTF8Char character;
uint32 attr = 0; Attributes attr;
bool cursorVisible = _IsCursorVisible(); bool cursorVisible = _IsCursorVisible();
@@ -1139,7 +1136,7 @@ TermView::_DrawCursor()
character, attr) == A_CHAR character, attr) == A_CHAR
&& (fCursorStyle == BLOCK_CURSOR || !cursorVisible)) { && (fCursorStyle == BLOCK_CURSOR || !cursorVisible)) {
int32 width = IS_WIDTH(attr) ? FULL_WIDTH : HALF_WIDTH; int32 width = attr.IsWidth() ? FULL_WIDTH : HALF_WIDTH;
char buffer[5]; char buffer[5];
int32 bytes = UTF8Char::ByteCount(character.bytes[0]); int32 bytes = UTF8Char::ByteCount(character.bytes[0]);
memcpy(buffer, character.bytes, bytes); memcpy(buffer, character.bytes, bytes);
@@ -1160,15 +1157,15 @@ TermView::_DrawCursor()
fTextBuffer->GetCellAttributes( fTextBuffer->GetCellAttributes(
fCursor.y, fCursor.x, attr, count); fCursor.y, fCursor.x, attr, count);
else else
attr = fVisibleTextBuffer->GetLineColor( fVisibleTextBuffer->GetLineColor(fCursor.y - firstVisible, attr);
fCursor.y - firstVisible);
if (attr.IsBackSet())
rgb_back = attr.BackgroundColor(fTextBuffer->Palette());
if (IS_BACKSET(attr))
rgb_back = fTextBuffer->PaletteColor(IS_BACKCOLOR(attr));
SetHighColor(rgb_back); SetHighColor(rgb_back);
} }
if (IS_WIDTH(attr) && fCursorStyle != IBEAM_CURSOR) if (attr.IsWidth() && fCursorStyle != IBEAM_CURSOR)
rect.right += fFontWidth; rect.right += fFontWidth;
FillRect(rect); FillRect(rect);
@@ -1339,7 +1336,7 @@ TermView::Draw(BRect updateRect)
// draw the affected line parts // draw the affected line parts
if (x1 <= x2) { if (x1 <= x2) {
uint32 attr = 0; Attributes attr;
for (int32 j = y1; j <= y2; j++) { for (int32 j = y1; j <= y2; j++) {
int32 k = x1; int32 k = x1;
@@ -1383,12 +1380,10 @@ TermView::Draw(BRect updateRect)
rect.right = rect.left + fFontWidth * count - 1; rect.right = rect.left + fFontWidth * count - 1;
nextColumn = i + count; nextColumn = i + count;
} else } else
attr = fVisibleTextBuffer->GetLineColor(j - firstVisible); fVisibleTextBuffer->GetLineColor(j - firstVisible, attr);
if (IS_BACKSET(attr)) { if (attr.IsBackSet())
int backcolor = IS_BACKCOLOR(attr); rgb_back = attr.BackgroundColor(fTextBuffer->Palette());
rgb_back = fTextBuffer->PaletteColor(backcolor);
}
SetHighColor(rgb_back); SetHighColor(rgb_back);
rgb_back = HighColor(); rgb_back = HighColor();
@@ -1404,7 +1399,7 @@ TermView::Draw(BRect updateRect)
// side - drawing the whole string with one call render the // side - drawing the whole string with one call render the
// characters not aligned to cells grid - that looks much more // characters not aligned to cells grid - that looks much more
// inaccurate for full-width strings than for half-width ones. // inaccurate for full-width strings than for half-width ones.
if (IS_WIDTH(attr)) if (attr.IsWidth())
count = FULL_WIDTH; count = FULL_WIDTH;
_DrawLinePart(fFontWidth * i, (int32)_LineOffset(j), _DrawLinePart(fFontWidth * i, (int32)_LineOffset(j),
+3 -2
View File
@@ -23,6 +23,7 @@
#include <String.h> #include <String.h>
#include <View.h> #include <View.h>
#include "TerminalLine.h"
#include "TermPos.h" #include "TermPos.h"
#include "TermViewHighlight.h" #include "TermViewHighlight.h"
@@ -202,7 +203,7 @@ private:
void _Activate(); void _Activate();
void _Deactivate(); void _Deactivate();
void _DrawLinePart(float x1, float y1, uint32 attr, void _DrawLinePart(float x1, float y1, Attributes attr,
char* buffer, int32 width, char* buffer, int32 width,
Highlight* highlight, bool cursor, Highlight* highlight, bool cursor,
BView* inView); BView* inView);
@@ -315,7 +316,7 @@ private:
BScrollBar* fScrollBar; BScrollBar* fScrollBar;
InlineInput* fInline; InlineInput* fInline;
// Color and Attribute. // Color and Attributes.
rgb_color fTextForeColor; rgb_color fTextForeColor;
rgb_color fTextBackColor; rgb_color fTextBackColor;
rgb_color fCursorForeColor; rgb_color fCursorForeColor;
+1 -29
View File
@@ -30,7 +30,7 @@ TerminalBuffer::TerminalBuffer()
fAlternateScreen(NULL), fAlternateScreen(NULL),
fAlternateHistory(NULL), fAlternateHistory(NULL),
fAlternateScreenOffset(0), fAlternateScreenOffset(0),
fAlternateAttributes(0), fAlternateAttributes(),
fColorsPalette(NULL), fColorsPalette(NULL),
fListenerValid(false) fListenerValid(false)
{ {
@@ -280,34 +280,6 @@ TerminalBuffer::SetPaletteColor(uint8 index, rgb_color color)
} }
rgb_color
TerminalBuffer::PaletteColor(uint8 index)
{
return fColorsPalette[index];
}
int
TerminalBuffer::GuessPaletteColor(int red, int green, int blue)
{
int distance = 255 * 100;
int index = -1;
for (uint32 i = 0; i < kTermColorCount && distance > 0; i++) {
rgb_color color = fColorsPalette[i];
int r = 30 * abs(color.red - red);
int g = 59 * abs(color.green - green);
int b = 11 * abs(color.blue - blue);
int d = r + g + b;
if (distance > d) {
index = i;
distance = d;
}
}
return min_c(index, int(kTermColorCount - 1));
}
void void
TerminalBuffer::NotifyQuit(int32 reason) TerminalBuffer::NotifyQuit(int32 reason)
{ {
+3 -3
View File
@@ -42,8 +42,8 @@ public:
void SetCursorBlinking(bool blinking); void SetCursorBlinking(bool blinking);
void SetCursorHidden(bool hidden); void SetCursorHidden(bool hidden);
void SetPaletteColor(uint8 index, rgb_color color); void SetPaletteColor(uint8 index, rgb_color color);
rgb_color PaletteColor(uint8 index); inline const rgb_color*
int GuessPaletteColor(int red, int green, int blue); Palette() const { return fColorsPalette; }
void NotifyQuit(int32 reason); void NotifyQuit(int32 reason);
@@ -75,7 +75,7 @@ private:
TerminalLine** fAlternateScreen; TerminalLine** fAlternateScreen;
HistoryBuffer* fAlternateHistory; HistoryBuffer* fAlternateHistory;
int32 fAlternateScreenOffset; int32 fAlternateScreenOffset;
uint32 fAlternateAttributes; Attributes fAlternateAttributes;
rgb_color* fColorsPalette; rgb_color* fColorsPalette;
// listener/dirty region management // listener/dirty region management
+130 -6
View File
@@ -10,6 +10,7 @@
#ifndef TERMINAL_LINE_H #ifndef TERMINAL_LINE_H
#define TERMINAL_LINE_H #define TERMINAL_LINE_H
#include <GraphicsDefs.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include "TermConst.h" #include "TermConst.h"
@@ -17,19 +18,142 @@
#include "UTF8Char.h" #include "UTF8Char.h"
struct Attributes {
uint32 state;
uint32 foreground;
uint32 background;
Attributes() : state(0), foreground(0), background(0) {}
inline void Reset() { state = 0; foreground = 0; background = 0; }
inline bool IsWidth() const { return (state & A_WIDTH) == A_WIDTH; }
inline bool IsBold() const { return (state & BOLD) == BOLD; }
inline bool IsUnder() const { return (state & UNDERLINE) == UNDERLINE; }
inline bool IsInverse() const { return (state & INVERSE) == INVERSE; }
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 IsFont() const { return (state & FONT) == FONT; }
inline bool IsCR() const { return (state & DUMPCR) == DUMPCR; }
inline void SetDirectForeground(uint8 red, uint8 green, uint8 blue)
{
foreground = 0x80000000 | (red << 16) | (green << 8) | blue;
state &= ~FORECOLOR;
state |= FORESET;
}
inline void SetDirectBackground(uint8 red, uint8 green, uint8 blue)
{
background = 0x80000000 | (red << 16) | (green << 8) | blue;
state &= ~BACKCOLOR;
state |= BACKSET;
}
inline void SetIndexedForeground(uint32 index)
{
state &= ~FORECOLOR;
state |= FORESET;
state |= FORECOLORED(index);
foreground = 0;
}
inline void SetIndexedBackground(uint32 index)
{
state &= ~BACKCOLOR;
state |= BACKSET;
state |= BACKCOLORED(index);
background = 0;
}
inline void UnsetForeground()
{
state &= ~FORESET;
foreground = 0;
}
inline void UnsetBackground()
{
state &= ~BACKSET;
background = 0;
}
inline rgb_color
ForegroundColor(const rgb_color* indexedColors) const
{
if ((foreground & 0x80000000) != 0)
return make_color((foreground >> 16) & 0xFF,
(foreground >> 8) & 0xFF,
foreground & 0xFF);
else
return indexedColors[(state & FORECOLOR) >> 16];
}
inline rgb_color
BackgroundColor(const rgb_color* indexedColors) const
{
if ((background & 0x80000000) != 0)
return make_color((background >> 16) & 0xFF,
(background >> 8) & 0xFF,
background & 0xFF);
else
return indexedColors[(state & BACKCOLOR) >> 24];
}
inline Attributes&
operator&=(uint32 value) { state &= value; return *this; }
inline Attributes&
operator|=(uint32 value) { state |= value; return *this; }
inline uint32
operator|(uint32 value) { return state | value; }
inline uint32
operator&(uint32 value) { return state & value; }
inline bool
operator==(const Attributes& other) const
{
return state == other.state
&& foreground == other.foreground
&& background == other.background;
}
inline bool
operator!=(const Attributes& other) const
{
return state != other.state
|| foreground != other.foreground
|| background != other.background;
}
};
struct TerminalCell { struct TerminalCell {
UTF8Char character; UTF8Char character;
uint32 attributes; Attributes attributes;
}; };
struct TerminalLine { struct TerminalLine {
uint16 length; uint16 length;
bool softBreak; // soft line break bool softBreak; // soft line break
uint32 attributes; Attributes attributes;
TerminalCell cells[1]; TerminalCell cells[1];
inline void Clear(uint32 attr = 0, size_t count = 0) inline void Clear()
{
Clear(Attributes());
}
inline void Clear(size_t count)
{
Clear(Attributes(), count);
}
inline void Clear(Attributes attr, size_t count = 0)
{ {
length = 0; length = 0;
attributes = attr; attributes = attr;
@@ -41,7 +165,7 @@ struct TerminalLine {
struct AttributesRun { struct AttributesRun {
uint32 attributes; Attributes attributes;
uint16 offset; // character offset uint16 offset; // character offset
uint16 length; // length of the run in characters uint16 length; // length of the run in characters
}; };
@@ -52,7 +176,7 @@ struct HistoryLine {
uint16 attributesRunCount; // number of attribute runs uint16 attributesRunCount; // number of attribute runs
uint16 byteLength : 15; // number of bytes in the line uint16 byteLength : 15; // number of bytes in the line
bool softBreak : 1; // soft line break; bool softBreak : 1; // soft line break;
uint32 attributes; Attributes attributes;
AttributesRun* AttributesRuns() const AttributesRun* AttributesRuns() const
{ {