366 lines
8.8 KiB
C++
366 lines
8.8 KiB
C++
/*
|
|
* Copyright 2013, Haiku, Inc. All rights reserved.
|
|
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Ingo Weinhold, ingo_weinhold@gmx.de
|
|
* Siarzhuk Zharski, zharik@gmx.li
|
|
*/
|
|
#ifndef BASIC_TERMINAL_BUFFER_H
|
|
#define BASIC_TERMINAL_BUFFER_H
|
|
|
|
#include <limits.h>
|
|
#include <stack>
|
|
|
|
#include "HistoryBuffer.h"
|
|
#include "TermPos.h"
|
|
#include "UTF8Char.h"
|
|
|
|
|
|
class BString;
|
|
class TerminalCharClassifier;
|
|
struct TerminalLine;
|
|
|
|
|
|
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
|
|
{
|
|
return dirtyTop <= dirtyBottom;
|
|
}
|
|
|
|
void ExtendDirtyRegion(int32 top, int32 bottom)
|
|
{
|
|
if (top < dirtyTop)
|
|
dirtyTop = top;
|
|
if (bottom > dirtyBottom)
|
|
dirtyBottom = bottom;
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
linesScrolled = 0;
|
|
dirtyTop = INT_MAX;
|
|
dirtyBottom = INT_MIN;
|
|
invalidateAll = false;
|
|
messageSent = false;
|
|
}
|
|
|
|
TerminalBufferDirtyInfo()
|
|
{
|
|
Reset();
|
|
}
|
|
};
|
|
|
|
|
|
class BasicTerminalBuffer {
|
|
public:
|
|
BasicTerminalBuffer();
|
|
virtual ~BasicTerminalBuffer();
|
|
|
|
status_t Init(int32 width, int32 height,
|
|
int32 historyCapacity);
|
|
|
|
int32 Width() const { return fWidth; }
|
|
int32 Height() const { return fHeight; }
|
|
inline int32 HistorySize() const;
|
|
inline int32 HistoryCapacity() const;
|
|
|
|
bool IsAlternateScreenActive() const
|
|
{ return fAlternateScreenActive; }
|
|
|
|
TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; }
|
|
|
|
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(bool resetCursor);
|
|
|
|
void SynchronizeWith(
|
|
const BasicTerminalBuffer* other,
|
|
int32 offset, int32 dirtyTop,
|
|
int32 dirtyBottom);
|
|
|
|
bool IsFullWidthChar(int32 row, int32 column) const;
|
|
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;
|
|
void GetStringFromRegion(BString& string,
|
|
const TermPos& start,
|
|
const TermPos& end) const;
|
|
bool FindWord(const TermPos& pos,
|
|
TerminalCharClassifier* classifier,
|
|
bool findNonWords, TermPos& start,
|
|
TermPos& end) const;
|
|
int32 LineLength(int32 index) const;
|
|
int32 GetLineColor(int32 index) const;
|
|
|
|
bool PreviousLinePos(TermPos& pos) const;
|
|
bool NextLinePos(TermPos& pos, bool normalize) const;
|
|
// normalize specifies that the returned
|
|
// position must be a valid position, i.e.
|
|
// actually point to a character (as opposed
|
|
// to just pointing to the position after a
|
|
// character).
|
|
|
|
bool Find(const char* pattern, const TermPos& start,
|
|
bool forward, bool caseSensitive,
|
|
bool matchWord, TermPos& matchStart,
|
|
TermPos& matchEnd) const;
|
|
|
|
inline uint32 GetAttributes();
|
|
inline void SetAttributes(uint32 attributes);
|
|
|
|
// snapshots and data capture for debugging
|
|
void MakeLinesSnapshots(time_t timeStamp,
|
|
const char* fileName);
|
|
void StartStopDebugCapture();
|
|
void CaptureChar(char ch);
|
|
|
|
// insert chars/lines
|
|
void InsertChar(UTF8Char c);
|
|
void FillScreen(UTF8Char c, uint32 attr);
|
|
|
|
void InsertCR();
|
|
void InsertLF();
|
|
void InsertRI();
|
|
void InsertTab();
|
|
void InsertCursorBackTab(int32 numTabs);
|
|
void SetInsertMode(int flag);
|
|
void InsertSpace(int32 num);
|
|
void InsertLines(int32 numLines);
|
|
void InsertLastChar();
|
|
|
|
// delete chars/lines
|
|
inline void EraseChars(int32 numChars);
|
|
void EraseCharsFrom(int32 first, int32 numChars);
|
|
void EraseAbove();
|
|
void EraseBelow();
|
|
void EraseAll();
|
|
void DeleteChars(int32 numChars);
|
|
inline void DeleteColumns();
|
|
void DeleteColumnsFrom(int32 first);
|
|
void DeleteLines(int32 numLines);
|
|
|
|
// get and set cursor position
|
|
inline void SetCursor(int32 x, int32 y);
|
|
inline void SetCursorX(int32 x);
|
|
inline void SetCursorY(int32 y);
|
|
inline TermPos Cursor() const { return fCursor; }
|
|
void SaveCursor();
|
|
void RestoreCursor();
|
|
|
|
// move cursor
|
|
inline void MoveCursorRight(int32 num);
|
|
inline void MoveCursorLeft(int32 num);
|
|
inline void MoveCursorUp(int32 num);
|
|
inline void MoveCursorDown(int32 num);
|
|
inline void NextLine();
|
|
|
|
// scroll region
|
|
inline void ScrollBy(int32 numLines);
|
|
void SetScrollRegion(int32 top, int32 bottom);
|
|
void SetOriginMode(bool enabled);
|
|
void SaveOriginMode();
|
|
void RestoreOriginMode();
|
|
void SetTabStop(int32 x);
|
|
void ClearTabStop(int32 x);
|
|
void ClearAllTabStops();
|
|
|
|
protected:
|
|
virtual void NotifyListener();
|
|
|
|
inline int32 _LineIndex(int32 index) const;
|
|
inline TerminalLine* _LineAt(int32 index) const;
|
|
inline TerminalLine* _HistoryLineAt(int32 index,
|
|
TerminalLine* lineBuffer) const;
|
|
|
|
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);
|
|
static void _FreeLines(TerminalLine** lines, int32 count);
|
|
void _ClearLines(int32 first, int32 last);
|
|
|
|
status_t _ResizeHistory(int32 width,
|
|
int32 historyCapacity);
|
|
status_t _ResizeSimple(int32 width, int32 height,
|
|
int32 historyCapacity);
|
|
status_t _ResizeRewrap(int32 width, int32 height,
|
|
int32 historyCapacity);
|
|
status_t _ResetTabStops(int32 width);
|
|
|
|
void _Scroll(int32 top, int32 bottom,
|
|
int32 numLines);
|
|
void _SoftBreakLine();
|
|
void _PadLineToCursor();
|
|
static void _TruncateLine(TerminalLine* line, int32 length);
|
|
void _InsertGap(int32 width);
|
|
TerminalLine* _GetPartialLineString(BString& string,
|
|
int32 row, int32 startColumn,
|
|
int32 endColumn) const;
|
|
bool _PreviousChar(TermPos& pos, UTF8Char& c) const;
|
|
bool _NextChar(TermPos& pos, UTF8Char& c) const;
|
|
|
|
bool _PreviousLinePos(TerminalLine* lineBuffer,
|
|
TerminalLine*& line, TermPos& pos) const;
|
|
bool _NormalizeLinePos(TerminalLine* lineBuffer,
|
|
TerminalLine*& line, TermPos& pos) const;
|
|
|
|
protected:
|
|
// screen width/height
|
|
int32 fWidth;
|
|
int32 fHeight;
|
|
|
|
// scroll region top/bottom
|
|
int32 fScrollTop; // first line to scroll
|
|
int32 fScrollBottom; // last line to scroll (incl.)
|
|
|
|
// line buffers for the history (ring buffer)
|
|
TerminalLine** fScreen;
|
|
int32 fScreenOffset; // index of screen line 0
|
|
HistoryBuffer* fHistory;
|
|
|
|
uint32 fAttributes;
|
|
|
|
// cursor position (origin: (0, 0))
|
|
TermPos fCursor;
|
|
std::stack<TermPos> fSavedCursors;
|
|
bool fSoftWrappedCursor;
|
|
|
|
bool fOverwriteMode; // false for insert
|
|
bool fAlternateScreenActive;
|
|
bool fOriginMode;
|
|
bool fSavedOriginMode;
|
|
bool* fTabStops;
|
|
|
|
int fEncoding;
|
|
int fCaptureFile;
|
|
|
|
UTF8Char fLast;
|
|
|
|
// listener/dirty region management
|
|
TerminalBufferDirtyInfo fDirtyInfo;
|
|
};
|
|
|
|
|
|
int32
|
|
BasicTerminalBuffer::HistorySize() const
|
|
{
|
|
return fHistory != NULL ? fHistory->Size() : 0;
|
|
}
|
|
|
|
|
|
int32
|
|
BasicTerminalBuffer::HistoryCapacity() const
|
|
{
|
|
return fHistory != NULL ? fHistory->Capacity() : 0;
|
|
}
|
|
|
|
|
|
uint32
|
|
BasicTerminalBuffer::GetAttributes()
|
|
{
|
|
return fAttributes;
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::SetAttributes(uint32 attributes)
|
|
{
|
|
fAttributes = attributes;
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
SetCursor(x, fCursor.y);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::SetCursorY(int32 y)
|
|
{
|
|
SetCursor(fCursor.x, y);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::MoveCursorRight(int32 num)
|
|
{
|
|
SetCursor(fCursor.x + num, fCursor.y);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::MoveCursorLeft(int32 num)
|
|
{
|
|
SetCursor(fCursor.x - num, fCursor.y);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::MoveCursorUp(int32 num)
|
|
{
|
|
SetCursor(fCursor.x, fCursor.y - num);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::MoveCursorDown(int32 num)
|
|
{
|
|
SetCursor(fCursor.x, fCursor.y + num);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::ScrollBy(int32 numLines)
|
|
{
|
|
_Scroll(fScrollTop, fScrollBottom, numLines);
|
|
}
|
|
|
|
|
|
void
|
|
BasicTerminalBuffer::NextLine()
|
|
{
|
|
SetCursor(0, fCursor.y + 1);
|
|
}
|
|
|
|
#endif // BASIC_TERMINAL_BUFFER_H
|