diff --git a/src/apps/terminal/BasicTerminalBuffer.cpp b/src/apps/terminal/BasicTerminalBuffer.cpp index a870b74627..74e412ed24 100644 --- a/src/apps/terminal/BasicTerminalBuffer.cpp +++ b/src/apps/terminal/BasicTerminalBuffer.cpp @@ -122,6 +122,7 @@ BasicTerminalBuffer::Init(int32 width, int32 height, int32 historySize) fOverwriteMode = true; fAlternateScreenActive = false; + fOriginMode = fSavedOriginMode = false; fScreen = _AllocateLines(width, height); if (fScreen == NULL) @@ -604,6 +605,22 @@ BasicTerminalBuffer::InsertLF() } +void +BasicTerminalBuffer::InsertRI() +{ + fSoftWrappedCursor = false; + + // If we're at the beginning of the scroll region, scroll. Otherwise just + // reverse the cursor. + if (fCursor.y == fScrollTop) { + _Scroll(fScrollTop, fScrollBottom, -1); + } else { + if (fCursor.y > 0) + fCursor.y--; + _CursorChanged(); + } +} + void BasicTerminalBuffer::InsertLines(int32 numLines) { @@ -645,7 +662,7 @@ BasicTerminalBuffer::InsertSpace(int32 num) void -BasicTerminalBuffer::EraseChars(int32 numChars) +BasicTerminalBuffer::EraseCharsFrom(int32 first, int32 numChars) { TerminalLine* line = _LineAt(fCursor.y); if (fCursor.y >= line->length) @@ -653,8 +670,7 @@ BasicTerminalBuffer::EraseChars(int32 numChars) fSoftWrappedCursor = false; - int32 first = fCursor.x; - int32 end = min_c(fCursor.x + numChars, line->length); + int32 end = min_c(first + numChars, line->length); if (first > 0 && IS_WIDTH(line->cells[first - 1].attributes)) first--; if (end > 0 && IS_WIDTH(line->cells[end - 1].attributes)) @@ -713,7 +729,7 @@ void BasicTerminalBuffer::EraseAll() { fSoftWrappedCursor = false; - _Scroll(fScrollTop, fScrollBottom, fHeight); + _Scroll(0, fHeight - 1, fHeight); } @@ -740,13 +756,13 @@ BasicTerminalBuffer::DeleteChars(int32 numChars) void -BasicTerminalBuffer::DeleteColumns() +BasicTerminalBuffer::DeleteColumnsFrom(int32 first) { fSoftWrappedCursor = false; TerminalLine* line = _LineAt(fCursor.y); - if (fCursor.x < line->length) { - line->length = fCursor.x; + if (first < line->length) { + line->length = first; _Invalidate(fCursor.y, fCursor.y); } } @@ -762,21 +778,6 @@ BasicTerminalBuffer::DeleteLines(int32 numLines) } -void -BasicTerminalBuffer::SetCursor(int32 x, int32 y) -{ -//debug_printf("BasicTerminalBuffer::SetCursor(%d, %d)\n", x, y); - fSoftWrappedCursor = false; - x = restrict_value(x, 0, fWidth - 1); - y = restrict_value(y, 0, fHeight - 1); - if (x != fCursor.x || y != fCursor.y) { - fCursor.x = x; - fCursor.y = y; - _CursorChanged(); - } -} - - void BasicTerminalBuffer::SaveCursor() { @@ -787,7 +788,7 @@ BasicTerminalBuffer::SaveCursor() void BasicTerminalBuffer::RestoreCursor() { - SetCursor(fSavedCursor.x, fSavedCursor.y); + _SetCursor(fSavedCursor.x, fSavedCursor.y, true); } @@ -798,7 +799,29 @@ BasicTerminalBuffer::SetScrollRegion(int32 top, int32 bottom) fScrollBottom = restrict_value(bottom, fScrollTop, fHeight - 1); // also sets the cursor position - SetCursor(0, 0); + _SetCursor(0, 0, false); +} + + +void +BasicTerminalBuffer::SetOriginMode(bool enabled) +{ + fOriginMode = enabled; + _SetCursor(0, 0, false); +} + + +void +BasicTerminalBuffer::SaveOriginMode() +{ + fSavedOriginMode = fOriginMode; +} + + +void +BasicTerminalBuffer::RestoreOriginMode() +{ + fOriginMode = fSavedOriginMode; } @@ -812,6 +835,28 @@ BasicTerminalBuffer::NotifyListener() // #pragma mark - private methods +void +BasicTerminalBuffer::_SetCursor(int32 x, int32 y, bool absolute) +{ +//debug_printf("BasicTerminalBuffer::_SetCursor(%d, %d)\n", x, y); + fSoftWrappedCursor = false; + + x = restrict_value(x, 0, fWidth - 1); + if (fOriginMode && !absolute) { + y += fScrollTop; + y = restrict_value(y, fScrollTop, fScrollBottom); + } else { + y = restrict_value(y, 0, fHeight - 1); + } + + if (x != fCursor.x || y != fCursor.y) { + fCursor.x = x; + fCursor.y = y; + _CursorChanged(); + } +} + + void BasicTerminalBuffer::_InvalidateAll() { @@ -984,6 +1029,7 @@ BasicTerminalBuffer::_ResizeSimple(int32 width, int32 height, fScrollTop = 0; fScrollBottom = fHeight - 1; + fOriginMode = fSavedOriginMode = false; fScreenOffset = 0; @@ -1177,6 +1223,7 @@ BasicTerminalBuffer::_ResizeRewrap(int32 width, int32 height, fScrollTop = 0; fScrollBottom = fHeight - 1; + fOriginMode = fSavedOriginMode = false; return B_OK; } diff --git a/src/apps/terminal/BasicTerminalBuffer.h b/src/apps/terminal/BasicTerminalBuffer.h index 7456afd59b..3b134b8d00 100644 --- a/src/apps/terminal/BasicTerminalBuffer.h +++ b/src/apps/terminal/BasicTerminalBuffer.h @@ -106,21 +106,24 @@ public: void InsertCR(); void InsertLF(); + void InsertRI(); void SetInsertMode(int flag); void InsertSpace(int32 num); void InsertLines(int32 numLines); // delete chars/lines - void EraseChars(int32 numChars); + inline void EraseChars(int32 numChars); + void EraseCharsFrom(int32 first, int32 numChars); void EraseAbove(); void EraseBelow(); void EraseAll(); void DeleteChars(int32 numChars); - void DeleteColumns(); + inline void DeleteColumns(); + void DeleteColumnsFrom(int32 first); void DeleteLines(int32 numLines); // get and set cursor position - void SetCursor(int32 x, int32 y); + inline void SetCursor(int32 x, int32 y); inline void SetCursorX(int32 x); inline void SetCursorY(int32 y); inline TermPos Cursor() const { return fCursor; } @@ -136,6 +139,9 @@ public: // scroll region inline void ScrollBy(int32 numLines); void SetScrollRegion(int32 top, int32 bottom); + void SetOriginMode(bool enabled); + void SaveOriginMode(); + void RestoreOriginMode(); protected: virtual void NotifyListener(); @@ -147,6 +153,7 @@ protected: inline void _Invalidate(int32 top, int32 bottom); inline void _CursorChanged(); + void _SetCursor(int32 x, int32 y, bool absolute); void _InvalidateAll(); static TerminalLine** _AllocateLines(int32 width, int32 count); @@ -193,6 +200,8 @@ protected: bool fOverwriteMode; // false for insert bool fAlternateScreenActive; + bool fOriginMode; + bool fSavedOriginMode; int fEncoding; @@ -236,6 +245,24 @@ BasicTerminalBuffer::InsertChar(const char* c, int32 length, uint32 width, uint3 } +void +BasicTerminalBuffer::EraseChars(int32 numChars) +{ + EraseCharsFrom(fCursor.x, numChars); +} + +void +BasicTerminalBuffer::DeleteColumns() +{ + DeleteColumnsFrom(fCursor.x); +} + +void +BasicTerminalBuffer::SetCursor(int32 x, int32 y) +{ + _SetCursor(x, y, false); +} + void BasicTerminalBuffer::SetCursorX(int32 x) { diff --git a/src/apps/terminal/TermParse.cpp b/src/apps/terminal/TermParse.cpp index 2e7c50e957..f385ec2ec4 100644 --- a/src/apps/terminal/TermParse.cpp +++ b/src/apps/terminal/TermParse.cpp @@ -311,8 +311,6 @@ TermParse::EscParse() int now_coding = -1; - ushort attr = BACKCOLOR; - int param[NPARAM]; int nparam = 1; @@ -325,6 +323,8 @@ TermParse::EscParse() int width = 1; BAutolock locker(fBuffer); + fAttr = fSavedAttr = BACKCOLOR; + while (!fQuitting) { uchar c; if (_NextParseChar(c) < B_OK) @@ -371,7 +371,7 @@ TermParse::EscParse() //debug_printf("TermParse: char: '%c' (%d), parse state: %d\n", c, c, parsestate[c]); switch (parsestate[c]) { case CASE_PRINT: - fBuffer->InsertChar((char)c, attr); + fBuffer->InsertChar((char)c, fAttr); break; case CASE_PRINT_GR: @@ -422,7 +422,7 @@ TermParse::EscParse() B_EUC_CONVERSION); } - fBuffer->InsertChar(dstbuf, 4, width, attr); + fBuffer->InsertChar(dstbuf, 4, width, fAttr); break; case CASE_PRINT_CS96: @@ -431,7 +431,7 @@ TermParse::EscParse() cbuf[1] = c | 0x80; cbuf[2] = 0; CodeConv::ConvertToInternal(cbuf, 2, dstbuf, B_EUC_CONVERSION); - fBuffer->InsertChar(dstbuf, 4, attr); + fBuffer->InsertChar(dstbuf, 4, fAttr); break; case CASE_LF: @@ -446,7 +446,7 @@ TermParse::EscParse() cbuf[0] = c; cbuf[1] = '\0'; CodeConv::ConvertToInternal(cbuf, 1, dstbuf, now_coding); - fBuffer->InsertChar(dstbuf, 4, attr); + fBuffer->InsertChar(dstbuf, 4, fAttr); break; case CASE_SJIS_INSTRING: @@ -455,7 +455,7 @@ TermParse::EscParse() cbuf[1] = c; cbuf[2] = '\0'; CodeConv::ConvertToInternal(cbuf, 2, dstbuf, now_coding); - fBuffer->InsertChar(dstbuf, 4, attr); + fBuffer->InsertChar(dstbuf, 4, fAttr); break; case CASE_UTF8_2BYTE: @@ -466,7 +466,7 @@ TermParse::EscParse() cbuf[1] = c; cbuf[2] = '\0'; - fBuffer->InsertChar(cbuf, 2, attr); + fBuffer->InsertChar(cbuf, 2, fAttr); break; case CASE_UTF8_3BYTE: @@ -481,7 +481,7 @@ TermParse::EscParse() break; cbuf[2] = c; cbuf[3] = '\0'; - fBuffer->InsertChar(cbuf, 3, attr); + fBuffer->InsertChar(cbuf, 3, fAttr); break; case CASE_MBCS: @@ -645,9 +645,22 @@ TermParse::EscParse() parsestate = groundtable; break; - case CASE_EL: // delete line + case CASE_EL: // ESC [ ...K delete line /* EL */ - fBuffer->DeleteColumns(); + switch (param[0]) { + case DEFAULT: + case 0: + fBuffer->DeleteColumns(); + break; + + case 1: + fBuffer->EraseCharsFrom(0, fBuffer->Cursor().x + 1); + break; + + case 2: + fBuffer->DeleteColumnsFrom(0); + break; + } parsestate = groundtable; break; @@ -695,32 +708,32 @@ TermParse::EscParse() switch (param[row]) { case DEFAULT: case 0: /* Reset attribute */ - attr = 0; + fAttr = 0; break; case 1: case 5: /* Bold */ - attr |= BOLD; + fAttr |= BOLD; break; case 4: /* Underline */ - attr |= UNDERLINE; + fAttr |= UNDERLINE; break; case 7: /* Inverse */ - attr |= INVERSE; + fAttr |= INVERSE; break; case 22: /* Not Bold */ - attr &= ~BOLD; + fAttr &= ~BOLD; break; case 24: /* Not Underline */ - attr &= ~UNDERLINE; + fAttr &= ~UNDERLINE; break; case 27: /* Not Inverse */ - attr &= ~INVERSE; + fAttr &= ~INVERSE; break; case 30: @@ -731,13 +744,13 @@ TermParse::EscParse() case 35: case 36: case 37: - attr &= ~FORECOLOR; - attr |= FORECOLORED(param[row] - 30); - attr |= FORESET; + fAttr &= ~FORECOLOR; + fAttr |= FORECOLORED(param[row] - 30); + fAttr |= FORESET; break; case 39: - attr &= ~FORESET; + fAttr &= ~FORESET; break; case 40: @@ -748,13 +761,13 @@ TermParse::EscParse() case 45: case 46: case 47: - attr &= ~BACKCOLOR; - attr |= BACKCOLORED(param[row] - 40); - attr |= BACKSET; + fAttr &= ~BACKCOLOR; + fAttr |= BACKCOLORED(param[row] - 40); + fAttr |= BACKSET; break; case 49: - attr &= ~BACKSET; + fAttr &= ~BACKSET; break; } } @@ -822,13 +835,13 @@ TermParse::EscParse() case CASE_DECSC: /* DECSC */ - fBuffer->SaveCursor(); + _DecSaveCursor(); parsestate = groundtable; break; case CASE_DECRC: /* DECRC */ - fBuffer->RestoreCursor(); + _DecRestoreCursor(); parsestate = groundtable; break; @@ -840,10 +853,7 @@ TermParse::EscParse() case CASE_RI: /* RI */ - if (fBuffer->Cursor().y == 0) - fBuffer->ScrollBy(-1); - else - fBuffer->MoveCursorUp(1); + fBuffer->InsertRI(); parsestate = groundtable; break; @@ -1095,6 +1105,10 @@ TermParse::_DecPrivateModeSet(int value) // screen). // Not supported yet. break; + case 6: + // Set Origin Mode. + fBuffer->SetOriginMode(true); + break; case 9: // Set Mouse X and Y on button press. fBuffer->ReportX10MouseEvent(true); @@ -1139,7 +1153,7 @@ TermParse::_DecPrivateModeSet(int value) case 1049: // Save cursor as in DECSC and use Alternate Screen Buffer, clearing // it first. - fBuffer->SaveCursor(); + _DecSaveCursor(); fBuffer->UseAlternateScreenBuffer(true); break; } @@ -1166,6 +1180,10 @@ TermParse::_DecPrivateModeReset(int value) // Normal Video (Leaves Reverse Video, cf. there). // Not supported yet. break; + case 6: + // Reset Origin Mode. + fBuffer->SetOriginMode(false); + break; case 9: // Disable Mouse X and Y on button press. fBuffer->ReportX10MouseEvent(false); @@ -1210,7 +1228,25 @@ TermParse::_DecPrivateModeReset(int value) case 1049: // Use Normal Screen Buffer and restore cursor as in DECRC. fBuffer->UseNormalScreenBuffer(); - fBuffer->RestoreCursor(); + _DecRestoreCursor(); break; } } + + +void +TermParse::_DecSaveCursor() +{ + fBuffer->SaveCursor(); + fBuffer->SaveOriginMode(); + fSavedAttr = fAttr; +} + + +void +TermParse::_DecRestoreCursor() +{ + fBuffer->RestoreCursor(); + fBuffer->RestoreOriginMode(); + fAttr = fSavedAttr; +} diff --git a/src/apps/terminal/TermParse.h b/src/apps/terminal/TermParse.h index 5b7fa84070..85fa2ad168 100644 --- a/src/apps/terminal/TermParse.h +++ b/src/apps/terminal/TermParse.h @@ -78,9 +78,14 @@ private: void _DeviceStatusReport(int n); void _DecPrivateModeSet(int value); void _DecPrivateModeReset(int value); + void _DecSaveCursor(); + void _DecRestoreCursor(); int fFd; + ushort fAttr; + ushort fSavedAttr; + thread_id fParseThread; thread_id fReaderThread; sem_id fReaderSem;