From b512213be6f7cf9660c07e24a81b7597c8776116 Mon Sep 17 00:00:00 2001 From: Siarzhuk Zharski Date: Thu, 31 Jan 2013 22:39:27 +0100 Subject: [PATCH] Support Background Color Erase, switch to xterm-256color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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. --- src/apps/terminal/BasicTerminalBuffer.cpp | 115 ++++++++++++++----- src/apps/terminal/BasicTerminalBuffer.h | 63 ++++++++--- src/apps/terminal/Shell.cpp | 5 +- src/apps/terminal/TermParse.cpp | 128 +++++++++++++--------- src/apps/terminal/TermParse.h | 3 - src/apps/terminal/TermView.cpp | 53 +++++---- src/apps/terminal/TerminalLine.h | 6 +- 7 files changed, 249 insertions(+), 124 deletions(-) diff --git a/src/apps/terminal/BasicTerminalBuffer.cpp b/src/apps/terminal/BasicTerminalBuffer.cpp index 19f4416e8e..e70c2098c5 100644 --- a/src/apps/terminal/BasicTerminalBuffer.cpp +++ b/src/apps/terminal/BasicTerminalBuffer.cpp @@ -6,6 +6,7 @@ #include "BasicTerminalBuffer.h" #include +#include #include #include #include @@ -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; } } } diff --git a/src/apps/terminal/BasicTerminalBuffer.h b/src/apps/terminal/BasicTerminalBuffer.h index 2be3efe833..e84847afa4 100644 --- a/src/apps/terminal/BasicTerminalBuffer.h +++ b/src/apps/terminal/BasicTerminalBuffer.h @@ -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); } diff --git a/src/apps/terminal/Shell.cpp b/src/apps/terminal/Shell.cpp index 12c3c92689..2209f072d4 100644 --- a/src/apps/terminal/Shell.cpp +++ b/src/apps/terminal/Shell.cpp @@ -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); diff --git a/src/apps/terminal/TermParse.cpp b/src/apps/terminal/TermParse.cpp index e892f47e1b..4078679138 100644 --- a/src/apps/terminal/TermParse.cpp +++ b/src/apps/terminal/TermParse.cpp @@ -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); } diff --git a/src/apps/terminal/TermParse.h b/src/apps/terminal/TermParse.h index 01a9cf3a7d..625457322a 100644 --- a/src/apps/terminal/TermParse.h +++ b/src/apps/terminal/TermParse.h @@ -86,9 +86,6 @@ private: int fFd; - uint32 fAttr; - uint32 fSavedAttr; - thread_id fParseThread; thread_id fReaderThread; sem_id fReaderSem; diff --git a/src/apps/terminal/TermView.cpp b/src/apps/terminal/TermView.cpp index 5cb6f8c7b0..160b5c985b 100644 --- a/src/apps/terminal/TermView.cpp +++ b/src/apps/terminal/TermView.cpp @@ -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; } diff --git a/src/apps/terminal/TerminalLine.h b/src/apps/terminal/TerminalLine.h index dcbca0e5ec..5f2e4a7d9c 100644 --- a/src/apps/terminal/TerminalLine.h +++ b/src/apps/terminal/TerminalLine.h @@ -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; } };