home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3.4.17 [SPARC, PA-RISC] / nextstep33_risc.iso / NextLibrary / TeX / tex / src / texview / ComScroll.m < prev    next >
Encoding:
Text File  |  1992-05-31  |  8.6 KB  |  371 lines

  1. /* Generated by Interface Builder */
  2.  
  3. #import "ComScroll.h"
  4. #import "CText.h"
  5. #import <appkit/nextstd.h>
  6. #import <appkit/Application.h>
  7. #import <appkit/Window.h>
  8. #import <appkit/Font.h>
  9. #import <appkit/Panel.h>
  10.  
  11. extern char defaultfont[] ;
  12.  
  13. extern void error(), configure() ;
  14.  
  15. static void getptys (master, slave)
  16. int *master, *slave ;
  17. {
  18.    char device[12];
  19.    char *block, *num;
  20.    char *blockLoc;
  21.    char *numLoc;
  22.    char *msLoc;
  23.    struct sgttyb setp =
  24.       {B9600, B9600, (char)0x7f, (char)0x15, (ECHO|CRMOD|ANYP|PASS8|PASS8OUT)};
  25.    struct tchars setc =
  26.       {CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK};
  27.    struct ltchars sltc =
  28.       {CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT};
  29.    int lset =
  30.       (LCRTBS|LCRTERA|LCRTKIL|LCTLECH|LPENDIN|LDECCTQ);
  31.    int setd = NTTYDISC;
  32.  
  33.    strcpy(device, "/dev/pty??");
  34.    blockLoc = &device[ strlen("/dev/pty") ];
  35.    numLoc = &device[ strlen("/dev/pty?") ];
  36.    msLoc = &device[ strlen("/dev/") ];
  37.    for (block = "pqrs"; *block; block++) {
  38.       *blockLoc = *block;
  39.       for (num = "0123456789abcdef"; *num; num++) {
  40.          *numLoc = *num;
  41.          *master = open(device, O_RDWR);
  42.          if (*master >= 0) {
  43.             *msLoc = 't';
  44.             *slave = open(device, O_RDWR);
  45.             if (*slave >= 0) {
  46.                (void) ioctl(*slave, TIOCSETP, (char *)&setp);
  47.                (void) ioctl(*slave, TIOCSETC, (char *)&setc);
  48.                (void) ioctl(*slave, TIOCSETD, (char *)&setd);
  49.                (void) ioctl(*slave, TIOCSLTC, (char *)&sltc);
  50.                (void) ioctl(*slave, TIOCLSET, (char *)&lset);
  51.                return;
  52.             }
  53.          }
  54.       }
  55.    }
  56.    *master = -1;
  57.    *slave = -1;
  58. }
  59.  
  60. @implementation ComScroll
  61.  
  62. + newFrame:(const NXRect *)frameRect
  63. {
  64.    self = [super newFrame:frameRect] ;
  65.    [self setVertScrollerRequired: YES] ;
  66.    [self setBackgroundGray: NX_WHITE] ;
  67.    [self awake] ;
  68.    childID = 0 ;
  69.    waiting = 0 ;
  70.    return self ;
  71. }
  72.  
  73. - awake
  74. {
  75.    NXRect trect ;
  76.    Font *mf = 0 ;
  77.  
  78.    configure() ;
  79.    if (defaultfont[0]) {
  80.       char *p = defaultfont ;
  81.       char fname[100] ;
  82.       char *q = fname ;
  83.       float size ;
  84.  
  85.       for (; *p && *p != ':'; p++, q++)
  86.          *q = *p ;
  87.       *q = 0 ;
  88.       if (*p && sscanf(p+1, "%f", &size)==1)
  89.          mf = [Font newFont:fname size:size] ;
  90.    }
  91.    if (mf == 0)
  92.       mf = [Font newFont:"Ohlfs" size:10] ;
  93.    trect.origin.x = trect.origin.y = 0 ;
  94.    [self getContentSize: &(trect.size)] ;
  95.    text = [[CText alloc]
  96.                   initFrame:&trect text:NULL alignment:NX_LEFTALIGNED] ;
  97.    [text setFont:mf] ;
  98.    [text notifyAncestorWhenFrameChanged:YES] ;
  99. // [text setEditable:NO] ;
  100.    [text setEditable:YES] ;
  101.    [text setHorizResizable:NO] ;
  102.    [text setVertResizable:YES] ;
  103.    [text setMinSize:&(trect.size)] ;
  104.    trect.size.height = 1000000 ;
  105.    trect.size.width = 1200 ;
  106.    [text setMaxSize:&(trect.size)] ;
  107.    [self setAutoresizeSubviews:YES] ;
  108.    [self setAutosizing: NX_HEIGHTSIZABLE | NX_WIDTHSIZABLE] ;
  109.    [text setMonoFont:YES] ;
  110.    [text setOpaque:YES] ;
  111.    [text setFontPanelEnabled:YES] ;
  112.    [self setDocView:text] ;
  113.    [text setDelegate:self] ;
  114.    [text setController:self] ;
  115.    return self ;
  116. }
  117.  
  118. /*
  119.  *   Currently (yuck!) we only handle leading back spaces.
  120.  */
  121. - addText:(const char *)s
  122. {
  123.    int bs = 0 ;
  124.    int i, j ;
  125.    char inbuf[400] ;
  126.  
  127.    bs = 200 ;
  128.    i = 200 ;
  129.    while (*s) {
  130.       if (*s == 8) {
  131.          i-- ;
  132.          if (i < bs)
  133.             bs = i ;
  134.       } else
  135.          inbuf[i++] = *s ;
  136.       s++ ;
  137.    }
  138.    inbuf[i] = 0 ;
  139.  
  140.    j = [text textLength] + bs - 200 ;
  141.    if (j < 0) {
  142.       j = 0 ;
  143.    }
  144.    [text setSel:j :bs+j];
  145.    [text replaceSel:inbuf + bs] ;
  146.    [text scrollSelToVisible];
  147.    return self;
  148. }
  149.  
  150. - handler:(int)fd
  151. {
  152.    int r ;
  153.    char outbuf[200] ;
  154.  
  155.    if (childID == 0)
  156.       return self ;
  157. /* printf("In handler\n") ; */
  158.    while ((r = read(fd, outbuf, 199)) > 0) {
  159. /*    printf("<%d> bytes\n", r) ; */
  160.       if (waiting) {
  161.          struct timeval tv ;
  162.          struct timezone tzp ;
  163.  
  164.          gettimeofday(&tv, &tzp) ;
  165.          if (tv.tv_sec > waittime.tv_sec ||
  166.              (tv.tv_sec == waittime.tv_sec && tv.tv_usec > waittime.tv_usec)) {
  167.             [[self window] makeKeyAndOrderFront:0] ;
  168.             waiting = 0 ;
  169.          }
  170.       }
  171.       if (eofcount > 0) {
  172.          write(fd, eofchar, 1) ;
  173.          eofcount-- ;
  174.       }
  175.       outbuf[r] = 0 ;
  176.       [self addText:outbuf] ;
  177.    }
  178.    if (r == 0)
  179.       [self closeChild:fd] ;
  180.    else if (errno != EWOULDBLOCK) {
  181.       [self closeChild:fd] ;
  182.    }
  183. /* printf("Out handler\n") ; */
  184.    return self ;
  185. }
  186.  
  187. static void cm_handler(fd, sender)
  188. int fd ;
  189. id sender ;
  190. {
  191.    [sender handler:fd] ;
  192. }
  193.  
  194. - closeChild:(int)fd
  195. {
  196.    if (childID) {
  197.       if (fdadded)
  198.          DPSRemoveFD(fd) ;
  199.       childID = 0 ;
  200.       close(fd) ;
  201.       masterFD = 0 ;
  202.    }
  203. // [text setEditable:NO] ;
  204.    [text setEditable:YES] ;
  205.    return self ;
  206. }
  207.  
  208. static void msleep(long len) {
  209.    struct timeval tv ;
  210.  
  211.    tv.tv_usec = len % 1000000 ;
  212.    tv.tv_sec = len / 1000000 ;
  213.    select(0, 0, 0, 0, &tv) ;
  214. }
  215.  
  216. - killOff
  217. {
  218.    if (childID) {
  219.       kill(childID, SIGTERM) ;
  220.       childID = 0 ;
  221.    }
  222.    return self ;
  223. }
  224.  
  225. - logCommand:(const char *)s inBack:(int)async
  226. {
  227.    int masterPty, slavePty ;
  228.    int tty, numFds, fd;
  229.    int processGroup;
  230.    int pidChild;
  231.    int i ;
  232.  
  233.    while (wait3(0, WNOHANG, 0) > 0) ; /* allow zombies to go away */
  234.    if (childID)
  235.       if (masterFD)
  236.          [self handler:masterFD] ;
  237.    if (childID) {  // are we busy??
  238. /*    i = NXRunAlertPanel(NULL, "Command window busy",
  239.     "Cancel request", "Force EOF and override", "Force ^C and override", 0) ;
  240.  */
  241.       i = NX_ALERTALTERNATE ;
  242.       if (i != NX_ALERTDEFAULT) {
  243.          if (i == NX_ALERTALTERNATE)
  244.             eofchar[0] = 4 ;
  245.          else
  246.             eofchar[0] = 3 ;
  247.          write(masterFD, eofchar, 1) ;
  248.          eofcount = 3 ;
  249.          for (i=0; i<5; i++) {
  250.             if (childID) {
  251.                msleep(300000) ;
  252.                [self handler:masterFD] ;
  253.             }
  254.          }
  255.       }
  256.    }
  257.    if (childID) {
  258.       // we tried nicely, now we get mean.
  259.       kill(childID, SIGTERM) ;
  260.       msleep(300000) ;
  261.       [self handler:masterFD] ;
  262.       if (childID)
  263.          [self closeChild:masterFD] ;
  264.    }
  265.    if (childID) {
  266.       error("you'll have to intercede for me; I couldn't get it to die.") ;
  267.       return 0 ;
  268.    }
  269.    [self addText:" - "] ;
  270.    [self addText:s] ;
  271.    [self addText:"\n"] ;
  272.    while (wait3(0, WNOHANG, 0) > 0) ; /* allow zombies to go away again */
  273.    tty = open("/dev/tty", O_RDWR);
  274.    getptys(&masterPty, &slavePty);
  275.    if (masterPty <= 0 || slavePty <= 0)
  276.        error("! error grabbing ptys for subprocess") ;
  277.  
  278.    // remove the controlling tty if launched from a shell,
  279.    // but not Workspace;
  280.    // so that we have job control over the parent application in shell
  281.    // and so that subprocesses can be restarted in Workspace
  282.    if  (tty<0) {
  283.       if ((tty = open("/dev/tty", 2))>=0) {
  284.          ioctl(tty, TIOCNOTTY, 0);
  285.          close(tty);
  286.       }
  287.    } else {
  288.       close(tty) ;
  289.    }
  290.    switch (pidChild = vfork()) {
  291.    case -1:   // error
  292.       error("! error starting UNIX vfork of subprocess.") ;
  293.    case 0:   // child
  294.       dup2(slavePty, 0);
  295.       dup2(slavePty, 1);
  296.       dup2(slavePty, 2);
  297.       numFds = getdtablesize();
  298.       for (fd=3; fd<numFds; fd++)
  299.          close(fd);
  300.       processGroup = getpid();
  301.       ioctl(0, TIOCSPGRP, (char *)&processGroup);
  302.       setpgrp (0, processGroup);
  303.       execl("/bin/csh", "csh", "-c", s, 0) ;
  304.       error("! vfork (child)") ;
  305.    default:   // parent
  306.       close(slavePty);
  307.       childID = pidChild ;
  308.       eofcount = 3 ;
  309.       if (async) {
  310.          [text setEditable:YES] ;
  311.          if (fcntl(masterPty, F_SETFL, FNDELAY) == -1)
  312.             error("! couldn't fcntl") ;
  313.          DPSAddFD(masterPty, cm_handler, self, NX_MODALRESPTHRESHOLD) ;
  314.          fdadded = 1 ;
  315.          masterFD = masterPty ;
  316.          eofcount = 0 ;
  317.       } else {
  318.          struct timezone tzp ;
  319.  
  320.          fdadded = 0 ;
  321.          masterFD = 0 ;
  322.          eofcount = 3 ;
  323.          eofchar[0] = 4 ;
  324.          write(masterPty, "\004", 1) ;
  325.          waiting = ! [[self window] isVisible] ;
  326.          gettimeofday(&waittime, &tzp) ;
  327.          waittime.tv_sec += 5 ; /* pop up after five seconds if necessary */
  328.          [self handler:masterPty] ;
  329.       }
  330.       break ;
  331.    }
  332.    return self ;
  333. }
  334.  
  335. - abortCommand:sender
  336. {
  337.     return self;
  338. }
  339.  
  340. - sendToMaster:(const char *)s
  341. {
  342.    if (masterFD)
  343.       write(masterFD, s, strlen(s)) ;
  344.    return self ;
  345. }
  346.  
  347. - (BOOL)textWillChange:textObject
  348. {
  349.     [text setSel:[text textLength] :0];
  350.     [text scrollSelToVisible];
  351.     return NO;
  352. }
  353. - clear
  354. {
  355.    [text selectAll:self] ;
  356.    if ([text isEditable])
  357.       [text delete:self] ;
  358.    else {
  359.       [text setEditable:YES] ;
  360.       [text delete:self] ;
  361.       [text setEditable:NO] ;
  362.    }
  363.    return self ;
  364. }
  365.  
  366. - text
  367. {
  368.    return text ;
  369. }
  370. @end
  371.