This is a minimalistic version of a terminal.
It can be run under R5 and Haiku (binary compatible) and should work with the Haiku app_server and input_server. It gives access to a /bin/sh like a normal terminal, but has no fancy features like different text encoding support and it cannot even redraw itself when something else overdraws it. But it's pretty impressiv that it works so well under Haiku. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12068 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6109122c9b
commit
160bd2ffca
576
src/tests/apps/miniterminal/Console.cpp
Normal file
576
src/tests/apps/miniterminal/Console.cpp
Normal file
@ -0,0 +1,576 @@
|
||||
/*
|
||||
* Console.cpp - Mimicing the console driver
|
||||
* Based on the console driver.
|
||||
*
|
||||
* Copyright 2005 Michael Lotz. All rights reserved.
|
||||
* Distributed under the Haiku License.
|
||||
*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include "Console.h"
|
||||
#include "ViewBuffer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
Console::Console(ViewBuffer *output)
|
||||
: fOutput(output)
|
||||
{
|
||||
fOutput->GetSize(&fColumns, &fLines);
|
||||
fOutput->SetResizeCallback(&ResizeCallback, this);
|
||||
ResetConsole();
|
||||
GotoXY(0, 0);
|
||||
SaveCursor(true);
|
||||
fOutput->Clear(0x0f);
|
||||
}
|
||||
|
||||
|
||||
Console::~Console()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::ResetConsole()
|
||||
{
|
||||
fAttr = 0x0f;
|
||||
fScrollTop = 0;
|
||||
fScrollBottom = fLines - 1;
|
||||
fBrightAttr = true;
|
||||
fReverseAttr = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::ResizeCallback(int32 width, int32 height, void *data)
|
||||
{
|
||||
Console *console = (Console *)data;
|
||||
|
||||
console->fColumns = width;
|
||||
console->fLines = height;
|
||||
console->SetScrollRegion(console->fScrollTop, height - 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::SetScrollRegion(int top, int bottom)
|
||||
{
|
||||
if (top < 0)
|
||||
top = 0;
|
||||
if (bottom >= fLines)
|
||||
bottom = fLines - 1;
|
||||
if (top > bottom)
|
||||
return;
|
||||
|
||||
fScrollTop = top;
|
||||
fScrollBottom = bottom;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::ScrollUp()
|
||||
{
|
||||
// see if cursor is outside of scroll region
|
||||
if (fY < fScrollTop || fY > fScrollBottom)
|
||||
return;
|
||||
|
||||
if (fY - fScrollTop > 1) {
|
||||
// move the screen up one
|
||||
fOutput->Blit(0, fScrollTop + 1, fColumns, fY - fScrollTop, 0, fScrollTop);
|
||||
}
|
||||
|
||||
// clear the bottom line
|
||||
fOutput->FillGlyph(0, fY, fColumns, 1, ' ', fAttr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::ScrollDown()
|
||||
{
|
||||
// see if cursor is outside of scroll region
|
||||
if (fY < fScrollTop || fY > fScrollBottom)
|
||||
return;
|
||||
|
||||
if (fScrollBottom - fY > 1) {
|
||||
// move the screen down one
|
||||
fOutput->Blit(0, fY, fColumns, fScrollBottom - fY, 0, fY + 1);
|
||||
}
|
||||
|
||||
// clear the top line
|
||||
fOutput->FillGlyph(0, fY, fColumns, 1, ' ', fAttr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::LineFeed()
|
||||
{
|
||||
if (fY == fScrollBottom) {
|
||||
// we hit the bottom of our scroll region
|
||||
ScrollUp();
|
||||
} else if (fY < fScrollBottom) {
|
||||
fY++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::RLineFeed()
|
||||
{
|
||||
if (fY == fScrollTop) {
|
||||
// we hit the top of our scroll region
|
||||
ScrollDown();
|
||||
} else if (fY > fScrollTop) {
|
||||
fY--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::CariageReturn()
|
||||
{
|
||||
fX = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::Delete()
|
||||
{
|
||||
if (fX > 0) {
|
||||
fX--;
|
||||
} else if (fY > 0) {
|
||||
fY--;
|
||||
fX = fColumns - 1;
|
||||
} else {
|
||||
ScrollDown();
|
||||
fY--;
|
||||
fX = fColumns - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fOutput->PutGlyph(fX, fY, ' ', fAttr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::Tab()
|
||||
{
|
||||
fX = (fX + TAB_SIZE) & ~TAB_MASK;
|
||||
if (fX >= fColumns) {
|
||||
fX -= fColumns;
|
||||
LineFeed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::EraseLine(erase_line_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case LINE_ERASE_WHOLE:
|
||||
fOutput->FillGlyph(0, fY, fColumns, 1, ' ', fAttr);
|
||||
break;
|
||||
case LINE_ERASE_LEFT:
|
||||
fOutput->FillGlyph(0, fY, fX + 1, 1, ' ', fAttr);
|
||||
break;
|
||||
case LINE_ERASE_RIGHT:
|
||||
fOutput->FillGlyph(fX, fY, fColumns - fX, 1, ' ', fAttr);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::EraseScreen(erase_screen_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case SCREEN_ERASE_WHOLE:
|
||||
fOutput->Clear(fAttr);
|
||||
break;
|
||||
case SCREEN_ERASE_UP:
|
||||
fOutput->FillGlyph(0, 0, fColumns, fY + 1, ' ', fAttr);
|
||||
break;
|
||||
case SCREEN_ERASE_DOWN:
|
||||
fOutput->FillGlyph(fY, 0, fColumns, fLines - fY, ' ', fAttr);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::SaveCursor(bool save_attrs)
|
||||
{
|
||||
fSavedX = fX;
|
||||
fSavedY = fY;
|
||||
|
||||
if (save_attrs)
|
||||
fSavedAttr = fAttr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::RestoreCursor(bool restore_attrs)
|
||||
{
|
||||
fX = fSavedX;
|
||||
fY = fSavedY;
|
||||
|
||||
if (restore_attrs)
|
||||
fAttr = fSavedAttr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::UpdateCursor(int x, int y)
|
||||
{
|
||||
fOutput->MoveCursor(x, y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::GotoXY(int new_x, int new_y)
|
||||
{
|
||||
if (new_x >= fColumns)
|
||||
new_x = fColumns - 1;
|
||||
if (new_x < 0)
|
||||
new_x = 0;
|
||||
if (new_y >= fLines)
|
||||
new_y = fLines - 1;
|
||||
if (new_y < 0)
|
||||
new_y = 0;
|
||||
|
||||
fX = new_x;
|
||||
fY = new_y;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::PutChar(const char c)
|
||||
{
|
||||
fOutput->PutGlyph(fX, fY, c, fAttr);
|
||||
if (++fX >= fColumns) {
|
||||
CariageReturn();
|
||||
LineFeed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::SetVT100Attributes(int32 *args, int32 argCount)
|
||||
{
|
||||
if (argCount == 0) {
|
||||
// that's the default (attributes off)
|
||||
argCount++;
|
||||
args[0] = 0;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < argCount; i++) {
|
||||
switch (args[i]) {
|
||||
case 0: // reset
|
||||
fAttr = 0x0f;
|
||||
fBrightAttr = true;
|
||||
fReverseAttr = false;
|
||||
break;
|
||||
case 1: // bright
|
||||
fBrightAttr = true;
|
||||
fAttr |= 0x08; // set the bright bit
|
||||
break;
|
||||
case 2: // dim
|
||||
fBrightAttr = false;
|
||||
fAttr &= ~0x08; // unset the bright bit
|
||||
break;
|
||||
case 4: // underscore we can't do
|
||||
break;
|
||||
case 5: // blink
|
||||
fAttr |= 0x80; // set the blink bit
|
||||
break;
|
||||
case 7: // reverse
|
||||
fReverseAttr = true;
|
||||
fAttr = ((fAttr & BMASK) >> 4) | ((fAttr & FMASK) << 4);
|
||||
if (fBrightAttr)
|
||||
fAttr |= 0x08;
|
||||
break;
|
||||
case 8: // hidden?
|
||||
break;
|
||||
|
||||
/* foreground colors */
|
||||
case 30: fAttr = (fAttr & ~FMASK) | 0 | (fBrightAttr ? 0x08 : 0); break; // black
|
||||
case 31: fAttr = (fAttr & ~FMASK) | 4 | (fBrightAttr ? 0x08 : 0); break; // red
|
||||
case 32: fAttr = (fAttr & ~FMASK) | 2 | (fBrightAttr ? 0x08 : 0); break; // green
|
||||
case 33: fAttr = (fAttr & ~FMASK) | 6 | (fBrightAttr ? 0x08 : 0); break; // yellow
|
||||
case 34: fAttr = (fAttr & ~FMASK) | 1 | (fBrightAttr ? 0x08 : 0); break; // blue
|
||||
case 35: fAttr = (fAttr & ~FMASK) | 5 | (fBrightAttr ? 0x08 : 0); break; // magenta
|
||||
case 36: fAttr = (fAttr & ~FMASK) | 3 | (fBrightAttr ? 0x08 : 0); break; // cyan
|
||||
case 37: fAttr = (fAttr & ~FMASK) | 7 | (fBrightAttr ? 0x08 : 0); break; // white
|
||||
|
||||
/* background colors */
|
||||
case 40: fAttr = (fAttr & ~BMASK) | (0 << 4); break; // black
|
||||
case 41: fAttr = (fAttr & ~BMASK) | (4 << 4); break; // red
|
||||
case 42: fAttr = (fAttr & ~BMASK) | (2 << 4); break; // green
|
||||
case 43: fAttr = (fAttr & ~BMASK) | (6 << 4); break; // yellow
|
||||
case 44: fAttr = (fAttr & ~BMASK) | (1 << 4); break; // blue
|
||||
case 45: fAttr = (fAttr & ~BMASK) | (5 << 4); break; // magenta
|
||||
case 46: fAttr = (fAttr & ~BMASK) | (3 << 4); break; // cyan
|
||||
case 47: fAttr = (fAttr & ~BMASK) | (7 << 4); break; // white
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Console::ProcessVT100Command(const char c, bool seen_bracket, int32 *args, int32 argCount)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (seen_bracket) {
|
||||
switch(c) {
|
||||
case 'H': /* set cursor position */
|
||||
case 'f': {
|
||||
int32 row = argCount > 0 ? args[0] : 1;
|
||||
int32 col = argCount > 1 ? args[1] : 1;
|
||||
if (row > 0)
|
||||
row--;
|
||||
if (col > 0)
|
||||
col--;
|
||||
GotoXY(col, row);
|
||||
break;
|
||||
}
|
||||
case 'A': { /* move up */
|
||||
int32 deltay = argCount > 0 ? -args[0] : -1;
|
||||
if (deltay == 0)
|
||||
deltay = -1;
|
||||
GotoXY(fX, fY + deltay);
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
case 'B': { /* move down */
|
||||
int32 deltay = argCount > 0 ? args[0] : 1;
|
||||
if (deltay == 0)
|
||||
deltay = 1;
|
||||
GotoXY(fX, fY + deltay);
|
||||
break;
|
||||
}
|
||||
case 'D': { /* move left */
|
||||
int32 deltax = argCount > 0 ? -args[0] : -1;
|
||||
if (deltax == 0)
|
||||
deltax = -1;
|
||||
GotoXY(fX + deltax, fY);
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
case 'C': { /* move right */
|
||||
int32 deltax = argCount > 0 ? args[0] : 1;
|
||||
if (deltax == 0)
|
||||
deltax = 1;
|
||||
GotoXY(fX + deltax, fY);
|
||||
break;
|
||||
}
|
||||
case '`':
|
||||
case 'G': { /* set X position */
|
||||
int32 newx = argCount > 0 ? args[0] : 1;
|
||||
if (newx > 0)
|
||||
newx--;
|
||||
GotoXY(newx, fY);
|
||||
break;
|
||||
}
|
||||
case 'd': { /* set y position */
|
||||
int32 newy = argCount > 0 ? args[0] : 1;
|
||||
if (newy > 0)
|
||||
newy--;
|
||||
GotoXY(fX, newy);
|
||||
break;
|
||||
}
|
||||
case 's': /* save current cursor */
|
||||
SaveCursor(false);
|
||||
break;
|
||||
case 'u': /* restore cursor */
|
||||
RestoreCursor(false);
|
||||
break;
|
||||
case 'r': { /* set scroll region */
|
||||
int32 low = argCount > 0 ? args[0] : 1;
|
||||
int32 high = argCount > 1 ? args[1] : fLines;
|
||||
if (low <= high)
|
||||
SetScrollRegion(low - 1, high - 1);
|
||||
break;
|
||||
}
|
||||
case 'L': { /* scroll virtual down at cursor */
|
||||
int32 lines = argCount > 0 ? args[0] : 1;
|
||||
while (lines > 0) {
|
||||
ScrollDown();
|
||||
lines--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'M': { /* scroll virtual up at cursor */
|
||||
int32 lines = argCount > 0 ? args[0] : 1;
|
||||
while (lines > 0) {
|
||||
ScrollUp();
|
||||
lines--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'K':
|
||||
if (argCount == 0 || args[0] == 0) {
|
||||
// erase to end of line
|
||||
EraseLine(LINE_ERASE_RIGHT);
|
||||
} else if (argCount > 0) {
|
||||
if (args[0] == 1)
|
||||
EraseLine(LINE_ERASE_LEFT);
|
||||
else if (args[0] == 2)
|
||||
EraseLine(LINE_ERASE_WHOLE);
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
if (argCount == 0 || args[0] == 0) {
|
||||
// erase to end of screen
|
||||
EraseScreen(SCREEN_ERASE_DOWN);
|
||||
} else if (argCount > 0) {
|
||||
if (args[0] == 1)
|
||||
EraseScreen(SCREEN_ERASE_UP);
|
||||
else if (args[0] == 2)
|
||||
EraseScreen(SCREEN_ERASE_WHOLE);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (argCount >= 0)
|
||||
SetVT100Attributes(args, argCount);
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
}
|
||||
} else {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
ResetConsole();
|
||||
break;
|
||||
case 'D':
|
||||
RLineFeed();
|
||||
break;
|
||||
case 'M':
|
||||
LineFeed();
|
||||
break;
|
||||
case '7':
|
||||
SaveCursor(true);
|
||||
break;
|
||||
case '8':
|
||||
RestoreCursor(true);
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::Write(const void *buf, size_t len)
|
||||
{
|
||||
UpdateCursor(-1, -1); // hide the cursor
|
||||
|
||||
const char *c;
|
||||
size_t pos = 0;
|
||||
|
||||
while (pos < len) {
|
||||
c = &((const char *)buf)[pos++];
|
||||
|
||||
switch (fState) {
|
||||
case CONSOLE_STATE_NORMAL:
|
||||
// just output the stuff
|
||||
switch (*c) {
|
||||
case '\n':
|
||||
LineFeed();
|
||||
break;
|
||||
case '\r':
|
||||
CariageReturn();
|
||||
break;
|
||||
case 0x8: // backspace
|
||||
Delete();
|
||||
break;
|
||||
case '\t':
|
||||
Tab();
|
||||
break;
|
||||
case '\a':
|
||||
// beep
|
||||
printf("<BEEP>\n");
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
case 0x1b:
|
||||
// escape character
|
||||
fArgCount = -1;
|
||||
fState = CONSOLE_STATE_GOT_ESCAPE;
|
||||
break;
|
||||
default:
|
||||
PutChar(*c);
|
||||
}
|
||||
break;
|
||||
case CONSOLE_STATE_GOT_ESCAPE:
|
||||
// look for either commands with no argument, or the '[' character
|
||||
switch (*c) {
|
||||
case '[':
|
||||
fState = CONSOLE_STATE_SEEN_BRACKET;
|
||||
break;
|
||||
default:
|
||||
fArgs[fArgCount] = 0;
|
||||
ProcessVT100Command(*c, false, fArgs, fArgCount + 1);
|
||||
fState = CONSOLE_STATE_NORMAL;
|
||||
}
|
||||
break;
|
||||
case CONSOLE_STATE_SEEN_BRACKET:
|
||||
switch (*c) {
|
||||
case '0'...'9':
|
||||
fArgCount = 0;
|
||||
fArgs[fArgCount] = *c - '0';
|
||||
fState = CONSOLE_STATE_PARSING_ARG;
|
||||
break;
|
||||
case '?':
|
||||
// private DEC mode parameter follows - we ignore those anyway
|
||||
// ToDo: check if it was really used in combination with a mode command
|
||||
break;
|
||||
default:
|
||||
ProcessVT100Command(*c, true, fArgs, fArgCount + 1);
|
||||
fState = CONSOLE_STATE_NORMAL;
|
||||
}
|
||||
break;
|
||||
case CONSOLE_STATE_NEW_ARG:
|
||||
switch (*c) {
|
||||
case '0'...'9':
|
||||
fArgCount++;
|
||||
if (fArgCount == MAX_ARGS) {
|
||||
fState = CONSOLE_STATE_NORMAL;
|
||||
break;
|
||||
}
|
||||
fArgs[fArgCount] = *c - '0';
|
||||
fState = CONSOLE_STATE_PARSING_ARG;
|
||||
break;
|
||||
default:
|
||||
ProcessVT100Command(*c, true, fArgs, fArgCount + 1);
|
||||
fState = CONSOLE_STATE_NORMAL;
|
||||
}
|
||||
break;
|
||||
case CONSOLE_STATE_PARSING_ARG:
|
||||
// parse args
|
||||
switch (*c) {
|
||||
case '0'...'9':
|
||||
fArgs[fArgCount] *= 10;
|
||||
fArgs[fArgCount] += *c - '0';
|
||||
break;
|
||||
case ';':
|
||||
fState = CONSOLE_STATE_NEW_ARG;
|
||||
break;
|
||||
default:
|
||||
ProcessVT100Command(*c, true, fArgs, fArgCount + 1);
|
||||
fState = CONSOLE_STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCursor(fX, fY); // show it again
|
||||
}
|
96
src/tests/apps/miniterminal/Console.h
Normal file
96
src/tests/apps/miniterminal/Console.h
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef _CONSOLE_H_
|
||||
#define _CONSOLE_H_
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#define TAB_SIZE 8
|
||||
#define TAB_MASK 7
|
||||
|
||||
#define FMASK 0x0f
|
||||
#define BMASK 0x70
|
||||
|
||||
typedef enum {
|
||||
CONSOLE_STATE_NORMAL = 0,
|
||||
CONSOLE_STATE_GOT_ESCAPE,
|
||||
CONSOLE_STATE_SEEN_BRACKET,
|
||||
CONSOLE_STATE_NEW_ARG,
|
||||
CONSOLE_STATE_PARSING_ARG,
|
||||
} console_state;
|
||||
|
||||
typedef enum {
|
||||
SCREEN_ERASE_WHOLE,
|
||||
SCREEN_ERASE_UP,
|
||||
SCREEN_ERASE_DOWN
|
||||
} erase_screen_mode;
|
||||
|
||||
typedef enum {
|
||||
LINE_ERASE_WHOLE,
|
||||
LINE_ERASE_LEFT,
|
||||
LINE_ERASE_RIGHT
|
||||
} erase_line_mode;
|
||||
|
||||
#define MAX_ARGS 8
|
||||
|
||||
class ViewBuffer;
|
||||
|
||||
class Console {
|
||||
public:
|
||||
Console(ViewBuffer *output);
|
||||
~Console();
|
||||
|
||||
void ResetConsole();
|
||||
|
||||
void SetScrollRegion(int top, int bottom);
|
||||
void ScrollUp();
|
||||
void ScrollDown();
|
||||
|
||||
void LineFeed();
|
||||
void RLineFeed();
|
||||
void CariageReturn();
|
||||
|
||||
void Delete();
|
||||
void Tab();
|
||||
|
||||
void EraseLine(erase_line_mode mode);
|
||||
void EraseScreen(erase_screen_mode mode);
|
||||
|
||||
void SaveCursor(bool save_attrs);
|
||||
void RestoreCursor(bool restore_attrs);
|
||||
void UpdateCursor(int x, int y);
|
||||
void GotoXY(int new_x, int new_y);
|
||||
|
||||
void PutChar(const char c);
|
||||
|
||||
void SetVT100Attributes(int32 *args, int32 argCount);
|
||||
bool ProcessVT100Command(const char c, bool seen_bracket, int32 *args, int32 argCount);
|
||||
|
||||
void Write(const void *buf, size_t len);
|
||||
|
||||
private:
|
||||
static void ResizeCallback(int32 width, int32 height, void *data);
|
||||
|
||||
int32 fLines;
|
||||
int32 fColumns;
|
||||
|
||||
uint8 fAttr;
|
||||
uint8 fSavedAttr;
|
||||
bool fBrightAttr;
|
||||
bool fReverseAttr;
|
||||
|
||||
int32 fX; // current x coordinate
|
||||
int32 fY; // current y coordinate
|
||||
int32 fSavedX; // used to save x and y
|
||||
int32 fSavedY;
|
||||
|
||||
int32 fScrollTop; // top of the scroll region
|
||||
int32 fScrollBottom; // bottom of the scroll region
|
||||
|
||||
/* state machine */
|
||||
console_state fState;
|
||||
int32 fArgCount;
|
||||
int32 fArgs[MAX_ARGS];
|
||||
|
||||
ViewBuffer *fOutput;
|
||||
};
|
||||
|
||||
#endif
|
13
src/tests/apps/miniterminal/Jamfile
Normal file
13
src/tests/apps/miniterminal/Jamfile
Normal file
@ -0,0 +1,13 @@
|
||||
SubDir OBOS_TOP src tests apps miniterminal ;
|
||||
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src tests apps miniterminal ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src apps terminal MYOB ] ;
|
||||
|
||||
App MiniTerminal :
|
||||
MiniApp.cpp
|
||||
MiniWin.cpp
|
||||
MiniView.cpp
|
||||
Console.cpp
|
||||
ViewBuffer.cpp ;
|
||||
|
||||
LinkSharedOSLibs MiniTerminal : libbe.so ;
|
39
src/tests/apps/miniterminal/MiniApp.cpp
Normal file
39
src/tests/apps/miniterminal/MiniApp.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Part of the MiniTerminal.
|
||||
*
|
||||
* Copyright 2005 Michael Lotz. All rights reserved.
|
||||
* Distributed under the Haiku License.
|
||||
*/
|
||||
|
||||
#include "MiniApp.h"
|
||||
#include "MiniWin.h"
|
||||
#include "MiniView.h"
|
||||
|
||||
MiniApp::MiniApp()
|
||||
: BApplication("application/x-vnd.Haiku.MiniTerminal")
|
||||
{
|
||||
fWindow = new MiniWin(BRect(50, 50, 630, 435));
|
||||
fWindow->Show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MiniApp::ReadyToRun()
|
||||
{
|
||||
fWindow->View()->Start();
|
||||
}
|
||||
|
||||
|
||||
MiniApp::~MiniApp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
MiniApp *app = new MiniApp();
|
||||
app->Run();
|
||||
delete app;
|
||||
return 0;
|
||||
}
|
19
src/tests/apps/miniterminal/MiniApp.h
Normal file
19
src/tests/apps/miniterminal/MiniApp.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _MINI_APP_H_
|
||||
#define _MINI_APP_H_
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
class MiniWin;
|
||||
|
||||
class MiniApp : public BApplication {
|
||||
public:
|
||||
MiniApp();
|
||||
virtual ~MiniApp();
|
||||
|
||||
virtual void ReadyToRun();
|
||||
|
||||
private:
|
||||
MiniWin *fWindow;
|
||||
};
|
||||
|
||||
#endif
|
306
src/tests/apps/miniterminal/MiniView.cpp
Normal file
306
src/tests/apps/miniterminal/MiniView.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* MiniTerminal - A basic windowed terminal to allow
|
||||
* command-line interaction from within app_server.
|
||||
* Based on consoled and MuTerminal.
|
||||
*
|
||||
* Copyright 2005 Michael Lotz. All rights reserved.
|
||||
* Distributed under the Haiku License.
|
||||
*
|
||||
* Copyright 2004-2005, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <image.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "MiniView.h"
|
||||
#include "Console.h"
|
||||
|
||||
#include "VTkeymap.h"
|
||||
|
||||
//#define TRACE_MINI_TERMINAL
|
||||
#ifdef TRACE_MINI_TERMINAL
|
||||
#ifdef __HAIKU__
|
||||
#define TRACE(x) debug_printf x
|
||||
#else
|
||||
#define TRACE(x) printf x
|
||||
#endif
|
||||
#else
|
||||
#define TRACE(x)
|
||||
#endif
|
||||
|
||||
void
|
||||
Setenv(const char *var, const char *value)
|
||||
{
|
||||
int envindex = 0;
|
||||
const int len = strlen(var);
|
||||
const int val_len = strlen (value);
|
||||
|
||||
while (environ [envindex] != NULL) {
|
||||
if (strncmp (environ [envindex], var, len) == 0) {
|
||||
/* found it */
|
||||
environ[envindex] = (char *)malloc ((unsigned)len + val_len + 1);
|
||||
sprintf (environ [envindex], "%s%s", var, value);
|
||||
return;
|
||||
}
|
||||
envindex ++;
|
||||
}
|
||||
|
||||
environ [envindex] = (char *) malloc ((unsigned)len + val_len + 1);
|
||||
sprintf (environ [envindex], "%s%s", var, value);
|
||||
environ [++envindex] = NULL;
|
||||
}
|
||||
|
||||
static int32
|
||||
ConsoleWriter(void *arg)
|
||||
{
|
||||
char buf[1024];
|
||||
ssize_t len;
|
||||
MiniView *view = (MiniView *)arg;
|
||||
|
||||
for (;;) {
|
||||
len = read(view->fMasterFD, buf, sizeof(buf));
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
view->fConsole->Write(buf, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32
|
||||
ExecuteShell(void *arg)
|
||||
{
|
||||
MiniView *view = (MiniView *)arg;
|
||||
|
||||
for (;;) {
|
||||
const char *argv[3];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "--login";
|
||||
argv[2] = NULL;
|
||||
|
||||
int saved_stdin = dup(0);
|
||||
int saved_stdout = dup(1);
|
||||
int saved_stderr = dup(2);
|
||||
|
||||
dup2(view->fSlaveFD, 0);
|
||||
dup2(view->fSlaveFD, 1);
|
||||
dup2(view->fSlaveFD, 2);
|
||||
|
||||
thread_id shell = load_image(2, argv, (const char **)environ);
|
||||
setpgid(shell, 0);
|
||||
|
||||
status_t return_code;
|
||||
wait_for_thread(shell, &return_code);
|
||||
|
||||
dup2(saved_stdin, 0);
|
||||
dup2(saved_stdout, 1);
|
||||
dup2(saved_stderr, 2);
|
||||
close(saved_stdin);
|
||||
close(saved_stdout);
|
||||
close(saved_stderr);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
MiniView::MiniView(BRect frame)
|
||||
: ViewBuffer(frame)
|
||||
{
|
||||
}
|
||||
|
||||
MiniView::~MiniView()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MiniView::Start()
|
||||
{
|
||||
fConsole = new Console(this);
|
||||
|
||||
if (OpenTTY() != B_OK) {
|
||||
TRACE(("error in OpenTTY\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// we're a session leader
|
||||
setsid();
|
||||
|
||||
// move our stdin and stdout to the console
|
||||
dup2(fSlaveFD, 0);
|
||||
dup2(fSlaveFD, 1);
|
||||
dup2(fSlaveFD, 2);
|
||||
|
||||
if (SpawnThreads() != B_OK)
|
||||
TRACE(("error in SpawnThreads\n"));
|
||||
}
|
||||
|
||||
status_t
|
||||
MiniView::OpenTTY()
|
||||
{
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir("/dev/pt");
|
||||
if (dir != NULL) {
|
||||
struct dirent *entry;
|
||||
char name[64];
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_name[0] == '.') // filter out . and ..
|
||||
continue;
|
||||
|
||||
sprintf(name, "/dev/pt/%s", entry->d_name);
|
||||
|
||||
fMasterFD = open(name, O_RDWR);
|
||||
if (fMasterFD >= 0) {
|
||||
sprintf(name, "/dev/tt/%s", entry->d_name);
|
||||
|
||||
fSlaveFD = open(name, O_RDWR);
|
||||
if (fSlaveFD < 0) {
|
||||
TRACE(("cannot open tty\n"));
|
||||
close(fMasterFD);
|
||||
} else {
|
||||
struct termios tio;
|
||||
tcgetattr(fSlaveFD, &tio);
|
||||
|
||||
// set signal default
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGTTOU, SIG_DFL);
|
||||
|
||||
// set terminal interface
|
||||
tio.c_line = 0;
|
||||
tio.c_lflag |= ECHOE;
|
||||
|
||||
// input: nl->nl, cr->nl
|
||||
tio.c_iflag &= ~(INLCR|IGNCR);
|
||||
tio.c_iflag |= ICRNL;
|
||||
tio.c_iflag &= ~ISTRIP;
|
||||
|
||||
// output: cr->cr, nl in not retrun, no delays, ln->cr/ln
|
||||
tio.c_oflag &= ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
|
||||
tio.c_oflag |= ONLCR;
|
||||
tio.c_oflag |= OPOST;
|
||||
|
||||
// baud rate is 19200 (equal to beterm)
|
||||
tio.c_cflag &= ~(CBAUD);
|
||||
tio.c_cflag |= B19200;
|
||||
|
||||
tio.c_cflag &= ~CSIZE;
|
||||
tio.c_cflag |= CS8;
|
||||
tio.c_cflag |= CREAD;
|
||||
|
||||
tio.c_cflag |= HUPCL;
|
||||
tio.c_iflag &= ~(IGNBRK|BRKINT);
|
||||
|
||||
// enable signals, canonical processing (erase, kill, etc), echo
|
||||
tio.c_lflag |= ISIG|ICANON|ECHO|ECHOE|ECHONL;
|
||||
tio.c_lflag &= ~ECHOK;
|
||||
|
||||
tio.c_lflag &= ~IEXTEN;
|
||||
|
||||
// set control charactors
|
||||
tio.c_cc[VINTR] = 'C' & 0x1f; /* '^C' */
|
||||
tio.c_cc[VQUIT] = '\\'& 0x1f; /* '^\' */
|
||||
tio.c_cc[VERASE] = 0x08; /* '^H' */
|
||||
tio.c_cc[VKILL] = 'U' & 0x1f; /* '^U' */
|
||||
tio.c_cc[VEOF] = 'D' & 0x1f; /* '^D' */
|
||||
tio.c_cc[VEOL] = 0; /* '^@' */
|
||||
tio.c_cc[VMIN] = 4;
|
||||
tio.c_cc[VTIME] = 0;
|
||||
tio.c_cc[VEOL2] = 0; /* '^@' */
|
||||
tio.c_cc[VSWTCH] = 0; /* '^@' */
|
||||
tio.c_cc[VSTART] = 'S' & 0x1f; /* '^S' */
|
||||
tio.c_cc[VSTOP] = 'Q' & 0x1f; /* '^Q' */
|
||||
tio.c_cc[VSUSP] = '@' & 0x1f; /* '^@' */
|
||||
|
||||
// set terminal interface
|
||||
tcsetattr(fSlaveFD, TCSANOW, &tio);
|
||||
|
||||
// set window size (currently disabled)
|
||||
/*ws.ws_row = rows;
|
||||
ws.ws_col = cols;
|
||||
|
||||
ioctl(con->tty_slave_fd, TIOCSWINSZ, &ws);*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Setenv("TTY", name);
|
||||
}
|
||||
|
||||
if (fMasterFD < 0 || fSlaveFD < 0) {
|
||||
TRACE(("could not open master or slave fd\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
Setenv("TERM", "beterm");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MiniView::KeyDown(const char *bytes, int32 numBytes)
|
||||
{
|
||||
// TODO: add interrupt char handling
|
||||
uint32 mod = modifiers();
|
||||
if (numBytes == 1) {
|
||||
if (mod & B_OPTION_KEY) {
|
||||
char c = bytes[0] | 0x80;
|
||||
write(fMasterFD, &c, 1);
|
||||
} else {
|
||||
switch (bytes[0]) {
|
||||
case B_LEFT_ARROW:
|
||||
write(fMasterFD, LEFT_ARROW_KEY_CODE, sizeof(LEFT_ARROW_KEY_CODE));
|
||||
break;
|
||||
case B_RIGHT_ARROW:
|
||||
write(fMasterFD, RIGHT_ARROW_KEY_CODE, sizeof(RIGHT_ARROW_KEY_CODE));
|
||||
break;
|
||||
case B_UP_ARROW:
|
||||
write(fMasterFD, UP_ARROW_KEY_CODE, sizeof(UP_ARROW_KEY_CODE));
|
||||
break;
|
||||
case B_DOWN_ARROW:
|
||||
write(fMasterFD, DOWN_ARROW_KEY_CODE, sizeof(DOWN_ARROW_KEY_CODE));
|
||||
break;
|
||||
default:
|
||||
write(fMasterFD, bytes, numBytes);
|
||||
}
|
||||
}
|
||||
} else
|
||||
write(fMasterFD, bytes, numBytes);
|
||||
}
|
||||
|
||||
status_t
|
||||
MiniView::SpawnThreads()
|
||||
{
|
||||
fConsoleWriter = spawn_thread(&ConsoleWriter, "console writer", B_URGENT_DISPLAY_PRIORITY, this);
|
||||
if (fConsoleWriter < 0)
|
||||
return B_ERROR;
|
||||
TRACE(("console writer thread is: %d\n", fConsoleWriter));
|
||||
|
||||
fShellProcess = spawn_thread(&ExecuteShell, "shell process", B_URGENT_DISPLAY_PRIORITY, this);
|
||||
if (fShellProcess < 0)
|
||||
return B_ERROR;
|
||||
TRACE(("shell process thread is: %d\n", fShellProcess));
|
||||
|
||||
resume_thread(fConsoleWriter);
|
||||
resume_thread(fShellProcess);
|
||||
return B_OK;
|
||||
}
|
24
src/tests/apps/miniterminal/MiniView.h
Normal file
24
src/tests/apps/miniterminal/MiniView.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef _MINI_TERMINAL_H_
|
||||
#define _MINI_TERMINAL_H_
|
||||
|
||||
#include "ViewBuffer.h"
|
||||
#include "Console.h"
|
||||
|
||||
class MiniView : public ViewBuffer {
|
||||
public:
|
||||
MiniView(BRect frame);
|
||||
virtual ~MiniView();
|
||||
|
||||
void Start();
|
||||
status_t OpenTTY();
|
||||
status_t SpawnThreads();
|
||||
virtual void KeyDown(const char *bytes, int32 numBytes);
|
||||
|
||||
Console *fConsole;
|
||||
int fMasterFD;
|
||||
int fSlaveFD;
|
||||
thread_id fShellProcess;
|
||||
thread_id fConsoleWriter;
|
||||
};
|
||||
|
||||
#endif
|
29
src/tests/apps/miniterminal/MiniWin.cpp
Normal file
29
src/tests/apps/miniterminal/MiniWin.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Part of the MiniTerminal.
|
||||
*
|
||||
* Copyright 2005 Michael Lotz. All rights reserved.
|
||||
* Distributed under the Haiku License.
|
||||
*/
|
||||
|
||||
#include "MiniWin.h"
|
||||
#include "MiniView.h"
|
||||
|
||||
MiniWin::MiniWin(BRect bounds)
|
||||
: BWindow(bounds, "MiniTerminal", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE)
|
||||
{
|
||||
fView = new MiniView(bounds.OffsetToSelf(0, 0));
|
||||
AddChild(fView);
|
||||
fView->MakeFocus();
|
||||
}
|
||||
|
||||
|
||||
MiniWin::~MiniWin()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MiniView *
|
||||
MiniWin::View()
|
||||
{
|
||||
return fView;
|
||||
}
|
19
src/tests/apps/miniterminal/MiniWin.h
Normal file
19
src/tests/apps/miniterminal/MiniWin.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _MINI_WIN_H_
|
||||
#define _MINI_WIN_H_
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
class MiniView;
|
||||
|
||||
class MiniWin : public BWindow {
|
||||
public:
|
||||
MiniWin(BRect bounds);
|
||||
virtual ~MiniWin();
|
||||
|
||||
MiniView *View();
|
||||
|
||||
private:
|
||||
MiniView *fView;
|
||||
};
|
||||
|
||||
#endif
|
232
src/tests/apps/miniterminal/ViewBuffer.cpp
Normal file
232
src/tests/apps/miniterminal/ViewBuffer.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* ViewBuffer - Mimicing a frame buffer output - but using a BView.
|
||||
* Based on frame_buffer_console.
|
||||
*
|
||||
* Copyright 2005 Michael Lotz. All rights reserved.
|
||||
* Distributed under the Haiku License.
|
||||
*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "ViewBuffer.h"
|
||||
|
||||
#define CHAR_WIDTH 7
|
||||
#define CHAR_HEIGHT 12
|
||||
|
||||
// Palette is (black and white are swapt like in normal BeOS Terminal)
|
||||
// 0 - black,
|
||||
// 1 - blue,
|
||||
// 2 - green,
|
||||
// 3 - cyan,
|
||||
// 4 - red,
|
||||
// 5 - magenta,
|
||||
// 6 - yellow,
|
||||
// 7 - white
|
||||
// 8-15 - same but bright (we're ignoring those)
|
||||
|
||||
static uint32 sPalette32[] = {
|
||||
0xffffff,
|
||||
0x0000ff,
|
||||
0x00ff00,
|
||||
0x00ffff,
|
||||
0xff0000,
|
||||
0xff00ff,
|
||||
0xffff00,
|
||||
0x000000,
|
||||
};
|
||||
|
||||
|
||||
ViewBuffer::ViewBuffer(BRect frame)
|
||||
: BView(frame, "ViewBuffer", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS)
|
||||
{
|
||||
SetFont(be_fixed_font);
|
||||
|
||||
fColumns = frame.IntegerWidth() / CHAR_WIDTH;
|
||||
fRows = frame.IntegerHeight() / CHAR_HEIGHT;
|
||||
fResizeCallback = NULL;
|
||||
|
||||
// initially, the cursor is hidden
|
||||
fCursorX = -1;
|
||||
fCursorY = -1;
|
||||
|
||||
// initialize private palette
|
||||
for (int i = 0; i < 8; i++) {
|
||||
fPalette[i].red = (sPalette32[i] >> 16) & 0xff;
|
||||
fPalette[i].green = (sPalette32[i] >> 8) & 0xff;
|
||||
fPalette[i].blue = (sPalette32[i] >> 0) & 0xff;
|
||||
fPalette[i].alpha = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ViewBuffer::~ViewBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::FrameResized(float width, float height)
|
||||
{
|
||||
fColumns = (int32)width / CHAR_WIDTH;
|
||||
fRows = (int32)height / CHAR_HEIGHT;
|
||||
|
||||
if (fResizeCallback)
|
||||
fResizeCallback(fColumns, fRows, fResizeCallbackData);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ViewBuffer::GetSize(int32 *width, int32 *height)
|
||||
{
|
||||
*width = fColumns;
|
||||
*height = fRows;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::SetResizeCallback(resize_callback callback, void *data)
|
||||
{
|
||||
fResizeCallback = callback;
|
||||
fResizeCallbackData = data;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
ViewBuffer::ForegroundColor(uint8 attr)
|
||||
{
|
||||
return attr & 0x7;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
ViewBuffer::BackgroundColor(uint8 attr)
|
||||
{
|
||||
return (attr >> 4) & 0x7;
|
||||
}
|
||||
|
||||
|
||||
rgb_color
|
||||
ViewBuffer::GetPaletteEntry(uint8 index)
|
||||
{
|
||||
return fPalette[index];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::PutGlyph(int32 x, int32 y, uint8 glyph, uint8 attr)
|
||||
{
|
||||
if (x >= fColumns || y >= fRows)
|
||||
return;
|
||||
|
||||
RenderGlyph(x, y, glyph, attr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::FillGlyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uint8 attr)
|
||||
{
|
||||
if (x >= fColumns || y >= fRows)
|
||||
return;
|
||||
|
||||
int32 left = x + width;
|
||||
if (left > fColumns)
|
||||
left = fColumns;
|
||||
|
||||
int32 bottom = y + height;
|
||||
if (bottom > fRows)
|
||||
bottom = fRows;
|
||||
|
||||
for (; y < bottom; y++) {
|
||||
for (int32 x2 = x; x2 < left; x2++) {
|
||||
RenderGlyph(x2, y, glyph, attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::RenderGlyph(int32 x, int32 y, uint8 glyph, uint8 attr)
|
||||
{
|
||||
BPoint where(x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 3);
|
||||
|
||||
char string[2];
|
||||
string[0] = glyph;
|
||||
string[1] = 0;
|
||||
|
||||
if (LockLooper()) {
|
||||
SetHighColor(GetPaletteEntry(ForegroundColor(attr)));
|
||||
SetLowColor(GetPaletteEntry(BackgroundColor(attr)));
|
||||
FillRect(BRect(x * CHAR_WIDTH, y * CHAR_HEIGHT, (x + 1) * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT), B_SOLID_LOW);
|
||||
DrawString(string, where);
|
||||
Sync();
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::DrawCursor(int32 x, int32 y)
|
||||
{
|
||||
if (x < 0 || y < 0)
|
||||
return;
|
||||
|
||||
x *= CHAR_WIDTH;
|
||||
y *= CHAR_HEIGHT;
|
||||
|
||||
if (LockLooper()) {
|
||||
InvertRect(BRect(x, y, x + CHAR_WIDTH, y + CHAR_HEIGHT));
|
||||
Sync();
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::MoveCursor(int32 x, int32 y)
|
||||
{
|
||||
DrawCursor(fCursorX, fCursorY);
|
||||
DrawCursor(x, y);
|
||||
|
||||
fCursorX = x;
|
||||
fCursorY = y;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::Blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty)
|
||||
{
|
||||
height *= CHAR_HEIGHT;
|
||||
width *= CHAR_WIDTH;
|
||||
|
||||
srcx *= CHAR_WIDTH;
|
||||
srcy *= CHAR_HEIGHT;
|
||||
BRect source(srcx, srcy, srcx + width, srcy + height);
|
||||
|
||||
destx *= CHAR_WIDTH;
|
||||
desty *= CHAR_HEIGHT;
|
||||
BRect dest(destx, desty, destx + width, desty + height);
|
||||
|
||||
if (LockLooper()) {
|
||||
CopyBits(source, dest);
|
||||
Sync();
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewBuffer::Clear(uint8 attr)
|
||||
{
|
||||
if (LockLooper()) {
|
||||
SetLowColor(GetPaletteEntry(BackgroundColor(attr)));
|
||||
SetViewColor(LowColor());
|
||||
FillRect(Frame(), B_SOLID_LOW);
|
||||
Sync();
|
||||
UnlockLooper();
|
||||
}
|
||||
|
||||
fCursorX = -1;
|
||||
fCursorY = -1;
|
||||
}
|
43
src/tests/apps/miniterminal/ViewBuffer.h
Normal file
43
src/tests/apps/miniterminal/ViewBuffer.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef _VIEW_BUFFER_H_
|
||||
#define _VIEW_BUFFER_H_
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <View.h>
|
||||
|
||||
typedef void (*resize_callback)(int32 width, int32 height, void *data);
|
||||
|
||||
class ViewBuffer : public BView {
|
||||
public:
|
||||
ViewBuffer(BRect frame);
|
||||
virtual ~ViewBuffer();
|
||||
|
||||
virtual void FrameResized(float new_width, float new_height);
|
||||
void SetResizeCallback(resize_callback callback, void *data);
|
||||
status_t GetSize(int32 *width, int32 *height);
|
||||
|
||||
uint8 ForegroundColor(uint8 attr);
|
||||
uint8 BackgroundColor(uint8 attr);
|
||||
rgb_color GetPaletteEntry(uint8 index);
|
||||
|
||||
void PutGlyph(int32 x, int32 y, uint8 glyph, uint8 attr);
|
||||
void FillGlyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uint8 attr);
|
||||
void RenderGlyph(int32 x, int32 y, uint8 glyph, uint8 attr);
|
||||
|
||||
void DrawCursor(int32 x, int32 y);
|
||||
void MoveCursor(int32 x, int32 y);
|
||||
|
||||
void Blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty);
|
||||
void Clear(uint8 attr);
|
||||
|
||||
private:
|
||||
int32 fColumns;
|
||||
int32 fRows;
|
||||
resize_callback fResizeCallback;
|
||||
void *fResizeCallbackData;
|
||||
int32 fCursorX;
|
||||
int32 fCursorY;
|
||||
|
||||
rgb_color fPalette[8];
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user