SerialConnect: implement scrollback.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <ScrollView.h>
|
||||
#include <SerialPort.h>
|
||||
|
||||
#include "SerialApp.h"
|
||||
@@ -41,13 +42,30 @@ SerialWindow::SerialWindow()
|
||||
B_DOCUMENT_WINDOW, B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS)
|
||||
, fLogFilePanel(NULL)
|
||||
{
|
||||
SetLayout(new BGroupLayout(B_VERTICAL, 0.0f));
|
||||
BMenuBar* menuBar = new BMenuBar(Bounds(), "menuBar");
|
||||
menuBar->ResizeToPreferred();
|
||||
|
||||
BMenuBar* menuBar = new BMenuBar("menuBar");
|
||||
fTermView = new TermView();
|
||||
BRect r = Bounds();
|
||||
r.top = menuBar->Bounds().bottom + 1;
|
||||
r.right -= B_V_SCROLL_BAR_WIDTH;
|
||||
fTermView = new TermView(r);
|
||||
fTermView->ResizeToPreferred();
|
||||
|
||||
r = fTermView->Frame();
|
||||
r.left = r.right + 1;
|
||||
r.right = r.left + B_V_SCROLL_BAR_WIDTH;
|
||||
r.top -= 1;
|
||||
r.bottom -= B_H_SCROLL_BAR_HEIGHT - 1;
|
||||
BScrollBar* scrollBar = new BScrollBar(r, "scrollbar", NULL, 0, 0,
|
||||
B_VERTICAL);
|
||||
|
||||
scrollBar->SetTarget(fTermView);
|
||||
|
||||
ResizeTo(r.right - 1, r.bottom + B_H_SCROLL_BAR_HEIGHT - 1);
|
||||
|
||||
AddChild(menuBar);
|
||||
AddChild(fTermView);
|
||||
AddChild(scrollBar);
|
||||
|
||||
fConnectionMenu = new BMenu("Connection");
|
||||
BMenu* fileMenu = new BMenu("File");
|
||||
@@ -62,7 +80,7 @@ SerialWindow::SerialWindow()
|
||||
// TODO edit menu - what's in it ?
|
||||
//BMenu* editMenu = new BMenu("Edit");
|
||||
//menuBar->AddItem(editMenu);
|
||||
|
||||
|
||||
BMenuItem* logFile = new BMenuItem("Log to file" B_UTF8_ELLIPSIS,
|
||||
new BMessage(kMsgLogfile));
|
||||
fileMenu->AddItem(logFile);
|
||||
@@ -78,23 +96,23 @@ SerialWindow::SerialWindow()
|
||||
|
||||
// Configuring all this by menus may be a bit unhandy. Make a setting
|
||||
// window instead ?
|
||||
fBaudrateMenu = new BMenu("Baud rate");
|
||||
fBaudrateMenu = new BMenu("Baud rate");
|
||||
fBaudrateMenu->SetRadioMode(true);
|
||||
settingsMenu->AddItem(fBaudrateMenu);
|
||||
|
||||
fParityMenu = new BMenu("Parity");
|
||||
fParityMenu = new BMenu("Parity");
|
||||
fParityMenu->SetRadioMode(true);
|
||||
settingsMenu->AddItem(fParityMenu);
|
||||
|
||||
fStopbitsMenu = new BMenu("Stop bits");
|
||||
fStopbitsMenu = new BMenu("Stop bits");
|
||||
fStopbitsMenu->SetRadioMode(true);
|
||||
settingsMenu->AddItem(fStopbitsMenu);
|
||||
|
||||
fFlowcontrolMenu = new BMenu("Flow control");
|
||||
fFlowcontrolMenu = new BMenu("Flow control");
|
||||
fFlowcontrolMenu->SetRadioMode(true);
|
||||
settingsMenu->AddItem(fFlowcontrolMenu);
|
||||
|
||||
fDatabitsMenu = new BMenu("Data bits");
|
||||
fDatabitsMenu = new BMenu("Data bits");
|
||||
fDatabitsMenu->SetRadioMode(true);
|
||||
settingsMenu->AddItem(fDatabitsMenu);
|
||||
|
||||
@@ -147,7 +165,7 @@ SerialWindow::SerialWindow()
|
||||
message->AddInt32("baudrate", kBaudrateConstants[i]);
|
||||
|
||||
char buffer[7];
|
||||
sprintf(buffer,"%d", kBaudrates[i]);
|
||||
sprintf(buffer, "%d", kBaudrates[i]);
|
||||
BMenuItem* item = new BMenuItem(buffer, message);
|
||||
|
||||
fBaudrateMenu->AddItem(item);
|
||||
@@ -181,7 +199,6 @@ SerialWindow::SerialWindow()
|
||||
}
|
||||
|
||||
|
||||
|
||||
SerialWindow::~SerialWindow()
|
||||
{
|
||||
delete fLogFilePanel;
|
||||
@@ -198,7 +215,7 @@ void SerialWindow::MenusBeginning()
|
||||
int deviceCount = serialPort.CountDevices();
|
||||
bool connected = false;
|
||||
|
||||
for(int i = 0; i < deviceCount; i++)
|
||||
for (int i = 0; i < deviceCount; i++)
|
||||
{
|
||||
char buffer[256];
|
||||
serialPort.GetDeviceName(i, buffer, 256);
|
||||
@@ -210,7 +227,7 @@ void SerialWindow::MenusBeginning()
|
||||
|
||||
const BString& connectedPort = ((SerialApp*)be_app)->GetPort();
|
||||
|
||||
if(connectedPort == buffer) {
|
||||
if (connectedPort == buffer) {
|
||||
connected = true;
|
||||
portItem->SetMarked(true);
|
||||
}
|
||||
@@ -223,7 +240,7 @@ void SerialWindow::MenusBeginning()
|
||||
|
||||
BMenuItem* disconnect = new BMenuItem("Disconnect",
|
||||
new BMessage(kMsgOpenPort), 'Z', B_OPTION_KEY);
|
||||
if(!connected)
|
||||
if (!connected)
|
||||
disconnect->SetEnabled(false);
|
||||
fConnectionMenu->AddItem(disconnect);
|
||||
} else {
|
||||
@@ -233,6 +250,7 @@ void SerialWindow::MenusBeginning()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SerialWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch(message->what)
|
||||
@@ -240,7 +258,7 @@ void SerialWindow::MessageReceived(BMessage* message)
|
||||
case kMsgOpenPort:
|
||||
{
|
||||
BMenuItem* disconnectMenu;
|
||||
if(message->FindPointer("source", (void**)&disconnectMenu) == B_OK)
|
||||
if (message->FindPointer("source", (void**)&disconnectMenu) == B_OK)
|
||||
disconnectMenu->SetMarked(false);
|
||||
be_app->PostMessage(new BMessage(*message));
|
||||
break;
|
||||
@@ -257,7 +275,7 @@ void SerialWindow::MessageReceived(BMessage* message)
|
||||
case kMsgLogfile:
|
||||
{
|
||||
// Let's lazy init the file panel
|
||||
if(fLogFilePanel == NULL) {
|
||||
if (fLogFilePanel == NULL) {
|
||||
fLogFilePanel = new BFilePanel(B_SAVE_PANEL, &be_app_messenger,
|
||||
NULL, B_FILE_NODE, false);
|
||||
fLogFilePanel->SetMessage(message);
|
||||
@@ -273,71 +291,63 @@ void SerialWindow::MessageReceived(BMessage* message)
|
||||
parity_mode parity;
|
||||
uint32 flowcontrol;
|
||||
|
||||
if(message->FindInt32("databits", (int32*)&dataBits) == B_OK)
|
||||
{
|
||||
for(int i = 0; i < fDatabitsMenu->CountItems(); i++)
|
||||
{
|
||||
if (message->FindInt32("databits", (int32*)&dataBits) == B_OK) {
|
||||
for (int i = 0; i < fDatabitsMenu->CountItems(); i++) {
|
||||
BMenuItem* item = fDatabitsMenu->ItemAt(i);
|
||||
int32 code;
|
||||
item->Message()->FindInt32("databits", &code);
|
||||
|
||||
if(code == dataBits)
|
||||
if (code == dataBits)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(message->FindInt32("stopbits", (int32*)&stopBits) == B_OK)
|
||||
{
|
||||
for(int i = 0; i < fStopbitsMenu->CountItems(); i++)
|
||||
{
|
||||
if (message->FindInt32("stopbits", (int32*)&stopBits) == B_OK) {
|
||||
for (int i = 0; i < fStopbitsMenu->CountItems(); i++) {
|
||||
BMenuItem* item = fStopbitsMenu->ItemAt(i);
|
||||
int32 code;
|
||||
item->Message()->FindInt32("stopbits", &code);
|
||||
|
||||
if(code == stopBits)
|
||||
if (code == stopBits)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(message->FindInt32("parity", (int32*)&parity) == B_OK)
|
||||
if (message->FindInt32("parity", (int32*)&parity) == B_OK)
|
||||
{
|
||||
for(int i = 0; i < fParityMenu->CountItems(); i++)
|
||||
{
|
||||
for (int i = 0; i < fParityMenu->CountItems(); i++) {
|
||||
BMenuItem* item = fParityMenu->ItemAt(i);
|
||||
int32 code;
|
||||
item->Message()->FindInt32("parity", &code);
|
||||
|
||||
if(code == parity)
|
||||
if (code == parity)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(message->FindInt32("flowcontrol", (int32*)&flowcontrol) == B_OK)
|
||||
{
|
||||
for(int i = 0; i < fFlowcontrolMenu->CountItems(); i++)
|
||||
{
|
||||
if (message->FindInt32("flowcontrol", (int32*)&flowcontrol)
|
||||
== B_OK) {
|
||||
for (int i = 0; i < fFlowcontrolMenu->CountItems(); i++) {
|
||||
BMenuItem* item = fFlowcontrolMenu->ItemAt(i);
|
||||
int32 code;
|
||||
item->Message()->FindInt32("flowcontrol", &code);
|
||||
|
||||
if(code == (int32)flowcontrol)
|
||||
if (code == (int32)flowcontrol)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(message->FindInt32("baudrate", &baudrate) == B_OK)
|
||||
{
|
||||
for(int i = 0; i < fBaudrateMenu->CountItems(); i++)
|
||||
{
|
||||
if (message->FindInt32("baudrate", &baudrate) == B_OK) {
|
||||
for (int i = 0; i < fBaudrateMenu->CountItems(); i++) {
|
||||
BMenuItem* item = fBaudrateMenu->ItemAt(i);
|
||||
int32 code;
|
||||
item->Message()->FindInt32("baudrate", &code);
|
||||
|
||||
if(baudrate == code)
|
||||
if (baudrate == code)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -23,6 +23,7 @@ class SerialWindow: public BWindow
|
||||
|
||||
private:
|
||||
TermView* fTermView;
|
||||
|
||||
BMenu* fConnectionMenu;
|
||||
BMenu* fDatabitsMenu;
|
||||
BMenu* fStopbitsMenu;
|
||||
|
||||
@@ -11,27 +11,30 @@
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <Layout.h>
|
||||
#include <ScrollBar.h>
|
||||
|
||||
#include "SerialApp.h"
|
||||
|
||||
|
||||
struct ScrollBufferItem {
|
||||
int cols;
|
||||
VTermScreenCell cells[];
|
||||
};
|
||||
|
||||
|
||||
TermView::TermView()
|
||||
:
|
||||
BView("TermView", B_WILL_DRAW | B_FRAME_EVENTS)
|
||||
{
|
||||
SetFont(be_fixed_font);
|
||||
_Init();
|
||||
}
|
||||
|
||||
font_height height;
|
||||
GetFontHeight(&height);
|
||||
fFontHeight = height.ascent + height.descent + height.leading + 1;
|
||||
fFontWidth = be_fixed_font->StringWidth("X");
|
||||
fTerm = vterm_new(kDefaultHeight, kDefaultWidth);
|
||||
|
||||
fTermScreen = vterm_obtain_screen(fTerm);
|
||||
vterm_screen_set_callbacks(fTermScreen, &sScreenCallbacks, this);
|
||||
vterm_screen_reset(fTermScreen, 1);
|
||||
|
||||
vterm_parser_set_utf8(fTerm, 1);
|
||||
TermView::TermView(BRect r)
|
||||
:
|
||||
BView(r, "TermView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS)
|
||||
{
|
||||
_Init();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +44,8 @@ TermView::~TermView()
|
||||
}
|
||||
|
||||
|
||||
void TermView::AttachedToWindow()
|
||||
void
|
||||
TermView::AttachedToWindow()
|
||||
{
|
||||
MakeFocus();
|
||||
|
||||
@@ -49,7 +53,7 @@ void TermView::AttachedToWindow()
|
||||
VTermPos firstPos;
|
||||
firstPos.row = 0;
|
||||
firstPos.col = 0;
|
||||
vterm_screen_get_cell(fTermScreen, firstPos, &cell);
|
||||
_GetCell(firstPos, cell);
|
||||
|
||||
rgb_color background;
|
||||
background.red = cell.bg.red;
|
||||
@@ -61,17 +65,15 @@ void TermView::AttachedToWindow()
|
||||
}
|
||||
|
||||
|
||||
void TermView::Draw(BRect updateRect)
|
||||
void
|
||||
TermView::Draw(BRect updateRect)
|
||||
{
|
||||
VTermRect updatedChars = PixelsToGlyphs(updateRect);
|
||||
VTermRect updatedChars = _PixelsToGlyphs(updateRect);
|
||||
|
||||
VTermPos pos;
|
||||
font_height height;
|
||||
GetFontHeight(&height);
|
||||
|
||||
int availableRows, availableCols;
|
||||
vterm_get_size(fTerm, &availableRows, &availableCols);
|
||||
|
||||
for (pos.row = updatedChars.start_row; pos.row <= updatedChars.end_row;
|
||||
pos.row++) {
|
||||
float x = updatedChars.start_col * fFontWidth + kBorderSpacing;
|
||||
@@ -82,19 +84,7 @@ void TermView::Draw(BRect updateRect)
|
||||
pos.col <= updatedChars.end_col;) {
|
||||
VTermScreenCell cell;
|
||||
|
||||
if (pos.col < 0 || pos.row < 0 || pos.col >= availableCols
|
||||
|| pos.row >= availableRows) {
|
||||
|
||||
// All cells outside the used terminal area are drawn with the
|
||||
// same background color as the top-left one.
|
||||
VTermPos firstPos;
|
||||
firstPos.row = 0;
|
||||
firstPos.col = 0;
|
||||
vterm_screen_get_cell(fTermScreen, firstPos, &cell);
|
||||
cell.chars[0] = 0;
|
||||
cell.width = 1;
|
||||
} else
|
||||
vterm_screen_get_cell(fTermScreen, pos, &cell);
|
||||
_GetCell(pos, cell);
|
||||
|
||||
rgb_color foreground, background;
|
||||
foreground.red = cell.fg.red;
|
||||
@@ -119,7 +109,7 @@ void TermView::Draw(BRect updateRect)
|
||||
BPoint penLocation = PenLocation();
|
||||
FillRect(BRect(penLocation.x, penLocation.y - height.ascent,
|
||||
penLocation.x + cell.width * fFontWidth - 1,
|
||||
penLocation.y + height.descent + height.leading - 1),
|
||||
penLocation.y + height.descent + height.leading),
|
||||
B_SOLID_LOW);
|
||||
|
||||
if (cell.chars[0] == 0) {
|
||||
@@ -138,15 +128,17 @@ void TermView::Draw(BRect updateRect)
|
||||
}
|
||||
|
||||
|
||||
void TermView::FrameResized(float width, float height)
|
||||
void
|
||||
TermView::FrameResized(float width, float height)
|
||||
{
|
||||
VTermRect newSize = PixelsToGlyphs(BRect(0, 0, width - 2 * kBorderSpacing,
|
||||
VTermRect newSize = _PixelsToGlyphs(BRect(0, 0, width - 2 * kBorderSpacing,
|
||||
height - 2 * kBorderSpacing));
|
||||
vterm_set_size(fTerm, newSize.end_row, newSize.end_col);
|
||||
}
|
||||
|
||||
|
||||
void TermView::GetPreferredSize(float* width, float* height)
|
||||
void
|
||||
TermView::GetPreferredSize(float* width, float* height)
|
||||
{
|
||||
if (width != NULL)
|
||||
*width = kDefaultWidth * fFontWidth + 2 * kBorderSpacing;
|
||||
@@ -155,7 +147,8 @@ void TermView::GetPreferredSize(float* width, float* height)
|
||||
}
|
||||
|
||||
|
||||
void TermView::KeyDown(const char* bytes, int32 numBytes)
|
||||
void
|
||||
TermView::KeyDown(const char* bytes, int32 numBytes)
|
||||
{
|
||||
BMessage* keyEvent = new BMessage(kMsgDataWrite);
|
||||
keyEvent->AddData("data", B_RAW_TYPE, bytes, numBytes);
|
||||
@@ -163,7 +156,8 @@ void TermView::KeyDown(const char* bytes, int32 numBytes)
|
||||
}
|
||||
|
||||
|
||||
void TermView::MessageReceived(BMessage* message)
|
||||
void
|
||||
TermView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch(message->what)
|
||||
{
|
||||
@@ -183,7 +177,8 @@ void TermView::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
|
||||
void TermView::PushBytes(const char* bytes, size_t length)
|
||||
void
|
||||
TermView::PushBytes(const char* bytes, size_t length)
|
||||
{
|
||||
vterm_push_bytes(fTerm, bytes, length);
|
||||
}
|
||||
@@ -192,7 +187,27 @@ void TermView::PushBytes(const char* bytes, size_t length)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
VTermRect TermView::PixelsToGlyphs(BRect pixels) const
|
||||
void
|
||||
TermView::_Init()
|
||||
{
|
||||
SetFont(be_fixed_font);
|
||||
|
||||
font_height height;
|
||||
GetFontHeight(&height);
|
||||
fFontHeight = height.ascent + height.descent + height.leading + 1;
|
||||
fFontWidth = be_fixed_font->StringWidth("X");
|
||||
fTerm = vterm_new(kDefaultHeight, kDefaultWidth);
|
||||
|
||||
fTermScreen = vterm_obtain_screen(fTerm);
|
||||
vterm_screen_set_callbacks(fTermScreen, &sScreenCallbacks, this);
|
||||
vterm_screen_reset(fTermScreen, 1);
|
||||
|
||||
vterm_parser_set_utf8(fTerm, 1);
|
||||
}
|
||||
|
||||
|
||||
VTermRect
|
||||
TermView::_PixelsToGlyphs(BRect pixels) const
|
||||
{
|
||||
pixels.OffsetBy(-kBorderSpacing, -kBorderSpacing);
|
||||
|
||||
@@ -201,7 +216,7 @@ VTermRect TermView::PixelsToGlyphs(BRect pixels) const
|
||||
rect.end_col = (int)ceil(pixels.right / fFontWidth);
|
||||
rect.start_row = (int)floor(pixels.top / fFontHeight);
|
||||
rect.end_row = (int)ceil(pixels.bottom / fFontHeight);
|
||||
/*
|
||||
#if 0
|
||||
printf(
|
||||
"TOP %d ch < %f px\n"
|
||||
"BTM %d ch < %f px\n"
|
||||
@@ -212,12 +227,12 @@ VTermRect TermView::PixelsToGlyphs(BRect pixels) const
|
||||
rect.start_col, pixels.left,
|
||||
rect.end_col, pixels.right
|
||||
);
|
||||
*/
|
||||
#endif
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
BRect TermView::GlyphsToPixels(const VTermRect& glyphs) const
|
||||
BRect TermView::_GlyphsToPixels(const VTermRect& glyphs) const
|
||||
{
|
||||
BRect rect;
|
||||
rect.top = glyphs.start_row * fFontHeight;
|
||||
@@ -242,40 +257,128 @@ BRect TermView::GlyphsToPixels(const VTermRect& glyphs) const
|
||||
}
|
||||
|
||||
|
||||
BRect TermView::GlyphsToPixels(const int width, const int height) const
|
||||
BRect
|
||||
TermView::_GlyphsToPixels(const int width, const int height) const
|
||||
{
|
||||
VTermRect rect;
|
||||
rect.start_row = 0;
|
||||
rect.start_col = 0;
|
||||
rect.end_row = height;
|
||||
rect.end_col = width;
|
||||
return GlyphsToPixels(rect);
|
||||
return _GlyphsToPixels(rect);
|
||||
}
|
||||
|
||||
|
||||
void TermView::Damage(VTermRect rect)
|
||||
void
|
||||
TermView::_GetCell(VTermPos pos, VTermScreenCell& cell)
|
||||
{
|
||||
Invalidate();
|
||||
// Invalidate(GlyphsToPixels(rect));
|
||||
int availableRows, availableCols;
|
||||
vterm_get_size(fTerm, &availableRows, &availableCols);
|
||||
|
||||
if (pos.col < 0 || pos.row < -kScrollBackSize || pos.col >= availableCols
|
||||
|| pos.row >= availableRows) {
|
||||
// All cells outside the used terminal area are drawn with the same
|
||||
// background color as the top-left one.
|
||||
// TODO should they use the attributes of the closest neighbor instead?
|
||||
VTermPos firstPos;
|
||||
firstPos.row = 0;
|
||||
firstPos.col = 0;
|
||||
vterm_screen_get_cell(fTermScreen, firstPos, &cell);
|
||||
cell.chars[0] = 0;
|
||||
cell.width = 1;
|
||||
} else if (pos.row < 0) {
|
||||
// This is a cell from the scroll-back buffer
|
||||
int offset = - pos.row - 1;
|
||||
ScrollBufferItem* line = (ScrollBufferItem*)fScrollBuffer.ItemAt(offset);
|
||||
if (line == NULL || pos.col >= line->cols) {
|
||||
VTermPos firstPos;
|
||||
firstPos.row = 0;
|
||||
firstPos.col = 0;
|
||||
vterm_screen_get_cell(fTermScreen, firstPos, &cell);
|
||||
cell.chars[0] = 0;
|
||||
cell.width = 1;
|
||||
} else
|
||||
cell = line->cells[pos.col];
|
||||
} else
|
||||
vterm_screen_get_cell(fTermScreen, pos, &cell);
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
int TermView::Damage(VTermRect rect, void* user)
|
||||
void
|
||||
TermView::_Damage(VTermRect rect)
|
||||
{
|
||||
// Invalidate();
|
||||
Invalidate(_GlyphsToPixels(rect));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::_PushLine(int cols, const VTermScreenCell* cells)
|
||||
{
|
||||
ScrollBufferItem* item = (ScrollBufferItem*)malloc(sizeof(int)
|
||||
+ cols * sizeof(VTermScreenCell));
|
||||
item->cols = cols;
|
||||
memcpy(item->cells, cells, cols * sizeof(VTermScreenCell));
|
||||
|
||||
fScrollBuffer.AddItem(item, 0);
|
||||
|
||||
free(fScrollBuffer.RemoveItem(kScrollBackSize));
|
||||
|
||||
int availableRows, availableCols;
|
||||
vterm_get_size(fTerm, &availableRows, &availableCols);
|
||||
|
||||
VTermRect dirty;
|
||||
dirty.start_col = 0;
|
||||
dirty.end_col = availableCols;
|
||||
dirty.end_row = 0;
|
||||
dirty.start_row = -fScrollBuffer.CountItems();
|
||||
// FIXME we should rather use CopyRect if possible, and only invalidate the
|
||||
// newly exposed area here.
|
||||
Invalidate(_GlyphsToPixels(dirty));
|
||||
|
||||
BScrollBar* scrollBar = ScrollBar(B_VERTICAL);
|
||||
if (scrollBar != NULL) {
|
||||
// FIXME this is not exactly right, it's off by a few pixels so one step
|
||||
// isn't exactly equal to one line.
|
||||
float range = (fScrollBuffer.CountItems() + availableRows) * fFontHeight;
|
||||
scrollBar->SetRange(availableRows * fFontHeight - range, 0.0f);
|
||||
// TODO we need to adjust this in FrameResized, as availableRows can
|
||||
// change
|
||||
scrollBar->SetProportion(availableRows * fFontHeight / range);
|
||||
scrollBar->SetSteps(fFontHeight, fFontHeight * 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */ int
|
||||
TermView::_Damage(VTermRect rect, void* user)
|
||||
{
|
||||
TermView* view = (TermView*)user;
|
||||
view->Damage(rect);
|
||||
view->_Damage(rect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const VTermScreenCallbacks TermView::sScreenCallbacks = {
|
||||
&TermView::Damage,
|
||||
/* static */ int
|
||||
TermView::_PushLine(int cols, const VTermScreenCell* cells, void* user)
|
||||
{
|
||||
TermView* view = (TermView*)user;
|
||||
view->_PushLine(cols, cells);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const
|
||||
VTermScreenCallbacks TermView::sScreenCallbacks = {
|
||||
&TermView::_Damage,
|
||||
/*.moverect =*/ NULL,
|
||||
/*.movecursor =*/ NULL,
|
||||
/*.settermprop =*/ NULL,
|
||||
/*.setmousefunc =*/ NULL,
|
||||
/*.bell =*/ NULL,
|
||||
/*.resize =*/ NULL,
|
||||
&TermView::_PushLine,
|
||||
/*.sb_popline =*/ NULL,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012, Adrien Destugues, [email protected]
|
||||
* Copyright 2012-2014, Adrien Destugues, [email protected]
|
||||
* Distributed under the terms of the MIT licence.
|
||||
*/
|
||||
|
||||
@@ -10,31 +10,45 @@ extern "C" {
|
||||
#include <vterm.h>
|
||||
}
|
||||
|
||||
|
||||
class TermView: public BView
|
||||
{
|
||||
public:
|
||||
TermView();
|
||||
~TermView();
|
||||
TermView();
|
||||
TermView(BRect bounds);
|
||||
~TermView();
|
||||
|
||||
void AttachedToWindow();
|
||||
void Draw(BRect updateRect);
|
||||
void FrameResized(float width, float height);
|
||||
void GetPreferredSize(float* width, float* height);
|
||||
void KeyDown(const char* bytes, int32 numBytes);
|
||||
void MessageReceived(BMessage* message);
|
||||
|
||||
void PushBytes(const char* bytes, const size_t length);
|
||||
|
||||
void AttachedToWindow();
|
||||
void Draw(BRect updateRect);
|
||||
void FrameResized(float width, float height);
|
||||
void GetPreferredSize(float* width, float* height);
|
||||
void KeyDown(const char* bytes, int32 numBytes);
|
||||
void MessageReceived(BMessage* message);
|
||||
void PushBytes(const char* bytes, const size_t length);
|
||||
|
||||
private:
|
||||
VTermRect PixelsToGlyphs(BRect pixels) const;
|
||||
BRect GlyphsToPixels(const VTermRect& glyphs) const;
|
||||
BRect GlyphsToPixels(const int width, const int height) const;
|
||||
void Damage(VTermRect rect);
|
||||
void _Init();
|
||||
|
||||
static int Damage(VTermRect rect, void* user);
|
||||
VTermRect _PixelsToGlyphs(BRect pixels) const;
|
||||
BRect _GlyphsToPixels(const VTermRect& glyphs) const;
|
||||
BRect _GlyphsToPixels(const int width, const int height)
|
||||
const;
|
||||
void _GetCell(VTermPos pos, VTermScreenCell& cell);
|
||||
|
||||
void _Damage(VTermRect rect);
|
||||
void _PushLine(int cols, const VTermScreenCell* cells);
|
||||
|
||||
static int _Damage(VTermRect rect, void* user);
|
||||
static int _PushLine(int cols, const VTermScreenCell* cells,
|
||||
void* user);
|
||||
static int _PopLine(int cols, const VTermScreenCell* cells,
|
||||
void* user);
|
||||
|
||||
private:
|
||||
VTerm* fTerm;
|
||||
VTermScreen* fTermScreen;
|
||||
BList fScrollBuffer;
|
||||
float fFontWidth;
|
||||
float fFontHeight;
|
||||
|
||||
@@ -43,4 +57,5 @@ class TermView: public BView
|
||||
static const int kDefaultWidth = 80;
|
||||
static const int kDefaultHeight = 25;
|
||||
static const int kBorderSpacing = 3;
|
||||
static const int kScrollBackSize = 1000;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user