home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
APPS
/
hl10osrc.zoo
/
Lib
/
Terminal.cc
< prev
next >
Wrap
Text File
|
2009-11-06
|
23KB
|
936 lines
/* -*- Mode: C -*- */
/* Terminal.cc - Terminal class implementation
* Inspired by the User Interface Manager code in chapter
* 12 of "C++, a guide for C programmers", by Sharam Hekmatpour,
* (c) 1990 by Prentice Hall of Australia Pty Ltd.
* Created by Robert Heller on Sat Dec 7 22:05:49 1991
*
* ------------------------------------------------------------------
* Home Libarian by Deepwoods Software
* Common Class library implementation code
* ------------------------------------------------------------------
* Modification History:
* ------------------------------------------------------------------
* Contents:
* ------------------------------------------------------------------
*
*
* Copyright (c) 1991,1992 by Robert heller (D/B/A Deepwoods Software)
* All Rights Reserved
*
*/
#include <Terminal.h>
#ifndef MESSYDOS
// Globals used by termcap library...
// (Weirdness of OSK's termcap library...)
#ifdef OSK
char PC_;
#else
char PC;
#endif
char* BC;
char* UP;
short ospeed;
#endif
short Terminal::cline; // current line
short Terminal::ccol; // current column
short Terminal::lines; // screen lines
short Terminal::colms; // screen columns
ErrFun Terminal::errFun;
char Terminal::termBuf[bufSize];
Terminal* Terminal::term;
#ifdef OSK
sgbuf Terminal::ttym;
sgbuf Terminal::xttym;
#endif
#ifndef MESSYDOS
char Terminal::TermType[48]; // terminal type name
char Terminal::TCapBuf[TCapsLen]; // termcap buffer
char Terminal::tcapbuf[TCapsLen]; // copy
// termcap capabilities
char* Terminal::BC; // backspace character
char* Terminal::UP; // up line sequence
char* Terminal::CL; // clear screen
char* Terminal::CM; // cursor movement
char* Terminal::CE; // clear to eol
char* Terminal::CD; // clear to eos
char* Terminal::SO; // standout start
char* Terminal::SE; // standout end
char* Terminal::HO; // home cursor
char* Terminal::KD; // down arrow key
char* Terminal::KU; // up arrow key
char* Terminal::KR; // right arrow key
char* Terminal::KL; // left arrow key
char* Terminal::KH; // home key
char* Terminal::KB; // backspace key
char* Terminal::TI; // terminal init
char* Terminal::TE; // terminal de-init
short Terminal::ospeed; // baud rate (used for padding)
char Terminal::PC; // pad character
#endif
// Interrupt handler...
int Interrupt()
{
Terminal::term->PlainPen();
Terminal::term->ExitChars();
#ifdef OSK
_ss_opt(0, &(Terminal::ttym));
intercept(0);
#endif
exit(1);
return(0);
}
#ifdef OSK
// This is how signals are handled by OSK programs...
static void Intercept(int sig)
{
if (sig == SIGINT) Interrupt();
return;
}
#endif
// Constructor: fetch terminal type, termcap info, and initialize terminal
Terminal::Terminal ()
{
char* temp;
// make sure called only once
if (term != 0) Error(termErr,"in Terminal");
term = this; // self reference
#ifdef MESSYDOS
gppconio_init();
text_info screen_info;
gettextinfo(&screen_info);
lines = screen_info.screenheight;
colms = screen_info.screenwidth;
cline = 0;
ccol = 0;
PlainPen();
#else
SE = ""; // (set here so Error won't crash)
#ifdef OSK
// Get vanila terminal modes
if (_gs_opt(0, &ttym) < 0) Error(sysErr,"for _gs_opt");
#endif
// Get terminal type
char *tt = getenv("TERM");
// Unknown?? give up...
if (tt == 0) Error(sysErr,"Env. TERM not set!");
// remember type...
strcpy(TermType,tt);
// Fetch termcap entry...
if (tgetent(TCapBuf,TermType) <= 0)
Error(sysErr,"Unknown Terminal Type!");
// Fetch needed caps.
char* ptr = tcapbuf;
// pad character:
#ifdef OSK
if (temp = tgetstr("pc",&ptr)) {
PC = PC_ = *temp;
} else PC = PC_ = 0;
#else
if (temp = tgetstr("pc",&ptr)) {
PC = PC = *temp;
} else PC = PC = 0;
#endif
::BC = BC = tgetstr("bc",&ptr); // backspace:
if (BC == 0) ::BC = BC = "\010"; // make sure it is something
::UP = UP = tgetstr("up",&ptr); // up line
CL = tgetstr("cl",&ptr); // clear display
CM = tgetstr("cm",&ptr); // cursor movement
CE = tgetstr("ce",&ptr); // clear to EOL
CD = tgetstr("cd",&ptr); // clear to EOS
SO = tgetstr("so",&ptr); // standout begin
SE = tgetstr("se",&ptr); // standout end
HO = tgetstr("ho",&ptr); // home cursor
KD = tgetstr("kd",&ptr); // down arrow key
KU = tgetstr("ku",&ptr); // up arrow key
KR = tgetstr("kr",&ptr); // right arrow key
KL = tgetstr("kl",&ptr); // left arrow key
KH = tgetstr("kh",&ptr); // home key
KB = tgetstr("kb",&ptr); // backspace key
TI = tgetstr("ti",&ptr); // term init string
TE = tgetstr("te",&ptr); // term de-init string
lines = tgetnum("li"); // lines
colms = tgetnum("co"); // columns
#ifdef OSK
::ospeed = ospeed = ttym.sg_baud; // baud rate
#endif
// handle missing features
if (CE == 0) CE = "\007";
if (SO == 0) SO = "";
if (SE == 0) SE = "";
if (TI == 0) TI = "";
if (TE == 0) TE = "";
if (KD == 0) KD = "\016"; // ^N
if (KU == 0) KU = "\020"; // ^P
if (KR == 0) KR = "\006"; // ^F
if (KL == 0) KL = "\002"; // ^B
if (KH == 0) {
if (KD[0] == '\033' || KU[0] == '\033' ||
KR[0] == '\033' || KL[0] == '\033')
KH = "\033\033"; // ESC-ESC (^[^[)
else KH = "\033"; // ESC (^[)
}
if (KB == 0) KB = "\010";
// check to be sure terminal is not too dumb...
if (HO == 0) Error(sysErr,"Need ho");
if (CD == 0 && CL == 0) Error(sysErr,"Need either cd or cl!");
if (CM == 0) Error(sysErr,"Need cm");
if (lines < 1 || colms < 1) {
Error(sysErr,"Incomplete termcap entry");
}
if (CD == 0) CD = "\007";
// make sure we didn't overflow buffer
if (ptr >= &tcapbuf[TCapsLen]) {
Error(sysErr,"Terminal description too big!");
}
#ifdef OSK
// setup for raw terminal modes
xttym = ttym; // make a copy of the vanila setup
xttym.sg_backsp = 0; // disable editing
xttym.sg_delete = 0;
xttym.sg_echo = 0; // echoing
xttym.sg_alf = 0; // auto lf's
xttym.sg_nulls = 0; // nulls
xttym.sg_pause = 0; // pausing
xttym.sg_bspch = 0; // backspacing
xttym.sg_dlnch = 0; // delete line
xttym.sg_eorch = 0; // end of record
xttym.sg_eofch = 0; // end of file
xttym.sg_rlnch = 0; // redraw line
xttym.sg_dulnch = 0;
xttym.sg_psch = 0;
xttym.sg_kbich = 0; // interrupting
xttym.sg_kbach = 0;
xttym.sg_xon = 0; // xon/xoff (might be a bad idea...)
xttym.sg_xoff = 0;
xttym.sg_tabcr = 0; // tab handling
// set raw mode
if (_ss_opt(0, &xttym) < 0) Error(sysErr,"for _ss_opt");
// setup interceptor
if (intercept((int (*)(...))Intercept) < 0) Error(sysErr,"for intercept");
#endif
#endif
Clear(); // clear screen
InitChars(); // initialize terminal
}
// Destructor: restore terminal state
Terminal::~Terminal ()
{
PlainPen(); // plain pen
PenPos(lines-1,0); // bottom of screen
ExitChars(); // de-init
#ifdef OSK
// restore modes
if (_ss_opt(0, &ttym) < 0) Error(sysErr,"for _ss_opt");
// can interception of signals
if (intercept(0) < 0) Error(sysErr,"for intercept");
#endif
}
#ifdef MESSYDOS
extern "C" {
void sound(int);
}
void Terminal::Bell()
{
sound(440);
sleep(1);
sound(0);
}
Terminal &Terminal::put(unsigned char ch)
{
#ifdef BARF1
gotoxy(ccol+1,cline+1);
#endif
putch(ch);
#ifdef BARF2
ccol++;
if (ccol >= colms)
{
ccol = 0;
cline++;
if (cline >= lines) cline = 0;
}
#endif
}
// get a terminal key press. This function will hang and wait for a key press
int Terminal::GetKey ()
{
int ch; // input key
ch = kbd_getkey();
// check posible magic keys
switch (ch)
{
case K_ESC:
case K_HOME: return escCmd;
case K_CTLP:
case K_UP: return upCmd;
case K_CTLB:
case K_LEFT: return leftCmd;
case K_CTLF:
case K_RIGHT: return rightCmd;
case K_CTLN:
case K_DOWN: return downCmd;
// case K_CTLH:
case K_BACK: return backCmd;
// plain key.
default: return ch;
}
}
// check to see if a key has been pressed. Does not hang. Does not
// actually read the key.
Boolean Terminal::KeyAvailable()
{
if ( kbd_ready() ) return true;
else return false;
}
// Error handler
void Terminal::Error (ErrKind err,const char *msg)
{
if (errFun != 0) (*errFun)(err,msg);
else {
if (err == sysErr) {
// fetch system error message for system errors
printf("Error: %s %s\n",strerror(errno),msg);
Interrupt();
} else {
printf("Error: %s %s\n",
(err == termErr ? "Terminal" : "Memory"),
msg);
Interrupt();
}
}
}
// Write a string to the message line (bottom terminal line) in standout
// mode
void Terminal::Message (const char* msg)
{
int lastRow = lines;
int xcline = cline;
int xccol = ccol;
RevsPen();
strncpy(termBuf,msg,colms);
register len = strlen(msg);
if (len >= colms) {
termBuf[len = (colms-1)] = '\0';
while (len >= (colms-1) - 3) termBuf[--len] = '.';
} else {
while (len < (colms-1)) termBuf[len++] = ' ';
termBuf[len] = '\0';
}
PutStrAt(lastRow-1,0,termBuf);
PenPos(xcline,xccol); PlainPen();
}
// read in a line of text. Editing is allowed and the input is echoed.
int Terminal::GetLine (char* buffer,int bufsize,const char* terminators)
{
int pos = 0;
int nchars = 0;
int ch;
// save base position
int xcline = cline;
int xccol = ccol;
static char spaces[bufSize+2];
memset(buffer,0,bufsize); // clear out buffer
// determine max field width
int fieldwidth = (bufsize < (colms - xccol)
? bufsize : (colms - xccol));
if (fieldwidth < 1) return(-1); // field too small
// create a buffer of spaces (for clearing)
memset(spaces,' ',fieldwidth);
spaces[fieldwidth] = '\0';
// clear out field
PutStrAt(xcline,xccol,spaces);
PenPos(xcline,xccol); // reset position
for (;;) {
ch = GetKey(); // get a key
switch (ch) { // fan out based on key
case escCmd : // Escape - flush buffer and start over
memset(buffer,0,bufsize);
PutStrAt(xcline,xccol,spaces);
PenPos(xcline,xccol);
nchars = 0;
pos = 0;
break;
case backCmd : // backspace - delete character
if (pos > 0) {
strncpy(&buffer[pos-1],
&buffer[pos],
(nchars-pos)+1);
PenPos(cline,ccol-1);
put(&buffer[pos-1],
(nchars-pos));
put(' ');
pos--; nchars--;
PenPos(xcline,xccol+pos);
} else Bell();
break;
case deleCmd : // delete line delete to BOF
if (pos > 0) {
strncpy(buffer,&buffer[pos],
(nchars-pos)+1);
PenPos(xcline,xccol);
put(buffer,(nchars-pos));
nchars -= pos;
pos = 0;
put(spaces,
fieldwidth-nchars);
PenPos(xcline,xccol+pos);
} else Bell();
break;
case rightCmd : // right arrow - move right
if (pos < nchars) {
pos++;
PenPos(xcline,xccol+pos);
} else Bell();
break;
case leftCmd : // left arror - move left
if (pos > 0) {
PenPos(cline,ccol-1);
pos--;
} else Bell();
break;
default : // something else.
// terminator??
if (strchr(terminators,ch) != 0) {
// yep. reset pos and return
PenPos(xcline,xccol);
return(nchars);
} else if (pos == nchars && // no room?
nchars >= fieldwidth) Bell();
else {
if (ch < ' ') Bell(); // funny char?
else {
// normal charactor. shove
// into buffer and echo.
buffer[pos] = ch;
put(buffer[pos]);
pos++;
if (pos > nchars) nchars++;
}
}
break;
}
}
}
// put a character at some specified place
void Terminal::PutCharAt (int row,int col,int ch)
{
if (col >= colms) {
row++;
col = 0;
}
PenPos(row,col);
char cch = ch & charMask;
Mode m = (Mode) (ch & modeMask);
if (m == revsPen) RevsPen();
else if (m == defPen) PlainPen();
put(cch);
ccol++;
}
// Put a plain string someplace
void Terminal::PutStrAt (int row,int col,const char* str)
{
int slen = strlen(str);
int mright = colms - (col+slen);
int right = (mright < 0 ? -mright : 0);
int left = slen - right;
if (left > 0) {
PenPos(row,col);
put((char*)str,left);
ccol += left;
}
if (right > 0) {
PenPos(row+1,0);
put((char*)(str+left),right);
ccol += right;
}
}
// like above, but this is a string of chars with attributes
void Terminal::PutStrAt (int row,int col,const short* str)
{
while (*str != 0) {
PutCharAt(row,col,(int)*str);
row = cline; col = ccol;
str++;
}
}
//Put a plain string in a rectangluar area. If the string is too long,
//returns a pointer to the un-displayed tail of the string. Returns
//NULL (0) if the string fit. Does dump wrapping (indicated with a '\'
//and displayes non-printable characters with a '.'.
char* Terminal::PutStrInBox(int row,int col,int width,int height,const char* str)
{
int rrow = 0,rcol = 0;
PenPos(row,col);
for (char* p = (char*)str; *p != '\0'; p++) {
if (rcol == width) {
put('\\');
rcol = 0;
rrow++;
PenPos(row+rrow,col);
}
if (rrow >= height) return(p);
else if (*p == '\n') {
while (rcol++ < width) put(' ');
rcol = 0;
rrow++;
PenPos(row+rrow,col);
} else if (*p < ' ') {
put('.');
rcol++;
ccol++;
} else {
put(*p);
rcol++;
ccol++;
}
}
while (rrow < height) {
while (rcol < width) {
put(' ');
rcol++;
ccol++;
}
rcol = 0;
rrow++;
if (rrow < height) PenPos(row+rrow,col);
}
return(0);
}
#else
// code output functions.
static int tputc (char c) {return write(1,&c,1);}
void Terminal::WriteCode(const char* code) {tputs(code,1,tputc);}
void Terminal::WriteCodeLines(const char* code,int l) {tputs(code,l,tputc);}
// set cursor position
void Terminal::PenPos (int row, int col)
{
row = (row < 0 ? 0 : (row >= lines ? lines - 1 : row));
col = (col < 0 ? 0 : (col >= colms ? colms - 1 : col));
PosCode(termBuf,row+1,col+1);
WriteCode(termBuf);
cline = row; ccol = col;
}
// get a terminal key press. This function will hang and wait for a key press
int Terminal::GetKey ()
{
char ch; // input key
char buff[10]; // look ahead buffer
for (int k = 0;;) {
// get a character
read(0,&ch,1);
buff[k++] = ch; // save in buffer
// check posible magic keys
if (strncmp(buff,KD,k) == 0) {
if (KD[k] == 0) return downCmd;
} else if (strncmp(buff,KU,k) == 0) {
if (KU[k] == 0) return upCmd;
} else if (strncmp(buff,KR,k) == 0) {
if (KR[k] == 0) return rightCmd;
} else if (strncmp(buff,KL,k) == 0) {
if (KL[k] == 0) return leftCmd;
} else if (strncmp(buff,KH,k) == 0) {
if (KH[k] == 0) return escCmd;
} else if (strncmp(buff,KB,k) == 0) {
if (KB[k] == 0) return backCmd;
} else if (k > 1) { // no known prefix. must be some other key
// sort of prefix - probably undefined function key
Bell();
k = 0;
continue;
// magic single character keys
} else if (ch == '\016') return downCmd; // ^N
else if (ch == '\020') return upCmd; // ^P
else if (ch == '\006') return rightCmd; // ^F
else if (ch == '\002') return leftCmd; // ^B
else if (ch == '\010') return backCmd; // ^H
else if (ch == '\177') return backCmd; // RUBOUT
else if (ch == '\025') return deleCmd; // ^U
// plain key.
else return (int) ch;
}
}
// check to see if a key has been pressed. Does not hang. Does not
// actually read the key.
Boolean Terminal::KeyAvailable()
{
#ifdef OSK
return(_gs_rdy(0) > 0);
#endif
}
// Error handler
void Terminal::Error (ErrKind err,const char *msg)
{
if (errFun != 0) (*errFun)(err,msg);
else {
if (err == sysErr) {
// fetch system error message for system errors
sprintf(termBuf,"Error: %s %s\n",strerror(errno),msg);
write(1,termBuf,strlen(termBuf));
Interrupt();
} else {
sprintf(termBuf,"Error: %s %s\n",
(err == termErr ? "Terminal" : "Memory"),
msg);
write(1,termBuf,strlen(termBuf));
Interrupt();
}
}
}
// Write a string to the message line (bottom terminal line) in standout
// mode
void Terminal::Message (const char* msg)
{
int lastRow = lines;
int xcline = cline;
int xccol = ccol;
PenPos(lastRow,0); RevsPen();
strncpy(termBuf,msg,colms);
register len = strlen(msg);
if (len >= colms) {
termBuf[len = (colms-1)] = '\0';
while (len >= (colms-1) - 3) termBuf[--len] = '.';
} else {
while (len < (colms-1)) termBuf[len++] = ' ';
termBuf[len] = '\0';
}
write(1,termBuf,len);
PenPos(xcline,xccol); PlainPen();
}
// read in a line of text. Editing is allowed and the input is echoed.
int Terminal::GetLine (char* buffer,int bufsize,const char* terminators)
{
int pos = 0;
int nchars = 0;
int ch;
// save base position
int xcline = cline;
int xccol = ccol;
static char spaces[bufSize];
memset(buffer,0,bufsize); // clear out buffer
// determine max field width
int fieldwidth = (bufsize < (colms - xccol)
? bufsize : (colms - xccol));
if (fieldwidth < 1) return(-1); // field too small
// create a buffer of spaces (for clearing)
memset(spaces,' ',fieldwidth);
// clear out field
write(1,spaces,fieldwidth);
PenPos(xcline,xccol); // reset position
for (;;) {
ch = GetKey(); // get a key
switch (ch) { // fan out based on key
case escCmd : // Escape - flush buffer and start over
memset(buffer,0,bufsize);
PenPos(xcline,xccol);
write(1,spaces,fieldwidth);
PenPos(xcline,xccol);
nchars = 0;
pos = 0;
break;
case backCmd : // backspace - delete character
if (pos > 0) {
strncpy(&buffer[pos-1],
&buffer[pos],
(nchars-pos)+1);
WriteCode(BC);
write(1,&buffer[pos-1],
(nchars-pos));
write(1,spaces,1);
pos--; nchars--;
PenPos(xcline,xccol+pos);
} else Bell();
break;
case deleCmd : // delete line delete to BOF
if (pos > 0) {
strncpy(buffer,&buffer[pos],
(nchars-pos)+1);
PenPos(xcline,xccol);
write(1,buffer,(nchars-pos));
nchars -= pos;
pos = 0;
write(1,spaces,
fieldwidth-nchars);
PenPos(xcline,xccol+pos);
} else Bell();
break;
case rightCmd : // right arrow - move right
if (pos < nchars) {
pos++;
PenPos(xcline,xccol+pos);
} else Bell();
break;
case leftCmd : // left arror - move left
if (pos > 0) {
WriteCode(BC);
pos--;
} else Bell();
break;
default : // something else.
// terminator??
if (strchr(terminators,ch) != 0) {
// yep. reset pos and return
PenPos(xcline,xccol);
return(nchars);
} else if (pos == nchars && // no room?
nchars >= fieldwidth) Bell();
else {
if (ch < ' ') Bell(); // funny char?
else {
// normal charactor. shove
// into buffer and echo.
buffer[pos] = ch;
write(1,&buffer[pos],1);
pos++;
if (pos > nchars) nchars++;
}
}
break;
}
}
}
// put a character at some specified place
void Terminal::PutCharAt (int row,int col,int ch)
{
if (col >= colms) {
row++;
col = 0;
}
PenPos(row,col);
char cch = ch & charMask;
Mode m = (Mode) (ch & modeMask);
if (m == revsPen) RevsPen();
else if (m == defPen) PlainPen();
write(1,&cch,1);
ccol++;
}
// Put a plain string someplace
void Terminal::PutStrAt (int row,int col,const char* str)
{
int slen = strlen(str);
int mright = colms - (col+slen);
int right = (mright < 0 ? -mright : 0);
int left = slen - right;
if (left > 0) {
PenPos(row,col);
write(1,(char*)str,left);
ccol += left;
}
if (right > 0) {
PenPos(row+1,0);
write(1,(char*)(str+left),right);
ccol += right;
}
}
// like above, but this is a string of chars with attributes
void Terminal::PutStrAt (int row,int col,const short* str)
{
while (*str != 0) {
PutCharAt(row,col,(int)*str);
row = cline; col = ccol;
str++;
}
}
//Put a plain string in a rectangluar area. If the string is too long,
//returns a pointer to the un-displayed tail of the string. Returns
//NULL (0) if the string fit. Does dump wrapping (indicated with a '\'
//and displayes non-printable characters with a '.'.
char* Terminal::PutStrInBox(int row,int col,int width,int height,const char* str)
{
int rrow = 0,rcol = 0;
PenPos(row,col);
for (char* p = (char*)str; *p != '\0'; p++) {
if (rcol == width) {
write(1,"\\",1);
rcol = 0;
rrow++;
PenPos(row+rrow,col);
}
if (rrow >= height) return(p);
else if (*p == '\n') {
while (rcol++ < width) write(1," ",1);
rcol = 0;
rrow++;
PenPos(row+rrow,col);
} else if (*p < ' ') {
write(1,".",1);
rcol++;
ccol++;
} else {
write(1,p,1);
rcol++;
ccol++;
}
}
while (rrow < height) {
while (rcol < width) {
write(1," ",1);
rcol++;
ccol++;
}
rcol = 0;
rrow++;
if (rrow < height) PenPos(row+rrow,col);
}
return(0);
}
#endif
// process forking - very O/S dependent and posible hairy...
#ifdef OSK
extern char** environ;
typedef int (*ProcFunc)(const char* modname,int parmsize,const char *parmptr,
short type,short lang,int datasize,short prior,
short pathcnt);
extern "MWC" {
int os9exec(ProcFunc procfunc,const char* modname,const char** argv,
const char** envp,unsigned stacksize,short priority,
short pathcnt);
};
// fork a process
int Terminal::forkprog (const char** argv)
{
static char errorbuffer[512];
// remember where we are
int xcline = cline;
int xccol = ccol;
// reset position and reset terminal
PenPos(lines-1,0);
PlainPen();
ExitChars();
_ss_opt(0, &ttym);
// try to fork the process
int pid = os9exec(os9forkc,argv[0],argv,environ,0,0,3);
// failure??
if (pid < 0) {
// yep. revert terminal and spit out a message
int error = errno;
_ss_opt(0, &xttym);
InitChars();
cline = xcline; ccol = xccol;
sprintf(errorbuffer,"Error in fork: %s",strerror(error));
Message(errorbuffer);
errno = error;
return (-1); // display not disturbed
} else {
// fork worked. Wait for process to finish
int error = 0;
while (wait(&error) == 0) ; // waiting...
error &= 0x00FFFF; // completion status...
// revert terminal
_ss_opt(0, &xttym);
InitChars();
cline = xcline; ccol = xccol;
// did process crash??
if (error == 0) {
// nope
PenPos(xcline,xccol);
// success, but display might be trashed
return(1);
} else {
// child crashed.
// fetch error message
sprintf(errorbuffer,"Error in child: %s",
strerror(error));
Message(errorbuffer);
// stash error code
errno = error;
// process crashed, but might have trashed the display
return (0);
}
}
}
#endif
#ifdef MESSYDOS
#include <process.h>
#include <string.h>
// fork a process
int Terminal::forkprog (const char** argv)
{
static char errorbuffer[512];
// remember where we are
int xcline = cline;
int xccol = ccol;
// reset position and reset terminal
PenPos(lines-1,0);
PlainPen();
ExitChars();
// try to fork the process
int error = spawnvp(P_WAIT,argv[0],argv);
// failure??
error &= 0x00FFFF; // completion status...
// revert terminal
InitChars();
cline = xcline; ccol = xccol;
// did process crash??
if (error == 0) {
// nope
PenPos(xcline,xccol);
// success, but display might be trashed
return(1);
} else if (error < 0) {
// child was stillborn
error = errno;
InitChars();
cline = xcline; ccol = xccol;
sprintf(errorbuffer,"Error in fork: %s",strerror(error));
Message(errorbuffer);
errno = error;
return (-1); // display not disturbed
} else {
// child crashed.
// fetch error message
sprintf(errorbuffer,"Error in child: %s",
strerror(error));
Message(errorbuffer);
// stash error code
errno = error;
// process crashed, but might have trashed the display
return (0);
}
}
#endif