* Some preparations for DEC private mode settings support.

* Implemented alternate screen buffer support. Not used by any program
  yet, since we still use the beterm termcap entry.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26003 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2008-06-17 22:49:06 +00:00
parent 9c95cbf21f
commit d04aae8b80
7 changed files with 253 additions and 20 deletions

View File

@ -120,6 +120,7 @@ BasicTerminalBuffer::Init(int32 width, int32 height, int32 historySize)
fScreenOffset = 0;
fOverwriteMode = true;
fAlternateScreenActive = false;
fScreen = _AllocateLines(width, height);
if (fScreen == NULL)
@ -162,12 +163,10 @@ BasicTerminalBuffer::ResizeTo(int32 width, int32 height, int32 historyCapacity)
if (width == fWidth && height == fHeight)
return SetHistoryCapacity(historyCapacity);
// TODO: When alternate screen support is implemented, do that only when
// not using the alternate screen.
if (true)
return _ResizeRewrap(width, height, historyCapacity);
if (fAlternateScreenActive)
return _ResizeSimple(width, height, historyCapacity);
return _ResizeSimple(width, height, historyCapacity);
return _ResizeRewrap(width, height, historyCapacity);
}
@ -179,11 +178,13 @@ BasicTerminalBuffer::SetHistoryCapacity(int32 historyCapacity)
void
BasicTerminalBuffer::Clear()
BasicTerminalBuffer::Clear(bool resetCursor)
{
fScreenOffset = 0;
_ClearLines(0, fHeight - 1);
fCursor.SetTo(0, 0);
if (resetCursor)
fCursor.SetTo(0, 0);
if (fHistory != NULL)
fHistory->Clear();
@ -585,7 +586,8 @@ BasicTerminalBuffer::InsertLF()
if (fCursor.y == fScrollBottom) {
_Scroll(fScrollTop, fScrollBottom, 1);
} else {
fCursor.y++;
if (fCursor.y < fHeight - 1)
fCursor.y++;
_CursorChanged();
}
}
@ -731,7 +733,7 @@ BasicTerminalBuffer::SetCursor(int32 x, int32 y)
{
//debug_printf("BasicTerminalBuffer::SetCursor(%d, %d)\n", x, y);
x = restrict_value(x, 0, fWidth - 1);
y = restrict_value(y, fScrollTop, fScrollBottom);
y = restrict_value(y, 0, fHeight - 1);
if (x != fCursor.x || y != fCursor.y) {
fCursor.x = x;
fCursor.y = y;
@ -775,6 +777,18 @@ BasicTerminalBuffer::NotifyListener()
// #pragma mark - private methods
void
BasicTerminalBuffer::_InvalidateAll()
{
fDirtyInfo.invalidateAll = true;
if (!fDirtyInfo.messageSent) {
NotifyListener();
fDirtyInfo.messageSent = true;
}
}
/* static */ TerminalLine**
BasicTerminalBuffer::_AllocateLines(int32 width, int32 count)
{

View File

@ -21,6 +21,7 @@ struct TerminalBufferDirtyInfo {
int32 linesScrolled; // number of lines added to the history
int32 dirtyTop; // dirty line range
int32 dirtyBottom; //
bool invalidateAll;
bool messageSent; // listener has been notified
bool IsDirtyRegionValid() const
@ -41,6 +42,7 @@ struct TerminalBufferDirtyInfo {
linesScrolled = 0;
dirtyTop = INT_MAX;
dirtyBottom = INT_MIN;
invalidateAll = false;
messageSent = false;
}
};
@ -61,11 +63,11 @@ public:
TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; }
status_t ResizeTo(int32 width, int32 height);
status_t ResizeTo(int32 width, int32 height,
virtual status_t ResizeTo(int32 width, int32 height);
virtual status_t ResizeTo(int32 width, int32 height,
int32 historyCapacity);
status_t SetHistoryCapacity(int32 historyCapacity);
void Clear();
void Clear(bool resetCursor);
void SynchronizeWith(
const BasicTerminalBuffer* other,
@ -139,6 +141,7 @@ protected:
inline void _Invalidate(int32 top, int32 bottom);
inline void _CursorChanged();
void _InvalidateAll();
static TerminalLine** _AllocateLines(int32 width, int32 count);
static void _FreeLines(TerminalLine** lines, int32 count);
@ -182,6 +185,7 @@ protected:
TermPos fSavedCursor;
bool fOverwriteMode; // false for insert
bool fAlternateScreenActive;
int fEncoding;

View File

@ -790,13 +790,15 @@ TermParse::EscParse()
case CASE_DECSET:
/* DECSET */
// dpmodes(term, bitset);
for (int i = 0; i < nparam; i++)
_DecPrivateModeSet(param[i]);
parsestate = groundtable;
break;
case CASE_DECRST:
/* DECRST */
// dpmodes(term, bitclr);
for (int i = 0; i < nparam; i++)
_DecPrivateModeReset(param[i]);
parsestate = groundtable;
break;
@ -1070,3 +1072,80 @@ TermParse::_DeviceStatusReport(int n)
return;
}
}
void
TermParse::_DecPrivateModeSet(int value)
{
switch (value) {
case 1:
// Application Cursor Keys (whatever that means).
// Not supported yet.
break;
case 5:
// Reverse Video (inverses colors for the complete screen
// -- when followed by normal video, that's shortly flashes the
// screen).
// Not supported yet.
break;
case 12:
// Start Blinking Cursor.
// Not supported yet.
break;
case 25:
// Show Cursor
// Not supported yet.
break;
case 1034:
// Interpret "meta" key, sets eighth bit.
// Not supported yet.
break;
case 1049:
// Save cursor as in DECSC and use Alternate Screen Buffer, clearing
// it first.
fBuffer->SaveCursor();
fBuffer->UseAlternateScreenBuffer();
break;
}
}
void
TermParse::_DecPrivateModeReset(int value)
{
switch (value) {
case 1:
// Normal Cursor Keys (whatever that means).
// Not supported yet.
break;
case 3:
// 80 Column Mode.
// Not supported yet.
break;
case 4:
// Jump (Fast) Scroll.
// Not supported yet.
break;
case 5:
// Normal Video (Leaves Reverse Video, cf. there).
// Not supported yet.
break;
case 12:
// Stop Blinking Cursor.
// Not supported yet.
break;
case 25:
// Hide Cursor
// Not supported yet.
break;
case 1034:
// Dont interpret "meta" key.
// Not supported yet.
break;
case 1049:
// Use Normal Screen Buffer and restore cursor as in DECRC.
fBuffer->RestoreCursor();
fBuffer->UseNormalScreenBuffer();
break;
}
}

View File

@ -76,6 +76,8 @@ private:
status_t _ReadParserBuffer();
void _DeviceStatusReport(int n);
void _DecPrivateModeSet(int value);
void _DecPrivateModeReset(int value);
int fFd;

View File

@ -710,9 +710,9 @@ TermView::Clear()
{
BAutolock _(fTextBuffer);
fTextBuffer->Clear();
fTextBuffer->Clear(true);
}
fVisibleTextBuffer->Clear();
fVisibleTextBuffer->Clear(true);
//debug_printf("Invalidate()\n");
Invalidate();
@ -1563,10 +1563,6 @@ TermView::_SynchronizeWithTextBuffer(int32 visibleDirtyTop,
{
TerminalBufferDirtyInfo& info = fTextBuffer->DirtyInfo();
int32 linesScrolled = info.linesScrolled;
BRect bounds = Bounds();
int32 firstVisible = _LineAt(0);
int32 lastVisible = _LineAt(bounds.bottom);
int32 historySize = fTextBuffer->HistorySize();
//debug_printf("TermView::_SynchronizeWithTextBuffer(): dirty: %ld - %ld, "
//"scrolled: %ld, visible dirty: %ld - %ld\n", info.dirtyTop, info.dirtyBottom,
@ -1630,6 +1626,22 @@ TermView::_SynchronizeWithTextBuffer(int32 visibleDirtyTop,
fScrolledSinceLastSync = 0;
}
// Simple case first -- complete invalidation.
if (info.invalidateAll) {
Invalidate();
_UpdateScrollBarRange();
int32 offset = _LineAt(0);
fVisibleTextBuffer->SynchronizeWith(fTextBuffer, offset, offset,
offset + fTextBuffer->Height() + 2);
info.Reset();
return;
}
BRect bounds = Bounds();
int32 firstVisible = _LineAt(0);
int32 lastVisible = _LineAt(bounds.bottom);
int32 historySize = fTextBuffer->HistorySize();
bool doScroll = false;
if (linesScrolled > 0) {
_UpdateScrollBarRange();

View File

@ -5,6 +5,8 @@
#include "TerminalBuffer.h"
#include <algorithm>
#include <Message.h>
#include "Coding.h"
@ -18,6 +20,9 @@ TerminalBuffer::TerminalBuffer()
:
BLocker("terminal buffer"),
fEncoding(M_UTF8),
fAlternateScreen(NULL),
fAlternateHistory(NULL),
fAlternateScreenOffset(0),
fListenerValid(false)
{
}
@ -25,6 +30,8 @@ TerminalBuffer::TerminalBuffer()
TerminalBuffer::~TerminalBuffer()
{
delete fAlternateScreen;
delete fAlternateHistory;
}
@ -34,6 +41,10 @@ TerminalBuffer::Init(int32 width, int32 height, int32 historySize)
if (Sem() < 0)
return Sem();
fAlternateScreen = _AllocateLines(width, height);
if (fAlternateScreen == NULL)
return B_NO_MEMORY;
return BasicTerminalBuffer::Init(width, height, historySize);
}
@ -95,3 +106,100 @@ TerminalBuffer::NotifyListener()
if (fListenerValid)
fListener.SendMessage(MSG_TERMINAL_BUFFER_CHANGED);
}
status_t
TerminalBuffer::ResizeTo(int32 width, int32 height)
{
int32 historyCapacity = 0;
if (!fAlternateScreenActive)
historyCapacity = HistoryCapacity();
else if (fAlternateHistory != NULL)
historyCapacity = fAlternateHistory->Capacity();
return ResizeTo(width, height, historyCapacity);
}
status_t
TerminalBuffer::ResizeTo(int32 width, int32 height, int32 historyCapacity)
{
// switch to the normal screen buffer first
bool alternateScreenActive = fAlternateScreenActive;
if (alternateScreenActive)
_SwitchScreenBuffer();
int32 oldWidth = fWidth;
int32 oldHeight = fHeight;
// Resize the normal screen buffer/history.
status_t error = BasicTerminalBuffer::ResizeTo(width, height,
historyCapacity);
if (error != B_OK) {
if (alternateScreenActive)
_SwitchScreenBuffer();
return error;
}
TermPos cursor = fCursor;
// Switch to the alternate screen buffer and resize it.
if (fAlternateScreen != NULL) {
_SwitchScreenBuffer();
fWidth = oldWidth;
fHeight = oldHeight;
fCursor.SetTo(0, 0);
error = BasicTerminalBuffer::ResizeTo(width, height, 0);
if (error != B_OK) {
// This sucks -- we can't do anything about it. Delete the
// alternate screen buffer.
_FreeLines(fAlternateScreen, oldHeight);
fAlternateScreen = NULL;
}
// Switch back.
if (!alternateScreenActive)
_SwitchScreenBuffer();
fWidth = width;
fHeight = height;
fCursor = cursor;
}
return error;
}
void
TerminalBuffer::UseAlternateScreenBuffer()
{
if (fAlternateScreenActive || fAlternateScreen == NULL)
return;
_SwitchScreenBuffer();
Clear(false);
_InvalidateAll();
}
void
TerminalBuffer::UseNormalScreenBuffer()
{
if (!fAlternateScreenActive)
return;
_SwitchScreenBuffer();
_InvalidateAll();
}
void
TerminalBuffer::_SwitchScreenBuffer()
{
std::swap(fScreen, fAlternateScreen);
std::swap(fHistory, fAlternateHistory);
std::swap(fScreenOffset, fAlternateScreenOffset);
fAlternateScreenActive = !fAlternateScreenActive;
}

View File

@ -28,12 +28,26 @@ public:
void SetTitle(const char* title);
void NotifyQuit(int32 reason);
virtual status_t ResizeTo(int32 width, int32 height);
virtual status_t ResizeTo(int32 width, int32 height,
int32 historyCapacity);
void UseAlternateScreenBuffer();
void UseNormalScreenBuffer();
protected:
virtual void NotifyListener();
private:
void _SwitchScreenBuffer();
private:
int fEncoding;
TerminalLine** fAlternateScreen;
HistoryBuffer* fAlternateHistory;
int32 fAlternateScreenOffset;
// listener/dirty region management
BMessenger fListener;
bool fListenerValid;