Encapsulated low level terminal stuff into a Shell class, which also

supersedes spawn_shell(). Removed window parameter from TermParse. Since 
we already have a pointer to the view, we just call Window() on it (only 
used in one place, no need to save a pointer). Other cleanups. 


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21628 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini 2007-07-17 07:58:37 +00:00
parent ca210f74f1
commit f3d05c8b3a
9 changed files with 229 additions and 85 deletions

View File

@ -11,7 +11,7 @@
#include "CodeConv.h"
#include "PrefHandler.h"
#include "spawn.h"
//#include "spawn.h"
#include "TermBuffer.h"
#include "TermWindow.h"
#include "TermConst.h"
@ -25,11 +25,10 @@
#include <String.h>
#include <TextView.h>
#include <signal.h>
//#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
// Globals
@ -119,14 +118,8 @@ TermApp::ReadyToRun()
void
TermApp::Quit()
{
if (!sUsageRequested){
int status;
kill(-gShPid, SIGHUP);
wait(&status);
if (!sUsageRequested)
_UnregisterTerminal();
}
BApplication::Quit();
}

View File

@ -47,12 +47,10 @@ extern int mbcstable[]; /* ESC $ */
#define NPARAM 10 // Max parameters
TermParse::TermParse(int fd, TermWindow *inWinObj, TermView *inViewObj,
CodeConv *inConvObj)
TermParse::TermParse(int fd, TermView *inViewObj, CodeConv *inConvObj)
:
fFd(fd),
fViewObj(inViewObj),
fWinObj(inWinObj),
fConvObj(inConvObj),
fParseThread(-1),
fParseSem(-1),
@ -807,7 +805,7 @@ TermParse::EscParse()
switch (mode_char) {
case '0':
case '2':
fWinObj->SetTitle(string);
fViewObj->Window()->SetTitle(string);
break;
case '1':
break;

View File

@ -39,14 +39,13 @@
class TermView;
class CodeConv;
class TermWindow;
//PtyReader buffer size.
#define READ_BUF_SIZE 2048
class TermParse : public BHandler {
public:
TermParse(int fd, TermWindow *inWinObj, TermView *inViewObj, CodeConv *inConvObj);
TermParse(int fd, TermView *inViewObj, CodeConv *inConvObj);
~TermParse();
status_t StartThreads();
@ -72,7 +71,6 @@ private:
int fFd;
TermView *fViewObj;
TermWindow *fWinObj;
CodeConv *fConvObj;
thread_id fParseThread;

View File

@ -63,9 +63,9 @@ const static rgb_color kTermColorTable[16] = {
};
TermView::TermView(BRect frame, CodeConv *inCodeConv, int fd)
TermView::TermView(BRect frame, CodeConv *inCodeConv)
: BView(frame, "termview", B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
fTerminalFd(fd),
fShell(NULL),
fFontWidth(0),
fFontHeight(0),
fFontAscent(0),
@ -122,6 +122,25 @@ TermView::~TermView()
}
status_t
TermView::AttachShell(Shell *shell)
{
if (shell == NULL)
return B_BAD_VALUE;
fShell = shell;
return B_OK;
}
void
TermView::DetachShell()
{
fShell = NULL;
}
//! Get width and height for terminal font
void
TermView::GetFontSize(int* _width, int* _height)
@ -1010,11 +1029,7 @@ TermView::UpdateSIGWINCH()
ScrollTo(0, fTop);
ResizeScrBarRange();
struct winsize ws;
ws.ws_row = fTermRows;
ws.ws_col = fTermColumns;
ioctl(fTerminalFd, TIOCSWINSZ, &ws);
kill(-gShPid, SIGWINCH);
fShell->UpdateWindowSize(fTermRows, fTermColumns);
fFrameResized = 0;
if (fScrRegionSet == 0)
@ -1033,11 +1048,11 @@ TermView::DeviceStatusReport(int n)
switch (n) {
case 5:
len = sprintf(sbuf,"\033[0n") ;
write(fTerminalFd, sbuf, len);
fShell->Write(sbuf, len);
break ;
case 6:
len = sprintf(sbuf,"\033[%d;%dR", fTermRows, fTermColumns) ;
write(fTerminalFd, sbuf, len);
fShell->Write(sbuf, len);
break ;
default:
return;
@ -1210,10 +1225,10 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
// If bytes[0] equal intr charactor,
// send signal to shell process group.
tcgetattr(fTerminalFd, &tio);
fShell->GetAttr(tio);
if (*bytes == tio.c_cc[VINTR]) {
if (tio.c_lflag & ISIG)
kill(-gShPid, SIGINT);
fShell->Signal(SIGINT);
}
// Terminal changes RET, ENTER, F1...F12, and ARROW key code.
@ -1224,24 +1239,24 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
case B_RETURN:
c = 0x0d;
if (key == RETURN_KEY || key == ENTER_KEY) {
write(fTerminalFd, &c, 1);
fShell->Write(&c, 1);
return;
} else {
write(fTerminalFd, bytes, numBytes);
fShell->Write(bytes, numBytes);
return;
}
break;
case B_LEFT_ARROW:
if (key == LEFT_ARROW_KEY) {
write(fTerminalFd, LEFT_ARROW_KEY_CODE, sizeof(LEFT_ARROW_KEY_CODE)-1);
fShell->Write(LEFT_ARROW_KEY_CODE, sizeof(LEFT_ARROW_KEY_CODE)-1);
return;
}
break;
case B_RIGHT_ARROW:
if (key == RIGHT_ARROW_KEY) {
write(fTerminalFd, RIGHT_ARROW_KEY_CODE, sizeof(RIGHT_ARROW_KEY_CODE)-1);
fShell->Write(RIGHT_ARROW_KEY_CODE, sizeof(RIGHT_ARROW_KEY_CODE)-1);
return;
}
break;
@ -1256,7 +1271,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
}
if (key == UP_ARROW_KEY) {
write(fTerminalFd, UP_ARROW_KEY_CODE, sizeof(UP_ARROW_KEY_CODE)-1);
fShell->Write(UP_ARROW_KEY_CODE, sizeof(UP_ARROW_KEY_CODE)-1);
return;
}
break;
@ -1269,21 +1284,21 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
}
if (key == DOWN_ARROW_KEY) {
write(fTerminalFd, DOWN_ARROW_KEY_CODE, sizeof(DOWN_ARROW_KEY_CODE)-1);
fShell->Write(DOWN_ARROW_KEY_CODE, sizeof(DOWN_ARROW_KEY_CODE)-1);
return;
}
break;
case B_INSERT:
if (key == INSERT_KEY) {
write(fTerminalFd, INSERT_KEY_CODE, sizeof(INSERT_KEY_CODE)-1);
fShell->Write(INSERT_KEY_CODE, sizeof(INSERT_KEY_CODE)-1);
return;
}
break;
case B_HOME:
if (key == HOME_KEY) {
write(fTerminalFd, HOME_KEY_CODE, sizeof(HOME_KEY_CODE)-1);
fShell->Write(HOME_KEY_CODE, sizeof(HOME_KEY_CODE)-1);
return;
}
break;
@ -1298,7 +1313,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
}
if (key == PAGE_UP_KEY) {
write(fTerminalFd, PAGE_UP_KEY_CODE, sizeof(PAGE_UP_KEY_CODE)-1);
fShell->Write(PAGE_UP_KEY_CODE, sizeof(PAGE_UP_KEY_CODE)-1);
return;
}
break;
@ -1311,14 +1326,14 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
}
if (key == PAGE_DOWN_KEY) {
write(fTerminalFd, PAGE_DOWN_KEY_CODE, sizeof(PAGE_DOWN_KEY_CODE)-1);
fShell->Write(PAGE_DOWN_KEY_CODE, sizeof(PAGE_DOWN_KEY_CODE)-1);
return;
}
break;
case B_END:
if (key == END_KEY) {
write(fTerminalFd, END_KEY_CODE, sizeof(END_KEY_CODE)-1);
fShell->Write(END_KEY_CODE, sizeof(END_KEY_CODE)-1);
return;
}
break;
@ -1326,7 +1341,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
case B_FUNCTION_KEY:
for (c = 0; c < 12; c++) {
if (key == function_keycode_table[c]) {
write(fTerminalFd, function_key_char_table[c], 5);
fShell->Write(function_key_char_table[c], 5);
return;
}
}
@ -1341,12 +1356,12 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
if (GetEncoding() != M_UTF8) {
int cnum = fCodeConv->ConvertFromInternal(bytes, numBytes,
(char *)dstbuf, GetEncoding());
write(fTerminalFd, dstbuf, cnum);
fShell->Write(dstbuf, cnum);
return;
}
}
write(fTerminalFd, bytes, numBytes);
fShell->Write(bytes, numBytes);
}
@ -1428,7 +1443,7 @@ TermView::MessageReceived(BMessage *msg)
case MENU_CLEAR_ALL:
DoClearAll();
write(fTerminalFd, ctrl_l, 1);
fShell->Write(ctrl_l, 1);
break;
case MSGRUN_CURSOR:
@ -1589,10 +1604,10 @@ TermView::WritePTY(const uchar *text, int numBytes)
uchar *destBuffer = (uchar *)malloc(numBytes * 3);
numBytes = fCodeConv->ConvertFromInternal((char*)text, numBytes,
(char*)destBuffer, GetEncoding());
write(fTerminalFd, destBuffer, numBytes);
fShell->Write(destBuffer, numBytes);
free(destBuffer);
} else {
write(fTerminalFd, text, numBytes);
fShell->Write(text, numBytes);
}
}

View File

@ -44,7 +44,6 @@
#define CUROFF 0
#define CURON 1
#define VIEW_THR_CODE 'vtcd'
#define MOUSE_THR_CODE 'mtcd'
#define RECT_BUF_SIZE 32
@ -95,12 +94,16 @@ class CodeConv;
class BPopUpMenu;
class BScrollBar;
class BString;
class Shell;
class TermView : public BView {
public:
TermView(BRect frame, CodeConv *inCodeConv, int fd);
TermView(BRect frame, CodeConv *inCodeConv);
~TermView();
status_t AttachShell(Shell *shell);
void DetachShell();
void SetTermFont(const BFont *halfFont, const BFont *fullFont);
void GetFontSize(int *width, int *height);
BRect SetTermSize(int rows, int cols, bool flag);
@ -225,7 +228,7 @@ class TermView : public BView {
bool CheckSelectedRegion(const CurPos &pos);
inline void Redraw(int, int, int, int);
int fTerminalFd;
Shell *fShell;
// Font and Width
BFont fHalfFont;

View File

@ -56,7 +56,7 @@ extern PrefHandler *gTermPref;
TermWindow::TermWindow(BRect frame, const char* title, const char *command)
: BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE),
fPfd(-1),
fShell(NULL),
fTermParse(NULL),
fMenubar(NULL),
fFilemenu(NULL),
@ -96,9 +96,10 @@ TermWindow::TermWindow(BRect frame, const char* title, const char *command)
// Get encoding name (setenv TTYPE in spawn_shell functions)
const char *encoding = longname2shortname(gTermPref->getString(PREF_TEXT_ENCODING));
fPfd = spawn_shell(rows, cols, command, encoding);
if (fPfd < 0)
throw fPfd;
fShell = new Shell();
status_t status = fShell->Open(rows, cols, command, encoding);
if (status < 0)
throw status;
InitWindow();
}
@ -106,7 +107,9 @@ TermWindow::TermWindow(BRect frame, const char* title, const char *command)
TermWindow::~TermWindow()
{
close(fPfd);
fTermView->DetachShell();
delete fShell;
delete fTermParse;
delete fCodeConv;
if (fPrefWindow)
@ -159,7 +162,9 @@ TermWindow::InitWindow()
textframe.top = fMenubar->Bounds().bottom + 1.0;
fCodeConv = new CodeConv();
fTermView = new TermView(Bounds(), fCodeConv, fPfd);
fTermView = new TermView(Bounds(), fCodeConv);
fTermView->AttachShell(fShell);
/*
* MuTerm has two views. BaseView is window base view.
@ -214,7 +219,7 @@ TermWindow::InitWindow()
// Initialize TermParse
SetEncoding(longname2id(gTermPref->getString(PREF_TEXT_ENCODING)));
fTermParse = new TermParse(fPfd, this, fTermView, fCodeConv);
fTermParse = new TermParse(fShell->FD(), fTermView, fCodeConv);
if (fTermParse->StartThreads() < B_OK)
return;
@ -463,7 +468,7 @@ TermWindow::MessageReceived(BMessage *message)
}
else if (!strcmp("tty", spe.FindString("property", i))) {
BMessage reply(B_REPLY);
reply.AddString("result", ttyname(fPfd));
reply.AddString("result", fShell->TTYName());
message->SendReply(&reply);
} else {
BWindow::MessageReceived(message);

View File

@ -45,7 +45,7 @@ class TermParse;
class CodeConv;
class PrefWindow;
class FindWindow;
class Shell;
class TermWindow : public BWindow {
public:
@ -74,7 +74,7 @@ class TermWindow : public BWindow {
/*
* data member
*/
int fPfd;
Shell *fShell;
TermParse *fTermParse;
BMenuBar *fMenubar;
BMenu *fFilemenu, *fEditmenu, *fEncodingmenu, *fHelpmenu, *fFontMenu, *fWindowSizeMenu, *fNewFontMenu;

View File

@ -30,20 +30,21 @@
*/
#include <dirent.h>
#include <sys/param.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <kernel/OS.h>
#include <unistd.h>
#include <OS.h>
#include "TermConst.h"
#include "spawn.h"
@ -53,18 +54,20 @@ extern PrefHandler *gTermPref;
/* default shell command and options. */
#define SHELL_COMMAND "/bin/sh -login"
extern char **environ;
const char *kSpawnAlertMessage = "alert --stop " "'Cannot execute \"%s\":\n"
const static char *kSpawnAlertMessage = "alert --stop " "'Cannot execute \"%s\":\n"
"\t%s\n'"
"'Use Default Shell' 'Abort'";
/*
* Set environment varriable.
* Set environment variable.
*/
#if !defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
int
extern char **environ;
static int
setenv(const char *var, const char *value, bool overwrite)
{
int envindex = 0;
@ -110,9 +113,9 @@ typedef struct
#define PTY_NG 1 /* pty open or set termios NG */
#define PTY_WS 2 /* pty need WINSIZE (row and col ) */
/* global variables */
pid_t gShPid;
static pid_t sShPid;
static status_t
@ -130,7 +133,7 @@ receive_handshake_message(handshake_t& handshake)
}
int
static int
spawn_shell(int row, int col, const char *command, const char *coding)
{
signal(SIGTTOU, SIG_IGN);
@ -180,7 +183,7 @@ spawn_shell(int row, int col, const char *command, const char *coding)
thread_id terminalThread = find_thread(NULL);
/* Fork a child process. */
if ((gShPid = fork()) < 0) {
if ((sShPid = fork()) < 0) {
close(master);
return -1;
}
@ -188,7 +191,7 @@ spawn_shell(int row, int col, const char *command, const char *coding)
handshake_t handshake;
if (gShPid == 0) {
if (sShPid == 0) {
// Now in child process.
/*
@ -443,7 +446,7 @@ spawn_shell(int row, int col, const char *command, const char *coding)
handshake.row = row;
handshake.col = col;
handshake.status = PTY_WS;
send_handshake_message(gShPid, handshake);
send_handshake_message(sShPid, handshake);
break;
}
}
@ -451,3 +454,116 @@ spawn_shell(int row, int col, const char *command, const char *coding)
return (done > 0) ? master : -1;
}
static void
close_shell(int fd)
{
if (fd < 0)
return;
close(fd);
int status;
kill(-sShPid, SIGHUP);
wait(&status);
}
Shell::Shell()
:fFd(-1)
{
}
Shell::~Shell()
{
Close();
}
status_t
Shell::Open(int row, int col, const char *command, const char *coding)
{
fFd = spawn_shell(row, col, command, coding);
if (fFd < 0)
return fFd;
return B_OK;
}
void
Shell::Close()
{
if (fFd >= 0) {
close_shell(fFd);
fFd = -1;
}
}
const char *
Shell::TTYName() const
{
return ttyname(fFd);
}
ssize_t
Shell::Read(void *buffer, size_t numBytes)
{
if (fFd < 0)
return B_NO_INIT;
return read(fFd, buffer, numBytes);
}
ssize_t
Shell::Write(const void *buffer, size_t numBytes)
{
if (fFd < 0)
return B_NO_INIT;
return write(fFd, buffer, numBytes);
}
void
Shell::UpdateWindowSize(int rows, int columns)
{
struct winsize winSize;
winSize.ws_row = rows;
winSize.ws_col = columns;
ioctl(fFd, TIOCSWINSZ, &winSize);
Signal(SIGWINCH);
}
void
Shell::Signal(int signal)
{
kill(-sShPid, signal);
}
status_t
Shell::GetAttr(struct termios &attr)
{
return tcgetattr(fFd, &attr);
}
status_t
Shell::SetAttr(struct termios &attr)
{
return tcsetattr(fFd, TCSANOW, &attr);
}
int
Shell::FD() const
{
return fFd;
}

View File

@ -80,14 +80,30 @@
#define APC 0x9F
#define RDEL 0xFF
/*
* Prototype:
*/
int spawn_shell (int, int, const char *, const char *);
void Setenv (const char *, const char *);
class Shell {
public:
Shell();
~Shell();
extern pid_t gShPid; /* shell process ID */
status_t Open(int row, int col, const char *command, const char *coding);
void Close();
const char * TTYName() const;
ssize_t Read(void *buffer, size_t numBytes);
ssize_t Write(const void *buffer, size_t numBytes);
void UpdateWindowSize(int row, int columns);
void Signal(int signal);
status_t GetAttr(struct termios &attr);
status_t SetAttr(struct termios &attr);
int FD() const;
private:
int fFd;
};
#endif /* SPAWN_H */