Terminal changes. This is still work in progress, some features
are disabled, lots of commented debug code is still in there, and quite a bit of cleanup is needed, but basically things work at least as well as before with several improvements: * Changed TerminalBuffer from an interface to a complete implementation. Removed all related code from TermView. Removed the now obsolete TermBuffer. TermParse uses TerminalBuffer instead of TermView, and TerminalBuffer asynchronously notifies TermView. This avoids potential deadlocks, fixing #1918. It also speeds up tty-output-bound programs. E.g. a "seq 10000" is about twice at fast with the default terminal size in my setup, now. It's still horribly slow compared to e.g. Konsole, though. * Replaced CurPos by a more compact and fully inline class TermPos. * Removed the offset feature (that insets the used text area) from TermView, thus simplifying the code. Instead put the view into a new parent view which provides the insets. This also fixes artifacts that could sometimes be observed in the insets area. * Scrolling related changes: - When scrolling fully down, the (80x25 or whatever) terminal screen is seen. It is not possible to scroll below the screen as in Be's Terminal. Scrolling in Haiku's Terminal was weirdly broken in this respect. As a side effect this fixes #2070. - When not scrolled fully down, further output won't cause any scrolling. It is thus possible to read earlier output while something is still going on. Fixes #1772. - Particularly to avoid unnecessary scrolling in the not scrolled fully down case, TermView no longer actually scrolls. It only sets an internal offset and manually uses CopyBits() as needed. Introduced a (hacky) BScrollView subclass using a BScrollBar subclass to make that possible. * Selection related changes: - Double/triple click plus dragging allows for selecting multiple words/lines. - Word selection no longer selects ranges of non-space characters. Instead it knows that words are made of alpha numerical chars and a certain set of other chars, and selects a range of commonly classified characters (word chars, non-word non-whitespace chars, whitespace chars). The non-alpha-num word characters should be made user-settable. Due to missing multi-byte character classification multi-byte whitespace is not recognized. - Beyond the end of the line there no longer are invisible spaces. Trying to select the region selects the end of the line (i.e. line break). This is similar to how Konsole and xterm work. - Added auto-scrolling when selecting with the mouse. Formerly the Terminal scrolled only while moving the mouse. The scroll speed might need some fine-tuning. - Don't know what change exactly did that (likely the switch to non-end-inclusive text ranges used internally), but the occasional selection artifacts are gone. * Resizing the terminal window re-wraps soft-wrapped lines. * The find functionality seemed to be completely broken. At least it never found anything for me. Should work now, though multi-byte characters are not matched correctly in case-insensitive mode. Regressions: * Printing is disabled. * Cursor blinking is disabled. Do we want it anyway? * In several cases full-width characters are not handled correctly (in more cases than before). * Shrinking the terminal width doesn't work very well with "less" (and probably other full-screen terminal apps), due to line re-wrapping. "less" expects them to be truncated only. When supporting an alternate screen buffer re-wrapping should be disabled for it, which should solve the problem. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25881 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,4 +26,5 @@ class CodeConv {
|
||||
static unsigned short UTF8toUnicode(const char *utf8);
|
||||
};
|
||||
|
||||
|
||||
#endif /* CODECONV_H */
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2005, Haiku, Inc.
|
||||
* Copyright (c) 2003-4 Kian Duffy <[email protected]>
|
||||
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Kian Duffy <[email protected]>
|
||||
*/
|
||||
#include "CurPos.h"
|
||||
|
||||
CurPos::CurPos()
|
||||
{
|
||||
}
|
||||
|
||||
CurPos::CurPos(int32 X, int32 Y)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
|
||||
CurPos::CurPos(const CurPos& cp)
|
||||
{
|
||||
x = cp.x;
|
||||
y = cp.y;
|
||||
}
|
||||
|
||||
CurPos &
|
||||
CurPos::operator=(const CurPos& from)
|
||||
{
|
||||
x = from.x;
|
||||
y = from.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
CurPos::Set(int32 X, int32 Y)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
|
||||
bool
|
||||
CurPos::operator!=(const CurPos& from) const
|
||||
{
|
||||
return ((x != from.x) || (y != from.y));
|
||||
}
|
||||
|
||||
bool
|
||||
CurPos::operator==(const CurPos& from) const
|
||||
{
|
||||
return ((x == from.x) && (y == from.y));
|
||||
}
|
||||
|
||||
CurPos
|
||||
CurPos::operator+(const CurPos& from) const
|
||||
{
|
||||
return CurPos(x + from.x, y + from.y);
|
||||
}
|
||||
|
||||
CurPos
|
||||
CurPos::operator- (const CurPos& from) const
|
||||
{
|
||||
return CurPos(x - from.x, y - from.y);
|
||||
}
|
||||
|
||||
bool
|
||||
CurPos::operator> (const CurPos& from) const
|
||||
{
|
||||
if (y > from.y)
|
||||
return true;
|
||||
else
|
||||
if (y == from.y && x > from.x)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CurPos::operator>= (const CurPos& from) const
|
||||
{
|
||||
if (y > from.y)
|
||||
return true;
|
||||
else
|
||||
if (y == from.y && x >= from.x)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CurPos::operator< (const CurPos& from) const
|
||||
{
|
||||
if (y < from.y)
|
||||
return true;
|
||||
else
|
||||
if (y == from.y && x < from.x)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CurPos::operator<= (const CurPos& from) const
|
||||
{
|
||||
if (y < from.y)
|
||||
return true;
|
||||
else
|
||||
if (y == from.y && x <= from.x)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2005, Haiku, Inc.
|
||||
* Copyright (c) 2003-4 Kian Duffy <[email protected]>
|
||||
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Kian Duffy <[email protected]>
|
||||
*/
|
||||
#ifndef CURPOS_H_INCLUDED
|
||||
#define CURPOS_H_INCLUDED
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class CurPos
|
||||
{
|
||||
public:
|
||||
CurPos();
|
||||
CurPos(int32 X, int32 Y);
|
||||
CurPos(const CurPos& cp);
|
||||
|
||||
void Set(int32 X, int32 Y);
|
||||
|
||||
CurPos &operator= (const CurPos &from);
|
||||
CurPos operator+ (const CurPos&) const;
|
||||
CurPos operator- (const CurPos&) const;
|
||||
bool operator!= (const CurPos&) const;
|
||||
bool operator== (const CurPos&) const;
|
||||
bool operator> (const CurPos&) const;
|
||||
bool operator>= (const CurPos&) const;
|
||||
bool operator< (const CurPos&) const;
|
||||
bool operator<= (const CurPos&) const;
|
||||
|
||||
int32 x;
|
||||
int32 y;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,6 @@ Application Terminal :
|
||||
Arguments.cpp
|
||||
CodeConv.cpp
|
||||
Coding.cpp
|
||||
CurPos.cpp
|
||||
FindWindow.cpp
|
||||
MenuUtil.cpp
|
||||
Terminal.cpp
|
||||
@@ -19,9 +18,10 @@ Application Terminal :
|
||||
Shell.cpp
|
||||
SmartTabView.cpp
|
||||
TermApp.cpp
|
||||
TermBuffer.cpp
|
||||
TerminalBuffer.cpp
|
||||
TerminalCharClassifier.cpp
|
||||
TermParse.cpp
|
||||
TermScrollView.cpp
|
||||
TermView.cpp
|
||||
TermWindow.cpp
|
||||
TTextControl.cpp
|
||||
|
||||
@@ -234,7 +234,7 @@ Shell::ViewAttached(TermView *view)
|
||||
if (fAttached)
|
||||
return;
|
||||
|
||||
status_t status = fTermParse->StartThreads(view);
|
||||
status_t status = fTermParse->StartThreads(view->TextBuffer());
|
||||
if (status < B_OK) {
|
||||
// TODO: What can we do here ?
|
||||
fprintf(stderr, "Shell:ViewAttached():"
|
||||
|
||||
@@ -1,550 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2006, Haiku, Inc.
|
||||
* Copyright (c) 2003-4 Kian Duffy <[email protected]>
|
||||
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Kian Duffy <[email protected]>
|
||||
*/
|
||||
|
||||
/************************************************************************
|
||||
MuTerminal Internal Buffer Format.
|
||||
|
||||
a. 4bytes character buffer.
|
||||
|
||||
3bytes character buffer (UTF8).
|
||||
1byte status buffer.
|
||||
|
||||
b. 2bytes extended buffer.
|
||||
|
||||
2byte attribute buffer.
|
||||
|
||||
< attribute buffer> <------- character buffer -------->
|
||||
WBURMfbF rrfffbbb / ssssssss 11111111 22222222 33333333
|
||||
|||||||| || | | | | | |
|
||||
|||||||| || | | status utf8 1st utf8 2nd utf8 3rd
|
||||
|||||||| || | |
|
||||
|||||||| || | \--> background color
|
||||
|||||||| || \-----> foreground color
|
||||
|||||||| |\-------> dumped CR
|
||||
|||||||| \--------> Reserve
|
||||
||||||||
|
||||
||||||||
|
||||
|||||||\----------> Font information (Not use)
|
||||
||||||\-----------> background color flag
|
||||
|||||\------------> foreground color flag
|
||||
||||\-------------> mouse selected
|
||||
|||\--------------> reverse attr
|
||||
||\---------------> underline attr
|
||||
|\----------------> bold attr
|
||||
\-----------------> character width
|
||||
|
||||
c. 2byte status buffer.
|
||||
|
||||
0x00 (A_CHAR): character available.
|
||||
0x01 (NO_CHAR): buffer is empty.
|
||||
0xFF (IN_STRING): before buffer is full width character (never draw).
|
||||
|
||||
**Language environment. (Not impliment)
|
||||
|
||||
--- half width character set ---
|
||||
0 ... Western (Latin1 / ISO-8859-1, MacRoman)
|
||||
1 ... Central European(Latin2 / ISO-8859-2)
|
||||
2 ... Turkish (Latin3 / ISO-8859-3)
|
||||
3 ... Baltic (Latin4 / ISO-8859-4)
|
||||
4 ... Cyrillic (Cyrillic / ISO-8859-5)
|
||||
5 ... Greek (Greek / ISO-8859-7)
|
||||
6 ... Trukish (Latin5 / ISO-8859-9)
|
||||
|
||||
--- full width character set ---
|
||||
7 ... Japanese (EUC, SJIS, ISO-2022-jp / JIS X 0201, 0208, 0212)
|
||||
8 ... Chinese (Big5, EUC-tw, ISO-2022-cn / GB2312, CNS-11643-1...7)
|
||||
9 ... Korean (EUC-kr, ISO-2022-kr / KS C 5601)
|
||||
|
||||
--- Universal character set ---
|
||||
10 ... Unicode (UTF8)
|
||||
|
||||
* Variables is set CodeConv class.
|
||||
* Unicode character width sets CodeConv::UTF8FontWidth member.
|
||||
|
||||
JIS X 0201 (half width kana ideograph) character use 1 column,
|
||||
but it font is full width font on preference panel.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#include "TermBuffer.h"
|
||||
|
||||
#include "CurPos.h"
|
||||
#include "TermConst.h"
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define ROW(x) (((x) + fRowOffset) % fBufferSize)
|
||||
|
||||
|
||||
TermBuffer::TermBuffer(int rows, int cols, int bufferSize)
|
||||
{
|
||||
if (rows < 1)
|
||||
rows = 1;
|
||||
if (cols < MIN_COLS)
|
||||
cols = MIN_COLS;
|
||||
else if (cols > MAX_COLS)
|
||||
cols = MAX_COLS;
|
||||
|
||||
fColumnSize = MAX_COLS;
|
||||
fCurrentColumnSize = cols;
|
||||
fRowSize = rows;
|
||||
|
||||
fRowOffset = 0;
|
||||
|
||||
fSelStart.Set(-1,-1);
|
||||
fSelEnd.Set(-1,-1);
|
||||
|
||||
fBufferSize = bufferSize;
|
||||
if (fBufferSize < 1000)
|
||||
fBufferSize = 1000;
|
||||
|
||||
// Allocate buffer
|
||||
fBuffer = (term_buffer**)malloc(sizeof(term_buffer*) * fBufferSize);
|
||||
|
||||
for (int i = 0; i < fBufferSize; i++) {
|
||||
fBuffer[i] = (term_buffer *)calloc(fColumnSize + 1, sizeof(term_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TermBuffer::~TermBuffer()
|
||||
{
|
||||
for (int i = 0; i < fBufferSize; i++) {
|
||||
free(fBuffer[i]);
|
||||
}
|
||||
|
||||
free(fBuffer);
|
||||
}
|
||||
|
||||
|
||||
//! Gets a character from TermBuffer
|
||||
int
|
||||
TermBuffer::GetChar(int row, int col, uchar *buf, ushort *attr)
|
||||
{
|
||||
if (row < 0 || col < 0)
|
||||
return -1;
|
||||
|
||||
term_buffer *ptr = (fBuffer[row % fBufferSize] + col);
|
||||
|
||||
if (ptr->status == A_CHAR)
|
||||
memcpy(buf, (char *)(ptr->code), 4);
|
||||
|
||||
*attr = ptr->attr;
|
||||
|
||||
return ptr->status;
|
||||
}
|
||||
|
||||
|
||||
//! Get a string (length = num) from given position.
|
||||
int
|
||||
TermBuffer::GetString(int row, int col, int num, uchar *buf,
|
||||
ushort *attr)
|
||||
{
|
||||
int count = 0, all_count = 0;
|
||||
term_buffer *ptr;
|
||||
|
||||
ptr = (fBuffer[row % fBufferSize]);
|
||||
ptr += col;
|
||||
*attr = ptr->attr;
|
||||
|
||||
if (ptr->status == NO_CHAR) {
|
||||
// Buffer is empty and No selected by mouse.
|
||||
do {
|
||||
if (col >= fCurrentColumnSize)
|
||||
return -1;
|
||||
|
||||
col++;
|
||||
ptr++;
|
||||
count--;
|
||||
if (ptr->status == A_CHAR)
|
||||
return count;
|
||||
|
||||
if (fSelStart.y == row) {
|
||||
if (col == fSelStart.x)
|
||||
return count;
|
||||
}
|
||||
|
||||
if (fSelEnd.y == row) {
|
||||
if (col - 1 == fSelEnd.x)
|
||||
return count;
|
||||
}
|
||||
} while (col <= num);
|
||||
|
||||
return count;
|
||||
} else if (IS_WIDTH(ptr->attr)) {
|
||||
memcpy(buf, (char *)ptr->code, 4);
|
||||
return 2;
|
||||
}
|
||||
|
||||
while (col <= num) {
|
||||
memcpy(buf, ptr->code, 4);
|
||||
all_count++;
|
||||
|
||||
if (*buf == 0) {
|
||||
*buf = ' ';
|
||||
*(buf + 1) = '\0';
|
||||
}
|
||||
if (ptr->attr != (ptr + 1)->attr)
|
||||
return all_count;
|
||||
|
||||
buf += strlen((char *)buf);
|
||||
ptr++;
|
||||
col++;
|
||||
|
||||
if (fSelStart.y == row) {
|
||||
if (col == fSelStart.x)
|
||||
return all_count;
|
||||
}
|
||||
if (fSelEnd.y == row) {
|
||||
if (col - 1 == fSelEnd.x)
|
||||
return all_count;
|
||||
}
|
||||
}
|
||||
|
||||
return all_count;
|
||||
}
|
||||
|
||||
|
||||
//! Write a character at the cursor point.
|
||||
void
|
||||
TermBuffer::WriteChar(const CurPos &pos, const uchar *u, ushort attr)
|
||||
{
|
||||
const int row = pos.y;
|
||||
const int col = pos.x;
|
||||
|
||||
term_buffer *ptr = (fBuffer[ROW(row)] + col);
|
||||
memcpy ((char *)ptr->code, u, 4);
|
||||
|
||||
if (IS_WIDTH(attr))
|
||||
(ptr + 1)->status = IN_STRING;
|
||||
|
||||
ptr->status = A_CHAR;
|
||||
ptr->attr = attr;
|
||||
}
|
||||
|
||||
|
||||
//! Write CR status to buffer attribute.
|
||||
void
|
||||
TermBuffer::WriteCR(const CurPos &pos)
|
||||
{
|
||||
int row = pos.y;
|
||||
int col = pos.x;
|
||||
|
||||
term_buffer *ptr = (fBuffer[ROW(row)] + col);
|
||||
ptr->attr |= DUMPCR;
|
||||
}
|
||||
|
||||
|
||||
//! Insert 'num' spaces at cursor point.
|
||||
void
|
||||
TermBuffer::InsertSpace(const CurPos &pos, int num)
|
||||
{
|
||||
const int row = pos.y;
|
||||
const int col = pos.x;
|
||||
|
||||
for (int i = fCurrentColumnSize - num; i >= col; i--) {
|
||||
*(fBuffer[ROW(row)] + i + num) = *(fBuffer[ROW(row)] + i);
|
||||
}
|
||||
|
||||
memset(fBuffer[ROW(row)] + col, 0, num * sizeof(term_buffer));
|
||||
}
|
||||
|
||||
|
||||
//! Delete 'num' characters at cursor point.
|
||||
void
|
||||
TermBuffer::DeleteChar(const CurPos &pos, int num)
|
||||
{
|
||||
const int row = pos.y;
|
||||
const int col = pos.x;
|
||||
|
||||
term_buffer *ptr = fBuffer[ROW(row)];
|
||||
size_t movesize = fCurrentColumnSize - (col + num);
|
||||
|
||||
memmove(ptr + col, ptr + col + num, movesize * sizeof(term_buffer));
|
||||
memset(ptr + (fCurrentColumnSize - num), 0, num * sizeof(term_buffer));
|
||||
}
|
||||
|
||||
|
||||
//! Erase characters below cursor position.
|
||||
void
|
||||
TermBuffer::EraseBelow(const CurPos &pos)
|
||||
{
|
||||
const int row = pos.y;
|
||||
const int col = pos.x;
|
||||
|
||||
memset(fBuffer[ROW(row)] + col, 0, (fColumnSize - col ) * sizeof(term_buffer));
|
||||
|
||||
for (int i = row; i < fRowSize; i++) {
|
||||
_EraseLine(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Scroll the terminal buffer region
|
||||
void
|
||||
TermBuffer::ScrollRegion(int top, int bot, int dir, int num)
|
||||
{
|
||||
if (dir == SCRUP) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
term_buffer *ptr = fBuffer[ROW(top)];
|
||||
|
||||
for (int j = top; j < bot; j++) {
|
||||
fBuffer[ROW(j)] = fBuffer[ROW(j+1)];
|
||||
}
|
||||
|
||||
fBuffer[ROW(bot)] = ptr;
|
||||
_EraseLine(bot);
|
||||
}
|
||||
} else {
|
||||
// scroll up
|
||||
for (int i = 0; i < num; i++) {
|
||||
term_buffer *ptr = fBuffer[ROW(bot)];
|
||||
|
||||
for (int j = bot; j > top; j--) {
|
||||
fBuffer[ROW(j)] = fBuffer[ROW(j-1)];
|
||||
}
|
||||
|
||||
fBuffer[ROW(top)] = ptr;
|
||||
_EraseLine(top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Scroll the terminal buffer.
|
||||
void
|
||||
TermBuffer::ScrollLine()
|
||||
{
|
||||
for (int i = fRowSize; i < fRowSize * 2; i++) {
|
||||
_EraseLine(i);
|
||||
}
|
||||
|
||||
fRowOffset++;
|
||||
}
|
||||
|
||||
|
||||
//! Resize the terminal buffer.
|
||||
void
|
||||
TermBuffer::ResizeTo(int newRows, int newCols, int offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
// make sure the new size is within the allowed limits
|
||||
if (newRows < 1)
|
||||
newRows = 1;
|
||||
|
||||
if (newCols < MIN_COLS)
|
||||
newCols = MIN_COLS;
|
||||
else if (newCols > MAX_COLS)
|
||||
newCols = MAX_COLS;
|
||||
|
||||
if (newRows <= fRowSize) {
|
||||
for (i = newRows; i <= fRowSize; i++)
|
||||
_EraseLine(i);
|
||||
} else {
|
||||
for (i = fRowSize; i <= newRows * 2; i++)
|
||||
_EraseLine(i);
|
||||
}
|
||||
|
||||
fCurrentColumnSize = newCols;
|
||||
fRowOffset += offset;
|
||||
fRowSize = newRows;
|
||||
}
|
||||
|
||||
|
||||
//! Get the buffer's size.
|
||||
int32
|
||||
TermBuffer::Size() const
|
||||
{
|
||||
return fBufferSize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermBuffer::_EraseLine(int row)
|
||||
{
|
||||
memset(fBuffer[ROW(row)], 0, fColumnSize * sizeof(term_buffer));
|
||||
}
|
||||
|
||||
|
||||
//! Clear the contents of the TermBuffer.
|
||||
void
|
||||
TermBuffer::Clear()
|
||||
{
|
||||
for (int i = 0; i < fBufferSize; i++) {
|
||||
memset(fBuffer[i], 0, fColumnSize * sizeof(term_buffer));
|
||||
}
|
||||
|
||||
fRowOffset = 0;
|
||||
DeSelect();
|
||||
}
|
||||
|
||||
|
||||
//! Mark text in the given range as selected
|
||||
void
|
||||
TermBuffer::Select(const CurPos &start, const CurPos &end)
|
||||
{
|
||||
if (end < start) {
|
||||
fSelStart = end;
|
||||
fSelEnd = start;
|
||||
} else {
|
||||
fSelStart = start;
|
||||
fSelEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Mark text in the given range as not selected
|
||||
void
|
||||
TermBuffer::DeSelect()
|
||||
{
|
||||
fSelStart.Set(-1, -1);
|
||||
fSelEnd.Set(-1, -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
TermBuffer::FindWord(const CurPos &pos, CurPos *start, CurPos *end)
|
||||
{
|
||||
uchar buf[5];
|
||||
ushort attr;
|
||||
int x, y, start_x;
|
||||
|
||||
y = pos.y;
|
||||
|
||||
// Search start point
|
||||
for (x = pos.x - 1; x >= 0; x--) {
|
||||
if (GetChar(y, x, buf, &attr) == NO_CHAR || *buf == ' ') {
|
||||
++x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
start_x = x;
|
||||
|
||||
// Search end point
|
||||
for (x = pos.x; x < fColumnSize; x++) {
|
||||
if (GetChar(y, x, buf, &attr) == NO_CHAR || *buf == ' ') {
|
||||
--x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start_x > x)
|
||||
return false;
|
||||
|
||||
if (start != NULL)
|
||||
start->Set(start_x, y);
|
||||
|
||||
if (end != NULL)
|
||||
end->Set(x, y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Get one character from the selected region.
|
||||
void
|
||||
TermBuffer::GetCharFromRegion(int x, int y, BString &str)
|
||||
{
|
||||
uchar buf[5];
|
||||
ushort attr;
|
||||
int status;
|
||||
|
||||
status = GetChar(y, x, buf, &attr);
|
||||
|
||||
switch (status) {
|
||||
case NO_CHAR:
|
||||
if (IS_CR (attr))
|
||||
str += '\n';
|
||||
else
|
||||
str += ' ';
|
||||
break;
|
||||
|
||||
case IN_STRING:
|
||||
break;
|
||||
|
||||
default:
|
||||
str += (const char *)&buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Delete useless char at end of line and convert LF code.
|
||||
/* static */
|
||||
inline void
|
||||
TermBuffer::AvoidWaste(BString &str)
|
||||
{
|
||||
// TODO: Remove the goto
|
||||
|
||||
int32 len, point;
|
||||
|
||||
start:
|
||||
len = str.Length() - 1;
|
||||
point = str.FindLast (' ');
|
||||
|
||||
if (len > 0 && len == point) {
|
||||
str.RemoveLast (" ");
|
||||
goto start;
|
||||
}
|
||||
// str += '\n';
|
||||
}
|
||||
|
||||
|
||||
//! Get a string from the given region.
|
||||
void
|
||||
TermBuffer::GetStringFromRegion(BString &str, const CurPos &start, const CurPos &end)
|
||||
{
|
||||
int y;
|
||||
|
||||
if (start.y == end.y) {
|
||||
y = start.y;
|
||||
for (int x = start.x ; x <= end.x; x++) {
|
||||
GetCharFromRegion(x, y, str);
|
||||
}
|
||||
} else {
|
||||
y = start.y;
|
||||
for (int x = start.x ; x < fCurrentColumnSize; x++) {
|
||||
GetCharFromRegion(x, y, str);
|
||||
}
|
||||
AvoidWaste(str);
|
||||
|
||||
for (y = start.y + 1 ; y < end.y; y++) {
|
||||
for (int x = 0 ; x < fCurrentColumnSize; x++) {
|
||||
GetCharFromRegion(x, y, str);
|
||||
}
|
||||
AvoidWaste(str);
|
||||
}
|
||||
|
||||
y = end.y;
|
||||
for (int x = 0 ; x <= end.x; x++) {
|
||||
GetCharFromRegion(x, y, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Returns the complete internal buffer as a BString
|
||||
void
|
||||
TermBuffer::ToString(BString &str)
|
||||
{
|
||||
for (int y = 0; y < fRowSize; y++) {
|
||||
for (int x = 0; x < fCurrentColumnSize; x++) {
|
||||
GetCharFromRegion(x, y, str);
|
||||
}
|
||||
}
|
||||
AvoidWaste(str);
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-4 Kian Duffy <[email protected]>
|
||||
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files or portions
|
||||
* thereof (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice
|
||||
* in the binary, as well as this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided with
|
||||
* the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef _TERMBUFFER_H
|
||||
#define _TERMBUFFER_H
|
||||
|
||||
#include "CurPos.h"
|
||||
#include "TermConst.h"
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
struct term_buffer
|
||||
{
|
||||
uchar code[4];
|
||||
int16 attr;
|
||||
int16 status;
|
||||
};
|
||||
|
||||
|
||||
class CurPos;
|
||||
class BString;
|
||||
|
||||
class TermBuffer {
|
||||
public:
|
||||
TermBuffer(int row, int col, int bufferSize = 1000);
|
||||
~TermBuffer();
|
||||
|
||||
//
|
||||
// Get and Put charactor.
|
||||
//
|
||||
int GetChar(int row, int col, uchar *u, ushort *attr);
|
||||
int GetString(int row, int col, int num, uchar *u, ushort *attr);
|
||||
void GetStringFromRegion(BString ©Str, const CurPos &start, const CurPos &end);
|
||||
|
||||
void WriteChar(const CurPos &pos, const uchar *u, ushort attr);
|
||||
void WriteCR(const CurPos &pos);
|
||||
void InsertSpace(const CurPos &pos, int num);
|
||||
|
||||
//
|
||||
// Delete Character.
|
||||
//
|
||||
void DeleteChar(const CurPos &pos, int num);
|
||||
void EraseBelow(const CurPos &pos);
|
||||
|
||||
//
|
||||
// Movement and Scroll buffer.
|
||||
//
|
||||
void ScrollRegion(int top, int bot, int dir, int num);
|
||||
void ScrollLine();
|
||||
|
||||
//
|
||||
// Resize buffer.
|
||||
//
|
||||
void ResizeTo(int newRows, int newCols, int offset);
|
||||
|
||||
//
|
||||
// Clear contents of TermBuffer.
|
||||
//
|
||||
void Clear();
|
||||
|
||||
//
|
||||
// Selection Methods
|
||||
//
|
||||
void Select(const CurPos &start, const CurPos &end);
|
||||
void DeSelect();
|
||||
|
||||
const CurPos &GetSelectionStart() { return fSelStart; };
|
||||
const CurPos &GetSelectionEnd() { return fSelEnd; };
|
||||
|
||||
//
|
||||
// Other methods
|
||||
//
|
||||
bool FindWord(const CurPos &pos, CurPos *start, CurPos *end);
|
||||
|
||||
void GetCharFromRegion (int x, int y, BString &str);
|
||||
static void AvoidWaste (BString &str);
|
||||
|
||||
void ToString(BString &str);
|
||||
|
||||
int32 Size() const;
|
||||
|
||||
private:
|
||||
void _EraseLine(int line);
|
||||
|
||||
term_buffer **fBuffer;
|
||||
int fBufferSize;
|
||||
|
||||
int fColumnSize;
|
||||
int fRowSize;
|
||||
int fCurrentColumnSize;
|
||||
int fRowOffset;
|
||||
|
||||
CurPos fSelStart;
|
||||
CurPos fSelEnd;
|
||||
};
|
||||
|
||||
#endif // _TERMBUFFER_H
|
||||
@@ -83,6 +83,10 @@ const uint32 MSG_FONT_CHANGED = 'fntc';
|
||||
const uint32 SAVE_AS_DEFAULT = 'sadf';
|
||||
const uint32 MSG_CHECK_CHILDREN = 'ckch';
|
||||
|
||||
const uint32 MSG_TERMINAL_BUFFER_CHANGED = 'bufc';
|
||||
const uint32 MSG_SET_TERMNAL_TITLE = 'sett';
|
||||
const uint32 MSG_QUIT_TERMNAL = 'qutt';
|
||||
|
||||
// Preference Read/Write Keys
|
||||
const char* const PREF_HALF_FONT_FAMILY = "Half Font Family";
|
||||
const char* const PREF_HALF_FONT_STYLE = "Half Font Style";
|
||||
@@ -144,7 +148,7 @@ enum{
|
||||
|
||||
#define MIN_COLS 10
|
||||
#define MAX_COLS 256
|
||||
#define MIN_ROWS 1
|
||||
#define MIN_ROWS 10
|
||||
#define MAX_ROWS 256
|
||||
|
||||
// Insert mode flag
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Beep.h>
|
||||
#include <Message.h>
|
||||
|
||||
@@ -117,6 +118,7 @@ status_t
|
||||
TermParse::GetReaderBuf(uchar &c)
|
||||
{
|
||||
status_t status;
|
||||
#if 0
|
||||
do {
|
||||
status = acquire_sem_etc(fReaderSem, 1, B_TIMEOUT, 10000);
|
||||
} while (status == B_INTERRUPTED);
|
||||
@@ -127,17 +129,23 @@ TermParse::GetReaderBuf(uchar &c)
|
||||
|
||||
// Reset cursor blinking time and turn on cursor blinking.
|
||||
fBuffer->SetCurDraw(true);
|
||||
#endif
|
||||
|
||||
// wait new input from pty.
|
||||
fBuffer->Unlock();
|
||||
do {
|
||||
status = acquire_sem(fReaderSem);
|
||||
} while (status == B_INTERRUPTED);
|
||||
fBuffer->Lock();
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
#if 0
|
||||
} else if (status == B_OK) {
|
||||
// Do nothing
|
||||
} else
|
||||
return status;
|
||||
#endif
|
||||
|
||||
c = fReadBuffer[fBufferPosition % READ_BUF_SIZE];
|
||||
fBufferPosition++;
|
||||
@@ -147,7 +155,7 @@ TermParse::GetReaderBuf(uchar &c)
|
||||
release_sem(fReaderLocker);
|
||||
}
|
||||
|
||||
fBuffer->SetCurDraw(false);
|
||||
// fBuffer->SetCurDraw(false);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -343,6 +351,9 @@ TermParse::EscParse()
|
||||
int *parsestate = groundtable;
|
||||
|
||||
while (!fQuitting) {
|
||||
// TODO: Fix the locking!
|
||||
BAutolock locker(fBuffer);
|
||||
|
||||
uchar c;
|
||||
if (GetReaderBuf(c) < B_OK)
|
||||
break;
|
||||
@@ -383,6 +394,7 @@ TermParse::EscParse()
|
||||
now_coding = fBuffer->Encoding();
|
||||
}
|
||||
|
||||
//debug_printf("TermParse: char: '%c' (%d), parse state: %d\n", c, c, parsestate[c]);
|
||||
switch (parsestate[c]) {
|
||||
case CASE_PRINT:
|
||||
cbuf[0] = c;
|
||||
@@ -767,7 +779,7 @@ TermParse::EscParse()
|
||||
case CASE_CPR:
|
||||
// Q & D hack by Y.Hayakawa ([email protected])
|
||||
// 21-JUL-99
|
||||
fBuffer->DeviceStatusReport(param[0]);
|
||||
_DeviceStatusReport(param[0]);
|
||||
parsestate = groundtable;
|
||||
break;
|
||||
|
||||
@@ -975,3 +987,27 @@ TermParse::_escparse_thread(void *data)
|
||||
{
|
||||
return reinterpret_cast<TermParse *>(data)->EscParse();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermParse::_DeviceStatusReport(int n)
|
||||
{
|
||||
char sbuf[16] ;
|
||||
int len;
|
||||
|
||||
switch (n) {
|
||||
case 5:
|
||||
{
|
||||
const char* toWrite = "\033[0n";
|
||||
write(fFd, toWrite, strlen(toWrite));
|
||||
break ;
|
||||
}
|
||||
case 6:
|
||||
len = sprintf(sbuf, "\033[%ld;%ldR", fBuffer->Height(),
|
||||
fBuffer->Width()) ;
|
||||
write(fFd, sbuf, len);
|
||||
break ;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ private:
|
||||
|
||||
// Reading ReadBuf at one Char.
|
||||
status_t GetReaderBuf(uchar &c);
|
||||
|
||||
|
||||
void _DeviceStatusReport(int n);
|
||||
|
||||
int fFd;
|
||||
|
||||
thread_id fParseThread;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TERM_POS_H
|
||||
#define TERM_POS_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
class TermPos {
|
||||
public:
|
||||
int32 x;
|
||||
int32 y;
|
||||
|
||||
inline TermPos() : x(0), y(0) { }
|
||||
inline TermPos(int32 x, int32 y) : x(x), y(y) { }
|
||||
inline TermPos(const TermPos& other) : x(other.x), y(other.y) { }
|
||||
|
||||
inline void SetTo(int32 x, int32 y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
inline bool operator==(const TermPos& other) const
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
inline bool operator!=(const TermPos& other) const
|
||||
{
|
||||
return x != other.x || y != other.y;
|
||||
}
|
||||
|
||||
inline bool operator<=(const TermPos& other) const
|
||||
{
|
||||
return y < other.y || y == other.y && x <= other.x;
|
||||
}
|
||||
|
||||
inline bool operator>=(const TermPos& other) const
|
||||
{
|
||||
return other <= *this;
|
||||
}
|
||||
|
||||
inline bool operator<(const TermPos& other) const
|
||||
{
|
||||
return !(*this >= other);
|
||||
}
|
||||
|
||||
inline bool operator>(const TermPos& other) const
|
||||
{
|
||||
return !(*this <= other);
|
||||
}
|
||||
|
||||
inline TermPos& operator=(const TermPos& other)
|
||||
{
|
||||
x = other.x;
|
||||
y = other.y;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // TERM_POS_H
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
// NOTE: Nasty hack to get access to BScrollView's private parts.
|
||||
#include <ScrollBar.h>
|
||||
#define private protected
|
||||
#include <ScrollView.h>
|
||||
#undef private
|
||||
|
||||
#include "TermScrollView.h"
|
||||
|
||||
|
||||
class TermScrollBar : public BScrollBar {
|
||||
public:
|
||||
TermScrollBar(BRect frame, const char *name, BView *target,
|
||||
float min, float max, orientation direction)
|
||||
:
|
||||
BScrollBar(frame, name, target, min, max, direction)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ValueChanged(float newValue)
|
||||
{
|
||||
if (BView* target = Target())
|
||||
Target()->ScrollTo(0, newValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TermScrollView::TermScrollView(const char* name, BView* child, BView* target,
|
||||
uint32 resizingMode)
|
||||
:
|
||||
BScrollView(name, child, resizingMode, 0, false, true)
|
||||
{
|
||||
// replace the vertical scroll bar with our own
|
||||
if (fVerticalScrollBar != NULL) {
|
||||
BRect frame(fVerticalScrollBar->Frame());
|
||||
RemoveChild(fVerticalScrollBar);
|
||||
|
||||
TermScrollBar* scrollBar = new TermScrollBar(frame, "_VSB_", target, 0,
|
||||
1000, B_VERTICAL);
|
||||
AddChild(scrollBar);
|
||||
fVerticalScrollBar = scrollBar;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TermScrollView::~TermScrollView()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TERM_SCROLL_VIEW_H
|
||||
#define TERM_SCROLL_VIEW_H
|
||||
|
||||
#include <ScrollView.h>
|
||||
|
||||
|
||||
class TermScrollView : public BScrollView {
|
||||
public:
|
||||
TermScrollView(const char* name, BView* child,
|
||||
BView* target,
|
||||
uint32 resizingMode = B_FOLLOW_ALL);
|
||||
~TermScrollView();
|
||||
};
|
||||
|
||||
|
||||
#endif // TERM_SCROLL_VIEW_H
|
||||
+831
-1101
File diff suppressed because it is too large
Load Diff
@@ -12,12 +12,13 @@
|
||||
#ifndef TERMVIEW_H
|
||||
#define TERMVIEW_H
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Messenger.h>
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "CurPos.h"
|
||||
#include "TerminalBuffer.h"
|
||||
#include "TermPos.h"
|
||||
|
||||
|
||||
class BClipboard;
|
||||
@@ -27,7 +28,7 @@ class BString;
|
||||
class Shell;
|
||||
class TermBuffer;
|
||||
|
||||
class TermView : public BView, public TerminalBuffer {
|
||||
class TermView : public BView {
|
||||
public:
|
||||
TermView(BRect frame, int32 argc, const char **argv, int32 historySize = 1000);
|
||||
TermView(int rows, int columns, int32 argc, const char **argv, int32 historySize = 1000);
|
||||
@@ -40,6 +41,8 @@ public:
|
||||
virtual void GetPreferredSize(float *width, float *height);
|
||||
|
||||
const char *TerminalName() const;
|
||||
|
||||
inline TerminalBuffer* TextBuffer() const { return fTextBuffer; }
|
||||
|
||||
void GetTermFont(BFont *font) const;
|
||||
void SetTermFont(const BFont *font);
|
||||
@@ -67,52 +70,12 @@ public:
|
||||
void SelectAll();
|
||||
void Clear();
|
||||
|
||||
// Output Charactor
|
||||
void Insert(uchar *string, ushort attr);
|
||||
void InsertCR();
|
||||
void InsertLF();
|
||||
void InsertNewLine(int num);
|
||||
void SetInsertMode(int flag);
|
||||
void InsertSpace(int num);
|
||||
|
||||
// Delete Charactor
|
||||
void EraseBelow();
|
||||
void DeleteChar(int num);
|
||||
void DeleteColumns();
|
||||
void DeleteLine(int num);
|
||||
|
||||
// Get and Set Cursor position
|
||||
void SetCurPos(int x, int y);
|
||||
void SetCurX(int x);
|
||||
void SetCurY(int y);
|
||||
void GetCurPos(CurPos *inCurPos);
|
||||
int GetCurX();
|
||||
int GetCurY();
|
||||
void SaveCursor();
|
||||
void RestoreCursor();
|
||||
|
||||
// Move Cursor
|
||||
void MoveCurRight(int num);
|
||||
void MoveCurLeft(int num);
|
||||
void MoveCurUp(int num);
|
||||
void MoveCurDown(int num);
|
||||
|
||||
// Cursor setting
|
||||
void DrawCursor();
|
||||
void BlinkCursor();
|
||||
void SetCurDraw(bool flag);
|
||||
void SetCurBlinking(bool flag);
|
||||
|
||||
// Scroll region
|
||||
void ScrollRegion(int top, int bot, int dir, int num);
|
||||
void SetScrollRegion(int top, int bot);
|
||||
void ScrollAtCursor();
|
||||
|
||||
// Other
|
||||
void DeviceStatusReport(int);
|
||||
void UpdateLine();
|
||||
void ScrollScreen();
|
||||
void ScrollScreenDraw();
|
||||
void GetFrameSize(float *width, float *height);
|
||||
bool Find(const BString &str, bool forwardSearch, bool matchCase, bool matchWord);
|
||||
void GetSelection(BString &str);
|
||||
@@ -135,12 +98,22 @@ protected:
|
||||
virtual void FrameResized(float width, float height);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
virtual void ScrollTo(BPoint where);
|
||||
|
||||
virtual status_t GetSupportedSuites(BMessage *msg);
|
||||
virtual BHandler* ResolveSpecifier(BMessage *msg, int32 index,
|
||||
BMessage *specifier, int32 form,
|
||||
const char *property);
|
||||
|
||||
private:
|
||||
// point and text offset conversion
|
||||
inline int32 _LineAt(float y);
|
||||
inline float _LineOffset(int32 index);
|
||||
inline TermPos _ConvertToTerminal(const BPoint &p);
|
||||
inline BPoint _ConvertFromTerminal(const TermPos &pos);
|
||||
|
||||
inline void _InvalidateTextRect(int32 x1, int32 y1, int32 x2, int32 y2);
|
||||
|
||||
status_t _InitObject(int32 argc, const char **argv);
|
||||
|
||||
status_t _AttachShell(Shell *shell);
|
||||
@@ -148,17 +121,18 @@ private:
|
||||
|
||||
void _AboutRequested();
|
||||
|
||||
void _DrawLines(int , int, ushort, uchar *, int, int, int, BView *);
|
||||
int _TermDraw(const CurPos &start, const CurPos &end);
|
||||
int _TermDrawRegion(CurPos start, CurPos end);
|
||||
int _TermDrawSelectedRegion(CurPos start, CurPos end);
|
||||
inline void _Redraw(int, int, int, int);
|
||||
void _DrawLinePart(int32 x1, int32 y1, uint16 attr, char *buf,
|
||||
int32 width, bool mouse, bool cursor, BView *inView);
|
||||
void _DrawCursor();
|
||||
void _InvalidateTextRange(TermPos start, TermPos end);
|
||||
|
||||
void _DoPrint(BRect updateRect);
|
||||
void _ResizeScrBarRange(void);
|
||||
void _UpdateScrollBarRange();
|
||||
void _DoFileDrop(entry_ref &ref);
|
||||
|
||||
void _WritePTY(const uchar *text, int num_byteses);
|
||||
void _SynchronizeWithTextBuffer(BRect* invalidateWhenScrolling);
|
||||
|
||||
void _WritePTY(const char* text, int32 numBytes);
|
||||
|
||||
// Comunicate Input Method
|
||||
// void _DoIMStart (BMessage* message);
|
||||
@@ -168,33 +142,36 @@ private:
|
||||
// void _DoIMConfirm (void);
|
||||
// void _ConfirmString(const char *, int32);
|
||||
|
||||
// Mouse select
|
||||
void _Select(CurPos start, CurPos end);
|
||||
void _AddSelectRegion(CurPos);
|
||||
void _ResizeSelectRegion(CurPos);
|
||||
|
||||
void _DeSelect();
|
||||
// selection
|
||||
void _Select(TermPos start, TermPos end, bool inclusive,
|
||||
bool setInitialSelection);
|
||||
void _ExtendSelection(TermPos, bool inclusive, bool useInitialSelection);
|
||||
void _Deselect();
|
||||
bool _HasSelection() const;
|
||||
void _SelectWord(BPoint where, bool extend, bool useInitialSelection);
|
||||
void _SelectLine(BPoint where, bool extend, bool useInitialSelection);
|
||||
|
||||
// select word function
|
||||
void _SelectWord(BPoint where, int mod);
|
||||
void _SelectLine(BPoint where, int mod);
|
||||
void _AutoScrollUpdate();
|
||||
|
||||
// point and text offset conversion.
|
||||
CurPos _ConvertToTerminal(const BPoint &p);
|
||||
BPoint _ConvertFromTerminal(const CurPos &pos);
|
||||
bool _CheckSelectedRegion(const TermPos &pos) const;
|
||||
bool _CheckSelectedRegion(int32 row, int32 firstColumn,
|
||||
int32& lastColumn) const;
|
||||
|
||||
bool _CheckSelectedRegion(const CurPos &pos);
|
||||
|
||||
void _UpdateSIGWINCH();
|
||||
|
||||
static void _FixFontAttributes(BFont &font);
|
||||
|
||||
void _ScrollTo(float y, bool scrollGfx);
|
||||
void _ScrollToRange(TermPos start, TermPos end);
|
||||
|
||||
private:
|
||||
class CharClassifier;
|
||||
|
||||
Shell *fShell;
|
||||
|
||||
BMessageRunner *fWinchRunner;
|
||||
BMessageRunner *fCursorBlinkRunner;
|
||||
BMessageRunner *fAutoScrollRunner;
|
||||
|
||||
CharClassifier *fCharClassifier;
|
||||
|
||||
// Font and Width
|
||||
BFont fHalfFont;
|
||||
@@ -203,19 +180,7 @@ private:
|
||||
int fFontAscent;
|
||||
struct escapement_delta fEscapement;
|
||||
|
||||
// Flags
|
||||
|
||||
// Update flag (Set on Insert).
|
||||
bool fUpdateFlag;
|
||||
|
||||
// Terminal insertmode flag (use Insert).
|
||||
bool fInsertModeFlag;
|
||||
|
||||
// Scroll count, range.
|
||||
int fScrollUpCount;
|
||||
int fScrollBarRange;
|
||||
|
||||
// Frame Resized flag.
|
||||
// frame resized flag.
|
||||
bool fFrameResized;
|
||||
|
||||
// Cursor Blinking, draw flag.
|
||||
@@ -227,10 +192,7 @@ private:
|
||||
int fCursorHeight;
|
||||
|
||||
// Cursor position.
|
||||
CurPos fCurPos;
|
||||
CurPos fCurStack;
|
||||
|
||||
int fBufferStartPos;
|
||||
TermPos fCursor;
|
||||
|
||||
// Terminal rows and columns.
|
||||
int fTermRows;
|
||||
@@ -238,12 +200,9 @@ private:
|
||||
|
||||
int fEncoding;
|
||||
|
||||
// Terminal view pointer.
|
||||
int fTop;
|
||||
|
||||
// Object pointer.
|
||||
TermBuffer *fTextBuffer;
|
||||
BScrollBar *fScrollBar;
|
||||
TerminalBuffer *fTextBuffer;
|
||||
BScrollBar *fScrollBar;
|
||||
|
||||
// Color and Attribute.
|
||||
rgb_color fTextForeColor, fTextBackColor;
|
||||
@@ -251,22 +210,24 @@ private:
|
||||
rgb_color fSelectForeColor, fSelectBackColor;
|
||||
|
||||
// Scroll Region
|
||||
int fScrTop;
|
||||
int fScrBot;
|
||||
float fScrollOffset;
|
||||
int32 fScrBufSize;
|
||||
bool fScrRegionSet;
|
||||
// TODO: That's the history capacity -- only needed until the text
|
||||
// buffer is created.
|
||||
float fAutoScrollSpeed;
|
||||
|
||||
BPoint fClickPoint;
|
||||
|
||||
// view selection
|
||||
CurPos fSelStart;
|
||||
CurPos fSelEnd;
|
||||
// selection
|
||||
TermPos fSelStart;
|
||||
TermPos fSelEnd;
|
||||
TermPos fInitialSelectionStart;
|
||||
TermPos fInitialSelectionEnd;
|
||||
bool fMouseTracking;
|
||||
int fSelectGranularity;
|
||||
|
||||
// Input Method parameter.
|
||||
int fIMViewPtr;
|
||||
CurPos fIMStartPos;
|
||||
CurPos fIMEndPos;
|
||||
TermPos fIMStartPos;
|
||||
TermPos fIMEndPos;
|
||||
BString fIMString;
|
||||
bool fIMflag;
|
||||
BMessenger fIMMessenger;
|
||||
|
||||
@@ -9,16 +9,9 @@
|
||||
|
||||
#include "TermWindow.h"
|
||||
|
||||
#include "Arguments.h"
|
||||
#include "Coding.h"
|
||||
#include "MenuUtil.h"
|
||||
#include "FindWindow.h"
|
||||
#include "PrefWindow.h"
|
||||
#include "PrefView.h"
|
||||
#include "PrefHandler.h"
|
||||
#include "SmartTabView.h"
|
||||
#include "TermConst.h"
|
||||
#include "TermView.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
@@ -35,12 +28,21 @@
|
||||
#include <ScrollView.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "Arguments.h"
|
||||
#include "Coding.h"
|
||||
#include "MenuUtil.h"
|
||||
#include "FindWindow.h"
|
||||
#include "PrefWindow.h"
|
||||
#include "PrefView.h"
|
||||
#include "PrefHandler.h"
|
||||
#include "SmartTabView.h"
|
||||
#include "TermConst.h"
|
||||
#include "TermScrollView.h"
|
||||
#include "TermView.h"
|
||||
|
||||
|
||||
const static int32 kMaxTabs = 6;
|
||||
const static int32 kTermViewOffset = 3;
|
||||
|
||||
// messages constants
|
||||
const static uint32 kNewTab = 'NTab';
|
||||
@@ -57,6 +59,34 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class TermViewContainerView : public BView {
|
||||
public:
|
||||
TermViewContainerView(TermView* termView)
|
||||
:
|
||||
BView(BRect(), "term view container", B_FOLLOW_ALL, 0),
|
||||
fTermView(termView)
|
||||
{
|
||||
termView->MoveTo(kTermViewOffset, kTermViewOffset);
|
||||
BRect frame(termView->Frame());
|
||||
ResizeTo(frame.right + kTermViewOffset, frame.bottom + kTermViewOffset);
|
||||
AddChild(termView);
|
||||
}
|
||||
|
||||
TermView* GetTermView() const { return fTermView; }
|
||||
|
||||
virtual void GetPreferredSize(float* _width, float* _height)
|
||||
{
|
||||
float width, height;
|
||||
fTermView->GetPreferredSize(&width, &height);
|
||||
*_width = width + 2 * kTermViewOffset;
|
||||
*_height = height + 2 * kTermViewOffset;
|
||||
}
|
||||
|
||||
private:
|
||||
TermView* fTermView;
|
||||
};
|
||||
|
||||
|
||||
TermWindow::TermWindow(BRect frame, const char* title, Arguments *args)
|
||||
: BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE),
|
||||
fTabView(NULL),
|
||||
@@ -394,9 +424,11 @@ TermWindow::MessageReceived(BMessage *message)
|
||||
break;
|
||||
|
||||
case MSG_COLOR_CHANGED:
|
||||
_SetTermColors(_ActiveTermView());
|
||||
{
|
||||
_SetTermColors(_ActiveTermViewContainerView());
|
||||
_ActiveTermView()->Invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
case SAVE_AS_DEFAULT:
|
||||
{
|
||||
@@ -460,7 +492,7 @@ TermWindow::MessageReceived(BMessage *message)
|
||||
_ResizeView(view);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
@@ -476,16 +508,21 @@ TermWindow::WindowActivated(bool activated)
|
||||
|
||||
|
||||
void
|
||||
TermWindow::_SetTermColors(TermView *termView)
|
||||
TermWindow::_SetTermColors(TermViewContainerView *containerView)
|
||||
{
|
||||
termView->SetTextColor(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR),
|
||||
PrefHandler::Default()->getRGB(PREF_TEXT_BACK_COLOR));
|
||||
PrefHandler* handler = PrefHandler::Default();
|
||||
rgb_color background = handler->getRGB(PREF_TEXT_BACK_COLOR);
|
||||
|
||||
termView->SetSelectColor(PrefHandler::Default()->getRGB(PREF_SELECT_FORE_COLOR),
|
||||
PrefHandler::Default()->getRGB(PREF_SELECT_BACK_COLOR));
|
||||
|
||||
termView->SetCursorColor(PrefHandler::Default()->getRGB(PREF_CURSOR_FORE_COLOR),
|
||||
PrefHandler::Default()->getRGB(PREF_CURSOR_BACK_COLOR));
|
||||
containerView->SetViewColor(background);
|
||||
|
||||
TermView *termView = containerView->GetTermView();
|
||||
termView->SetTextColor(handler->getRGB(PREF_TEXT_FORE_COLOR), background);
|
||||
|
||||
termView->SetSelectColor(handler->getRGB(PREF_SELECT_FORE_COLOR),
|
||||
handler->getRGB(PREF_SELECT_BACK_COLOR));
|
||||
|
||||
termView->SetCursorColor(handler->getRGB(PREF_CURSOR_FORE_COLOR),
|
||||
handler->getRGB(PREF_CURSOR_BACK_COLOR));
|
||||
}
|
||||
|
||||
|
||||
@@ -564,10 +601,11 @@ TermWindow::_AddTab(Arguments *args)
|
||||
new CustomTermView(PrefHandler::Default()->getInt32(PREF_ROWS),
|
||||
PrefHandler::Default()->getInt32(PREF_COLS),
|
||||
argc, (const char **)argv);
|
||||
|
||||
BScrollView *scrollView = new BScrollView("scrollView", view, B_FOLLOW_ALL,
|
||||
B_WILL_DRAW|B_FRAME_EVENTS, false, true);
|
||||
|
||||
|
||||
TermViewContainerView *containerView = new TermViewContainerView(view);
|
||||
BScrollView *scrollView = new TermScrollView("scrollView",
|
||||
containerView, view);
|
||||
|
||||
BTab *tab = new BTab;
|
||||
// TODO: Use a better name. For example, do like MacOsX's Terminal
|
||||
// and update the title using the last executed command ?
|
||||
@@ -585,9 +623,9 @@ TermWindow::_AddTab(Arguments *args)
|
||||
BFont font;
|
||||
_GetPreferredFont(font);
|
||||
view->SetTermFont(&font);
|
||||
|
||||
_SetTermColors(view);
|
||||
|
||||
|
||||
_SetTermColors(containerView);
|
||||
|
||||
int width, height;
|
||||
view->GetFontSize(&width, &height);
|
||||
|
||||
@@ -603,8 +641,8 @@ TermWindow::_AddTab(Arguments *args)
|
||||
// If it's the first time we're called, setup the window
|
||||
if (fTabView->CountTabs() == 1) {
|
||||
float viewWidth, viewHeight;
|
||||
view->GetPreferredSize(&viewWidth, &viewHeight);
|
||||
|
||||
containerView->GetPreferredSize(&viewWidth, &viewHeight);
|
||||
|
||||
// Resize Window
|
||||
ResizeTo(viewWidth + B_V_SCROLL_BAR_WIDTH,
|
||||
viewHeight + fMenubar->Bounds().Height());
|
||||
@@ -627,14 +665,36 @@ TermWindow::_RemoveTab(int32 index)
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
||||
TermViewContainerView*
|
||||
TermWindow::_ActiveTermViewContainerView() const
|
||||
{
|
||||
return _TermViewContainerViewAt(fTabView->Selection());
|
||||
}
|
||||
|
||||
TermView *
|
||||
TermWindow::_ActiveTermView()
|
||||
|
||||
TermViewContainerView*
|
||||
TermWindow::_TermViewContainerViewAt(int32 index) const
|
||||
{
|
||||
// TODO: BAD HACK:
|
||||
// We should probably use the observer api to tell
|
||||
// the various "tabs" when settings are changed. Fix this.
|
||||
return (TermView *)((BScrollView *)fTabView->ViewForTab(fTabView->Selection()))->Target();
|
||||
BScrollView* scrollView = (BScrollView*)fTabView->ViewForTab(index);
|
||||
return scrollView ? (TermViewContainerView*)scrollView->Target() : NULL;
|
||||
}
|
||||
|
||||
|
||||
TermView *
|
||||
TermWindow::_ActiveTermView() const
|
||||
{
|
||||
return _ActiveTermViewContainerView()->GetTermView();
|
||||
}
|
||||
|
||||
|
||||
TermView*
|
||||
TermWindow::_TermViewAt(int32 index) const
|
||||
{
|
||||
TermViewContainerView* view = _TermViewContainerViewAt(index);
|
||||
return view != NULL ? view->GetTermView() : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -647,12 +707,7 @@ TermWindow::_IndexOfTermView(TermView* termView) const
|
||||
// find the view
|
||||
int32 count = fTabView->CountTabs();
|
||||
for (int32 i = count - 1; i >= 0; i--) {
|
||||
BScrollView* scrollView
|
||||
= dynamic_cast<BScrollView*>(fTabView->ViewForTab(i));
|
||||
if (!scrollView)
|
||||
continue;
|
||||
|
||||
if (termView == scrollView->Target())
|
||||
if (termView == _TermViewAt(i))
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -668,11 +723,7 @@ TermWindow::_CheckChildren()
|
||||
int32 count = fTabView->CountTabs();
|
||||
for (int32 i = count - 1; i >= 0; i--) {
|
||||
// get the term view
|
||||
BScrollView* scrollView
|
||||
= dynamic_cast<BScrollView*>(fTabView->ViewForTab(i));
|
||||
if (!scrollView)
|
||||
continue;
|
||||
TermView* termView = dynamic_cast<TermView*>(scrollView->Target());
|
||||
TermView* termView = _TermViewAt(i);
|
||||
if (!termView)
|
||||
continue;
|
||||
|
||||
@@ -698,7 +749,7 @@ TermWindow::_ResizeView(TermView *view)
|
||||
minimumHeight + MAX_ROWS * fontHeight);
|
||||
|
||||
float width, height;
|
||||
view->GetPreferredSize(&width, &height);
|
||||
view->Parent()->GetPreferredSize(&width, &height);
|
||||
width += B_V_SCROLL_BAR_WIDTH;
|
||||
height += fMenubar->Bounds().Height() + 2;
|
||||
|
||||
|
||||
@@ -41,8 +41,9 @@ class BMenu;
|
||||
class BMenuBar;
|
||||
class FindWindow;
|
||||
class PrefWindow;
|
||||
class TermView;
|
||||
class SmartTabView;
|
||||
class TermView;
|
||||
class TermViewContainerView;
|
||||
|
||||
|
||||
class TermWindow : public BWindow {
|
||||
@@ -56,7 +57,7 @@ protected:
|
||||
virtual void MenusBeginning();
|
||||
|
||||
private:
|
||||
void _SetTermColors(TermView *termView);
|
||||
void _SetTermColors(TermViewContainerView *termView);
|
||||
void _InitWindow();
|
||||
void _SetupMenu();
|
||||
void _GetPreferredFont(BFont &font);
|
||||
@@ -64,7 +65,10 @@ private:
|
||||
void _DoPrint();
|
||||
void _AddTab(Arguments *args);
|
||||
void _RemoveTab(int32 index);
|
||||
TermView* _ActiveTermView();
|
||||
TermViewContainerView* _ActiveTermViewContainerView() const;
|
||||
TermViewContainerView* _TermViewContainerViewAt(int32 index) const;
|
||||
TermView* _ActiveTermView() const;
|
||||
TermView* _TermViewAt(int32 index) const;
|
||||
int32 _IndexOfTermView(TermView* termView) const;
|
||||
void _CheckChildren();
|
||||
void _ResizeView(TermView *view);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,59 +5,186 @@
|
||||
#ifndef TERMINAL_BUFFER_H
|
||||
#define TERMINAL_BUFFER_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <Locker.h>
|
||||
#include <Messenger.h>
|
||||
|
||||
#include "TermPos.h"
|
||||
#include "UTF8Char.h"
|
||||
|
||||
|
||||
class TerminalBuffer {
|
||||
class BString;
|
||||
class TerminalCharClassifier;
|
||||
|
||||
|
||||
struct TerminalBufferDirtyInfo {
|
||||
int32 linesScrolled; // number of lines added to the history
|
||||
int32 dirtyTop; // dirty line range
|
||||
int32 dirtyBottom; //
|
||||
bool messageSent; // listener has been notified
|
||||
|
||||
bool IsDirtyRegionValid() const
|
||||
{
|
||||
return dirtyTop <= dirtyBottom;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
linesScrolled = 0;
|
||||
dirtyTop = INT_MAX;
|
||||
dirtyBottom = INT_MIN;
|
||||
messageSent = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TerminalBuffer : public BLocker {
|
||||
public:
|
||||
TerminalBuffer();
|
||||
virtual ~TerminalBuffer();
|
||||
~TerminalBuffer();
|
||||
|
||||
virtual int Encoding() const = 0;
|
||||
status_t Init(int32 width, int32 height,
|
||||
int32 historySize);
|
||||
|
||||
// Output Character
|
||||
virtual void Insert(uchar* string, ushort attr) = 0;
|
||||
virtual void InsertCR() = 0;
|
||||
virtual void InsertLF() = 0;
|
||||
virtual void InsertNewLine(int num) = 0;
|
||||
virtual void SetInsertMode(int flag) = 0;
|
||||
virtual void InsertSpace(int num) = 0;
|
||||
void SetListener(BMessenger listener);
|
||||
|
||||
int Encoding() const;
|
||||
|
||||
int32 Width() const { return fWidth; }
|
||||
int32 Height() const { return fHeight; }
|
||||
TermPos Cursor() const { return fCursor; }
|
||||
int32 HistorySize() const { return fHistorySize; }
|
||||
|
||||
TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; }
|
||||
|
||||
status_t ResizeTo(int32 width, int32 height);
|
||||
void Clear();
|
||||
|
||||
bool IsFullWidthChar(int32 row, int32 column) const;
|
||||
int GetChar(int32 row, int32 column,
|
||||
UTF8Char& character,
|
||||
uint16& attributes) const;
|
||||
int32 GetString(int32 row, int32 firstColumn,
|
||||
int32 lastColumn, char* buffer,
|
||||
uint16& 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;
|
||||
|
||||
bool Find(const char* pattern, const TermPos& start,
|
||||
bool forward, bool caseSensitive,
|
||||
bool matchWord, TermPos& matchStart,
|
||||
TermPos& matchEnd) const;
|
||||
|
||||
// output character
|
||||
void InsertChar(UTF8Char c, uint32 attributes);
|
||||
void Insert(uchar* string, ushort attr);
|
||||
void InsertCR();
|
||||
void InsertLF();
|
||||
void InsertNewLine(int numLines);
|
||||
void SetInsertMode(int flag);
|
||||
void InsertSpace(int num);
|
||||
|
||||
// Delete Character
|
||||
virtual void EraseBelow() = 0;
|
||||
virtual void DeleteChar(int num) = 0;
|
||||
virtual void DeleteColumns() = 0;
|
||||
virtual void DeleteLine(int num) = 0;
|
||||
// delete character
|
||||
void EraseBelow();
|
||||
void DeleteChar(int num);
|
||||
void DeleteColumns();
|
||||
void DeleteLine(int num);
|
||||
|
||||
// Get and Set Cursor position
|
||||
virtual void SetCurPos(int x, int y) = 0;
|
||||
virtual void SetCurX(int x) = 0;
|
||||
virtual void SetCurY(int y) = 0;
|
||||
virtual int GetCurX() = 0;
|
||||
virtual void SaveCursor() = 0;
|
||||
virtual void RestoreCursor() = 0;
|
||||
// get and set cursor position
|
||||
// TODO: Inline most of these!
|
||||
void SetCurPos(int x, int y);
|
||||
void SetCurX(int x);
|
||||
void SetCurY(int y);
|
||||
int GetCurX();
|
||||
void SaveCursor();
|
||||
void RestoreCursor();
|
||||
|
||||
// Move Cursor
|
||||
virtual void MoveCurRight(int num) = 0;
|
||||
virtual void MoveCurLeft(int num) = 0;
|
||||
virtual void MoveCurUp(int num) = 0;
|
||||
virtual void MoveCurDown(int num) = 0;
|
||||
// move cursor
|
||||
void MoveCurRight(int num);
|
||||
void MoveCurLeft(int num);
|
||||
void MoveCurUp(int num);
|
||||
void MoveCurDown(int num);
|
||||
|
||||
// Cursor setting
|
||||
virtual void SetCurDraw(bool flag) = 0;
|
||||
// scroll region
|
||||
void ScrollRegion(int top, int bot, int dir,
|
||||
int num);
|
||||
void SetScrollRegion(int top, int bot);
|
||||
|
||||
// Scroll region
|
||||
virtual void ScrollRegion(int top, int bot, int dir,
|
||||
int num) = 0;
|
||||
virtual void SetScrollRegion(int top, int bot) = 0;
|
||||
virtual void ScrollAtCursor() = 0;
|
||||
// other
|
||||
void SetTitle(const char* title);
|
||||
void NotifyQuit(int32 reason);
|
||||
|
||||
// Other
|
||||
virtual void DeviceStatusReport(int) = 0;
|
||||
virtual void UpdateLine() = 0;
|
||||
private:
|
||||
struct Cell {
|
||||
UTF8Char character;
|
||||
uint16 attributes;
|
||||
};
|
||||
|
||||
virtual void SetTitle(const char* title) = 0;
|
||||
virtual void NotifyQuit(int32 reason) = 0;
|
||||
struct Line {
|
||||
int16 length;
|
||||
bool softBreak; // soft line break
|
||||
Cell cells[1];
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
length = 0;
|
||||
softBreak = false;
|
||||
}
|
||||
};
|
||||
|
||||
inline int32 _LineIndex(int32 index) const;
|
||||
inline Line* _LineAt(int32 index) const;
|
||||
inline Line* _HistoryLineAt(int32 index) 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);
|
||||
void _ClearLines(int32 first, int32 last);
|
||||
|
||||
void _Scroll(int32 top, int32 bottom,
|
||||
int32 numLines);
|
||||
void _SoftBreakLine();
|
||||
void _PadLineToCursor();
|
||||
void _InsertGap(int32 width);
|
||||
bool _GetPartialLineString(BString& string,
|
||||
int32 row, int32 startColumn,
|
||||
int32 endColumn) const;
|
||||
bool _PreviousChar(TermPos& pos, UTF8Char& c) const;
|
||||
bool _NextChar(TermPos& pos, UTF8Char& c) const;
|
||||
|
||||
private:
|
||||
// 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)
|
||||
Line** fHistory;
|
||||
int32 fHistoryCapacity;
|
||||
int32 fScreenOffset; // index of screen line 0
|
||||
int32 fHistorySize;
|
||||
|
||||
// cursor position (origin: (0, 0))
|
||||
TermPos fCursor;
|
||||
TermPos fSavedCursor;
|
||||
|
||||
bool fOverwriteMode; // false for insert
|
||||
|
||||
// listener/dirty region management
|
||||
BMessenger fListener;
|
||||
TerminalBufferDirtyInfo fDirtyInfo;
|
||||
};
|
||||
|
||||
#endif // TERMINAL_BUFFER_H
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "TerminalCharClassifier.h"
|
||||
|
||||
|
||||
TerminalCharClassifier::~TerminalCharClassifier()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TERMINAL_CHAR_CLASSIFIER_H
|
||||
#define TERMINAL_CHAR_CLASSIFIER_H
|
||||
|
||||
|
||||
enum {
|
||||
CHAR_TYPE_SPACE,
|
||||
CHAR_TYPE_WORD_CHAR,
|
||||
CHAR_TYPE_WORD_DELIMITER
|
||||
};
|
||||
|
||||
|
||||
class TerminalCharClassifier {
|
||||
public:
|
||||
virtual ~TerminalCharClassifier();
|
||||
|
||||
virtual int Classify(const char* character) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // TERMINAL_CHAR_CLASSIFIER_H
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef UTF8_CHAR_H
|
||||
#define UTF8_CHAR_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
struct UTF8Char {
|
||||
char bytes[4];
|
||||
|
||||
UTF8Char()
|
||||
{
|
||||
}
|
||||
|
||||
UTF8Char(char c)
|
||||
{
|
||||
bytes[0] = c;
|
||||
}
|
||||
|
||||
static int32 ByteCount(char firstChar)
|
||||
{
|
||||
// Note, this does not recognize invalid chars
|
||||
uint32 c = firstChar;
|
||||
if (c < 0x80)
|
||||
return 1;
|
||||
if (c < 0xe0)
|
||||
return 2;
|
||||
return c < 0xf0 ? 3 : 4;
|
||||
}
|
||||
|
||||
int32 ByteCount() const
|
||||
{
|
||||
return ByteCount(bytes[0]);
|
||||
}
|
||||
|
||||
bool IsSpace() const
|
||||
{
|
||||
// TODO: Support multi-byte chars!
|
||||
return ByteCount() == 1 ? isspace(bytes[0]) : false;
|
||||
}
|
||||
|
||||
UTF8Char ToLower() const
|
||||
{
|
||||
// TODO: Support multi-byte chars!
|
||||
if (ByteCount() > 1)
|
||||
return *this;
|
||||
|
||||
return UTF8Char((char)tolower(bytes[0]));
|
||||
}
|
||||
|
||||
bool operator==(const UTF8Char& other) const
|
||||
{
|
||||
int32 byteCount = ByteCount();
|
||||
bool equals = bytes[0] == other.bytes[0];
|
||||
if (byteCount > 1 && equals) {
|
||||
equals = bytes[1] == other.bytes[1];
|
||||
if (byteCount > 2 && equals) {
|
||||
equals = bytes[2] == other.bytes[2];
|
||||
if (byteCount > 3 && equals)
|
||||
equals = bytes[3] == other.bytes[3];
|
||||
}
|
||||
}
|
||||
return equals;
|
||||
}
|
||||
|
||||
bool operator!=(const UTF8Char& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // UTF8_CHAR_H
|
||||
Reference in New Issue
Block a user