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