home *** CD-ROM | disk | FTP | other *** search
- /* 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, (ECHO|CRMOD|ANYP|PASS8|PASS8OUT)};
- 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 ;
- }
-
- /*
- * Currently (yuck!) we only handle leading back spaces.
- */
- - addText:(const char *)s
- {
- int bs = 0 ;
- int i, j ;
- char inbuf[400] ;
-
- bs = 200 ;
- i = 200 ;
- while (*s) {
- if (*s == 8) {
- i-- ;
- if (i < bs)
- bs = i ;
- } else
- inbuf[i++] = *s ;
- s++ ;
- }
- inbuf[i] = 0 ;
-
- j = [text textLength] + bs - 200 ;
- if (j < 0) {
- j = 0 ;
- }
- [text setSel:j :bs+j];
- [text replaceSel:inbuf + bs] ;
- [text scrollSelToVisible];
- return self;
- }
-
- - handler:(int)fd
- {
- int r ;
- char outbuf[200] ;
-
- if (childID == 0)
- return self ;
- /* printf("In handler\n") ; */
- while ((r = read(fd, outbuf, 199)) > 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"] ;
- while (wait3(0, WNOHANG, 0) > 0) ; /* allow zombies to go away again */
- 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
-