* 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:
@@ -120,6 +120,7 @@ BasicTerminalBuffer::Init(int32 width, int32 height, int32 historySize)
|
|||||||
fScreenOffset = 0;
|
fScreenOffset = 0;
|
||||||
|
|
||||||
fOverwriteMode = true;
|
fOverwriteMode = true;
|
||||||
|
fAlternateScreenActive = false;
|
||||||
|
|
||||||
fScreen = _AllocateLines(width, height);
|
fScreen = _AllocateLines(width, height);
|
||||||
if (fScreen == NULL)
|
if (fScreen == NULL)
|
||||||
@@ -162,12 +163,10 @@ BasicTerminalBuffer::ResizeTo(int32 width, int32 height, int32 historyCapacity)
|
|||||||
if (width == fWidth && height == fHeight)
|
if (width == fWidth && height == fHeight)
|
||||||
return SetHistoryCapacity(historyCapacity);
|
return SetHistoryCapacity(historyCapacity);
|
||||||
|
|
||||||
// TODO: When alternate screen support is implemented, do that only when
|
if (fAlternateScreenActive)
|
||||||
// not using the alternate screen.
|
|
||||||
if (true)
|
|
||||||
return _ResizeRewrap(width, height, historyCapacity);
|
|
||||||
|
|
||||||
return _ResizeSimple(width, height, historyCapacity);
|
return _ResizeSimple(width, height, historyCapacity);
|
||||||
|
|
||||||
|
return _ResizeRewrap(width, height, historyCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -179,10 +178,12 @@ BasicTerminalBuffer::SetHistoryCapacity(int32 historyCapacity)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BasicTerminalBuffer::Clear()
|
BasicTerminalBuffer::Clear(bool resetCursor)
|
||||||
{
|
{
|
||||||
fScreenOffset = 0;
|
fScreenOffset = 0;
|
||||||
_ClearLines(0, fHeight - 1);
|
_ClearLines(0, fHeight - 1);
|
||||||
|
|
||||||
|
if (resetCursor)
|
||||||
fCursor.SetTo(0, 0);
|
fCursor.SetTo(0, 0);
|
||||||
|
|
||||||
if (fHistory != NULL)
|
if (fHistory != NULL)
|
||||||
@@ -585,6 +586,7 @@ BasicTerminalBuffer::InsertLF()
|
|||||||
if (fCursor.y == fScrollBottom) {
|
if (fCursor.y == fScrollBottom) {
|
||||||
_Scroll(fScrollTop, fScrollBottom, 1);
|
_Scroll(fScrollTop, fScrollBottom, 1);
|
||||||
} else {
|
} else {
|
||||||
|
if (fCursor.y < fHeight - 1)
|
||||||
fCursor.y++;
|
fCursor.y++;
|
||||||
_CursorChanged();
|
_CursorChanged();
|
||||||
}
|
}
|
||||||
@@ -731,7 +733,7 @@ BasicTerminalBuffer::SetCursor(int32 x, int32 y)
|
|||||||
{
|
{
|
||||||
//debug_printf("BasicTerminalBuffer::SetCursor(%d, %d)\n", x, y);
|
//debug_printf("BasicTerminalBuffer::SetCursor(%d, %d)\n", x, y);
|
||||||
x = restrict_value(x, 0, fWidth - 1);
|
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) {
|
if (x != fCursor.x || y != fCursor.y) {
|
||||||
fCursor.x = x;
|
fCursor.x = x;
|
||||||
fCursor.y = y;
|
fCursor.y = y;
|
||||||
@@ -775,6 +777,18 @@ BasicTerminalBuffer::NotifyListener()
|
|||||||
// #pragma mark - private methods
|
// #pragma mark - private methods
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicTerminalBuffer::_InvalidateAll()
|
||||||
|
{
|
||||||
|
fDirtyInfo.invalidateAll = true;
|
||||||
|
|
||||||
|
if (!fDirtyInfo.messageSent) {
|
||||||
|
NotifyListener();
|
||||||
|
fDirtyInfo.messageSent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* static */ TerminalLine**
|
/* static */ TerminalLine**
|
||||||
BasicTerminalBuffer::_AllocateLines(int32 width, int32 count)
|
BasicTerminalBuffer::_AllocateLines(int32 width, int32 count)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ struct TerminalBufferDirtyInfo {
|
|||||||
int32 linesScrolled; // number of lines added to the history
|
int32 linesScrolled; // number of lines added to the history
|
||||||
int32 dirtyTop; // dirty line range
|
int32 dirtyTop; // dirty line range
|
||||||
int32 dirtyBottom; //
|
int32 dirtyBottom; //
|
||||||
|
bool invalidateAll;
|
||||||
bool messageSent; // listener has been notified
|
bool messageSent; // listener has been notified
|
||||||
|
|
||||||
bool IsDirtyRegionValid() const
|
bool IsDirtyRegionValid() const
|
||||||
@@ -41,6 +42,7 @@ struct TerminalBufferDirtyInfo {
|
|||||||
linesScrolled = 0;
|
linesScrolled = 0;
|
||||||
dirtyTop = INT_MAX;
|
dirtyTop = INT_MAX;
|
||||||
dirtyBottom = INT_MIN;
|
dirtyBottom = INT_MIN;
|
||||||
|
invalidateAll = false;
|
||||||
messageSent = false;
|
messageSent = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -61,11 +63,11 @@ public:
|
|||||||
|
|
||||||
TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; }
|
TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; }
|
||||||
|
|
||||||
status_t ResizeTo(int32 width, int32 height);
|
virtual status_t ResizeTo(int32 width, int32 height);
|
||||||
status_t ResizeTo(int32 width, int32 height,
|
virtual status_t ResizeTo(int32 width, int32 height,
|
||||||
int32 historyCapacity);
|
int32 historyCapacity);
|
||||||
status_t SetHistoryCapacity(int32 historyCapacity);
|
status_t SetHistoryCapacity(int32 historyCapacity);
|
||||||
void Clear();
|
void Clear(bool resetCursor);
|
||||||
|
|
||||||
void SynchronizeWith(
|
void SynchronizeWith(
|
||||||
const BasicTerminalBuffer* other,
|
const BasicTerminalBuffer* other,
|
||||||
@@ -139,6 +141,7 @@ protected:
|
|||||||
|
|
||||||
inline void _Invalidate(int32 top, int32 bottom);
|
inline void _Invalidate(int32 top, int32 bottom);
|
||||||
inline void _CursorChanged();
|
inline void _CursorChanged();
|
||||||
|
void _InvalidateAll();
|
||||||
|
|
||||||
static TerminalLine** _AllocateLines(int32 width, int32 count);
|
static TerminalLine** _AllocateLines(int32 width, int32 count);
|
||||||
static void _FreeLines(TerminalLine** lines, int32 count);
|
static void _FreeLines(TerminalLine** lines, int32 count);
|
||||||
@@ -182,6 +185,7 @@ protected:
|
|||||||
TermPos fSavedCursor;
|
TermPos fSavedCursor;
|
||||||
|
|
||||||
bool fOverwriteMode; // false for insert
|
bool fOverwriteMode; // false for insert
|
||||||
|
bool fAlternateScreenActive;
|
||||||
|
|
||||||
int fEncoding;
|
int fEncoding;
|
||||||
|
|
||||||
|
|||||||
@@ -790,13 +790,15 @@ TermParse::EscParse()
|
|||||||
|
|
||||||
case CASE_DECSET:
|
case CASE_DECSET:
|
||||||
/* DECSET */
|
/* DECSET */
|
||||||
// dpmodes(term, bitset);
|
for (int i = 0; i < nparam; i++)
|
||||||
|
_DecPrivateModeSet(param[i]);
|
||||||
parsestate = groundtable;
|
parsestate = groundtable;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CASE_DECRST:
|
case CASE_DECRST:
|
||||||
/* DECRST */
|
/* DECRST */
|
||||||
// dpmodes(term, bitclr);
|
for (int i = 0; i < nparam; i++)
|
||||||
|
_DecPrivateModeReset(param[i]);
|
||||||
parsestate = groundtable;
|
parsestate = groundtable;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1070,3 +1072,80 @@ TermParse::_DeviceStatusReport(int n)
|
|||||||
return;
|
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:
|
||||||
|
// Don’t interpret "meta" key.
|
||||||
|
// Not supported yet.
|
||||||
|
break;
|
||||||
|
case 1049:
|
||||||
|
// Use Normal Screen Buffer and restore cursor as in DECRC.
|
||||||
|
fBuffer->RestoreCursor();
|
||||||
|
fBuffer->UseNormalScreenBuffer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ private:
|
|||||||
status_t _ReadParserBuffer();
|
status_t _ReadParserBuffer();
|
||||||
|
|
||||||
void _DeviceStatusReport(int n);
|
void _DeviceStatusReport(int n);
|
||||||
|
void _DecPrivateModeSet(int value);
|
||||||
|
void _DecPrivateModeReset(int value);
|
||||||
|
|
||||||
int fFd;
|
int fFd;
|
||||||
|
|
||||||
|
|||||||
@@ -710,9 +710,9 @@ TermView::Clear()
|
|||||||
|
|
||||||
{
|
{
|
||||||
BAutolock _(fTextBuffer);
|
BAutolock _(fTextBuffer);
|
||||||
fTextBuffer->Clear();
|
fTextBuffer->Clear(true);
|
||||||
}
|
}
|
||||||
fVisibleTextBuffer->Clear();
|
fVisibleTextBuffer->Clear(true);
|
||||||
|
|
||||||
//debug_printf("Invalidate()\n");
|
//debug_printf("Invalidate()\n");
|
||||||
Invalidate();
|
Invalidate();
|
||||||
@@ -1563,10 +1563,6 @@ TermView::_SynchronizeWithTextBuffer(int32 visibleDirtyTop,
|
|||||||
{
|
{
|
||||||
TerminalBufferDirtyInfo& info = fTextBuffer->DirtyInfo();
|
TerminalBufferDirtyInfo& info = fTextBuffer->DirtyInfo();
|
||||||
int32 linesScrolled = info.linesScrolled;
|
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, "
|
//debug_printf("TermView::_SynchronizeWithTextBuffer(): dirty: %ld - %ld, "
|
||||||
//"scrolled: %ld, visible dirty: %ld - %ld\n", info.dirtyTop, info.dirtyBottom,
|
//"scrolled: %ld, visible dirty: %ld - %ld\n", info.dirtyTop, info.dirtyBottom,
|
||||||
@@ -1630,6 +1626,22 @@ TermView::_SynchronizeWithTextBuffer(int32 visibleDirtyTop,
|
|||||||
fScrolledSinceLastSync = 0;
|
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;
|
bool doScroll = false;
|
||||||
if (linesScrolled > 0) {
|
if (linesScrolled > 0) {
|
||||||
_UpdateScrollBarRange();
|
_UpdateScrollBarRange();
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "TerminalBuffer.h"
|
#include "TerminalBuffer.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
|
||||||
#include "Coding.h"
|
#include "Coding.h"
|
||||||
@@ -18,6 +20,9 @@ TerminalBuffer::TerminalBuffer()
|
|||||||
:
|
:
|
||||||
BLocker("terminal buffer"),
|
BLocker("terminal buffer"),
|
||||||
fEncoding(M_UTF8),
|
fEncoding(M_UTF8),
|
||||||
|
fAlternateScreen(NULL),
|
||||||
|
fAlternateHistory(NULL),
|
||||||
|
fAlternateScreenOffset(0),
|
||||||
fListenerValid(false)
|
fListenerValid(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -25,6 +30,8 @@ TerminalBuffer::TerminalBuffer()
|
|||||||
|
|
||||||
TerminalBuffer::~TerminalBuffer()
|
TerminalBuffer::~TerminalBuffer()
|
||||||
{
|
{
|
||||||
|
delete fAlternateScreen;
|
||||||
|
delete fAlternateHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,6 +41,10 @@ TerminalBuffer::Init(int32 width, int32 height, int32 historySize)
|
|||||||
if (Sem() < 0)
|
if (Sem() < 0)
|
||||||
return Sem();
|
return Sem();
|
||||||
|
|
||||||
|
fAlternateScreen = _AllocateLines(width, height);
|
||||||
|
if (fAlternateScreen == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
return BasicTerminalBuffer::Init(width, height, historySize);
|
return BasicTerminalBuffer::Init(width, height, historySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,3 +106,100 @@ TerminalBuffer::NotifyListener()
|
|||||||
if (fListenerValid)
|
if (fListenerValid)
|
||||||
fListener.SendMessage(MSG_TERMINAL_BUFFER_CHANGED);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,12 +28,26 @@ public:
|
|||||||
void SetTitle(const char* title);
|
void SetTitle(const char* title);
|
||||||
void NotifyQuit(int32 reason);
|
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:
|
protected:
|
||||||
virtual void NotifyListener();
|
virtual void NotifyListener();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _SwitchScreenBuffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fEncoding;
|
int fEncoding;
|
||||||
|
|
||||||
|
TerminalLine** fAlternateScreen;
|
||||||
|
HistoryBuffer* fAlternateHistory;
|
||||||
|
int32 fAlternateScreenOffset;
|
||||||
|
|
||||||
// listener/dirty region management
|
// listener/dirty region management
|
||||||
BMessenger fListener;
|
BMessenger fListener;
|
||||||
bool fListenerValid;
|
bool fListenerValid;
|
||||||
|
|||||||
Reference in New Issue
Block a user