Support Background Color Erase, switch to xterm-256color
* Lot of fixes to add support of BCE (background color erase). Shell is switched to emulate xterm-256colors terminal, that is modern and declare the colors capabilities of our Terminal more precisely; * Move current character attributes fAttr from TermView to BasicTerminalBuffer. This reduces count of function parameters on call various InsertXXX routines; * In alternative screen buffer mode the whole cells "matrix" of the screen buffers is taken into account during drawing background of the cells in the view. In normal mode the "attributes" field of the TerminalLine is used to detect color of the area after the last character - there should be no changes with previous behaviour; * Fix attributes on kSpaceChar-padding short lines. Current _line_ attributes should be used instead of current _global_ attributes; * Fixed pads and gaps attributes, more accurate handling of ESC[K and K°; * _Invalidate strings just erased. Fix EraseChars DCH processing; * Fixes for ESC[J erase lines control sequences; * Added handling SGR 90-97, 100-107 codes; * Clean the newly allocated TerminalLine lines; * More precise cursor background [off-]color estimation at ends of lines. The current line attributes should be used instead of hard-coding it to fTextBackground; * Fixed background color erase in normal screen buffer modes. Wrong line indexes calculation messed the drawing results or just returned 0 [default] line attributes; * Some more BCE support: TerminalLine::Clear() now honors current character attributes; * Fixes #6143, #6510 and #6424.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "BasicTerminalBuffer.h"
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
@@ -106,6 +107,8 @@ BasicTerminalBuffer::BasicTerminalBuffer()
|
||||
fScreen(NULL),
|
||||
fScreenOffset(0),
|
||||
fHistory(NULL),
|
||||
fAttributes(0),
|
||||
fSavedAttributes(0),
|
||||
fSoftWrappedCursor(false),
|
||||
fOverwriteMode(false),
|
||||
fAlternateScreenActive(false),
|
||||
@@ -268,7 +271,7 @@ BasicTerminalBuffer::SynchronizeWith(const BasicTerminalBuffer* other,
|
||||
// directly into destLine.
|
||||
}
|
||||
} else
|
||||
destLine->Clear();
|
||||
destLine->Clear(fAttributes, fWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +307,28 @@ BasicTerminalBuffer::GetChar(int32 row, int32 column, UTF8Char& character,
|
||||
return A_CHAR;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::GetCellAttributes(int32 row, int32 column,
|
||||
uint32& attributes, uint32& count) const
|
||||
{
|
||||
count = 0;
|
||||
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
|
||||
TerminalLine* line = _HistoryLineAt(row, lineBuffer);
|
||||
if (line == NULL || column < 0)
|
||||
return;
|
||||
|
||||
uint32 c = column;
|
||||
for (; c < fWidth; c++) {
|
||||
TerminalCell& cell = line->cells[c];
|
||||
if (c > column && attributes != cell.attributes) {
|
||||
break;
|
||||
}
|
||||
attributes = cell.attributes;
|
||||
}
|
||||
count = c - column;
|
||||
// printf("r:%d c:%d count:%d a:%x\n", row, column, count, attributes);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BasicTerminalBuffer::GetString(int32 row, int32 firstColumn, int32 lastColumn,
|
||||
@@ -578,12 +603,12 @@ BasicTerminalBuffer::Find(const char* _pattern, const TermPos& start,
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 width, uint32 attributes)
|
||||
BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 width)
|
||||
{
|
||||
//debug_printf("BasicTerminalBuffer::InsertChar('%.*s' (%d), %#lx)\n",
|
||||
//(int)c.ByteCount(), c.bytes, c.bytes[0], attributes);
|
||||
if ((int32)width == FULL_WIDTH)
|
||||
attributes |= A_WIDTH;
|
||||
fAttributes |= A_WIDTH;
|
||||
|
||||
if (fSoftWrappedCursor || fCursor.x + (int32)width > fWidth)
|
||||
_SoftBreakLine();
|
||||
@@ -597,7 +622,7 @@ BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 width, uint32 attributes)
|
||||
|
||||
TerminalLine* line = _LineAt(fCursor.y);
|
||||
line->cells[fCursor.x].character = c;
|
||||
line->cells[fCursor.x].attributes = attributes;
|
||||
line->cells[fCursor.x].attributes = fAttributes;
|
||||
|
||||
if (line->length < fCursor.x + width)
|
||||
line->length = fCursor.x + width;
|
||||
@@ -638,14 +663,15 @@ BasicTerminalBuffer::FillScreen(UTF8Char c, uint32 width, uint32 attributes)
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertCR(uint32 attributes)
|
||||
BasicTerminalBuffer::InsertCR()
|
||||
{
|
||||
TerminalLine* line = _LineAt(fCursor.y);
|
||||
|
||||
line->attributes = attributes;
|
||||
line->attributes = fAttributes;
|
||||
line->softBreak = false;
|
||||
fSoftWrappedCursor = false;
|
||||
fCursor.x = 0;
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
_CursorChanged();
|
||||
}
|
||||
|
||||
@@ -685,7 +711,7 @@ BasicTerminalBuffer::InsertRI()
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertTab(uint32 attributes)
|
||||
BasicTerminalBuffer::InsertTab()
|
||||
{
|
||||
int32 x;
|
||||
|
||||
@@ -701,7 +727,7 @@ BasicTerminalBuffer::InsertTab(uint32 attributes)
|
||||
TerminalLine* line = _LineAt(fCursor.y);
|
||||
for (int32 i = fCursor.x; i <= x; i++) {
|
||||
line->cells[i].character = ' ';
|
||||
line->cells[i].attributes = attributes;
|
||||
line->cells[i].attributes = fAttributes;
|
||||
}
|
||||
fCursor.x = x;
|
||||
if (line->length < fCursor.x)
|
||||
@@ -745,6 +771,7 @@ BasicTerminalBuffer::InsertSpace(int32 num)
|
||||
line->cells[i].character = kSpaceChar;
|
||||
line->cells[i].attributes = line->cells[fCursor.x - 1].attributes;
|
||||
}
|
||||
line->attributes = fAttributes;
|
||||
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
}
|
||||
@@ -755,23 +782,35 @@ void
|
||||
BasicTerminalBuffer::EraseCharsFrom(int32 first, int32 numChars)
|
||||
{
|
||||
TerminalLine* line = _LineAt(fCursor.y);
|
||||
if (fCursor.y >= line->length)
|
||||
return;
|
||||
|
||||
/* if (IsAlternateScreenActive())*/ {
|
||||
int32 end = min_c(first + numChars, fWidth);
|
||||
for (int32 i = first; i < end; i++)
|
||||
line->cells[i].attributes = fAttributes;
|
||||
}
|
||||
|
||||
line->attributes = fAttributes;
|
||||
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
|
||||
// if (fCursor.x >= line->length)
|
||||
// return;
|
||||
|
||||
fSoftWrappedCursor = false;
|
||||
|
||||
int32 end = min_c(first + numChars, line->length);
|
||||
// printf("%d:%d - %d|", fCursor.y, first, end);
|
||||
if (first > 0 && IS_WIDTH(line->cells[first - 1].attributes))
|
||||
first--;
|
||||
if (end > 0 && IS_WIDTH(line->cells[end - 1].attributes))
|
||||
end++;
|
||||
|
||||
// printf("%d - %d\n", first, end);
|
||||
for (int32 i = first; i < end; i++) {
|
||||
line->cells[i].character = kSpaceChar;
|
||||
line->cells[i].attributes = 0;
|
||||
line->cells[i].attributes = fAttributes;
|
||||
}
|
||||
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
}
|
||||
|
||||
|
||||
@@ -791,11 +830,11 @@ BasicTerminalBuffer::EraseAbove()
|
||||
if (IS_WIDTH(line->cells[fCursor.x].attributes))
|
||||
to++;
|
||||
for (int32 i = 0; i <= to; i++) {
|
||||
line->cells[i].attributes = 0;
|
||||
line->cells[i].attributes = fAttributes;
|
||||
line->cells[i].character = kSpaceChar;
|
||||
}
|
||||
} else
|
||||
line->Clear();
|
||||
line->Clear(fAttributes, fWidth);
|
||||
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
}
|
||||
@@ -835,11 +874,19 @@ BasicTerminalBuffer::DeleteChars(int32 numChars)
|
||||
memmove(line->cells + fCursor.x, line->cells + fCursor.x + numChars,
|
||||
left * sizeof(TerminalCell));
|
||||
line->length = fCursor.x + left;
|
||||
// process BCE on freed tail cells
|
||||
for (int i = 0; i < numChars; i++)
|
||||
line->cells[fCursor.x + left + i].attributes = fAttributes;
|
||||
} else {
|
||||
// process BCE on freed tail cells
|
||||
for (int i = 0; i < line->length - fCursor.x; i++)
|
||||
line->cells[fCursor.x + i].attributes = fAttributes;
|
||||
// remove all remaining chars
|
||||
line->length = fCursor.x;
|
||||
}
|
||||
|
||||
// line->attributes = fAttributes;
|
||||
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
}
|
||||
}
|
||||
@@ -851,10 +898,15 @@ BasicTerminalBuffer::DeleteColumnsFrom(int32 first)
|
||||
fSoftWrappedCursor = false;
|
||||
|
||||
TerminalLine* line = _LineAt(fCursor.y);
|
||||
if (first < line->length) {
|
||||
|
||||
for (int32 i = first; i < fWidth; i++)
|
||||
line->cells[i].attributes = fAttributes;
|
||||
|
||||
if (first <= line->length) {
|
||||
line->length = first;
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
line->attributes = fAttributes;
|
||||
}
|
||||
_Invalidate(fCursor.y, fCursor.y);
|
||||
}
|
||||
|
||||
|
||||
@@ -991,12 +1043,14 @@ BasicTerminalBuffer::_AllocateLines(int32 width, int32 count)
|
||||
return NULL;
|
||||
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
lines[i] = (TerminalLine*)malloc(sizeof(TerminalLine)
|
||||
+ sizeof(TerminalCell) * (width - 1));
|
||||
const int32 size = sizeof(TerminalLine)
|
||||
+ sizeof(TerminalCell) * (width - 1);
|
||||
lines[i] = (TerminalLine*)malloc(size);
|
||||
if (lines[i] == NULL) {
|
||||
_FreeLines(lines, i);
|
||||
return NULL;
|
||||
}
|
||||
memset(lines[i], 0, size);
|
||||
}
|
||||
|
||||
return lines;
|
||||
@@ -1029,7 +1083,7 @@ BasicTerminalBuffer::_ClearLines(int32 first, int32 last)
|
||||
lastCleared = i;
|
||||
}
|
||||
|
||||
line->Clear();
|
||||
line->Clear(fAttributes, fWidth);
|
||||
}
|
||||
|
||||
if (firstCleared >= 0)
|
||||
@@ -1133,7 +1187,7 @@ BasicTerminalBuffer::_ResizeSimple(int32 width, int32 height,
|
||||
|
||||
// clear the remaining lines
|
||||
for (int32 i = endLine - firstLine; i < height; i++)
|
||||
lines[i]->Clear();
|
||||
lines[i]->Clear(fAttributes, width);
|
||||
|
||||
_FreeLines(fScreen, fHeight);
|
||||
fScreen = lines;
|
||||
@@ -1223,7 +1277,7 @@ BasicTerminalBuffer::_ResizeRewrap(int32 width, int32 height,
|
||||
// history first, though.
|
||||
if (history != NULL && destTotalLines >= height)
|
||||
history->AddLine(screen[destIndex]);
|
||||
destLine->Clear();
|
||||
destLine->Clear(fAttributes, width);
|
||||
newDestLine = false;
|
||||
}
|
||||
|
||||
@@ -1273,6 +1327,8 @@ BasicTerminalBuffer::_ResizeRewrap(int32 width, int32 height,
|
||||
sourceLine->cells + sourceX, toCopy * sizeof(TerminalCell));
|
||||
destLine->length += toCopy;
|
||||
}
|
||||
|
||||
destLine->attributes = sourceLine->attributes;
|
||||
|
||||
bool nextDestLine = false;
|
||||
if (toCopy == sourceLeft) {
|
||||
@@ -1319,7 +1375,7 @@ BasicTerminalBuffer::_ResizeRewrap(int32 width, int32 height,
|
||||
TerminalLine* line = screen[i % height];
|
||||
if (history != NULL && i >= height)
|
||||
history->AddLine(line);
|
||||
line->Clear();
|
||||
line->Clear(fAttributes, width);
|
||||
}
|
||||
|
||||
// Update the values
|
||||
@@ -1401,7 +1457,7 @@ BasicTerminalBuffer::_Scroll(int32 top, int32 bottom, int32 numLines)
|
||||
// lines
|
||||
fScreenOffset = (fScreenOffset + numLines) % fHeight;
|
||||
for (int32 i = bottom - numLines + 1; i <= bottom; i++)
|
||||
_LineAt(i)->Clear();
|
||||
_LineAt(i)->Clear(fAttributes, fWidth);
|
||||
} else {
|
||||
// Partial screen scroll. We move the screen offset anyway, but
|
||||
// have to move the unscrolled lines to their new location.
|
||||
@@ -1416,7 +1472,7 @@ BasicTerminalBuffer::_Scroll(int32 top, int32 bottom, int32 numLines)
|
||||
// update the screen offset and clear the new lines
|
||||
fScreenOffset = (fScreenOffset + numLines) % fHeight;
|
||||
for (int32 i = bottom - numLines + 1; i <= bottom; i++)
|
||||
_LineAt(i)->Clear();
|
||||
_LineAt(i)->Clear(fAttributes, fWidth);
|
||||
}
|
||||
|
||||
// scroll/extend dirty range
|
||||
@@ -1456,12 +1512,12 @@ BasicTerminalBuffer::_Scroll(int32 top, int32 bottom, int32 numLines)
|
||||
for (int32 i = top + numLines; i <= bottom; i++) {
|
||||
int32 lineToDrop = _LineIndex(i - numLines);
|
||||
int32 lineToKeep = _LineIndex(i);
|
||||
fScreen[lineToDrop]->Clear();
|
||||
fScreen[lineToDrop]->Clear(fAttributes, fWidth);
|
||||
std::swap(fScreen[lineToDrop], fScreen[lineToKeep]);
|
||||
}
|
||||
// clear any lines between the two swapped ranges above
|
||||
for (int32 i = bottom - numLines + 1; i < top + numLines; i++)
|
||||
_LineAt(i)->Clear();
|
||||
_LineAt(i)->Clear(fAttributes, fWidth);
|
||||
|
||||
_Invalidate(top, bottom);
|
||||
}
|
||||
@@ -1481,12 +1537,12 @@ BasicTerminalBuffer::_Scroll(int32 top, int32 bottom, int32 numLines)
|
||||
for (int32 i = bottom - numLines; i >= top; i--) {
|
||||
int32 lineToKeep = _LineIndex(i);
|
||||
int32 lineToDrop = _LineIndex(i + numLines);
|
||||
fScreen[lineToDrop]->Clear();
|
||||
fScreen[lineToDrop]->Clear(fAttributes, fWidth);
|
||||
std::swap(fScreen[lineToDrop], fScreen[lineToKeep]);
|
||||
}
|
||||
// clear any lines between the two swapped ranges above
|
||||
for (int32 i = bottom - numLines + 1; i < top + numLines; i++)
|
||||
_LineAt(i)->Clear();
|
||||
_LineAt(i)->Clear(fAttributes, fWidth);
|
||||
|
||||
_Invalidate(top, bottom);
|
||||
}
|
||||
@@ -1515,8 +1571,7 @@ BasicTerminalBuffer::_PadLineToCursor()
|
||||
if (line->length < fCursor.x) {
|
||||
for (int32 i = line->length; i < fCursor.x; i++) {
|
||||
line->cells[i].character = kSpaceChar;
|
||||
line->cells[i].attributes = 0;
|
||||
// TODO: Other attributes?
|
||||
// line->cells[i].attributes = line->attributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,8 @@ public:
|
||||
int GetChar(int32 row, int32 column,
|
||||
UTF8Char& character,
|
||||
uint32& attributes) const;
|
||||
void GetCellAttributes(int32 row, int32 column,
|
||||
uint32& attributes, uint32& count) const;
|
||||
int32 GetString(int32 row, int32 firstColumn,
|
||||
int32 lastColumn, char* buffer,
|
||||
uint32& attributes) const;
|
||||
@@ -104,6 +106,10 @@ public:
|
||||
bool matchWord, TermPos& matchStart,
|
||||
TermPos& matchEnd) const;
|
||||
|
||||
inline uint32 GetAttributes();
|
||||
inline void SetAttributes(uint32 attributes);
|
||||
inline void PreserveAttributes(bool store);
|
||||
|
||||
// snapshots and data capture for debugging
|
||||
void MakeLinesSnapshots(time_t timeStamp,
|
||||
const char* fileName);
|
||||
@@ -111,19 +117,17 @@ public:
|
||||
/*inline*/ void CaptureChar(char ch);
|
||||
|
||||
// insert chars/lines
|
||||
inline void InsertChar(UTF8Char c, uint32 attributes);
|
||||
void InsertChar(UTF8Char c, uint32 width,
|
||||
uint32 attributes);
|
||||
inline void InsertChar(UTF8Char c);
|
||||
void InsertChar(UTF8Char c, uint32 width);
|
||||
inline void InsertChar(const char* c, int32 length);
|
||||
inline void InsertChar(const char* c, int32 length,
|
||||
uint32 attributes);
|
||||
inline void InsertChar(const char* c, int32 length,
|
||||
uint32 width, uint32 attributes);
|
||||
uint32 width);
|
||||
void FillScreen(UTF8Char c, uint32 width, uint32 attr);
|
||||
|
||||
void InsertCR(uint32 attrs);
|
||||
void InsertCR();
|
||||
void InsertLF();
|
||||
void InsertRI();
|
||||
void InsertTab(uint32 attr);
|
||||
void InsertTab();
|
||||
void SetInsertMode(int flag);
|
||||
void InsertSpace(int32 num);
|
||||
void InsertLines(int32 numLines);
|
||||
@@ -178,7 +182,7 @@ protected:
|
||||
|
||||
static TerminalLine** _AllocateLines(int32 width, int32 count);
|
||||
static void _FreeLines(TerminalLine** lines, int32 count);
|
||||
void _ClearLines(int32 first, int32 last);
|
||||
void _ClearLines(int32 first, int32 last/*, uint32 attr = 0*/); //TODO attr
|
||||
|
||||
status_t _ResizeHistory(int32 width,
|
||||
int32 historyCapacity);
|
||||
@@ -214,6 +218,9 @@ protected:
|
||||
int32 fScreenOffset; // index of screen line 0
|
||||
HistoryBuffer* fHistory;
|
||||
|
||||
uint32 fAttributes;
|
||||
uint32 fSavedAttributes;
|
||||
|
||||
// cursor position (origin: (0, 0))
|
||||
TermPos fCursor;
|
||||
TermPos fSavedCursor;
|
||||
@@ -247,24 +254,48 @@ BasicTerminalBuffer::HistoryCapacity() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 attributes)
|
||||
uint32
|
||||
BasicTerminalBuffer::GetAttributes()
|
||||
{
|
||||
return InsertChar(c, 1, attributes);
|
||||
return fAttributes;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(const char* c, int32 length, uint32 attributes)
|
||||
BasicTerminalBuffer::SetAttributes(uint32 attributes)
|
||||
{
|
||||
return InsertChar(UTF8Char(c, length), 1, attributes);
|
||||
fAttributes = attributes;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(const char* c, int32 length, uint32 width, uint32 attributes)
|
||||
BasicTerminalBuffer::PreserveAttributes(bool store)
|
||||
{
|
||||
return InsertChar(UTF8Char(c, length), width, attributes);
|
||||
if (store)
|
||||
fSavedAttributes = fAttributes;
|
||||
else
|
||||
fAttributes = fSavedAttributes;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(UTF8Char c)
|
||||
{
|
||||
return InsertChar(c, 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(const char* c, int32 length)
|
||||
{
|
||||
return InsertChar(UTF8Char(c, length), 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(const char* c, int32 length, uint32 width)
|
||||
{
|
||||
return InsertChar(UTF8Char(c, length), width);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,10 @@
|
||||
#define CSWTCH 0
|
||||
#endif
|
||||
|
||||
// TODO: should extract from /etc/passwd instead???
|
||||
const char *kDefaultShell = "/bin/sh";
|
||||
const char *kTerminalType = "xterm-256color";
|
||||
//const char *kTerminalType = "xterm";
|
||||
|
||||
/*
|
||||
* Set environment variable.
|
||||
@@ -539,7 +542,7 @@ Shell::_Spawn(int row, int col, const ShellParameters& parameters)
|
||||
/*
|
||||
* setenv TERM and TTY.
|
||||
*/
|
||||
setenv("TERM", "xterm", true);
|
||||
setenv("TERM", kTerminalType, true);
|
||||
setenv("TTY", ttyName, true);
|
||||
setenv("TTYPE", parameters.Encoding(), true);
|
||||
|
||||
|
||||
@@ -72,8 +72,6 @@ TermParse::_NextParseChar()
|
||||
TermParse::TermParse(int fd)
|
||||
:
|
||||
fFd(fd),
|
||||
fAttr(BACKCOLOR),
|
||||
fSavedAttr(BACKCOLOR),
|
||||
fParseThread(-1),
|
||||
fReaderThread(-1),
|
||||
fReaderSem(-1),
|
||||
@@ -393,8 +391,6 @@ TermParse::EscParse()
|
||||
int width = 1;
|
||||
BAutolock locker(fBuffer);
|
||||
|
||||
fAttr = fSavedAttr = BACKCOLOR;
|
||||
|
||||
while (!fQuitting) {
|
||||
try {
|
||||
uchar c = _NextParseChar();
|
||||
@@ -416,7 +412,7 @@ TermParse::EscParse()
|
||||
|
||||
switch (parsestate[c]) {
|
||||
case CASE_PRINT:
|
||||
fBuffer->InsertChar((char)c, fAttr);
|
||||
fBuffer->InsertChar((char)c);
|
||||
break;
|
||||
|
||||
case CASE_PRINT_GR:
|
||||
@@ -470,7 +466,7 @@ TermParse::EscParse()
|
||||
dstbuf, &dstLen, &dummyState, '?');
|
||||
}
|
||||
|
||||
fBuffer->InsertChar(dstbuf, dstLen, width, fAttr);
|
||||
fBuffer->InsertChar(dstbuf, dstLen, width);
|
||||
break;
|
||||
|
||||
case CASE_PRINT_CS96:
|
||||
@@ -482,50 +478,50 @@ TermParse::EscParse()
|
||||
dstLen = sizeof(dstbuf);
|
||||
convert_to_utf8(B_EUC_CONVERSION, cbuf, &srcLen,
|
||||
dstbuf, &dstLen, &dummyState, '?');
|
||||
fBuffer->InsertChar(dstbuf, dstLen, fAttr);
|
||||
fBuffer->InsertChar(dstbuf, dstLen);
|
||||
break;
|
||||
|
||||
case CASE_PRINT_GRA:
|
||||
/* "Special characters and line drawing" enabled by \E(0 */
|
||||
switch (c) {
|
||||
case 'a':
|
||||
fBuffer->InsertChar("\xE2\x96\x92",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x96\x92",3);
|
||||
break;
|
||||
case 'j':
|
||||
fBuffer->InsertChar("\xE2\x94\x98",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x98",3);
|
||||
break;
|
||||
case 'k':
|
||||
fBuffer->InsertChar("\xE2\x94\x90",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x90",3);
|
||||
break;
|
||||
case 'l':
|
||||
fBuffer->InsertChar("\xE2\x94\x8C",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x8C",3);
|
||||
break;
|
||||
case 'm':
|
||||
fBuffer->InsertChar("\xE2\x94\x94",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x94",3);
|
||||
break;
|
||||
case 'n':
|
||||
fBuffer->InsertChar("\xE2\x94\xBC",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\xBC",3);
|
||||
break;
|
||||
case 'q':
|
||||
fBuffer->InsertChar("\xE2\x94\x80",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x80",3);
|
||||
break;
|
||||
case 't':
|
||||
fBuffer->InsertChar("\xE2\x94\x9C",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x9C",3);
|
||||
break;
|
||||
case 'u':
|
||||
fBuffer->InsertChar("\xE2\x94\xA4",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\xA4",3);
|
||||
break;
|
||||
case 'v':
|
||||
fBuffer->InsertChar("\xE2\x94\xB4",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\xB4",3);
|
||||
break;
|
||||
case 'w':
|
||||
fBuffer->InsertChar("\xE2\x94\xAC",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\xAC",3);
|
||||
break;
|
||||
case 'x':
|
||||
fBuffer->InsertChar("\xE2\x94\x82",3,fAttr);
|
||||
fBuffer->InsertChar("\xE2\x94\x82",3);
|
||||
break;
|
||||
default:
|
||||
fBuffer->InsertChar((char)c, fAttr);
|
||||
fBuffer->InsertChar((char)c);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -534,7 +530,7 @@ TermParse::EscParse()
|
||||
break;
|
||||
|
||||
case CASE_CR:
|
||||
fBuffer->InsertCR(fAttr);
|
||||
fBuffer->InsertCR();
|
||||
break;
|
||||
|
||||
case CASE_SJIS_KANA:
|
||||
@@ -544,7 +540,7 @@ TermParse::EscParse()
|
||||
dstLen = sizeof(dstbuf);
|
||||
convert_to_utf8(currentEncoding, cbuf, &srcLen,
|
||||
dstbuf, &dstLen, &dummyState, '?');
|
||||
fBuffer->InsertChar(dstbuf, dstLen, fAttr);
|
||||
fBuffer->InsertChar(dstbuf, dstLen);
|
||||
break;
|
||||
|
||||
case CASE_SJIS_INSTRING:
|
||||
@@ -556,7 +552,7 @@ TermParse::EscParse()
|
||||
dstLen = sizeof(dstbuf);
|
||||
convert_to_utf8(currentEncoding, cbuf, &srcLen,
|
||||
dstbuf, &dstLen, &dummyState, '?');
|
||||
fBuffer->InsertChar(dstbuf, dstLen, fAttr);
|
||||
fBuffer->InsertChar(dstbuf, dstLen);
|
||||
break;
|
||||
|
||||
case CASE_UTF8_2BYTE:
|
||||
@@ -567,7 +563,7 @@ TermParse::EscParse()
|
||||
cbuf[1] = c;
|
||||
cbuf[2] = '\0';
|
||||
|
||||
fBuffer->InsertChar(cbuf, 2, fAttr);
|
||||
fBuffer->InsertChar(cbuf, 2);
|
||||
break;
|
||||
|
||||
case CASE_UTF8_3BYTE:
|
||||
@@ -582,7 +578,7 @@ TermParse::EscParse()
|
||||
break;
|
||||
cbuf[2] = c;
|
||||
cbuf[3] = '\0';
|
||||
fBuffer->InsertChar(cbuf, 3, fAttr);
|
||||
fBuffer->InsertChar(cbuf, 3);
|
||||
break;
|
||||
|
||||
case CASE_MBCS:
|
||||
@@ -635,7 +631,7 @@ TermParse::EscParse()
|
||||
break;
|
||||
|
||||
case CASE_TAB:
|
||||
fBuffer->InsertTab(fAttr);
|
||||
fBuffer->InsertTab();
|
||||
break;
|
||||
|
||||
case CASE_ESC:
|
||||
@@ -833,38 +829,48 @@ TermParse::EscParse()
|
||||
case CASE_SGR:
|
||||
{
|
||||
/* SGR */
|
||||
uint32 attributes = fBuffer->GetAttributes();
|
||||
for (row = 0; row < nparam; ++row) {
|
||||
switch (param[row]) {
|
||||
case DEFAULT:
|
||||
case 0: /* Reset attribute */
|
||||
fAttr = 0;
|
||||
attributes = 0;
|
||||
break;
|
||||
|
||||
case 1: /* Bold */
|
||||
case 5:
|
||||
fAttr |= BOLD;
|
||||
attributes |= BOLD;
|
||||
break;
|
||||
|
||||
case 4: /* Underline */
|
||||
fAttr |= UNDERLINE;
|
||||
attributes |= UNDERLINE;
|
||||
break;
|
||||
|
||||
case 7: /* Inverse */
|
||||
fAttr |= INVERSE;
|
||||
attributes |= INVERSE;
|
||||
break;
|
||||
|
||||
case 22: /* Not Bold */
|
||||
fAttr &= ~BOLD;
|
||||
attributes &= ~BOLD;
|
||||
break;
|
||||
|
||||
case 24: /* Not Underline */
|
||||
fAttr &= ~UNDERLINE;
|
||||
attributes &= ~UNDERLINE;
|
||||
break;
|
||||
|
||||
case 27: /* Not Inverse */
|
||||
fAttr &= ~INVERSE;
|
||||
attributes &= ~INVERSE;
|
||||
break;
|
||||
|
||||
case 90:
|
||||
case 91:
|
||||
case 92:
|
||||
case 93:
|
||||
case 94:
|
||||
case 95:
|
||||
case 96:
|
||||
case 97:
|
||||
param[row] -= 60;
|
||||
case 30:
|
||||
case 31:
|
||||
case 32:
|
||||
@@ -873,18 +879,21 @@ TermParse::EscParse()
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
fAttr &= ~FORECOLOR;
|
||||
fAttr |= FORECOLORED(param[row] - 30);
|
||||
fAttr |= FORESET;
|
||||
attributes &= ~FORECOLOR;
|
||||
attributes |= FORECOLORED(param[row] - 30);
|
||||
attributes |= FORESET;
|
||||
break;
|
||||
|
||||
case 38:
|
||||
{
|
||||
if (nparam != 3 || param[1] != 5)
|
||||
break;
|
||||
fAttr &= ~FORECOLOR;
|
||||
fAttr |= FORECOLORED(param[2]);
|
||||
fAttr |= FORESET;
|
||||
if (nparam == 3 && param[1] == 5) {
|
||||
attributes &= ~FORECOLOR;
|
||||
attributes |= FORECOLORED(param[2]);
|
||||
attributes |= FORESET;
|
||||
|
||||
} else if (nparam == 5) {
|
||||
// TODO lookup
|
||||
}
|
||||
|
||||
row = nparam; // force exit of the parsing
|
||||
|
||||
@@ -892,9 +901,18 @@ TermParse::EscParse()
|
||||
}
|
||||
|
||||
case 39:
|
||||
fAttr &= ~FORESET;
|
||||
attributes &= ~FORESET;
|
||||
break;
|
||||
|
||||
case 100:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
case 106:
|
||||
case 107:
|
||||
param[row] -= 60;
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
@@ -903,18 +921,21 @@ TermParse::EscParse()
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
fAttr &= ~BACKCOLOR;
|
||||
fAttr |= BACKCOLORED(param[row] - 40);
|
||||
fAttr |= BACKSET;
|
||||
attributes &= ~BACKCOLOR;
|
||||
attributes |= BACKCOLORED(param[row] - 40);
|
||||
attributes |= BACKSET;
|
||||
break;
|
||||
|
||||
case 48:
|
||||
{
|
||||
if (nparam != 3 || param[1] != 5)
|
||||
break;
|
||||
fAttr &= ~BACKCOLOR;
|
||||
fAttr |= BACKCOLORED(param[2]);
|
||||
fAttr |= BACKSET;
|
||||
if (nparam == 3 && param[1] == 5) {
|
||||
attributes &= ~BACKCOLOR;
|
||||
attributes |= BACKCOLORED(param[2]);
|
||||
attributes |= BACKSET;
|
||||
|
||||
} else if (nparam == 5) {
|
||||
// TODO lookup
|
||||
}
|
||||
|
||||
row = nparam; // force exit of the parsing
|
||||
|
||||
@@ -922,10 +943,11 @@ TermParse::EscParse()
|
||||
}
|
||||
|
||||
case 49:
|
||||
fAttr &= ~BACKSET;
|
||||
attributes &= ~BACKSET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fBuffer->SetAttributes(attributes);
|
||||
parsestate = groundtable;
|
||||
break;
|
||||
}
|
||||
@@ -1446,7 +1468,7 @@ TermParse::_DecSaveCursor()
|
||||
{
|
||||
fBuffer->SaveCursor();
|
||||
fBuffer->SaveOriginMode();
|
||||
fSavedAttr = fAttr;
|
||||
fBuffer->PreserveAttributes(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1455,7 +1477,7 @@ TermParse::_DecRestoreCursor()
|
||||
{
|
||||
fBuffer->RestoreCursor();
|
||||
fBuffer->RestoreOriginMode();
|
||||
fAttr = fSavedAttr;
|
||||
fBuffer->PreserveAttributes(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -86,9 +86,6 @@ private:
|
||||
|
||||
int fFd;
|
||||
|
||||
uint32 fAttr;
|
||||
uint32 fSavedAttr;
|
||||
|
||||
thread_id fParseThread;
|
||||
thread_id fReaderThread;
|
||||
sem_id fReaderSem;
|
||||
|
||||
@@ -1012,17 +1012,30 @@ TermView::_DrawCursor()
|
||||
_DrawLinePart(fCursor.x * fFontWidth, (int32)rect.top, attr, buffer,
|
||||
width, selected, cursorVisible, this);
|
||||
} else {
|
||||
|
||||
if (selected)
|
||||
SetHighColor(fSelectBackColor);
|
||||
else if (cursorVisible )
|
||||
SetHighColor(fCursorBackColor );
|
||||
else {
|
||||
if (cursorVisible)
|
||||
SetHighColor(fCursorBackColor);
|
||||
uint32 count = 0;
|
||||
rgb_color rgb_back = fTextBackColor;
|
||||
if (fTextBuffer->IsAlternateScreenActive())
|
||||
// alternate screen uses cell attributes beyond the line ends
|
||||
fTextBuffer->GetCellAttributes(
|
||||
fCursor.y, fCursor.x, attr, count);
|
||||
else
|
||||
SetHighColor(cursorVisible ? fCursorBackColor : fTextBackColor);
|
||||
attr = fVisibleTextBuffer->GetLineColor(
|
||||
fCursor.y - firstVisible);
|
||||
|
||||
if (IS_BACKSET(attr))
|
||||
rgb_back = fTermColorTable[IS_BACKCOLOR(attr)];
|
||||
SetHighColor(rgb_back);
|
||||
}
|
||||
|
||||
FillRect(rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1215,29 +1228,31 @@ TermView::Draw(BRect updateRect)
|
||||
if (count == 0) {
|
||||
// No chars to draw : we just fill the rectangle with the
|
||||
// back color of the last char at the left
|
||||
int nextColumn = lastColumn + 1;
|
||||
BRect rect(fFontWidth * i, _LineOffset(j),
|
||||
fFontWidth * (lastColumn + 1) - 1, 0);
|
||||
fFontWidth * nextColumn - 1, 0);
|
||||
rect.bottom = rect.top + fFontHeight - 1;
|
||||
|
||||
if (insideSelection) {
|
||||
// This area is selected, fill it with the select color
|
||||
SetHighColor(fSelectBackColor);
|
||||
FillRect(rect);
|
||||
} else {
|
||||
rgb_color rgb_back = fTextBackColor;
|
||||
rgb_color rgb_back = insideSelection
|
||||
? fSelectBackColor : fTextBackColor;
|
||||
|
||||
int lineIndexInHistory = j + fTextBuffer->HistorySize();
|
||||
uint32 attr = fVisibleTextBuffer->GetLineColor(
|
||||
lineIndexInHistory);
|
||||
if (fTextBuffer->IsAlternateScreenActive()) {
|
||||
// alternate screen uses cell attributes beyond the line ends
|
||||
uint32 count = 0;
|
||||
fTextBuffer->GetCellAttributes(j, i, attr, count);
|
||||
rect.right = rect.left + fFontWidth * count - 1;
|
||||
nextColumn = i + count;
|
||||
} else
|
||||
attr = fVisibleTextBuffer->GetLineColor(j - firstVisible);
|
||||
|
||||
if (IS_BACKSET(attr))
|
||||
rgb_back = fTermColorTable[IS_BACKCOLOR(attr)];
|
||||
SetHighColor(rgb_back);
|
||||
FillRect(rect);
|
||||
}
|
||||
if (IS_BACKSET(attr))
|
||||
rgb_back = fTermColorTable[IS_BACKCOLOR(attr)];
|
||||
SetHighColor(rgb_back);
|
||||
rgb_back = HighColor();
|
||||
FillRect(rect);
|
||||
|
||||
// Go on to the next block
|
||||
i = lastColumn + 1;
|
||||
i = nextColumn;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,13 @@ struct TerminalLine {
|
||||
uint32 attributes;
|
||||
TerminalCell cells[1];
|
||||
|
||||
inline void Clear()
|
||||
inline void Clear(uint32 attr = 0, size_t count = 0)
|
||||
{
|
||||
length = 0;
|
||||
attributes = 0;
|
||||
attributes = attr;
|
||||
softBreak = false;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
cells[i].attributes = attr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user