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> #import <mach/cthreads.h> #import <dpsclient/dpsNeXT.h> #import <objc/objc.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[2000] ; 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[4000] ; 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; } - addText2:(const char *)s:(int) len { int j ; j = [text textLength]; [text setSel:j :len+j]; [text replaceSel:s] ; [text setSel:len+j-1 :len+j]; [text scrollSelToVisible]; return self; } - handler:(int)fd { int r ; char outbuf[2000] ; 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 ; } static int eots_wanted=0; static int rec(id self, char *pa, char *pe) { char *pr = pa; for(;;) { while(*(pr++) != 4) ; if(pr==pe) { /* letztes Zeichen war Ende */ *(--pr) = 0; [self addText2:pa:pr-pa] ; --eots_wanted; return (eots_wanted); } else if(pr > pe) { /* Ende noch nicht erreicht */ *pe = 0; [self addText2:pa:pe-pa] ; return (eots_wanted); } else { /* pa < pr < pe */ /* Ende war mittendrin */ *(--pr) = 0; if (pr-pa) [self addText2:pa:pr-pa] ; pa = ++pr; --eots_wanted; }; } } - MoConOut:(id)s { int c; char ch[100],*pe; extern int my_log_file; extern myPageView; extern int in_copy_file; if(!eots_wanted) return self; if(in_copy_file) { /* postscript interpretation is active, will worry WM */ SEL method = @selector(MoConOut:); [self perform:method with:self afterDelay:0 cancelPrevious:TRUE]; return(self); }; // thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 3000); c = read(0,ch,99); if(c==1 && *ch==4) { eots_wanted--; return self; }; [[self window] makeKeyAndOrderFront:nil] ; pe = &ch[c]; *pe = 4; /* set sentinell */ while( rec(self,ch,pe) ) { // thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 5000); c = read(0,ch,99); pe = &ch[c]; *pe = 4; /* set sentinell */ } ; [[myPageView window] makeKeyAndOrderFront:nil] ; return self; } void ModalConsoleOutput () { extern ComScroll *console; eots_wanted++; [console MoConOut:console]; }; @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.