This is ComScroll.m in view mode; [Download] [Up]
/* Generated by Interface Builder */
#import "ComScroll.h"
#import "CText.h"
#import <appkit/nextstd.h>
#import <appkit/Application.h>
#import <appkit/Window.h>
#import <appkit/Font.h>
#import <appkit/Panel.h>
extern char defaultfont[] ;
extern void error(), configure() ;
static void getptys (master, slave)
int *master, *slave ;
{
char device[12];
char *block, *num;
char *blockLoc;
char *numLoc;
char *msLoc;
struct sgttyb setp =
{B9600, B9600, (char)0x7f, (char)0x15, (CRMOD|ANYP)};
struct tchars setc =
{CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK};
struct ltchars sltc =
{CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT};
int lset =
(LCRTBS|LCRTERA|LCRTKIL|LCTLECH|LPENDIN|LDECCTQ);
int setd = NTTYDISC;
strcpy(device, "/dev/pty??");
blockLoc = &device[ strlen("/dev/pty") ];
numLoc = &device[ strlen("/dev/pty?") ];
msLoc = &device[ strlen("/dev/") ];
for (block = "pqrs"; *block; block++) {
*blockLoc = *block;
for (num = "0123456789abcdef"; *num; num++) {
*numLoc = *num;
*master = open(device, O_RDWR);
if (*master >= 0) {
*msLoc = 't';
*slave = open(device, O_RDWR);
if (*slave >= 0) {
(void) ioctl(*slave, TIOCSETP, (char *)&setp);
(void) ioctl(*slave, TIOCSETC, (char *)&setc);
(void) ioctl(*slave, TIOCSETD, (char *)&setd);
(void) ioctl(*slave, TIOCSLTC, (char *)&sltc);
(void) ioctl(*slave, TIOCLSET, (char *)&lset);
return;
}
}
}
}
*master = -1;
*slave = -1;
}
@implementation ComScroll
+ newFrame:(const NXRect *)frameRect
{
self = [super newFrame:frameRect] ;
[self setVertScrollerRequired: YES] ;
[self setBackgroundGray: NX_WHITE] ;
[self awake] ;
childID = 0 ;
waiting = 0 ;
return self ;
}
- awake
{
NXRect trect ;
Font *mf = 0 ;
configure() ;
if (defaultfont[0]) {
char *p = defaultfont ;
char fname[100] ;
char *q = fname ;
float size ;
for (; *p && *p != ':'; p++, q++)
*q = *p ;
*q = 0 ;
if (*p && sscanf(p+1, "%f", &size)==1)
mf = [Font newFont:fname size:size] ;
}
if (mf == 0)
mf = [Font newFont:"Ohlfs" size:10] ;
trect.origin.x = trect.origin.y = 0 ;
[self getContentSize: &(trect.size)] ;
text = [[CText alloc]
initFrame:&trect text:NULL alignment:NX_LEFTALIGNED] ;
[text setFont:mf] ;
[text notifyAncestorWhenFrameChanged:YES] ;
// [text setEditable:NO] ;
[text setEditable:YES] ;
[text setHorizResizable:NO] ;
[text setVertResizable:YES] ;
[text setMinSize:&(trect.size)] ;
trect.size.height = 1000000 ;
trect.size.width = 1200 ;
[text setMaxSize:&(trect.size)] ;
[self setAutoresizeSubviews:YES] ;
[self setAutosizing: NX_HEIGHTSIZABLE | NX_WIDTHSIZABLE] ;
[text setMonoFont:YES] ;
[text setOpaque:YES] ;
[text setFontPanelEnabled:YES] ;
[self setDocView:text] ;
[text setDelegate:self] ;
[text setController:self] ;
return self ;
}
- addText:(const char *)s
{
[text setSel:[text textLength] :0];
[text replaceSel:s] ;
[text scrollSelToVisible];
return self;
}
- handler:(int)fd
{
int r ;
char outbuf[1024] ;
if (childID == 0)
return self ;
/* printf("In handler\n") ; */
while ((r = read(fd, outbuf, 1023)) > 0) {
/* printf("<%d> bytes\n", r) ; */
if (waiting) {
struct timeval tv ;
struct timezone tzp ;
gettimeofday(&tv, &tzp) ;
if (tv.tv_sec > waittime.tv_sec ||
(tv.tv_sec == waittime.tv_sec && tv.tv_usec > waittime.tv_usec)) {
[[self window] makeKeyAndOrderFront:0] ;
waiting = 0 ;
}
}
if (eofcount > 0) {
write(fd, eofchar, 1) ;
eofcount-- ;
}
outbuf[r] = 0 ;
[self addText:outbuf] ;
}
if (r == 0)
[self closeChild:fd] ;
else if (errno != EWOULDBLOCK) {
[self closeChild:fd] ;
}
/* printf("Out handler\n") ; */
return self ;
}
static void cm_handler(fd, sender)
int fd ;
id sender ;
{
[sender handler:fd] ;
}
- closeChild:(int)fd
{
if (childID) {
if (fdadded)
DPSRemoveFD(fd) ;
childID = 0 ;
close(fd) ;
masterFD = 0 ;
}
// [text setEditable:NO] ;
[text setEditable:YES] ;
return self ;
}
static void msleep(long len) {
struct timeval tv ;
tv.tv_usec = len % 1000000 ;
tv.tv_sec = len / 1000000 ;
select(0, 0, 0, 0, &tv) ;
}
- killOff
{
if (childID) {
kill(childID, SIGTERM) ;
childID = 0 ;
}
return self ;
}
- logCommand:(const char *)s inBack:(int)async
{
int masterPty, slavePty ;
int tty, numFds, fd;
int processGroup;
int pidChild;
int i ;
while (wait3(0, WNOHANG, 0) > 0) ; /* allow zombies to go away */
if (childID)
if (masterFD)
[self handler:masterFD] ;
if (childID) { // are we busy??
/* i = NXRunAlertPanel(NULL, "Command window busy",
"Cancel request", "Force EOF and override", "Force ^C and override", 0) ;
*/
i = NX_ALERTALTERNATE ;
if (i != NX_ALERTDEFAULT) {
if (i == NX_ALERTALTERNATE)
eofchar[0] = 4 ;
else
eofchar[0] = 3 ;
write(masterFD, eofchar, 1) ;
eofcount = 3 ;
for (i=0; i<5; i++) {
if (childID) {
msleep(300000) ;
[self handler:masterFD] ;
}
}
}
}
if (childID) {
// we tried nicely, now we get mean.
kill(childID, SIGTERM) ;
msleep(300000) ;
[self handler:masterFD] ;
if (childID)
[self closeChild:masterFD] ;
}
if (childID) {
error("you'll have to intercede for me; I couldn't get it to die.") ;
return 0 ;
}
[self addText:" - "] ;
[self addText:s] ;
[self addText:"\n"] ;
tty = open("/dev/tty", O_RDWR);
getptys(&masterPty, &slavePty);
if (masterPty <= 0 || slavePty <= 0)
error("! error grabbing ptys for subprocess") ;
// remove the controlling tty if launched from a shell,
// but not Workspace;
// so that we have job control over the parent application in shell
// and so that subprocesses can be restarted in Workspace
if (tty<0) {
if ((tty = open("/dev/tty", 2))>=0) {
ioctl(tty, TIOCNOTTY, 0);
close(tty);
}
} else {
close(tty) ;
}
switch (pidChild = vfork()) {
case -1: // error
error("! error starting UNIX vfork of subprocess.") ;
case 0: // child
dup2(slavePty, 0);
dup2(slavePty, 1);
dup2(slavePty, 2);
numFds = getdtablesize();
for (fd=3; fd<numFds; fd++)
close(fd);
processGroup = getpid();
ioctl(0, TIOCSPGRP, (char *)&processGroup);
setpgrp (0, processGroup);
execl("/bin/csh", "csh", "-c", s, 0) ;
error("! vfork (child)") ;
default: // parent
close(slavePty);
childID = pidChild ;
eofcount = 3 ;
if (async) {
[text setEditable:YES] ;
if (fcntl(masterPty, F_SETFL, FNDELAY) == -1)
error("! couldn't fcntl") ;
DPSAddFD(masterPty, cm_handler, self, NX_MODALRESPTHRESHOLD) ;
fdadded = 1 ;
masterFD = masterPty ;
eofcount = 0 ;
} else {
struct timezone tzp ;
fdadded = 0 ;
masterFD = 0 ;
eofcount = 3 ;
eofchar[0] = 4 ;
write(masterPty, "\004", 1) ;
waiting = ! [[self window] isVisible] ;
gettimeofday(&waittime, &tzp) ;
waittime.tv_sec += 5 ; /* pop up after five seconds if necessary */
[self handler:masterPty] ;
}
break ;
}
return self ;
}
- abortCommand:sender
{
return self;
}
- sendToMaster:(const char *)s
{
if (masterFD)
write(masterFD, s, strlen(s)) ;
return self ;
}
- (BOOL)textWillChange:textObject
{
[text setSel:[text textLength] :0];
[text scrollSelToVisible];
return NO;
}
- clear
{
[text selectAll:self] ;
if ([text isEditable])
[text delete:self] ;
else {
[text setEditable:YES] ;
[text delete:self] ;
[text setEditable:NO] ;
}
return self ;
}
- text
{
return text ;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.