* Change the line history to a more compact format. We reserve
lines * (width + 8) bytes which is only a little more than a sixth of what it was before. The effect on performance is relatively small. In my tests I measured about 2% slowdown. * Fixed artifacts after soft-wrapped lines. * Re-enabled cursor blinking. I changed it so that the cursor is 1s shown and 0.5s hidden (instead of 1s each). Tell me what you think. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25957 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
345dc29f8a
commit
4c9d4b02ef
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,14 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "HistoryBuffer.h"
|
||||
#include "TermPos.h"
|
||||
#include "UTF8Char.h"
|
||||
|
||||
|
||||
class BString;
|
||||
class TerminalCharClassifier;
|
||||
struct TerminalLine;
|
||||
|
||||
|
||||
struct TerminalBufferDirtyInfo {
|
||||
@ -54,7 +56,8 @@ public:
|
||||
|
||||
int32 Width() const { return fWidth; }
|
||||
int32 Height() const { return fHeight; }
|
||||
int32 HistorySize() const { return fHistorySize; }
|
||||
inline int32 HistorySize() const;
|
||||
inline int32 HistoryCapacity() const;
|
||||
|
||||
TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; }
|
||||
|
||||
@ -125,40 +128,32 @@ public:
|
||||
void SetScrollRegion(int32 top, int32 bot);
|
||||
|
||||
protected:
|
||||
struct Cell {
|
||||
UTF8Char character;
|
||||
uint16 attributes;
|
||||
};
|
||||
|
||||
struct Line {
|
||||
int16 length;
|
||||
bool softBreak; // soft line break
|
||||
Cell cells[1];
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
length = 0;
|
||||
softBreak = false;
|
||||
}
|
||||
};
|
||||
|
||||
virtual void NotifyListener();
|
||||
|
||||
inline int32 _LineIndex(int32 index) const;
|
||||
inline Line* _LineAt(int32 index) const;
|
||||
inline Line* _HistoryLineAt(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();
|
||||
|
||||
static Line** _AllocateLines(int32 width, int32 count);
|
||||
static void _FreeLines(Line** lines, int32 count);
|
||||
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);
|
||||
|
||||
void _Scroll(int32 top, int32 bottom,
|
||||
int32 numLines);
|
||||
void _SoftBreakLine();
|
||||
void _PadLineToCursor();
|
||||
static void _TruncateLine(TerminalLine* line, int32 length);
|
||||
void _InsertGap(int32 width);
|
||||
bool _GetPartialLineString(BString& string,
|
||||
int32 row, int32 startColumn,
|
||||
@ -176,10 +171,9 @@ protected:
|
||||
int32 fScrollBottom; // last line to scroll (incl.)
|
||||
|
||||
// line buffers for the history (ring buffer)
|
||||
Line** fHistory;
|
||||
int32 fHistoryCapacity;
|
||||
TerminalLine** fScreen;
|
||||
int32 fScreenOffset; // index of screen line 0
|
||||
int32 fHistorySize;
|
||||
HistoryBuffer* fHistory;
|
||||
|
||||
// cursor position (origin: (0, 0))
|
||||
TermPos fCursor;
|
||||
@ -194,6 +188,20 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
int32
|
||||
BasicTerminalBuffer::HistorySize() const
|
||||
{
|
||||
return fHistory != NULL ? fHistory->Size() : 0;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BasicTerminalBuffer::HistoryCapacity() const
|
||||
{
|
||||
return fHistory != NULL ? fHistory->Capacity() : 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::InsertChar(const char* c, int32 length, uint32 attributes)
|
||||
{
|
||||
|
280
src/apps/terminal/HistoryBuffer.cpp
Normal file
280
src/apps/terminal/HistoryBuffer.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "HistoryBuffer.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include "TermConst.h"
|
||||
|
||||
|
||||
HistoryBuffer::HistoryBuffer()
|
||||
:
|
||||
fLines(NULL),
|
||||
fWidth(0),
|
||||
fCapacity(0),
|
||||
fNextLine(0),
|
||||
fSize(0),
|
||||
fBuffer(NULL),
|
||||
fBufferSize(0),
|
||||
fBufferAllocationOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HistoryBuffer::~HistoryBuffer()
|
||||
{
|
||||
delete[] fLines;
|
||||
delete[] fBuffer;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HistoryBuffer::Init(int32 width, int32 capacity)
|
||||
{
|
||||
if (width <= 0 || capacity <= 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
int32 bufferSize = (width + 4) * capacity;
|
||||
|
||||
if (capacity > 0) {
|
||||
fLines = new(std::nothrow) HistoryLine[capacity];
|
||||
fBuffer = new(std::nothrow) uint8[bufferSize];
|
||||
|
||||
if (fLines == NULL || fBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
fWidth = width;
|
||||
fCapacity = capacity;
|
||||
fNextLine = 0;
|
||||
fSize = 0;
|
||||
fBufferSize = bufferSize;
|
||||
fBufferAllocationOffset = 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryBuffer::Clear()
|
||||
{
|
||||
fNextLine = 0;
|
||||
fSize = 0;
|
||||
fBufferAllocationOffset = 0;
|
||||
}
|
||||
|
||||
|
||||
TerminalLine*
|
||||
HistoryBuffer::GetTerminalLineAt(int32 index, TerminalLine* buffer) const
|
||||
{
|
||||
HistoryLine* line = LineAt(index);
|
||||
if (line == NULL)
|
||||
return NULL;
|
||||
|
||||
int32 charCount = 0;
|
||||
const char* chars = line->Chars();
|
||||
buffer->length = 0;
|
||||
uint16 attributes = 0;
|
||||
AttributesRun* attributesRun = line->AttributesRuns();
|
||||
int32 attributesRunCount = line->attributesRunCount;
|
||||
int32 nextAttributesAt = attributesRunCount > 0
|
||||
? attributesRun->offset : INT_MAX;
|
||||
|
||||
for (int32 i = 0; i < line->byteLength;) {
|
||||
// get attributes
|
||||
if (charCount == nextAttributesAt) {
|
||||
if (attributesRunCount > 0) {
|
||||
attributes = attributesRun->attributes;
|
||||
nextAttributesAt = attributesRun->offset + attributesRun->length;
|
||||
attributesRun++;
|
||||
attributesRunCount--;
|
||||
} else {
|
||||
attributes = 0;
|
||||
nextAttributesAt = INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
// copy character
|
||||
TerminalCell& cell = buffer->cells[charCount++];
|
||||
int32 charLength = UTF8Char::ByteCount(chars[i]);
|
||||
cell.character.SetTo(chars + i, charLength);
|
||||
i += charLength;
|
||||
|
||||
// set attributes
|
||||
cell.attributes = attributes;
|
||||
|
||||
// full width char?
|
||||
if (cell.character.IsFullWidth()) {
|
||||
cell.attributes |= A_WIDTH;
|
||||
charCount++;
|
||||
}
|
||||
}
|
||||
|
||||
buffer->length = charCount;
|
||||
buffer->softBreak = line->softBreak;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryBuffer::AddLine(const TerminalLine* line)
|
||||
{
|
||||
//debug_printf("HistoryBuffer::AddLine(%p): length: %d\n", line, line->length);
|
||||
// determine the amount of memory we need for the line
|
||||
uint16 attributes = 0;
|
||||
int32 attributesRuns = 0;
|
||||
int32 byteLength = 0;
|
||||
for (int32 i = 0; i < line->length; i++) {
|
||||
const TerminalCell& cell = line->cells[i];
|
||||
byteLength += cell.character.ByteCount();
|
||||
if ((cell.attributes & CHAR_ATTRIBUTES) != attributes) {
|
||||
attributes = cell.attributes & CHAR_ATTRIBUTES;
|
||||
if (attributes != 0)
|
||||
attributesRuns++;
|
||||
}
|
||||
if (IS_WIDTH(cell.attributes))
|
||||
i++;
|
||||
}
|
||||
|
||||
//debug_printf(" attributesRuns: %ld, byteLength: %ld\n", attributesRuns, byteLength);
|
||||
|
||||
// allocate and translate the line
|
||||
HistoryLine* historyLine = _AllocateLine(attributesRuns, byteLength);
|
||||
|
||||
attributes = 0;
|
||||
AttributesRun* attributesRun = historyLine->AttributesRuns();
|
||||
|
||||
char* chars = historyLine->Chars();
|
||||
for (int32 i = 0; i < line->length; i++) {
|
||||
const TerminalCell& cell = line->cells[i];
|
||||
|
||||
// copy char
|
||||
int32 charLength = cell.character.ByteCount();
|
||||
memcpy(chars, cell.character.bytes, charLength);
|
||||
chars += charLength;
|
||||
|
||||
// deal with attributes
|
||||
if ((cell.attributes & CHAR_ATTRIBUTES) != attributes) {
|
||||
// terminate the previous attributes run
|
||||
if (attributes != 0) {
|
||||
attributesRun->length = i - attributesRun->offset;
|
||||
attributesRun++;
|
||||
}
|
||||
|
||||
attributes = cell.attributes & CHAR_ATTRIBUTES;
|
||||
|
||||
// init the new one
|
||||
if (attributes != 0) {
|
||||
attributesRun->attributes = attributes;
|
||||
attributesRun->offset = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_WIDTH(cell.attributes))
|
||||
i++;
|
||||
}
|
||||
|
||||
historyLine->softBreak = line->softBreak;
|
||||
//debug_printf(" line: \"%.*s\", history size now: %ld\n", historyLine->byteLength, historyLine->Chars(), fSize);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryBuffer::AddEmptyLines(int32 count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
if (count > fCapacity)
|
||||
count = fCapacity;
|
||||
|
||||
if (count + fSize > fCapacity)
|
||||
DropLines(count + fSize - fCapacity);
|
||||
|
||||
// All lines use the same buffer address, since they don't use any memory.
|
||||
AttributesRun* attributesRun
|
||||
= (AttributesRun*)(fBuffer + fBufferAllocationOffset);
|
||||
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
HistoryLine* line = _LineAt(fNextLine++);
|
||||
line->attributesRuns = attributesRun;
|
||||
line->attributesRunCount = 0;
|
||||
line->byteLength = 0;
|
||||
line->softBreak = false;
|
||||
}
|
||||
|
||||
fSize += count;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryBuffer::DropLines(int32 count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
if (count < fSize) {
|
||||
fSize -= count;
|
||||
} else {
|
||||
fSize = 0;
|
||||
fNextLine = 0;
|
||||
fBufferAllocationOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HistoryLine*
|
||||
HistoryBuffer::_AllocateLine(int32 attributesRuns, int32 byteLength)
|
||||
{
|
||||
// we need at least one spare line slot
|
||||
int32 toDrop = 0;
|
||||
if (fSize == fCapacity)
|
||||
toDrop = 1;
|
||||
|
||||
int32 bytesNeeded = attributesRuns * sizeof(AttributesRun) + byteLength;
|
||||
|
||||
if (fBufferAllocationOffset + bytesNeeded > fBufferSize) {
|
||||
// drop all lines after the allocation index
|
||||
for (; toDrop < fSize; toDrop++) {
|
||||
HistoryLine* line = _LineAt(fSize - toDrop - 1);
|
||||
int32 offset = (uint8*)line->AttributesRuns() - fBuffer;
|
||||
if (offset < fBufferAllocationOffset)
|
||||
break;
|
||||
}
|
||||
|
||||
fBufferAllocationOffset = 0;
|
||||
}
|
||||
|
||||
// drop all lines interfering
|
||||
int32 nextOffset = (fBufferAllocationOffset + bytesNeeded + 1) & ~1;
|
||||
for (; toDrop < fSize; toDrop++) {
|
||||
HistoryLine* line = _LineAt(fSize - toDrop - 1);
|
||||
int32 offset = (uint8*)line->AttributesRuns() - fBuffer;
|
||||
if (offset + line->BufferSize() <= fBufferAllocationOffset
|
||||
|| offset >= nextOffset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DropLines(toDrop);
|
||||
|
||||
// init the line
|
||||
HistoryLine* line = &fLines[fNextLine];
|
||||
fNextLine = (fNextLine + 1) % fCapacity;
|
||||
fSize++;
|
||||
line->attributesRuns = (AttributesRun*)(fBuffer + fBufferAllocationOffset);
|
||||
line->attributesRunCount = attributesRuns;
|
||||
line->byteLength = byteLength;
|
||||
|
||||
fBufferAllocationOffset = (fBufferAllocationOffset + bytesNeeded + 1) & ~1;
|
||||
// DropLines() may have changed fBufferAllocationOffset, so don't use
|
||||
// nextOffset.
|
||||
|
||||
return line;
|
||||
}
|
69
src/apps/terminal/HistoryBuffer.h
Normal file
69
src/apps/terminal/HistoryBuffer.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef HISTORY_BUFFER_H
|
||||
#define HISTORY_BUFFER_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "TerminalLine.h"
|
||||
|
||||
|
||||
struct HistoryLine;
|
||||
struct TerminalLine;
|
||||
|
||||
|
||||
class HistoryBuffer {
|
||||
public:
|
||||
HistoryBuffer();
|
||||
~HistoryBuffer();
|
||||
|
||||
status_t Init(int32 width, int32 capacity);
|
||||
|
||||
void Clear();
|
||||
|
||||
int32 Width() const { return fWidth; }
|
||||
int32 Capacity() const { return fCapacity; }
|
||||
int32 Size() const { return fSize; }
|
||||
|
||||
inline HistoryLine* LineAt(int32 index) const;
|
||||
TerminalLine* GetTerminalLineAt(int32 index,
|
||||
TerminalLine* buffer) const;
|
||||
|
||||
void AddLine(const TerminalLine* line);
|
||||
void AddEmptyLines(int32 count);
|
||||
void DropLines(int32 count);
|
||||
|
||||
private:
|
||||
HistoryLine* _AllocateLine(int32 attributesRuns,
|
||||
int32 byteLength);
|
||||
inline HistoryLine* _LineAt(int32 index) const;
|
||||
|
||||
private:
|
||||
HistoryLine* fLines;
|
||||
int32 fWidth;
|
||||
int32 fCapacity;
|
||||
int32 fNextLine;
|
||||
int32 fSize;
|
||||
uint8* fBuffer;
|
||||
int32 fBufferSize;
|
||||
int32 fBufferAllocationOffset;
|
||||
};
|
||||
|
||||
|
||||
inline HistoryLine*
|
||||
HistoryBuffer::_LineAt(int32 index) const
|
||||
{
|
||||
return &fLines[(fCapacity + fNextLine - index - 1) % fCapacity];
|
||||
}
|
||||
|
||||
|
||||
inline HistoryLine*
|
||||
HistoryBuffer::LineAt(int32 index) const
|
||||
{
|
||||
return index >= 0 && index < fSize ? _LineAt(index) : NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif // HISTORY_BUFFER_H
|
@ -11,6 +11,7 @@ Application Terminal :
|
||||
CodeConv.cpp
|
||||
Coding.cpp
|
||||
FindWindow.cpp
|
||||
HistoryBuffer.cpp
|
||||
MenuUtil.cpp
|
||||
Terminal.cpp
|
||||
PrefHandler.cpp
|
||||
|
@ -161,18 +161,19 @@ enum{
|
||||
#define IN_STRING 0xFF
|
||||
|
||||
// TermBuffer extended attribute
|
||||
#define A_WIDTH 0x8000
|
||||
#define BOLD 0x4000
|
||||
#define UNDERLINE 0x2000
|
||||
#define INVERSE 0x1000
|
||||
#define MOUSE 0x0800
|
||||
#define FORESET 0x0400
|
||||
#define BACKSET 0x0200
|
||||
#define FONT 0x0100
|
||||
#define RESERVE 0x0080
|
||||
#define DUMPCR 0x0040
|
||||
#define FORECOLOR 0x0038
|
||||
#define BACKCOLOR 0x0007
|
||||
#define A_WIDTH 0x8000
|
||||
#define BOLD 0x4000
|
||||
#define UNDERLINE 0x2000
|
||||
#define INVERSE 0x1000
|
||||
#define MOUSE 0x0800
|
||||
#define FORESET 0x0400
|
||||
#define BACKSET 0x0200
|
||||
#define FONT 0x0100
|
||||
#define RESERVE 0x0080
|
||||
#define DUMPCR 0x0040
|
||||
#define FORECOLOR 0x0038
|
||||
#define BACKCOLOR 0x0007
|
||||
#define CHAR_ATTRIBUTES 0x773f
|
||||
|
||||
#define IS_WIDTH(x) (((x) & A_WIDTH) )
|
||||
#define IS_BOLD(x) (((x) & BOLD) )
|
||||
|
@ -96,6 +96,10 @@ static const uint32 kAutoScroll = 'AScr';
|
||||
|
||||
static const bigtime_t kSyncUpdateGranularity = 100000; // 0.1 s
|
||||
|
||||
static const int32 kCursorBlinkIntervals = 3;
|
||||
static const int32 kCursorVisibleIntervals = 2;
|
||||
static const bigtime_t kCursorBlinkInterval = 500000;
|
||||
|
||||
static const rgb_color kBlackColor = { 0, 0, 0, 255 };
|
||||
static const rgb_color kWhiteColor = { 255, 255, 255, 255 };
|
||||
|
||||
@ -198,11 +202,8 @@ TermView::TermView(BRect frame, int32 argc, const char **argv, int32 historySize
|
||||
fFontHeight(0),
|
||||
fFontAscent(0),
|
||||
fFrameResized(false),
|
||||
fLastCursorTime(0),
|
||||
fCursorDrawFlag(true),
|
||||
fCursorStatus(true),
|
||||
fCursorBlinkingFlag(true),
|
||||
fCursorRedrawFlag(true),
|
||||
fLastActivityTime(0),
|
||||
fCursorState(0),
|
||||
fCursorHeight(0),
|
||||
fCursor(0, 0),
|
||||
fTermRows(ROWS_DEFAULT),
|
||||
@ -244,11 +245,8 @@ TermView::TermView(int rows, int columns, int32 argc, const char **argv, int32 h
|
||||
fFontHeight(0),
|
||||
fFontAscent(0),
|
||||
fFrameResized(false),
|
||||
fLastCursorTime(0),
|
||||
fCursorDrawFlag(true),
|
||||
fCursorStatus(true),
|
||||
fCursorBlinkingFlag(true),
|
||||
fCursorRedrawFlag(true),
|
||||
fLastActivityTime(0),
|
||||
fCursorState(0),
|
||||
fCursorHeight(0),
|
||||
fCursor(0, 0),
|
||||
fTermRows(rows),
|
||||
@ -302,11 +300,8 @@ TermView::TermView(BMessage *archive)
|
||||
fFontHeight(0),
|
||||
fFontAscent(0),
|
||||
fFrameResized(false),
|
||||
fLastCursorTime(0),
|
||||
fCursorDrawFlag(true),
|
||||
fCursorStatus(true),
|
||||
fCursorBlinkingFlag(true),
|
||||
fCursorRedrawFlag(true),
|
||||
fLastActivityTime(0),
|
||||
fCursorState(0),
|
||||
fCursorHeight(0),
|
||||
fCursor(0, 0),
|
||||
fTermRows(ROWS_DEFAULT),
|
||||
@ -379,8 +374,7 @@ TermView::_InitObject(int32 argc, const char **argv)
|
||||
return error;
|
||||
fTextBuffer->SetEncoding(fEncoding);
|
||||
|
||||
error = fVisibleTextBuffer->Init(fTermColumns, fTermRows + 2,
|
||||
fTermRows + 2);
|
||||
error = fVisibleTextBuffer->Init(fTermColumns, fTermRows + 2, 0);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -503,7 +497,7 @@ TermView::SetTermSize(int rows, int columns, bool resize)
|
||||
{
|
||||
BAutolock _(fTextBuffer);
|
||||
if (fTextBuffer->ResizeTo(columns, rows) != B_OK
|
||||
|| fVisibleTextBuffer->ResizeTo(columns, rows + 2, rows + 2)
|
||||
|| fVisibleTextBuffer->ResizeTo(columns, rows + 2, 0)
|
||||
!= B_OK) {
|
||||
return Bounds();
|
||||
}
|
||||
@ -718,6 +712,7 @@ TermView::Clear()
|
||||
BAutolock _(fTextBuffer);
|
||||
fTextBuffer->Clear();
|
||||
}
|
||||
fVisibleTextBuffer->Clear();
|
||||
|
||||
//debug_printf("Invalidate()\n");
|
||||
Invalidate();
|
||||
@ -750,59 +745,6 @@ TermView::_InvalidateTextRange(TermPos start, TermPos end)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::BlinkCursor()
|
||||
{
|
||||
#if 0
|
||||
if (fCursorDrawFlag
|
||||
&& fCursorBlinkingFlag
|
||||
&& Window()->IsActive()) {
|
||||
if (fCursorStatus)
|
||||
_TermDraw(fCurPos, fCurPos);
|
||||
else
|
||||
DrawCursor();
|
||||
|
||||
fCursorStatus = !fCursorStatus;
|
||||
fLastCursorTime = system_time();
|
||||
}
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
|
||||
//! Draw / Clear cursor.
|
||||
void
|
||||
TermView::SetCurDraw(bool flag)
|
||||
{
|
||||
#if 0
|
||||
if (!flag) {
|
||||
if (fCursorStatus)
|
||||
_TermDraw(fCurPos, fCurPos);
|
||||
|
||||
fCursorStatus = false;
|
||||
fCursorDrawFlag = false;
|
||||
} else {
|
||||
if (!fCursorDrawFlag) {
|
||||
fCursorDrawFlag = true;
|
||||
fCursorStatus = true;
|
||||
|
||||
if (LockLooper()) {
|
||||
DrawCursor();
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! Sets cursor Blinking flag.
|
||||
void
|
||||
TermView::SetCurBlinking(bool flag)
|
||||
{
|
||||
fCursorBlinkingFlag = flag;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TermView::_AttachShell(Shell *shell)
|
||||
{
|
||||
@ -905,6 +847,8 @@ TermView::_DrawCursor()
|
||||
UTF8Char character;
|
||||
uint16 attr;
|
||||
|
||||
bool cursorVisible = _IsCursorVisible();
|
||||
|
||||
bool selected = _CheckSelectedRegion(TermPos(fCursor.x, fCursor.y));
|
||||
if (fVisibleTextBuffer->GetChar(fCursor.y - firstVisible, fCursor.x,
|
||||
character, attr) == A_CHAR) {
|
||||
@ -920,18 +864,52 @@ TermView::_DrawCursor()
|
||||
buffer[bytes] = '\0';
|
||||
|
||||
_DrawLinePart(fCursor.x * fFontWidth, (int32)rect.top, attr, buffer,
|
||||
width, selected, true, this);
|
||||
width, selected, cursorVisible, this);
|
||||
} else {
|
||||
if (selected)
|
||||
SetHighColor(fSelectBackColor);
|
||||
else
|
||||
SetHighColor(fCursorBackColor);
|
||||
SetHighColor(cursorVisible ? fCursorBackColor : fTextBackColor);
|
||||
|
||||
FillRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TermView::_IsCursorVisible() const
|
||||
{
|
||||
return fCursorState < kCursorVisibleIntervals;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::_BlinkCursor()
|
||||
{
|
||||
bool wasVisible = _IsCursorVisible();
|
||||
|
||||
bigtime_t now = system_time();
|
||||
if (Window()->IsActive() && now - fLastActivityTime >= kCursorBlinkInterval)
|
||||
fCursorState = (fCursorState + 1) % kCursorBlinkIntervals;
|
||||
else
|
||||
fCursorState = 0;
|
||||
|
||||
if (wasVisible != _IsCursorVisible())
|
||||
_InvalidateTextRect(fCursor.x, fCursor.y, fCursor.x, fCursor.y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::_ActivateCursor(bool invalidate)
|
||||
{
|
||||
fLastActivityTime = system_time();
|
||||
if (invalidate && fCursorState != 0)
|
||||
_BlinkCursor();
|
||||
else
|
||||
fCursorState = 0;
|
||||
}
|
||||
|
||||
|
||||
//! Update scroll bar range and knob size.
|
||||
void
|
||||
TermView::_UpdateScrollBarRange()
|
||||
@ -983,10 +961,6 @@ TermView::AttachedToWindow()
|
||||
BMessage message(kUpdateSigWinch);
|
||||
fWinchRunner = new (std::nothrow) BMessageRunner(thisMessenger,
|
||||
&message, 500000);
|
||||
|
||||
BMessage blinkMessage(kBlinkCursor);
|
||||
fCursorBlinkRunner = new (std::nothrow) BMessageRunner(thisMessenger,
|
||||
&blinkMessage, 1000000);
|
||||
}
|
||||
|
||||
|
||||
@ -1009,8 +983,6 @@ TermView::Draw(BRect updateRect)
|
||||
// return;
|
||||
// }
|
||||
|
||||
// BAutolock _(fTextBuffer);
|
||||
|
||||
// debug_printf("TermView::Draw((%f, %f) - (%f, %f))\n", updateRect.left,
|
||||
// updateRect.top, updateRect.right, updateRect.bottom);
|
||||
// {
|
||||
@ -1027,8 +999,6 @@ TermView::Draw(BRect updateRect)
|
||||
// }
|
||||
// }
|
||||
|
||||
// _SynchronizeWithTextBuffer(&updateRect);
|
||||
|
||||
int32 x1 = (int32)(updateRect.left) / fFontWidth;
|
||||
int32 x2 = (int32)(updateRect.right) / fFontWidth;
|
||||
|
||||
@ -1045,7 +1015,6 @@ TermView::Draw(BRect updateRect)
|
||||
int32 k = x1;
|
||||
char buf[fTermColumns * 4 + 1];
|
||||
|
||||
// if (fTextBuffer->IsFullWidthChar(j, k))
|
||||
if (fVisibleTextBuffer->IsFullWidthChar(j - firstVisible, k))
|
||||
k--;
|
||||
|
||||
@ -1056,7 +1025,6 @@ TermView::Draw(BRect updateRect)
|
||||
int32 lastColumn = x2;
|
||||
bool insideSelection = _CheckSelectedRegion(j, i, lastColumn);
|
||||
uint16 attr;
|
||||
// int32 count = fTextBuffer->GetString(j, i, lastColumn, buf, attr);
|
||||
int32 count = fVisibleTextBuffer->GetString(j - firstVisible, i,
|
||||
lastColumn, buf, attr);
|
||||
|
||||
@ -1079,8 +1047,6 @@ TermView::Draw(BRect updateRect)
|
||||
_DrawLinePart(fFontWidth * i, (int32)_LineOffset(j),
|
||||
attr, buf, count, insideSelection, false, this);
|
||||
i += count;
|
||||
if (i >= fTermColumns)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1141,8 +1107,21 @@ void
|
||||
TermView::WindowActivated(bool active)
|
||||
{
|
||||
BView::WindowActivated(active);
|
||||
if (active == false) {
|
||||
if (active) {
|
||||
// start cursor blinking
|
||||
if (fCursorBlinkRunner == NULL) {
|
||||
BMessage blinkMessage(kBlinkCursor);
|
||||
fCursorBlinkRunner = new (std::nothrow) BMessageRunner(
|
||||
BMessenger(this), &blinkMessage, kCursorBlinkInterval);
|
||||
}
|
||||
} else {
|
||||
// DoIMConfirm();
|
||||
|
||||
// make sure the cursor becomes visible
|
||||
fCursorState = 0;
|
||||
_InvalidateTextRect(fCursor.x, fCursor.y, fCursor.x, fCursor.y);
|
||||
delete fCursorBlinkRunner;
|
||||
fCursorBlinkRunner = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1162,6 +1141,8 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
|
||||
currentMessage->FindInt32("key", &key);
|
||||
currentMessage->FindInt32("raw_char", &rawChar);
|
||||
|
||||
_ActivateCursor(true);
|
||||
|
||||
// Terminal filters RET, ENTER, F1...F12, and ARROW key code.
|
||||
// TODO: Cleanup
|
||||
if (numBytes == 1) {
|
||||
@ -1441,7 +1422,7 @@ TermView::MessageReceived(BMessage *msg)
|
||||
// }
|
||||
// }
|
||||
case kBlinkCursor:
|
||||
BlinkCursor();
|
||||
_BlinkCursor();
|
||||
break;
|
||||
case kUpdateSigWinch:
|
||||
_UpdateSIGWINCH();
|
||||
@ -1738,6 +1719,7 @@ TermView::_SynchronizeWithTextBuffer(int32 visibleDirtyTop,
|
||||
_InvalidateTextRect(fCursor.x, fCursor.y, fCursor.x, fCursor.y);
|
||||
fCursor = cursor;
|
||||
_InvalidateTextRect(fCursor.x, fCursor.y, fCursor.x, fCursor.y);
|
||||
_ActivateCursor(false);
|
||||
}
|
||||
|
||||
info.Reset();
|
||||
|
@ -70,11 +70,6 @@ public:
|
||||
void SelectAll();
|
||||
void Clear();
|
||||
|
||||
// Cursor setting
|
||||
void BlinkCursor();
|
||||
void SetCurDraw(bool flag);
|
||||
void SetCurBlinking(bool flag);
|
||||
|
||||
// Other
|
||||
void GetFrameSize(float *width, float *height);
|
||||
bool Find(const BString &str, bool forwardSearch, bool matchCase, bool matchWord);
|
||||
@ -126,6 +121,10 @@ private:
|
||||
void _DrawCursor();
|
||||
void _InvalidateTextRange(TermPos start, TermPos end);
|
||||
|
||||
bool _IsCursorVisible() const;
|
||||
void _BlinkCursor();
|
||||
void _ActivateCursor(bool invalidate);
|
||||
|
||||
void _DoPrint(BRect updateRect);
|
||||
void _UpdateScrollBarRange();
|
||||
void _DoFileDrop(entry_ref &ref);
|
||||
@ -185,11 +184,8 @@ private:
|
||||
bool fFrameResized;
|
||||
|
||||
// Cursor Blinking, draw flag.
|
||||
bigtime_t fLastCursorTime;
|
||||
bool fCursorDrawFlag;
|
||||
bool fCursorStatus;
|
||||
bool fCursorBlinkingFlag;
|
||||
bool fCursorRedrawFlag;
|
||||
bigtime_t fLastActivityTime;
|
||||
int32 fCursorState;
|
||||
int fCursorHeight;
|
||||
|
||||
// Cursor position.
|
||||
|
62
src/apps/terminal/TerminalLine.h
Normal file
62
src/apps/terminal/TerminalLine.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TERMINAL_LINE_H
|
||||
#define TERMINAL_LINE_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "UTF8Char.h"
|
||||
|
||||
|
||||
struct TerminalCell {
|
||||
UTF8Char character;
|
||||
uint16 attributes;
|
||||
};
|
||||
|
||||
|
||||
struct TerminalLine {
|
||||
int16 length;
|
||||
bool softBreak; // soft line break
|
||||
TerminalCell cells[1];
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
length = 0;
|
||||
softBreak = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct AttributesRun {
|
||||
uint16 attributes;
|
||||
uint16 offset; // character offset
|
||||
uint16 length; // length of the run in characters
|
||||
};
|
||||
|
||||
|
||||
struct HistoryLine {
|
||||
AttributesRun* attributesRuns;
|
||||
uint16 attributesRunCount; // number of attribute runs
|
||||
uint16 byteLength : 15; // number of bytes in the line
|
||||
bool softBreak : 1; // soft line break;
|
||||
|
||||
AttributesRun* AttributesRuns() const
|
||||
{
|
||||
return attributesRuns;
|
||||
}
|
||||
|
||||
char* Chars() const
|
||||
{
|
||||
return (char*)(attributesRuns + attributesRunCount);
|
||||
}
|
||||
|
||||
int32 BufferSize() const
|
||||
{
|
||||
return attributesRunCount * sizeof(AttributesRun) + byteLength;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // TERMINAL_LINE_H
|
@ -55,6 +55,12 @@ struct UTF8Char {
|
||||
return ByteCount(bytes[0]);
|
||||
}
|
||||
|
||||
bool IsFullWidth() const
|
||||
{
|
||||
// TODO: Implement!
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsSpace() const
|
||||
{
|
||||
// TODO: Support multi-byte chars!
|
||||
|
Loading…
Reference in New Issue
Block a user