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:
Ingo Weinhold
2008-06-09 17:04:26 +00:00
parent 80f4a4f272
commit 52b1d543e8
22 changed files with 2640 additions and 2120 deletions
+1
View File
@@ -26,4 +26,5 @@ class CodeConv {
static unsigned short UTF8toUnicode(const char *utf8); static unsigned short UTF8toUnicode(const char *utf8);
}; };
#endif /* CODECONV_H */ #endif /* CODECONV_H */
-113
View File
@@ -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;
}
-38
View File
@@ -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
+2 -2
View File
@@ -9,7 +9,6 @@ Application Terminal :
Arguments.cpp Arguments.cpp
CodeConv.cpp CodeConv.cpp
Coding.cpp Coding.cpp
CurPos.cpp
FindWindow.cpp FindWindow.cpp
MenuUtil.cpp MenuUtil.cpp
Terminal.cpp Terminal.cpp
@@ -19,9 +18,10 @@ Application Terminal :
Shell.cpp Shell.cpp
SmartTabView.cpp SmartTabView.cpp
TermApp.cpp TermApp.cpp
TermBuffer.cpp
TerminalBuffer.cpp TerminalBuffer.cpp
TerminalCharClassifier.cpp
TermParse.cpp TermParse.cpp
TermScrollView.cpp
TermView.cpp TermView.cpp
TermWindow.cpp TermWindow.cpp
TTextControl.cpp TTextControl.cpp
+1 -1
View File
@@ -234,7 +234,7 @@ Shell::ViewAttached(TermView *view)
if (fAttached) if (fAttached)
return; return;
status_t status = fTermParse->StartThreads(view); status_t status = fTermParse->StartThreads(view->TextBuffer());
if (status < B_OK) { if (status < B_OK) {
// TODO: What can we do here ? // TODO: What can we do here ?
fprintf(stderr, "Shell:ViewAttached():" fprintf(stderr, "Shell:ViewAttached():"
-550
View File
@@ -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);
}
-124
View File
@@ -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 &copyStr, 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
+5 -1
View File
@@ -83,6 +83,10 @@ const uint32 MSG_FONT_CHANGED = 'fntc';
const uint32 SAVE_AS_DEFAULT = 'sadf'; const uint32 SAVE_AS_DEFAULT = 'sadf';
const uint32 MSG_CHECK_CHILDREN = 'ckch'; 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 // Preference Read/Write Keys
const char* const PREF_HALF_FONT_FAMILY = "Half Font Family"; const char* const PREF_HALF_FONT_FAMILY = "Half Font Family";
const char* const PREF_HALF_FONT_STYLE = "Half Font Style"; const char* const PREF_HALF_FONT_STYLE = "Half Font Style";
@@ -144,7 +148,7 @@ enum{
#define MIN_COLS 10 #define MIN_COLS 10
#define MAX_COLS 256 #define MAX_COLS 256
#define MIN_ROWS 1 #define MIN_ROWS 10
#define MAX_ROWS 256 #define MAX_ROWS 256
// Insert mode flag // Insert mode flag
+38 -2
View File
@@ -13,6 +13,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <Autolock.h>
#include <Beep.h> #include <Beep.h>
#include <Message.h> #include <Message.h>
@@ -117,6 +118,7 @@ status_t
TermParse::GetReaderBuf(uchar &c) TermParse::GetReaderBuf(uchar &c)
{ {
status_t status; status_t status;
#if 0
do { do {
status = acquire_sem_etc(fReaderSem, 1, B_TIMEOUT, 10000); status = acquire_sem_etc(fReaderSem, 1, B_TIMEOUT, 10000);
} while (status == B_INTERRUPTED); } while (status == B_INTERRUPTED);
@@ -127,17 +129,23 @@ TermParse::GetReaderBuf(uchar &c)
// Reset cursor blinking time and turn on cursor blinking. // Reset cursor blinking time and turn on cursor blinking.
fBuffer->SetCurDraw(true); fBuffer->SetCurDraw(true);
#endif
// wait new input from pty. // wait new input from pty.
fBuffer->Unlock();
do { do {
status = acquire_sem(fReaderSem); status = acquire_sem(fReaderSem);
} while (status == B_INTERRUPTED); } while (status == B_INTERRUPTED);
fBuffer->Lock();
if (status < B_OK) if (status < B_OK)
return status; return status;
#if 0
} else if (status == B_OK) { } else if (status == B_OK) {
// Do nothing // Do nothing
} else } else
return status; return status;
#endif
c = fReadBuffer[fBufferPosition % READ_BUF_SIZE]; c = fReadBuffer[fBufferPosition % READ_BUF_SIZE];
fBufferPosition++; fBufferPosition++;
@@ -147,7 +155,7 @@ TermParse::GetReaderBuf(uchar &c)
release_sem(fReaderLocker); release_sem(fReaderLocker);
} }
fBuffer->SetCurDraw(false); // fBuffer->SetCurDraw(false);
return B_OK; return B_OK;
} }
@@ -343,6 +351,9 @@ TermParse::EscParse()
int *parsestate = groundtable; int *parsestate = groundtable;
while (!fQuitting) { while (!fQuitting) {
// TODO: Fix the locking!
BAutolock locker(fBuffer);
uchar c; uchar c;
if (GetReaderBuf(c) < B_OK) if (GetReaderBuf(c) < B_OK)
break; break;
@@ -383,6 +394,7 @@ TermParse::EscParse()
now_coding = fBuffer->Encoding(); now_coding = fBuffer->Encoding();
} }
//debug_printf("TermParse: char: '%c' (%d), parse state: %d\n", c, c, parsestate[c]);
switch (parsestate[c]) { switch (parsestate[c]) {
case CASE_PRINT: case CASE_PRINT:
cbuf[0] = c; cbuf[0] = c;
@@ -767,7 +779,7 @@ TermParse::EscParse()
case CASE_CPR: case CASE_CPR:
// Q & D hack by Y.Hayakawa ([email protected]) // Q & D hack by Y.Hayakawa ([email protected])
// 21-JUL-99 // 21-JUL-99
fBuffer->DeviceStatusReport(param[0]); _DeviceStatusReport(param[0]);
parsestate = groundtable; parsestate = groundtable;
break; break;
@@ -975,3 +987,27 @@ TermParse::_escparse_thread(void *data)
{ {
return reinterpret_cast<TermParse *>(data)->EscParse(); 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;
}
}
+3 -1
View File
@@ -68,7 +68,9 @@ private:
// Reading ReadBuf at one Char. // Reading ReadBuf at one Char.
status_t GetReaderBuf(uchar &c); status_t GetReaderBuf(uchar &c);
void _DeviceStatusReport(int n);
int fFd; int fFd;
thread_id fParseThread; thread_id fParseThread;
+65
View File
@@ -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
+52
View File
@@ -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()
{
}
+20
View File
@@ -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
File diff suppressed because it is too large Load Diff
+58 -97
View File
@@ -12,12 +12,13 @@
#ifndef TERMVIEW_H #ifndef TERMVIEW_H
#define TERMVIEW_H #define TERMVIEW_H
#include <Autolock.h>
#include <Messenger.h> #include <Messenger.h>
#include <String.h> #include <String.h>
#include <View.h> #include <View.h>
#include "CurPos.h"
#include "TerminalBuffer.h" #include "TerminalBuffer.h"
#include "TermPos.h"
class BClipboard; class BClipboard;
@@ -27,7 +28,7 @@ class BString;
class Shell; class Shell;
class TermBuffer; class TermBuffer;
class TermView : public BView, public TerminalBuffer { class TermView : public BView {
public: public:
TermView(BRect frame, int32 argc, const char **argv, int32 historySize = 1000); TermView(BRect frame, int32 argc, const char **argv, int32 historySize = 1000);
TermView(int rows, int columns, 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); virtual void GetPreferredSize(float *width, float *height);
const char *TerminalName() const; const char *TerminalName() const;
inline TerminalBuffer* TextBuffer() const { return fTextBuffer; }
void GetTermFont(BFont *font) const; void GetTermFont(BFont *font) const;
void SetTermFont(const BFont *font); void SetTermFont(const BFont *font);
@@ -67,52 +70,12 @@ public:
void SelectAll(); void SelectAll();
void Clear(); 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 // Cursor setting
void DrawCursor();
void BlinkCursor(); void BlinkCursor();
void SetCurDraw(bool flag); void SetCurDraw(bool flag);
void SetCurBlinking(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 // Other
void DeviceStatusReport(int);
void UpdateLine();
void ScrollScreen();
void ScrollScreenDraw();
void GetFrameSize(float *width, float *height); void GetFrameSize(float *width, float *height);
bool Find(const BString &str, bool forwardSearch, bool matchCase, bool matchWord); bool Find(const BString &str, bool forwardSearch, bool matchCase, bool matchWord);
void GetSelection(BString &str); void GetSelection(BString &str);
@@ -135,12 +98,22 @@ protected:
virtual void FrameResized(float width, float height); virtual void FrameResized(float width, float height);
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void ScrollTo(BPoint where);
virtual status_t GetSupportedSuites(BMessage *msg); virtual status_t GetSupportedSuites(BMessage *msg);
virtual BHandler* ResolveSpecifier(BMessage *msg, int32 index, virtual BHandler* ResolveSpecifier(BMessage *msg, int32 index,
BMessage *specifier, int32 form, BMessage *specifier, int32 form,
const char *property); const char *property);
private: 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 _InitObject(int32 argc, const char **argv);
status_t _AttachShell(Shell *shell); status_t _AttachShell(Shell *shell);
@@ -148,17 +121,18 @@ private:
void _AboutRequested(); void _AboutRequested();
void _DrawLines(int , int, ushort, uchar *, int, int, int, BView *); void _DrawLinePart(int32 x1, int32 y1, uint16 attr, char *buf,
int _TermDraw(const CurPos &start, const CurPos &end); int32 width, bool mouse, bool cursor, BView *inView);
int _TermDrawRegion(CurPos start, CurPos end); void _DrawCursor();
int _TermDrawSelectedRegion(CurPos start, CurPos end); void _InvalidateTextRange(TermPos start, TermPos end);
inline void _Redraw(int, int, int, int);
void _DoPrint(BRect updateRect); void _DoPrint(BRect updateRect);
void _ResizeScrBarRange(void); void _UpdateScrollBarRange();
void _DoFileDrop(entry_ref &ref); 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 // Comunicate Input Method
// void _DoIMStart (BMessage* message); // void _DoIMStart (BMessage* message);
@@ -168,33 +142,36 @@ private:
// void _DoIMConfirm (void); // void _DoIMConfirm (void);
// void _ConfirmString(const char *, int32); // void _ConfirmString(const char *, int32);
// Mouse select // selection
void _Select(CurPos start, CurPos end); void _Select(TermPos start, TermPos end, bool inclusive,
void _AddSelectRegion(CurPos); bool setInitialSelection);
void _ResizeSelectRegion(CurPos); void _ExtendSelection(TermPos, bool inclusive, bool useInitialSelection);
void _Deselect();
void _DeSelect();
bool _HasSelection() const; bool _HasSelection() const;
void _SelectWord(BPoint where, bool extend, bool useInitialSelection);
void _SelectLine(BPoint where, bool extend, bool useInitialSelection);
// select word function void _AutoScrollUpdate();
void _SelectWord(BPoint where, int mod);
void _SelectLine(BPoint where, int mod);
// point and text offset conversion. bool _CheckSelectedRegion(const TermPos &pos) const;
CurPos _ConvertToTerminal(const BPoint &p); bool _CheckSelectedRegion(int32 row, int32 firstColumn,
BPoint _ConvertFromTerminal(const CurPos &pos); int32& lastColumn) const;
bool _CheckSelectedRegion(const CurPos &pos);
void _UpdateSIGWINCH(); void _UpdateSIGWINCH();
static void _FixFontAttributes(BFont &font); void _ScrollTo(float y, bool scrollGfx);
void _ScrollToRange(TermPos start, TermPos end);
private: private:
class CharClassifier;
Shell *fShell; Shell *fShell;
BMessageRunner *fWinchRunner; BMessageRunner *fWinchRunner;
BMessageRunner *fCursorBlinkRunner; BMessageRunner *fCursorBlinkRunner;
BMessageRunner *fAutoScrollRunner;
CharClassifier *fCharClassifier;
// Font and Width // Font and Width
BFont fHalfFont; BFont fHalfFont;
@@ -203,19 +180,7 @@ private:
int fFontAscent; int fFontAscent;
struct escapement_delta fEscapement; struct escapement_delta fEscapement;
// Flags // frame resized flag.
// Update flag (Set on Insert).
bool fUpdateFlag;
// Terminal insertmode flag (use Insert).
bool fInsertModeFlag;
// Scroll count, range.
int fScrollUpCount;
int fScrollBarRange;
// Frame Resized flag.
bool fFrameResized; bool fFrameResized;
// Cursor Blinking, draw flag. // Cursor Blinking, draw flag.
@@ -227,10 +192,7 @@ private:
int fCursorHeight; int fCursorHeight;
// Cursor position. // Cursor position.
CurPos fCurPos; TermPos fCursor;
CurPos fCurStack;
int fBufferStartPos;
// Terminal rows and columns. // Terminal rows and columns.
int fTermRows; int fTermRows;
@@ -238,12 +200,9 @@ private:
int fEncoding; int fEncoding;
// Terminal view pointer.
int fTop;
// Object pointer. // Object pointer.
TermBuffer *fTextBuffer; TerminalBuffer *fTextBuffer;
BScrollBar *fScrollBar; BScrollBar *fScrollBar;
// Color and Attribute. // Color and Attribute.
rgb_color fTextForeColor, fTextBackColor; rgb_color fTextForeColor, fTextBackColor;
@@ -251,22 +210,24 @@ private:
rgb_color fSelectForeColor, fSelectBackColor; rgb_color fSelectForeColor, fSelectBackColor;
// Scroll Region // Scroll Region
int fScrTop; float fScrollOffset;
int fScrBot;
int32 fScrBufSize; int32 fScrBufSize;
bool fScrRegionSet; // TODO: That's the history capacity -- only needed until the text
// buffer is created.
float fAutoScrollSpeed;
BPoint fClickPoint; // selection
TermPos fSelStart;
// view selection TermPos fSelEnd;
CurPos fSelStart; TermPos fInitialSelectionStart;
CurPos fSelEnd; TermPos fInitialSelectionEnd;
bool fMouseTracking; bool fMouseTracking;
int fSelectGranularity;
// Input Method parameter. // Input Method parameter.
int fIMViewPtr; int fIMViewPtr;
CurPos fIMStartPos; TermPos fIMStartPos;
CurPos fIMEndPos; TermPos fIMEndPos;
BString fIMString; BString fIMString;
bool fIMflag; bool fIMflag;
BMessenger fIMMessenger; BMessenger fIMMessenger;
+98 -47
View File
@@ -9,16 +9,9 @@
#include "TermWindow.h" #include "TermWindow.h"
#include "Arguments.h" #include <stdio.h>
#include "Coding.h" #include <string.h>
#include "MenuUtil.h" #include <time.h>
#include "FindWindow.h"
#include "PrefWindow.h"
#include "PrefView.h"
#include "PrefHandler.h"
#include "SmartTabView.h"
#include "TermConst.h"
#include "TermView.h"
#include <Alert.h> #include <Alert.h>
#include <Application.h> #include <Application.h>
@@ -35,12 +28,21 @@
#include <ScrollView.h> #include <ScrollView.h>
#include <String.h> #include <String.h>
#include <stdio.h> #include "Arguments.h"
#include <string.h> #include "Coding.h"
#include <time.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 kMaxTabs = 6;
const static int32 kTermViewOffset = 3;
// messages constants // messages constants
const static uint32 kNewTab = 'NTab'; 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) TermWindow::TermWindow(BRect frame, const char* title, Arguments *args)
: BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE), : BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE),
fTabView(NULL), fTabView(NULL),
@@ -394,9 +424,11 @@ TermWindow::MessageReceived(BMessage *message)
break; break;
case MSG_COLOR_CHANGED: case MSG_COLOR_CHANGED:
_SetTermColors(_ActiveTermView()); {
_SetTermColors(_ActiveTermViewContainerView());
_ActiveTermView()->Invalidate(); _ActiveTermView()->Invalidate();
break; break;
}
case SAVE_AS_DEFAULT: case SAVE_AS_DEFAULT:
{ {
@@ -460,7 +492,7 @@ TermWindow::MessageReceived(BMessage *message)
_ResizeView(view); _ResizeView(view);
break; break;
} }
default: default:
BWindow::MessageReceived(message); BWindow::MessageReceived(message);
break; break;
@@ -476,16 +508,21 @@ TermWindow::WindowActivated(bool activated)
void void
TermWindow::_SetTermColors(TermView *termView) TermWindow::_SetTermColors(TermViewContainerView *containerView)
{ {
termView->SetTextColor(PrefHandler::Default()->getRGB(PREF_TEXT_FORE_COLOR), PrefHandler* handler = PrefHandler::Default();
PrefHandler::Default()->getRGB(PREF_TEXT_BACK_COLOR)); rgb_color background = handler->getRGB(PREF_TEXT_BACK_COLOR);
termView->SetSelectColor(PrefHandler::Default()->getRGB(PREF_SELECT_FORE_COLOR), containerView->SetViewColor(background);
PrefHandler::Default()->getRGB(PREF_SELECT_BACK_COLOR));
TermView *termView = containerView->GetTermView();
termView->SetCursorColor(PrefHandler::Default()->getRGB(PREF_CURSOR_FORE_COLOR), termView->SetTextColor(handler->getRGB(PREF_TEXT_FORE_COLOR), background);
PrefHandler::Default()->getRGB(PREF_CURSOR_BACK_COLOR));
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), new CustomTermView(PrefHandler::Default()->getInt32(PREF_ROWS),
PrefHandler::Default()->getInt32(PREF_COLS), PrefHandler::Default()->getInt32(PREF_COLS),
argc, (const char **)argv); argc, (const char **)argv);
BScrollView *scrollView = new BScrollView("scrollView", view, B_FOLLOW_ALL, TermViewContainerView *containerView = new TermViewContainerView(view);
B_WILL_DRAW|B_FRAME_EVENTS, false, true); BScrollView *scrollView = new TermScrollView("scrollView",
containerView, view);
BTab *tab = new BTab; BTab *tab = new BTab;
// TODO: Use a better name. For example, do like MacOsX's Terminal // TODO: Use a better name. For example, do like MacOsX's Terminal
// and update the title using the last executed command ? // and update the title using the last executed command ?
@@ -585,9 +623,9 @@ TermWindow::_AddTab(Arguments *args)
BFont font; BFont font;
_GetPreferredFont(font); _GetPreferredFont(font);
view->SetTermFont(&font); view->SetTermFont(&font);
_SetTermColors(view); _SetTermColors(containerView);
int width, height; int width, height;
view->GetFontSize(&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 it's the first time we're called, setup the window
if (fTabView->CountTabs() == 1) { if (fTabView->CountTabs() == 1) {
float viewWidth, viewHeight; float viewWidth, viewHeight;
view->GetPreferredSize(&viewWidth, &viewHeight); containerView->GetPreferredSize(&viewWidth, &viewHeight);
// Resize Window // Resize Window
ResizeTo(viewWidth + B_V_SCROLL_BAR_WIDTH, ResizeTo(viewWidth + B_V_SCROLL_BAR_WIDTH,
viewHeight + fMenubar->Bounds().Height()); viewHeight + fMenubar->Bounds().Height());
@@ -627,14 +665,36 @@ TermWindow::_RemoveTab(int32 index)
PostMessage(B_QUIT_REQUESTED); PostMessage(B_QUIT_REQUESTED);
} }
TermViewContainerView*
TermWindow::_ActiveTermViewContainerView() const
{
return _TermViewContainerViewAt(fTabView->Selection());
}
TermView *
TermWindow::_ActiveTermView() TermViewContainerView*
TermWindow::_TermViewContainerViewAt(int32 index) const
{ {
// TODO: BAD HACK: // TODO: BAD HACK:
// We should probably use the observer api to tell // We should probably use the observer api to tell
// the various "tabs" when settings are changed. Fix this. // 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 // find the view
int32 count = fTabView->CountTabs(); int32 count = fTabView->CountTabs();
for (int32 i = count - 1; i >= 0; i--) { for (int32 i = count - 1; i >= 0; i--) {
BScrollView* scrollView if (termView == _TermViewAt(i))
= dynamic_cast<BScrollView*>(fTabView->ViewForTab(i));
if (!scrollView)
continue;
if (termView == scrollView->Target())
return i; return i;
} }
@@ -668,11 +723,7 @@ TermWindow::_CheckChildren()
int32 count = fTabView->CountTabs(); int32 count = fTabView->CountTabs();
for (int32 i = count - 1; i >= 0; i--) { for (int32 i = count - 1; i >= 0; i--) {
// get the term view // get the term view
BScrollView* scrollView TermView* termView = _TermViewAt(i);
= dynamic_cast<BScrollView*>(fTabView->ViewForTab(i));
if (!scrollView)
continue;
TermView* termView = dynamic_cast<TermView*>(scrollView->Target());
if (!termView) if (!termView)
continue; continue;
@@ -698,7 +749,7 @@ TermWindow::_ResizeView(TermView *view)
minimumHeight + MAX_ROWS * fontHeight); minimumHeight + MAX_ROWS * fontHeight);
float width, height; float width, height;
view->GetPreferredSize(&width, &height); view->Parent()->GetPreferredSize(&width, &height);
width += B_V_SCROLL_BAR_WIDTH; width += B_V_SCROLL_BAR_WIDTH;
height += fMenubar->Bounds().Height() + 2; height += fMenubar->Bounds().Height() + 2;
+7 -3
View File
@@ -41,8 +41,9 @@ class BMenu;
class BMenuBar; class BMenuBar;
class FindWindow; class FindWindow;
class PrefWindow; class PrefWindow;
class TermView;
class SmartTabView; class SmartTabView;
class TermView;
class TermViewContainerView;
class TermWindow : public BWindow { class TermWindow : public BWindow {
@@ -56,7 +57,7 @@ protected:
virtual void MenusBeginning(); virtual void MenusBeginning();
private: private:
void _SetTermColors(TermView *termView); void _SetTermColors(TermViewContainerView *termView);
void _InitWindow(); void _InitWindow();
void _SetupMenu(); void _SetupMenu();
void _GetPreferredFont(BFont &font); void _GetPreferredFont(BFont &font);
@@ -64,7 +65,10 @@ private:
void _DoPrint(); void _DoPrint();
void _AddTab(Arguments *args); void _AddTab(Arguments *args);
void _RemoveTab(int32 index); 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; int32 _IndexOfTermView(TermView* termView) const;
void _CheckChildren(); void _CheckChildren();
void _ResizeView(TermView *view); void _ResizeView(TermView *view);
File diff suppressed because it is too large Load Diff
+167 -40
View File
@@ -5,59 +5,186 @@
#ifndef TERMINAL_BUFFER_H #ifndef TERMINAL_BUFFER_H
#define 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: public:
TerminalBuffer(); TerminalBuffer();
virtual ~TerminalBuffer(); ~TerminalBuffer();
virtual int Encoding() const = 0; status_t Init(int32 width, int32 height,
int32 historySize);
// Output Character void SetListener(BMessenger listener);
virtual void Insert(uchar* string, ushort attr) = 0;
virtual void InsertCR() = 0; int Encoding() const;
virtual void InsertLF() = 0;
virtual void InsertNewLine(int num) = 0; int32 Width() const { return fWidth; }
virtual void SetInsertMode(int flag) = 0; int32 Height() const { return fHeight; }
virtual void InsertSpace(int num) = 0; 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 // delete character
virtual void EraseBelow() = 0; void EraseBelow();
virtual void DeleteChar(int num) = 0; void DeleteChar(int num);
virtual void DeleteColumns() = 0; void DeleteColumns();
virtual void DeleteLine(int num) = 0; void DeleteLine(int num);
// Get and Set Cursor position // get and set cursor position
virtual void SetCurPos(int x, int y) = 0; // TODO: Inline most of these!
virtual void SetCurX(int x) = 0; void SetCurPos(int x, int y);
virtual void SetCurY(int y) = 0; void SetCurX(int x);
virtual int GetCurX() = 0; void SetCurY(int y);
virtual void SaveCursor() = 0; int GetCurX();
virtual void RestoreCursor() = 0; void SaveCursor();
void RestoreCursor();
// Move Cursor // move cursor
virtual void MoveCurRight(int num) = 0; void MoveCurRight(int num);
virtual void MoveCurLeft(int num) = 0; void MoveCurLeft(int num);
virtual void MoveCurUp(int num) = 0; void MoveCurUp(int num);
virtual void MoveCurDown(int num) = 0; void MoveCurDown(int num);
// Cursor setting // scroll region
virtual void SetCurDraw(bool flag) = 0; void ScrollRegion(int top, int bot, int dir,
int num);
void SetScrollRegion(int top, int bot);
// Scroll region // other
virtual void ScrollRegion(int top, int bot, int dir, void SetTitle(const char* title);
int num) = 0; void NotifyQuit(int32 reason);
virtual void SetScrollRegion(int top, int bot) = 0;
virtual void ScrollAtCursor() = 0;
// Other private:
virtual void DeviceStatusReport(int) = 0; struct Cell {
virtual void UpdateLine() = 0; UTF8Char character;
uint16 attributes;
};
virtual void SetTitle(const char* title) = 0; struct Line {
virtual void NotifyQuit(int32 reason) = 0; 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 #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
+77
View File
@@ -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