Annotation of 43BSDTahoe/new/jove/mac.c, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
                      3:  * is provided to you without charge, and with no warranty.  You may give  *
                      4:  * away copies of JOVE, including sources, provided that this notice is    *
                      5:  * included in all the files.                                              *
                      6:  ***************************************************************************/
                      7: 
                      8: 
                      9: /* (C) 1986, 1987, 1988 Ken Mitchum. This code is intended only for use with Jove. */
                     10: 
                     11: #include "tune.h"
                     12: #ifdef MAC
                     13: #define _mac 
                     14: #include <MacTypes.h>
                     15: #include "jove.h" 
                     16: #include <QuickDraw.h>
                     17: #include <WindowMgr.h>
                     18: #include <FontMgr.h>
                     19: #include <ListMgr.h>
                     20: #include <EventMgr.h>
                     21: #include <ControlMgr.h>
                     22: #include <DialogMgr.h>
                     23: #include <ResourceMgr.h>
                     24: #include <ToolboxUtil.h>
                     25: #include <HFS.h>
                     26: #include <StdFilePkg.h>
                     27: #include <MenuMgr.h>
                     28: #include <pascal.h>
                     29: #include <errno.h>
                     30: #include <SegmentLdr.h>
                     31: #include "mac.h"
                     32: #include "termcap.h"
                     33: 
                     34: /***************************************************/
                     35: 
                     36: /* these normally reside in "tune.c" which we don't use */
                     37: 
                     38: char *CmdDb;   /* see InitMac() */
                     39: char *p_tempfile = ".jrecXXX"; 
                     40: char *d_tempfile = ".joveXXX";
                     41: char *Joverc = ".joverc";      
                     42: 
                     43: 
                     44: void putcurs(),curset(),putp(),dellines(),inslines();
                     45: 
                     46: 
                     47: static WindowPtr theScreen;
                     48: 
                     49: int
                     50:        errno,
                     51:        EventCmd,
                     52:        Keyonly,
                     53:        Macmode,
                     54:        Bufchange,
                     55:        Modechange,
                     56:        Windchange;
                     57: 
                     58: 
                     59: 
                     60: 
                     61: /* Initialization Routines. */
                     62: 
                     63: void InitBinds()
                     64: {
                     65:        struct cmd *c;
                     66:        data_obj **p;
                     67:        int i;
                     68:        
                     69:        p = mainmap;
                     70:        for(i= 0; i < NCHARS; i++) {
                     71:                c = (struct cmd *) *p;
                     72:                c->c_map = F_MAINMAP;
                     73:                c->c_key = i;
                     74:                p++;
                     75:        }
                     76:        
                     77:        p = pref1map;
                     78:        for(i= 0; i < NCHARS; i++) {
                     79:                c = (struct cmd *) *p;
                     80:                c->c_map = F_PREF1MAP;
                     81:                c->c_key = i;
                     82:                p++;
                     83:        }
                     84:        p = pref2map;
                     85:        for(i= 0; i < NCHARS; i++) {
                     86:                c = (struct cmd *) *p;
                     87:                c->c_map = F_PREF2MAP;
                     88:                c->c_key = i;
                     89:                p++;
                     90:        }
                     91:        
                     92: }
                     93: 
                     94: static WindowPtr window;
                     95: static Rect r; 
                     96: static CursHandle cross;
                     97: 
                     98: void InitEvents()
                     99: {
                    100:        void InitSysMenu();
                    101:        
                    102:        window = theScreen;
                    103:        InitSysMenu();          
                    104:        SetRect(&r,window->portRect.left,
                    105:        window->portRect.top,
                    106:        window->portRect.right - SCROLLWIDTH,
                    107:        window->portRect.bottom - SCROLLWIDTH);
                    108:        cross = GetCursor(crossCursor);
                    109: }
                    110: 
                    111: void MacInit()
                    112: {
                    113:        char *gethome();
                    114:        void tn_init();
                    115: 
                    116:        tn_init();
                    117:        getdir();
                    118:        gethome();      /* before anyone changes it */
                    119:        CmdDb = malloc(strlen(gethome()) + 10);
                    120:        strcpy(CmdDb,gethome());
                    121:        strcat(CmdDb,"/cmds.doc");
                    122:        InitBinds();
                    123: }
                    124: 
                    125: 
                    126: /* dummy routines. */
                    127: 
                    128: void InitCM()
                    129: {
                    130: }
                    131: 
                    132: void ResetTerm(){}
                    133: 
                    134: void UnsetTerm(s)
                    135: char *s;
                    136: {
                    137: }
                    138: 
                    139: 
                    140: 
                    141: int dummy(){}
                    142: 
                    143: int (*signal(sig,func))()
                    144: int sig;
                    145: int (*func)();
                    146: {
                    147:        return(&dummy);
                    148: }
                    149: dorecover() {}
                    150: 
                    151: 
                    152: /* Surrogate unix-style file i/o routines for Jove. These replace the
                    153:    routines distributed in the libraries. They work with Jove, but may
                    154:    not be general enough for other purposes. */
                    155: 
                    156: #include <io.h>
                    157: #define NFILES 10
                    158: /*
                    159: #define fsetup(p) {p.ioCompletion = 0; p.ioVRefNum = cur_vol; p.ioDirID = cur_dir;p.ioFVersNum = 0;}
                    160: #define isetup(p) {p.ioCompletion = 0; p.ioVRefNum = cur_vol;}
                    161: */
                    162: 
                    163: static int cur_vol;    /* Disk or volume number */
                    164: static long cur_dir;   /* Directory number */
                    165: static int cur_vref;   /* ugh.. Vref for volume + directory */
                    166: 
                    167: struct ftab {
                    168:        int inuse;      /* 0 = closed 1 = binary 2 = text*/
                    169:        int refnum;     /* Mac file reference number */
                    170: } ft[NFILES];
                    171: 
                    172: fsetup(p)
                    173: HParmBlkPtr p;
                    174: {
                    175:        bzero(p,sizeof(HParamBlockRec));
                    176:        p->fileParam.ioVRefNum = cur_vol;
                    177:        p->fileParam.ioDirID = cur_dir;
                    178:        p->fileParam.ioFVersNum = 0;
                    179: }
                    180: 
                    181: isetup(p)
                    182: HIOParam *p;
                    183: {
                    184:        bzero(p,sizeof(HIOParam));
                    185:        p->ioVRefNum = cur_vol;
                    186: }
                    187: 
                    188:        
                    189: /* Kludge to convert Macintosh error codes to something like Unix. */
                    190: 
                    191: static int cvt_err(err)        /* some of these don't make sense... */
                    192: {
                    193:        switch(err) {
                    194:                case noErr: errno = 0; return(0);
                    195:                case dirFulErr: errno = ENOSPC; break;
                    196:                case dskFulErr: errno = ENOSPC; break;
                    197:                case nsvErr: errno = ENOENT; break;
                    198:                case ioErr: errno = EIO; break;
                    199:                case bdNamErr: errno = EINVAL; break;
                    200:                case fnOpnErr: errno = EBADF; break;    /* dubious... */
                    201:                case eofErr: errno = ESPIPE; break;             /* ditto */
                    202:                case posErr: errno = ESPIPE; break;
                    203:                case mFulErr: 
                    204:                case tmfoErr:
                    205:                case fnfErr: errno = ENOENT; break;
                    206:                case wPrErr: errno = EROFS; break;
                    207:                case fLckdErr: errno = EACCES; break;
                    208:                case fBsyErr: errno = EBUSY; break;
                    209:                case dupFNErr: errno = EEXIST; break;
                    210:                case opWrErr:
                    211:                case paramErr: errno = EINVAL; break;
                    212:                case rfNumErr: errno = EBADF; break;
                    213:                case gfpErr:
                    214:                case volOffLinErr: errno = ENODEV; break;
                    215:                case permErr: errno = EACCES; break;
                    216:                case volOnLinErr: errno = ENODEV; break;
                    217:                case nsDrvErr: errno = ENODEV; break;
                    218:                case noMacDskErr: errno = EIO; break;
                    219:                case extFSErr: errno = EIO; break;
                    220:                case fsRnErr: 
                    221:                case badMDBErr:
                    222:                case wrPermErr: errno = EPERM; break;
                    223:                default: errno = ENOENT;
                    224:        }
                    225:        return(-1);
                    226: }
                    227: 
                    228: static char *cvt_fnm(file)
                    229: char *file;
                    230: {
                    231:        static char nm[255];
                    232:        char *t;
                    233: 
                    234: 
                    235:        if(*file == '/') strcpy(nm,file + 1); /* full path */
                    236:        else {
                    237:                if(index(file + 1, '/') != NULL)
                    238:                        strcpy(nm,"/"); /* make a partial pathname */
                    239:                else *nm = '\0';
                    240:                strcat(nm,file);
                    241:        }
                    242:        t = nm;
                    243:        while(*t) {
                    244:                if(*t == '/') *t = ':';
                    245:                t++;
                    246:        }
                    247:        return(nm);
                    248: }
                    249: 
                    250: int creat(name,perm)   /* permission mode is irrelevant on a Mac */
                    251: char *name;
                    252: {
                    253:        int fd, err;
                    254:        char *nm;
                    255:        HParamBlockRec p;
                    256: 
                    257:        nm = cvt_fnm(name);     /* convert filename to Mac type name */
                    258:        CtoPstr(nm);
                    259:        for(fd = 0; fd < NFILES && ft[fd].inuse; fd++);
                    260:        if(fd == NFILES) {
                    261:                errno = EMFILE;
                    262:                return(-1);
                    263:        }
                    264:        fsetup(&p);     /* try to delete it, whether it is there or not. */
                    265:        p.fileParam.ioNamePtr = (StringPtr) nm;
                    266:        if((err = PBHDelete(&p,0)) != noErr && err != fnfErr) return(cvt_err(err));
                    267:        if(do_creat(&p,nm) != 0) return(-1);
                    268:        else {
                    269:                ft[fd].inuse++;
                    270:                ft[fd].refnum = p.ioParam.ioRefNum;
                    271:                return(fd + 1);
                    272:        }
                    273: }
                    274: 
                    275: int open(name,mode)
                    276: char *name;
                    277: {
                    278:        int fd, err;
                    279:        char *nm;
                    280:        HParamBlockRec p;
                    281: 
                    282:        nm = cvt_fnm(name);     /* convert filename to Mac type name */
                    283:        CtoPstr(nm);
                    284:        for(fd = 0; fd < NFILES && ft[fd].inuse; fd++);
                    285:        if(fd == NFILES) {
                    286:                errno = EMFILE;
                    287:                return(-1);
                    288:        }
                    289:        fsetup(&p);
                    290:        if((mode & 3) == O_RDONLY) p.ioParam.ioPermssn = fsRdPerm;
                    291:        if((mode & 3) == O_WRONLY) p.ioParam.ioPermssn = fsWrPerm;
                    292:        if((mode & 3) == O_RDWR) p.ioParam.ioPermssn = fsRdWrPerm;
                    293:        p.ioParam.ioNamePtr = (StringPtr) nm;
                    294:        p.ioParam.ioMisc = 0;
                    295:        if((err = PBHOpen(&p,0)) != noErr && err != fnfErr) return(cvt_err(err));
                    296:        if(err == noErr && mode & O_CREAT && mode & O_EXCL) {
                    297:                PBClose(&p,0);
                    298:                errno = EEXIST;
                    299:                return(-1);
                    300:        }
                    301:        if(err == fnfErr) {
                    302:                if(mode & O_CREAT) {
                    303:                        if(do_creat(&p,nm) != 0) return(-1);
                    304:                } else {
                    305:                        errno = ENOENT;
                    306:                        return(-1);
                    307:                }
                    308:        }
                    309:        ft[fd].inuse++;
                    310:        ft[fd].refnum = p.ioParam.ioRefNum;
                    311:        if(mode & O_APPEND)     p.ioParam.ioPosMode = fsFromLEOF;
                    312:        else p.ioParam.ioPosMode = fsFromStart;
                    313:        p.ioParam.ioPosOffset = 0;
                    314:        if((err = PBSetFPos(&p,0)) != noErr) {
                    315:                ft[fd].inuse = 0;
                    316:                return(cvt_err(err));
                    317:        }
                    318:        errno = 0;
                    319:        return(fd + 1);
                    320: }
                    321: 
                    322: static int do_creat(p,nm)
                    323: HParmBlkPtr p;
                    324: char *nm;
                    325: {
                    326:        int err;
                    327:        
                    328:        fsetup(p);
                    329:        p->fileParam.ioNamePtr = (StringPtr) nm;
                    330:        if((err = PBHCreate(p,0)) != noErr) return(cvt_err(err));
                    331:        fsetup(p);
                    332:        p->fileParam.ioNamePtr = (StringPtr) nm;
                    333:        p->fileParam.ioFDirIndex = 0;
                    334:        if((err = PBHGetFInfo(p,0)) != noErr) return(cvt_err(err));
                    335:        p->fileParam.ioDirID = cur_dir;
                    336:        p->fileParam.ioFlFndrInfo.fdType = 'TEXT';
                    337:        p->fileParam.ioFlFndrInfo.fdCreator = 'JV01';
                    338:        p->fileParam.ioFlFndrInfo.fdFlags = 0;
                    339:        p->fileParam.ioFVersNum = 0;
                    340:        if((err = PBHSetFInfo(p,0)) != noErr) return(cvt_err(err));
                    341:        fsetup(p);
                    342:        p->ioParam.ioNamePtr = (StringPtr) nm;
                    343:        p->ioParam.ioPermssn = fsRdWrPerm;
                    344:        p->ioParam.ioMisc = 0;
                    345:        if(cvt_err(PBHOpen(p,0))) return(-1);
                    346:        return(0);
                    347: }
                    348: 
                    349: 
                    350: int close(fd)
                    351: {
                    352:        int err;
                    353:        HParamBlockRec p;
                    354: 
                    355:        fsetup(&p);
                    356:        p.ioParam.ioRefNum = ft[--fd].refnum;
                    357:        ft[fd].inuse = 0;
                    358: /*     if(cvt_err(PBFlushFile(&p,0)) < 0) return(-1);
                    359:        fsetup(&p); */
                    360:        if(cvt_err(PBClose(&p,0)) < 0) return(-1);
                    361:        fsetup(&p);
                    362:        p.ioParam.ioNamePtr = 0;
                    363:        if(cvt_err(PBFlushVol(&p,0)) < 0) return(-1);
                    364: }
                    365: 
                    366: int read(fd,buf,n)
                    367: char *buf;
                    368: unsigned n;
                    369: {
                    370:        int err;
                    371:        IOParam p;
                    372:        if(fd == 0) return(con_read(buf,n));
                    373:        if(ft[--fd].inuse == 0) {
                    374:                errno = EBADF;
                    375:                return(-1);
                    376:        }
                    377:        isetup(&p);
                    378:        p.ioRefNum = ft[fd].refnum;
                    379:        p.ioBuffer = buf;
                    380:        p.ioReqCount = n;
                    381:        p.ioPosMode = fsFromMark;
                    382:        p.ioPosOffset = 0;
                    383:        if((err = PBRead(&p,0)) != noErr && err != eofErr) {
                    384:                cvt_err(err);
                    385:                return(-1);
                    386:        }
                    387:        while(n--) {            
                    388:                if(*buf == '\r') *buf = '\n';   /* convert from Mac style */
                    389:                buf++;
                    390:        }
                    391:        errno = 0;
                    392:        return(p.ioActCount);
                    393: }
                    394: 
                    395: int write(fd,buf,n)
                    396: char *buf;
                    397: unsigned n;
                    398: {
                    399:        int err;
                    400:        IOParam p;
                    401:        char *obuf, *s;
                    402:        
                    403:        if(fd == 0) return(con_write(buf,n));
                    404:        
                    405:        s = obuf = malloc(n + 1);
                    406:        if(obuf == 0)  return(-1);      /* shouldn't happen... */
                    407:        if(ft[--fd].inuse == 0) {
                    408:                errno = EBADF;
                    409:                free(obuf);
                    410:                return(-1);
                    411:        }
                    412:        isetup(&p);
                    413:        p.ioRefNum = ft[fd].refnum;
                    414:        p.ioBuffer = obuf;
                    415:        p.ioReqCount = (long) n;
                    416:        p.ioPosMode = fsFromMark;
                    417:        p.ioPosOffset = 0L;
                    418:        while(n--) {            
                    419:                if(*buf == '\n') *s = '\r';     /* make it look like Mac files */
                    420:                else(*s = *buf);
                    421:                buf++;
                    422:                s++;
                    423:        }
                    424:        if((err = PBWrite(&p,0)) != noErr) {
                    425:                free(obuf);
                    426:                return(-1);
                    427:        }
                    428:        free(obuf);
                    429:        return((int) p.ioActCount);
                    430: }
                    431: 
                    432: long lseek(fd,offset,type)     /* The Mac version of this doesn't allocate new space. */
                    433: long offset;
                    434: unsigned type;
                    435: {
                    436:        int err;
                    437:        long cur_mark, eof, new_mark;
                    438:        IOParam p;
                    439: 
                    440:        if(ft[--fd].inuse == 0) {
                    441:                errno = EBADF;
                    442:                return(-1);
                    443:        }
                    444: 
                    445:        isetup(&p);
                    446:        p.ioRefNum = ft[fd].refnum;
                    447:        if((err = PBGetFPos(&p,0)) != noErr) {
                    448:                cvt_err(err);
                    449:                return(-1);
                    450:        }
                    451:        cur_mark = p.ioPosOffset;
                    452:        isetup(&p);
                    453:        p.ioRefNum = ft[fd].refnum;
                    454:        if((err = PBGetEOF(&p,0)) != noErr) {
                    455:                cvt_err(err);
                    456:                return(-1);
                    457:        }
                    458:        eof = (long) p.ioMisc;
                    459:        switch(type) {
                    460:                case 0 :
                    461:                        new_mark = offset;
                    462:                        break;
                    463:                case 1 :
                    464:                        new_mark = offset + cur_mark;
                    465:                        break;
                    466:                case 2 :
                    467:                        new_mark = offset + eof;
                    468:        }
                    469:        if(new_mark > eof) {            /* need more space in file */
                    470:                isetup(&p);
                    471:                p.ioRefNum = ft[fd].refnum;
                    472:                p.ioMisc = (Ptr) new_mark;
                    473:                if((err = PBSetEOF(&p,0)) != noErr) {
                    474:                        cvt_err(err);
                    475:                        return(-1);
                    476:                }
                    477: /*             if((err = PBAllocContig(&p,0)) != noErr) {
                    478:                        cvt_err(err);
                    479:                        return(-1);
                    480:                }*/
                    481:        }
                    482:        isetup(&p);
                    483:        p.ioRefNum = ft[fd].refnum;
                    484:        p.ioPosOffset = new_mark;
                    485:        p.ioPosMode = fsFromStart;
                    486:        if((err = PBSetFPos(&p,0)) != noErr) {
                    487:                cvt_err(err);
                    488:                return(-1);
                    489:        }
                    490:        errno = 0;
                    491:        return(p.ioPosOffset);
                    492: }
                    493: 
                    494: int unlink(name)
                    495: char *name;
                    496: {      int fd, err;
                    497:        char *nm;
                    498:        HParamBlockRec p;
                    499: 
                    500:        nm = cvt_fnm(name);     /* convert filename to Mac type name */
                    501:        CtoPstr(nm);
                    502:        fsetup(&p);     /* try to delete it, whether it is there or not. */
                    503:        p.fileParam.ioNamePtr = (StringPtr) nm;
                    504:        if((err = PBHDelete(&p,0)) != noErr && err != fnfErr) return(cvt_err(err));
                    505:        return;
                    506: }
                    507: 
                    508: /* Console read and write routines */
                    509: 
                    510: static int con_write(buf,size)
                    511: unsigned  size;
                    512: char *buf;
                    513: {
                    514:        while(size--) putp(*buf++);
                    515:        return(size);
                    516: }
                    517: 
                    518: static int con_read(buf,size)
                    519: unsigned size;
                    520: char *buf;
                    521: {
                    522:        unsigned n;
                    523:        int p;
                    524: 
                    525:        
                    526:        n = 0;
                    527:        do {
                    528:                p = rawgetc();
                    529: #ifdef O_META
                    530:                if(p & 0x7f) p &= 0x7f;         /* was normal ascii char */
                    531: #endif
                    532:                *buf++ = p;
                    533:                n++;
                    534:        } while (rawchkc() && n <= size);
                    535:        return(n);
                    536: }
                    537: 
                    538: 
                    539: /* This didn't seem to be any place else */
                    540: 
                    541: int abs(n)
                    542: int n;
                    543: {
                    544:        return(n >= 0 ? n : -n);
                    545: 
                    546: }
                    547: 
                    548: /* Simplified stat() routine emulates what is needed most. */
                    549: 
                    550: int stat(fname,buf)
                    551: char *fname;
                    552: struct stat *buf;
                    553: {
                    554:        CInfoPBRec p;
                    555:        char *nm;
                    556:        
                    557:        nm = cvt_fnm(fname);
                    558:        CtoPstr(nm);
                    559:        bzero(&p,sizeof(CInfoPBRec));
                    560:        p.hFileInfo.ioCompletion = 0;
                    561:        p.hFileInfo.ioNamePtr = (StringPtr) nm;
                    562:        p.hFileInfo.ioFVersNum = 0;
                    563:        p.hFileInfo.ioFDirIndex = 0;
                    564:        p.hFileInfo.ioVRefNum = cur_vol;
                    565:        p.hFileInfo.ioDirID = cur_dir;
                    566:        
                    567:        switch (PBHGetFInfo(&p,0)) {
                    568:                
                    569:                case noErr :    errno = 0;
                    570:                                                break;
                    571:                case nsvErr:
                    572:                case paramErr:
                    573:                case bdNamErr :
                    574:                case fnfErr:    errno = ENOENT;
                    575:                                                break;
                    576:                case ioErr:             errno = EIO;
                    577:                                                break;
                    578:                default :               errno = ENOENT;
                    579:                                                break;
                    580:        }
                    581:        buf->st_dev = p.hFileInfo.ioVRefNum + 1;        /* don't want 0 */
                    582:        buf->st_ino = p.hFileInfo.ioDirID;
                    583:        buf->st_size = p.hFileInfo.ioFlLgLen;
                    584:        buf->st_mtime = p.hFileInfo.ioFlMdDat;
                    585:        buf->st_mode = (p.hFileInfo.ioFlAttrib & 0x10) ? S_IFDIR : 0;
                    586:        PtoCstr(nm);
                    587:        return(errno == 0 ? 0 : -1);
                    588: }
                    589: 
                    590: /* Directory related routines. Jove keeps track of the true Volume (disk) number and
                    591:    directory number, and avoids "Working Directory Reference Numbers", which are
                    592:    confusing. */
                    593:    
                    594: static int getdir()    /* call this only once, during startup. */
                    595: {
                    596:        WDPBRec p;
                    597: 
                    598:        p.ioCompletion = 0;
                    599:        p.ioNamePtr = 0;
                    600:        if(PBHGetVol(&p,0) != noErr) return(-1);        /* BIG trouble */
                    601:        cur_vol = p.ioWDVRefNum;
                    602:        cur_dir = p.ioWDDirID;
                    603:        SFSaveDisk = 0 - cur_vol;       /* these are for SF dialogs */
                    604:        CurDirStore = cur_dir;
                    605: }
                    606: 
                    607: static int setdir(vol,dir)
                    608: long dir;
                    609: {
                    610:        WDPBRec p;
                    611: 
                    612:        p.ioCompletion = 0;
                    613:        p.ioNamePtr = 0;
                    614:        p.ioVRefNum = vol;
                    615:        p.ioWDDirID = dir;
                    616:        if(PBHSetVol(&p,0) != noErr) return(-1);
                    617:        cur_vol = vol;
                    618:        cur_dir = dir;
                    619:        SFSaveDisk = 0 - vol;   /* these are for SF dialogs */
                    620:        CurDirStore = dir;
                    621: 
                    622: 
                    623: }
                    624: 
                    625: int chdir(dir)
                    626: char *dir;
                    627: {
                    628:        DirInfo d;
                    629:        WDPBRec p;
                    630:        char *t;
                    631:        char *nm; 
                    632:        
                    633:        if(strcmp(dir,"/") == 0) return(-1); /* There is no root... */
                    634:        nm = malloc(strlen(dir) + 2);
                    635:        if(nm == 0) return(-1);
                    636:        
                    637:        strcpy(nm,dir);
                    638:        t = nm;
                    639:        while(*t) {
                    640:                if(*t == '/') *t = ':';
                    641:                t++;
                    642:        }
                    643:        t = nm; 
                    644:        while(*t == ':') t++;   /*get rid of initial slashes */
                    645:        strcat(nm,":");
                    646:        CtoPstr(t);
                    647: 
                    648:        d.ioCompletion = 0;                     /* get the directory number */
                    649:        d.ioNamePtr = (StringPtr) t;
                    650:        d.ioVRefNum = cur_vol;
                    651:        d.ioFDirIndex = 0;
                    652:        d.ioDrDirID = 0;
                    653:        PBGetCatInfo(&d,0);
                    654:        free(nm);
                    655:        if(d.ioResult != noErr || ((d.ioFlAttrib & 0x10) == 0)) return(-1);
                    656:        if(setdir(d.ioVRefNum,d.ioDrDirID) < 0)return(-1);
                    657:        return(0);
                    658: }
                    659: 
                    660: /* Scandir returns the number of entries or -1 if the directory cannoot
                    661:    be opened or malloc fails. */
                    662: 
                    663: int scandir(dir, nmptr, qualify, sorter) /* this function has NOT been debugged */
                    664: char   *dir;
                    665: char   ***nmptr;
                    666: int    (*qualify)();
                    667: int    (*sorter)();
                    668: {
                    669:        HParamBlockRec fb;
                    670:        DirInfo d;
                    671:        long DirID;
                    672:        char    **ourarray, *nm, *t, buf[50];
                    673:        Str255 buf1;
                    674:        unsigned int    len, nalloc = 10,
                    675:                        nentries = 0;
                    676: 
                    677:        if(strcmp(dir,"/") == 0) return(-1); /* There is no root... */
                    678:        nm = malloc(strlen(dir) + 2);
                    679:        if(nm == 0) return(-1);
                    680:        
                    681:        strcpy(nm,dir);
                    682:        t = nm;
                    683:        while(*t) {
                    684:                if(*t == '/') *t = ':';
                    685:                t++;
                    686:        }
                    687:        t = nm; 
                    688:        while(*t == ':') t++;   /*get rid of initial slashes */
                    689:        strcat(nm,":");
                    690:        CtoPstr(t);
                    691: 
                    692:        d.ioCompletion = 0;                     /* get the directory number */
                    693:        d.ioNamePtr = (StringPtr) t;
                    694:        d.ioVRefNum = cur_vol;
                    695:        d.ioFDirIndex = 0;
                    696:        d.ioDrDirID = 0;
                    697:        PBGetCatInfo(&d,0);
                    698:        free(nm);
                    699:        fb.fileParam.ioDirID = DirID = d.ioDrDirID;
                    700:        fb.fileParam.ioCompletion = (long) 0;
                    701:        fb.fileParam.ioVRefNum = cur_vol;
                    702:        fb.fileParam.ioFVersNum = 0;
                    703:        fb.fileParam.ioNamePtr = buf1;
                    704: 
                    705:        if ((ourarray = (char **) malloc(nalloc * sizeof (char *))) == 0)
                    706: memfail:       complain("[Malloc failed: cannot scandir]");
                    707:        while (1) {
                    708:                fb.fileParam.ioFDirIndex = nentries;
                    709:                fb.fileParam.ioVRefNum = cur_vol;
                    710:                fb.fileParam.ioDirID = DirID;
                    711:                if(PBHGetFInfo(&fb,0) != noErr) break;  /* we are done, then */
                    712:                len = (char) *fb.fileParam.ioNamePtr;   /* pascal style string */
                    713:                strncpy(buf,fb.fileParam.ioNamePtr +1,len);
                    714:                buf[len] = '\0';
                    715: 
                    716:                if (qualify != 0 && (*qualify)(buf) == 0)
                    717:                        continue;
                    718:                if (nentries == nalloc) {
                    719:                        ourarray = (char **) realloc((char *) ourarray, (nalloc += 10) * sizeof (char *));
                    720:                        if (ourarray == 0)
                    721:                                goto memfail;
                    722:                }
                    723:                ourarray[nentries] = (char *) malloc(strlen(buf)+1);
                    724:                null_ncpy(ourarray[nentries], buf, strlen(buf));
                    725:                nentries += 1;
                    726:        }
                    727:        if ((nentries + 1) != nalloc)
                    728:                ourarray = (char **) realloc((char *) ourarray,
                    729:                                        ((nentries + 1) * sizeof (char *)));
                    730:        if (sorter != 0)
                    731:                qsort((char *) ourarray, nentries, sizeof (char **), sorter);
                    732:        *nmptr = ourarray;
                    733:        ourarray[nentries] = 0;         /* guaranteed 0 pointer */
                    734:        return nentries;
                    735: }
                    736: 
                    737: 
                    738: char *getwd()
                    739: {
                    740:        DirInfo d;
                    741:        static char ret[255];
                    742:        char nm[50], tmp[255];
                    743:        
                    744:        ret[0] = '\0';
                    745:        d.ioDrDirID = cur_dir;
                    746:        for(;;) {
                    747:                d.ioCompletion = 0;
                    748:                d.ioNamePtr = (StringPtr) nm;
                    749:                d.ioVRefNum = cur_vol;
                    750:                d.ioFDirIndex = -1;
                    751: 
                    752:                PBGetCatInfo(&d,0);
                    753:                if(d.ioResult != noErr) return(0);
                    754:                PtoCstr((char *) nm);
                    755:                strcpy(tmp,ret);
                    756:                strcpy(ret,"/");
                    757:                strcat(ret,nm);
                    758:                strcat(ret,tmp);
                    759:                if(d.ioDrDirID == 2) break;     /* home directory */
                    760:                d.ioDrDirID = d.ioDrParID;
                    761:        } 
                    762:        return(ret);
                    763: }
                    764: 
                    765: static char *gethome()         /* this will be startup directory */
                    766: {
                    767:        static char *ret = 0;
                    768:        
                    769: 
                    770:        if(ret == 0) {
                    771:                char *item = getwd();
                    772:                ret = malloc(strlen(item)+1);
                    773:                strcpy(ret,item);
                    774:        }
                    775:        return(ret);
                    776: }      
                    777: 
                    778:        
                    779: 
                    780: /* Routines that put up and manipulate the "About Jove" dialog. */
                    781: 
                    782: 
                    783: /* (ORIGINALLY IN) about_j.c. */
                    784: 
                    785: 
                    786: #define DLOGNAME "\pABOUT_JDLOG"
                    787: 
                    788: #define DONE_ITEM 1
                    789: #define LIST_ITEM 2
                    790: 
                    791: 
                    792: #define DWIDTH 460             /* there should be an easy way to get this */
                    793: #define DHEIGHT 240            /* from the resource file! */
                    794: 
                    795: WindowPtr makedisplay();
                    796: ListHandle makelist();
                    797: 
                    798: 
                    799: static WindowPtr theWindow;
                    800: static ListHandle theList;
                    801: static Rect theListRect;
                    802: static EventRecord theEvent;
                    803: 
                    804: 
                    805: 
                    806: static void about_j()
                    807: {
                    808:        void do_list(), do_events();
                    809:        
                    810:        WindowPtr OldWindow;
                    811:        
                    812:        GetPort(&OldWindow);
                    813:        
                    814:        if((theWindow = makedisplay()) == 0) return;
                    815:        SetPort(theWindow);
                    816:        if(theList = makelist()) {
                    817:                LActivate(1,theList);
                    818:                do_list();
                    819:                ShowWindow(theWindow);
                    820:                do_events();
                    821:        }
                    822:        SetPort(OldWindow);
                    823:        LDispose(theList);
                    824:        DisposDialog(theWindow);
                    825:        
                    826:        return;
                    827: }
                    828:                
                    829:        
                    830: static WindowPtr makedisplay()
                    831: {
                    832:        static int dlogid = 0;
                    833:        DialogPtr theDialog;
                    834:        Handle theHandle;
                    835:        Handle theResource;
                    836:        Str255 buf;
                    837:        long itemType;
                    838:        Rect theRect;
                    839:        short dh,dv;    /* to center dialog on the screen */
                    840:        Str255 nostring;
                    841:        
                    842:        if(dlogid == 0) {
                    843:                if((theResource = GetNamedResource('DLOG',DLOGNAME)) == 0)
                    844:                        return((WindowPtr) 0);
                    845:                itemType = 'DLOG';
                    846:                GetResInfo(theResource,&dlogid,&itemType,buf);
                    847:        }
                    848:        
                    849:        theDialog = GetNewDialog(dlogid,(long) 0,(WindowPtr) -1);
                    850:        strcpy((char *) nostring,"\p");
                    851:        ParamText("\pMacJove - Copyright (C) 1986, 1987, 1988 J. Payne, K. Gegenfurtner,",
                    852:        "\pK. Mitchum. Portions (C) THINK Technologies, Inc.",nostring,nostring);
                    853:        
                    854:        dh = screenBits.bounds.left + (screenBits.bounds.right - DWIDTH) / 2;
                    855:        dv = screenBits.bounds.top  + (screenBits.bounds.bottom - DHEIGHT) / 2;
                    856:        MoveWindow((WindowPtr)theDialog,dh,dv,0);
                    857:        ShowWindow((WindowPtr)theDialog);
                    858:        
                    859:        
                    860:        GetDItem(theDialog,LIST_ITEM,&itemType,&theHandle,&theRect);
                    861:        theListRect = theRect;
                    862:        theListRect.right -= 15;
                    863:        ((WindowPtr)theDialog)->txFont = FONT;
                    864:        ((WindowPtr)theDialog)->txSize = TEXTSIZE;
                    865:        
                    866:        return((WindowPtr) theDialog);
                    867: }
                    868: 
                    869: static void do_display()               /* draw necessary controls, lines */
                    870: {
                    871:        Rect rViewF;            /* framing rect for list */
                    872:        int offset;
                    873:        
                    874:        rViewF = theListRect;
                    875:        
                    876:        rViewF.left--;
                    877:        rViewF.top--;
                    878:        rViewF.right++;
                    879:        rViewF.bottom++;
                    880:        FrameRect(&rViewF);
                    881:        
                    882:        DrawControls(theWindow);
                    883: 
                    884: }
                    885: 
                    886: static ListHandle makelist()
                    887: {
                    888:        Point csize;
                    889:        Rect dataBounds, rView; /* list boundaries */   
                    890:        
                    891:        csize.h = csize.v = 0;
                    892:        SetRect(&dataBounds,0,0,1,0);   
                    893:        return(LNew(&theListRect,&dataBounds,csize,0,theWindow,0,0,0,1));
                    894: }
                    895: 
                    896: static void do_list()
                    897: {
                    898:        void printbind();
                    899:        
                    900:        int row, col;
                    901:        struct cmd *f;
                    902:        Str255 buf;
                    903:        Point theCell;
                    904: 
                    905:        theCell.h = 0;
                    906:        
                    907:        for(f = commands, row = 0; f->Name; f++, row++) {
                    908:                LAddRow(1,row,theList);
                    909:                theCell.v = row;
                    910: 
                    911:                printbind(f,buf);
                    912:                strcat(buf,f->Name);
                    913:                LSetCell(buf,strlen((char *)buf),theCell,theList);
                    914:                
                    915:        }
                    916: }
                    917: static void printbind(f,buf)
                    918: struct cmd *f;
                    919: char *buf;
                    920: {      
                    921:        char c;
                    922:        
                    923:        if(f->c_map == 0 || (c = f->c_key) == 0x7f) {
                    924:                strcpy(buf,"        ");
                    925:                return;
                    926:        }
                    927:        switch(f->c_map) {
                    928:                case F_MAINMAP :
                    929:                        strcpy(buf,"     ");
                    930:                        break;
                    931:                
                    932:                case F_PREF1MAP :
                    933:                        strcpy(buf," ESC ");
                    934:                        break;
                    935:                        
                    936:                case F_PREF2MAP :
                    937:                        strcpy(buf,"  ^X ");
                    938:                        break;
                    939:        }
                    940:        if(c < ' ') {
                    941:                buf[5] = '^';           /* control char */
                    942:                c |= 0x40;
                    943:        }
                    944:        else buf[5] = ' ';
                    945:        if(c >= 'a' && c<= 'z') c &= 0x5f;
                    946:        buf[6] = c;
                    947:        buf[7] = ' ';
                    948:        buf[8] = '\0';
                    949: }
                    950: 
                    951: 
                    952: 
                    953: static pascal Boolean ProcFilter(theDialog,event,itemHit)
                    954: DialogPtr theDialog;
                    955: EventRecord *event;
                    956: int *itemHit;
                    957: {
                    958:        theEvent = *event;
                    959:        if(theEvent.what == keyDown && theEvent.message & charCodeMask == '\r') {
                    960:                *itemHit = 1;
                    961:                return(TRUE);
                    962:        }
                    963:        if(theEvent.what == activateEvt && (WindowPtr) theEvent.message == theWindow) {
                    964:                LDoDraw(1,theList);
                    965:                LActivate(1,theList);
                    966:        }
                    967:        if(theEvent.what == updateEvt && (WindowPtr) theEvent.message == theWindow) {
                    968:                BeginUpdate(theWindow);
                    969:                do_display();
                    970:                DrawDialog(theWindow);
                    971:                LUpdate((GrafPtr) theWindow->visRgn,theList);
                    972:                EndUpdate(theWindow);
                    973:        }
                    974: 
                    975:        return(FALSE);
                    976: }
                    977:        
                    978: 
                    979: void do_events()
                    980: {
                    981:        int item,done;
                    982:        Point p;
                    983:        
                    984:        done = 0;
                    985:        
                    986:        while(!done) {
                    987:                ModalDialog(ProcFilter,&item);
                    988:                switch(item) {
                    989:                        case DONE_ITEM :
                    990:                                done = 1;
                    991:                        case LIST_ITEM :
                    992:                                p = theEvent.where;
                    993:                                GlobalToLocal(&p);
                    994:                                LClick(p,theEvent.modifiers,theList);
                    995:                }
                    996:        }
                    997: }
                    998: 
                    999: /* Window and Control related routines. */
                   1000: 
                   1001: /* (ORIGINALLY IN) tcon.c. 
                   1002:    control handler routines for Jove. K. Mitchum 12/86 */
                   1003: 
                   1004: 
                   1005: #define MINC 0
                   1006: #define MAXC (int)100
                   1007: #define INITC 0
                   1008: #define EVENTLIST (mDownMask | keyDownMask )
                   1009: 
                   1010: extern long GetCRefCon();      /* omitted in ControlMgr.h */
                   1011: 
                   1012: static Point p;
                   1013: static intext; /* mouse down in jove text */
                   1014: 
                   1015: void docontrols()      /* called from redisplay routines */
                   1016: {
                   1017:        void MakeScrollBar(),
                   1018:                AdjustScrollBar(),
                   1019:                drawfluff();
                   1020:        
                   1021:        Window *w;
                   1022:        int top;
                   1023: 
                   1024:        w = fwind;
                   1025:        top = 0;
                   1026:        do {
                   1027:                if(w->w_control) HideControl(w->w_control);
                   1028:                w = w->w_next;
                   1029:        } while (w != fwind);
                   1030:        w = fwind;
                   1031:        do {
                   1032:                w->w_topline = top;
                   1033:                if(w->w_control) AdjustScrollBar(w);
                   1034:                else MakeScrollBar(w);
                   1035:                ShowControl(w->w_control);
                   1036:                top += w->w_height;
                   1037:                w = w->w_next;
                   1038:        } while(w != fwind);
                   1039:        Windchange = 0;
                   1040:        drawfluff();
                   1041: }      
                   1042: 
                   1043: 
                   1044: void MakeScrollBar(w)  /* set up control */
                   1045: Window *w;
                   1046: {
                   1047:        Rect BarRect;
                   1048:        int wheight, wtop;
                   1049:        
                   1050:        WindowPtr window = theScreen;
                   1051:        wheight = w->w_height;
                   1052:        wtop = w->w_topline;
                   1053:        SetRect(&BarRect,window->portRect.right - SCROLLWIDTH + 1,
                   1054:                window->portRect.top -1 + wtop * HEIGHT,
                   1055:                window->portRect.right +1,
                   1056:                window->portRect.top + ((wheight + wtop) * HEIGHT));
                   1057:                w->w_control = ((char **) NewControl(window,&BarRect,"/psbar",1,INITC,
                   1058:                MINC,MAXC,scrollBarProc,w));
                   1059: }
                   1060: 
                   1061: void AdjustScrollBar(w)        /* redo existing control */
                   1062: Window *w;
                   1063: {
                   1064:        int wtop,wheight;
                   1065:        ControlHandle handle;
                   1066:        WindowPtr window;
                   1067:        
                   1068:        handle = (ControlHandle) w->w_control;
                   1069:        wtop = w->w_topline;
                   1070:        wheight = w->w_height;
                   1071:        window = (*handle)->contrlOwner;
                   1072: 
                   1073:        if(handle == 0) return;
                   1074: 
                   1075:        SizeControl(handle,SCROLLWIDTH,wheight * HEIGHT +1);
                   1076:        
                   1077:        MoveControl(handle,window->portRect.right - SCROLLWIDTH + 1,
                   1078:                window->portRect.top -1 + wtop * HEIGHT);
                   1079: }
                   1080: 
                   1081: void SetScrollBar(handle)      /* set value of the bar */
                   1082: ControlHandle handle;
                   1083: { 
                   1084: 
                   1085:        SetCtlValue(handle,ltoc());
                   1086: }
                   1087: 
                   1088: 
                   1089: 
                   1090: static void dodivider()        /* originally to divide windows, but not enough */
                   1091:                        /* room in between lines, so just put line at bottom */
                   1092: {
                   1093:        WindowPtr window;
                   1094:        PenState pnState;
                   1095:        
                   1096:        window = theScreen;
                   1097:        GetPenState(&pnState);
                   1098:        MoveTo(0,((MAXROW) * HEIGHT));
                   1099:        PenSize(1,1);
                   1100:        LineTo(window->portRect.right,(MAXROW) * HEIGHT);
                   1101:        SetPenState(&pnState);
                   1102:        return;
                   1103: }
                   1104: 
                   1105: static void drawfluff()                /* draw controls and dividers */
                   1106: {
                   1107:        WindowPtr window;
                   1108:        Window *w = fwind;
                   1109: 
                   1110:        window = theScreen;
                   1111:        DrawControls(window);
                   1112:        
                   1113:        dodivider();
                   1114: }      
                   1115: 
                   1116: void RemoveScrollBar(w)
                   1117: Window *w;
                   1118: {
                   1119:        if(w->w_control) DisposeControl(w->w_control);
                   1120:        dodivider();            /* erase the divider */
                   1121:        w->w_control = 0;
                   1122: 
                   1123: }
                   1124:        
                   1125: static pascal void DScroll(control,part)
                   1126: ControlHandle control;
                   1127: int part;
                   1128: {
                   1129:        DownScroll();
                   1130:        redisplay();
                   1131: }
                   1132: 
                   1133: static pascal void UScroll(control,part)
                   1134: ControlHandle control;
                   1135: int part;
                   1136: {
                   1137:        UpScroll();
                   1138:        redisplay();
                   1139: }
                   1140: 
                   1141: static pascal void NPage(control,part)
                   1142: ControlHandle control;
                   1143: int part;
                   1144: {      NextPage();
                   1145:        redisplay();
                   1146: }
                   1147: 
                   1148: static pascal void PPage(control,part)
                   1149: ControlHandle control;
                   1150: int part;
                   1151: {      PrevPage();
                   1152:        redisplay();
                   1153: }
                   1154: 
                   1155: static long npos;      /* number of lines in buffer */
                   1156: 
                   1157: static int ltoc()      /* calculate ctlvalue for line position */
                   1158: {
                   1159:        register long ipos;
                   1160:        register Line   *lp = curbuf->b_first;
                   1161: 
                   1162:        for (npos = 1; lp ; npos++, lp = lp->l_next)  {
                   1163:                if(lp == curline) ipos = npos;
                   1164:        }
                   1165:        return((int) ((ipos * MAXC) / npos));
                   1166: }
                   1167: 
                   1168: static Line *ctol(ctlv)        /* find buffer line for ctlvalue */
                   1169: int ctlv;
                   1170: {
                   1171: extern char *itoa();
                   1172:        register long ipos;
                   1173:        register Line   *lp = curbuf->b_first;
                   1174: 
                   1175:        ipos = (npos * ctlv)/MAXC;
                   1176:        while (ipos-- && lp->l_next) lp = lp->l_next;
                   1177:        return(lp);
                   1178: }
                   1179: 
                   1180: static void doWind(event,window)
                   1181: EventRecord *event;
                   1182: WindowPtr window;
                   1183: {
                   1184: #define track() TrackControl(whichControl,p,(ProcPtr) 0)
                   1185: 
                   1186:        ControlHandle whichControl;
                   1187:        Window *jwind, *cwind;
                   1188:        int notcurwind;
                   1189:        int cpart;      /* control part */
                   1190:        int oldval,newval,thumb = 0;
                   1191:        
                   1192:        p = event->where;
                   1193:        intext = 0;
                   1194:        notcurwind = 0;
                   1195:        GlobalToLocal(&p);
                   1196:        
                   1197:        if(event->what == mouseDown) {
                   1198:                if((cpart = FindControl(p,window,&whichControl)) == 0) return;
                   1199:                if((jwind = (Window *) (*whichControl)->contrlRfCon) !=  curwind) {
                   1200:                        notcurwind++;
                   1201:                        cwind = curwind;
                   1202:                        SetWind(jwind);
                   1203:                }
                   1204:                switch (cpart) {
                   1205:                        case inUpButton :       TrackControl(whichControl,p,(ProcPtr) DScroll); break;
                   1206:                        case inDownButton :     TrackControl(whichControl,p,(ProcPtr) UScroll); break;
                   1207:                        case inPageUp :         TrackControl(whichControl,p,(ProcPtr) PPage); break;
                   1208:                        case inPageDown :       TrackControl(whichControl,p,(ProcPtr) NPage); break;
                   1209:                        case inThumb :          if(track()) {
                   1210:                                                                        newval = GetCtlValue(whichControl);
                   1211:                                                                                
                   1212:                                                                        if(newval == MAXC) Eof();
                   1213:                                                                        else if(newval == MINC) Bof();
                   1214:                                                                        else SetLine(ctol(newval));
                   1215:                                                                }
                   1216:                                                                break;
                   1217:                                                                        
                   1218:                }
                   1219:                if(notcurwind) {
                   1220:                        SetWind(cwind);
                   1221:                        redisplay();
                   1222:                }
                   1223:                redisplay();    /* again, to set the cursor */
                   1224:        }
                   1225:        else {
                   1226:                if(findtext()) redisplay();
                   1227:        }
                   1228: }
                   1229: 
                   1230: 
                   1231: static void doGoAway(event,window)
                   1232: EventRecord *event;
                   1233: WindowPtr window;
                   1234: {
                   1235:        if(TrackGoAway(window,&event->where) == TRUE) Leave();
                   1236: }
                   1237: 
                   1238: static Window *rtowind(row)    /* return jove window row is in */
                   1239: int row;
                   1240: {
                   1241:        Window *w = fwind;
                   1242:        
                   1243:        do {
                   1244:                if((w->w_topline <= row) && ((w->w_height + w->w_topline) > row))
                   1245:                        return(w);
                   1246:                w = w->w_next;
                   1247:        } while(w != fwind);
                   1248:        return(0);
                   1249: }
                   1250: 
                   1251: static Line *windtol(w,row)            /* return line for row in window */
                   1252: Window *w;
                   1253: int row;
                   1254: {
                   1255:        Line *l = w->w_top;
                   1256:        
                   1257:        while(row--) if((l = l->l_next) == 0) return(0);
                   1258:        return(l);
                   1259: }
                   1260:        
                   1261: 
                   1262: static int findtext()          /* locate and move the point to match the mouse */
                   1263: {
                   1264:        int row,col;
                   1265:        Window *w;
                   1266:        Line *l;
                   1267:        ptoxy(p,&row,&col);
                   1268:        if((w = rtowind(row)) == 0) return(0);
                   1269:        if(w != curwind) SetWind(w);
                   1270:        row -= w->w_topline;            /* now have row number in window */
                   1271:        if(row >= w->w_height -1) return(0);
                   1272:        if((l = windtol(w,row)) == 0) return(0);
                   1273:        if(l->l_dline == 0) return(0);
                   1274:        this_cmd = LINECMD;
                   1275:        SetLine(l);             /* Curline is in linebuf now */
                   1276:        if(w->w_flags & W_NUMLINES) col -= 8;   /* adjust for line numbers */
                   1277:        if(col < 0) col = 0;
                   1278:        curchar = how_far(curline, col);
                   1279:        return(1);
                   1280: }
                   1281: 
                   1282:        
                   1283: static int ptoxy(p,row,col)    /* convert Point to terminal x,y coordinate */
                   1284: Point p;
                   1285: int *row,*col;
                   1286: {
                   1287:        *row = (p.v / HEIGHT);
                   1288:        *col = (p.h / WIDTH );
                   1289:        if((*row > MAXROW) || (*col > MAXCOL)) return(ERROR);
                   1290:        return(0);
                   1291: }
                   1292: 
                   1293: /* Event-related routines. The Event loop is CheckEvents(), and is called whenever
                   1294:    a console read occurs or a call to charp(). During certain activities, such as ask(),
                   1295:    etc. non-keyboard events are ignored. This is set by the variable Keyonly. 
                   1296:    As an update or activate event generates a call to redisplay(), it is important
                   1297:    that redisplay() and related routines NOT check for keyboard characters. */
                   1298:  
                   1299: /* (ORIGINALLY IN) tevent.c
                   1300:        event handler for Jove. K Mitchum 12/86 */
                   1301: 
                   1302: 
                   1303: #define SYS_ID 100
                   1304: #define NOFUNC (void (*)()) 0
                   1305: #define NEVENTS 16
                   1306: static int firsttime = 0;
                   1307: extern void doMouse(),dokeyDown(),doUpdate(),doActivate();
                   1308: static MenuHandle SysMenu;
                   1309: static void (*eventlist[])() =
                   1310: {
                   1311:        NOFUNC, /* nullEvent */
                   1312:        doMouse,/* mouseDown */
                   1313:        doMouse, /* mouseUp */
                   1314:        dokeyDown, /* keyDown */
                   1315:        NOFUNC, /* keyUp */
                   1316:        dokeyDown, /* autoKey */
                   1317:        doUpdate, /* updateEvt */
                   1318:        NOFUNC, /* diskEvt */
                   1319:        doActivate, /* activateEvt */
                   1320:        NOFUNC, /* not  used */
                   1321:        NOFUNC, /* networkEvt = 10 */
                   1322:        NOFUNC, /* driverEvt */
                   1323:        NOFUNC, /* app1Evt */
                   1324:        NOFUNC, /* app2Evt */
                   1325:        NOFUNC, /* app3Evt */
                   1326:        NOFUNC  /* app4Ev */
                   1327: };
                   1328: 
                   1329: 
                   1330: static void CheckEvents()
                   1331: {
                   1332: #define Ticks (long *) 0x16A
                   1333: 
                   1334:        void SetBufMenu(),
                   1335:                MarkModes();
                   1336:                
                   1337:        static EventRecord theEvent;
                   1338:        static Point Mousep;
                   1339:        static long time = 0;
                   1340: 
                   1341: 
                   1342:        static void (*fptr)();
                   1343:        
                   1344: #define HeapEnd (char **) 0x114
                   1345: #define ApplLimit (char **) 0x130
                   1346:        static long freesp = 50000;
                   1347:        
                   1348:        if(FrontWindow() == window) {
                   1349:                GetMouse(&Mousep);
                   1350:                if(PtInRect(Mousep,&r))
                   1351:                        SetCursor(*cross);
                   1352:                else SetCursor(&arrow);
                   1353:        }
                   1354:        
                   1355:        SystemTask();
                   1356:        if(EventCmd && !Keyonly) return;
                   1357:        if(Bufchange != 0) SetBufMenu();
                   1358:        if(Modechange != 0) MarkModes();
                   1359:        while(GetNextEvent(everyEvent,&theEvent)) {
                   1360:                if ((theEvent.what < NEVENTS) && (fptr = eventlist[theEvent.what])) {
                   1361:                        (*fptr)(&theEvent);
                   1362:                }
                   1363:                SystemTask();
                   1364:        }
                   1365:        if((*ApplLimit - *HeapEnd) < freesp) {
                   1366:                freesp = (((*ApplLimit - *HeapEnd)/5000) * 5000);
                   1367:                SysBeep(120);
                   1368:                s_mess("WARNING: Free memory down to %D bytes",freesp);
                   1369:                freesp -= 5000;
                   1370:                if(!Macmode) redisplay();
                   1371:        }
                   1372:        if((*Ticks - time) > 3600) {
                   1373:                time = *Ticks;
                   1374:                UpdModLine = YES;
                   1375:                redisplay();
                   1376:        }
                   1377: 
                   1378: }
                   1379: 
                   1380: 
                   1381: static void InitSysMenu()
                   1382: {
                   1383:        void InitLocalMenus();
                   1384:        
                   1385:        SysMenu = NewMenu(SYS_ID,"\p\24");
                   1386:        AppendMenu(SysMenu,"\pAbout Jove");
                   1387:        AddResMenu(SysMenu,'DRVR');
                   1388:        InsertMenu(SysMenu,0);
                   1389:        InitLocalMenus();
                   1390:        DrawMenuBar();
                   1391: }
                   1392: 
                   1393: extern void doWind(),doGoAway(),doSysMenu(),doSysClick();
                   1394: #define NMEVENTS 7
                   1395: static void (*mouselist[])() =
                   1396: {
                   1397:        NOFUNC, /* inDesk */
                   1398:        doSysMenu, /* inMenuBar */
                   1399:        doSysClick, /* inSysWindow */
                   1400:        doWind, /* inContent */
                   1401:        NOFUNC, /* inDrag */
                   1402:        NOFUNC, /* inGrow */
                   1403:        doGoAway /* inGoAwa */
                   1404: };
                   1405: 
                   1406: 
                   1407: static void doMouse(event)
                   1408: EventRecord *event;
                   1409: {
                   1410:        WindowPtr theWindow;
                   1411:        int wpart;
                   1412:        void (*fptr)();
                   1413:        
                   1414:        if(Keyonly) {
                   1415:                if(event->what == mouseDown) SysBeep(2);
                   1416:                return;
                   1417:        }
                   1418:        wpart = FindWindow(event->where,&theWindow);    
                   1419:        if ((wpart < NMEVENTS) && (fptr = mouselist[wpart])) {
                   1420:                (*fptr)(event,theWindow);
                   1421:        }
                   1422: 
                   1423: }
                   1424: 
                   1425: static void doSysMenu(event,window)
                   1426: EventRecord *event;
                   1427: WindowPtr window;
                   1428: {
                   1429:        void ProcMenu();
                   1430:        
                   1431:        int Menu,Item;
                   1432:        long result = MenuSelect(event->where);
                   1433:        Menu = (result >> 16) & 0xffff;
                   1434:        Item = result & 0xffff;
                   1435:        if(Item == 0) return;   /* no choice made */
                   1436:        
                   1437:        if(Menu == SYS_ID) {                    /* apple menu */
                   1438:                Str255 Name;
                   1439:                GrafPtr Port;
                   1440:                
                   1441:                if(Item == 1) about_j();
                   1442:                else {          
                   1443:                        GetItem(SysMenu,Item,Name);
                   1444:                        GetPort(&Port);
                   1445:                        OpenDeskAcc(Name);
                   1446:                        SetPort(Port);
                   1447:                }
                   1448:        }
                   1449:        else ProcMenu(Menu,Item);
                   1450:        HiliteMenu(0);
                   1451:        EventCmd = 1;
                   1452: 
                   1453:        menus_on();
                   1454:        return;
                   1455:        
                   1456: }
                   1457:                
                   1458: static void doSysClick(event,window)
                   1459: EventRecord *event;
                   1460: WindowPtr window;
                   1461: {
                   1462:        SystemClick(event,window);
                   1463: }              
                   1464:                
                   1465:        
                   1466:        
                   1467: static void doUpdate(event)
                   1468: EventRecord *event;
                   1469: {
                   1470:        WindowPtr theWindow, oldPort;
                   1471:        
                   1472:        theWindow = (WindowPtr) event->message;
                   1473: 
                   1474:        if(firsttime == 0) {            
                   1475:                firsttime++;
                   1476:                BeginUpdate(theWindow);
                   1477:                EndUpdate(theWindow);
                   1478:                return;
                   1479:        }
                   1480:                
                   1481: /*     redisplay(); */
                   1482:        GetPort(&oldPort);
                   1483:        SetPort(theWindow);
                   1484:        BeginUpdate(theWindow);
                   1485:        if(theWindow == theScreen && Windchange == 0
                   1486:                && Keyonly == 0) {
                   1487:                Placur(0,0);
                   1488:                drawfluff();
                   1489:                cl_scr(1);
                   1490:                redisplay();
                   1491:        }
                   1492:        EndUpdate(theWindow);
                   1493: 
                   1494:        SetPort(oldPort);
                   1495: }
                   1496: 
                   1497: static void doActivate(event)
                   1498: EventRecord *event;
                   1499: {
                   1500:        WindowPtr theWindow;
                   1501:        ControlHandle control;
                   1502:        int hilite;
                   1503:        
                   1504:        theWindow = (WindowPtr) event->message;
                   1505:        SetPort(theWindow);
                   1506:        if(event->modifiers & activeFlag) {
                   1507:                hilite = 0;
                   1508:        }
                   1509:        else hilite = 255;
                   1510:        for(control = (ControlHandle) (((WindowPeek) theWindow)->controlList);
                   1511:                 (control != 0); control = (*control)->nextControl) {
                   1512:                        HiliteControl(control,hilite);
                   1513:        }
                   1514: }
                   1515:                
                   1516: /* Keyboard routines. The Option key was formerly used as a meta key.
                   1517:    However, to take advantage of the full (non-ASCII) character set,
                   1518:    this was removed. The corresponding code is ifdeffed O_META. */
                   1519:    
                   1520: /* (ORIGINALLY IN) tkey.c
                   1521:    keyboard routines for Macintosh. K Mitchum 12/86 */
                   1522: 
                   1523: extern jmp_buf auxjmp;
                   1524: 
                   1525: static nchars = 0;
                   1526: static char charbuf[MCHARS];
                   1527: /* the following kludges a meta key out of the option key by
                   1528: sending an escape sequence back to the dispatch routines. this is
                   1529: not elegant but it works, and doesn't alter escape sequences for
                   1530: those that prefer them. to remap the control or meta keys,
                   1531: see mackeys.h. */
                   1532: 
                   1533: static void dokeyDown(event)
                   1534: EventRecord *event;
                   1535: {
                   1536:        unsigned mods;
                   1537:        register c;
                   1538:        static int cptr = 0;
                   1539:        
                   1540:        if(MCHARS - nchars < 2) return;
                   1541:                
                   1542:        c  = (char)((event->message)&(charCodeMask));
                   1543: 
                   1544:        if(c == '`') c = '\033';        /* for those used to escapes */
                   1545:        
                   1546:        mods = event->modifiers;
                   1547: 
                   1548: #ifdef O_META  
                   1549:        if (mods & (optionKey | cmdKey)) {
                   1550: #else
                   1551:        if (mods & (cmdKey)) {
                   1552: #endif
                   1553:                if(mods & shiftKey) 
                   1554:                        c  = sh_keycodes[(((event->message)&(keyCodeMask))>>8)];
                   1555:                else    
                   1556:                        c  = nsh_keycodes[(((event->message)&(keyCodeMask))>>8)];
                   1557: #ifdef O_META                  
                   1558:                if(mods & optionKey) {          /* make escape sequence */
                   1559:                        if(mods & cmdKey) c &= 0x1f;
                   1560:                        charbuf[cptr++] = '\033';
                   1561:                        cptr &= NMASK;          /* zero if necessary */
                   1562:                        nchars++;
                   1563:                }
                   1564:                else 
                   1565: #endif
                   1566:                {       /* command key (control key) */
                   1567:                        if((c == '2') || (c == '\\')) c = 0;    /* so we have a null char */
                   1568:                        if(c != '`') c &= 0x1f;         /* make a control char */
                   1569:                }
                   1570:        }
                   1571:        charbuf[cptr++] = c;
                   1572:        cptr &= NMASK;
                   1573:        nchars++;
                   1574: }
                   1575: 
                   1576: static int rawgetc()
                   1577: {
                   1578:        static int cptr = 0;
                   1579:        register c;
                   1580: 
                   1581:        if(EventCmd) longjmp(auxjmp,0); 
                   1582:        while(nchars <= 0) {
                   1583:                nchars = 0;
                   1584:                if(EventCmd) longjmp(auxjmp,0);
                   1585:                CheckEvents();  /* ugh! WAIT for a character */
                   1586:        }
                   1587:        nchars--;
                   1588:        c = charbuf[cptr++];
                   1589:        cptr &= NMASK;          /* zero if necessary */
                   1590:        return(c);
                   1591: }
                   1592: 
                   1593: int rawchkc()
                   1594: {
                   1595:        if(EventCmd) longjmp(auxjmp,0);
                   1596:        if(nchars == 0) CheckEvents();  /* this should NOT be necessary! */     
                   1597:        return(nchars > 0);
                   1598: }
                   1599: 
                   1600: /* Routines for calling the standard file dialogs, when macify is ON. If the user
                   1601:    changes the directory using the file dialogs, Jove's notion of the current directory
                   1602:    is updated. */
                   1603: 
                   1604:                                
                   1605: /* (ORIGINALLY IN) tmacf.c. K. Mitchum 12/86.
                   1606:    Macify routines for jove. */
                   1607: 
                   1608: int CurrentVol;                        /* see tfile.c */
                   1609: 
                   1610: 
                   1611: #define TYPES  -1
                   1612: 
                   1613: static Point px = {100,100};
                   1614: static char pmess[] = "\pSave file as: ";
                   1615: 
                   1616: static pascal Boolean Ffilter(p)
                   1617: FileParam *p;
                   1618: {
                   1619:        if(p->ioFlFndrInfo.fdType == 'APPL') return TRUE;
                   1620:        PtoCstr((char *) p->ioNamePtr);
                   1621:        if(strcmp(p->ioNamePtr,d_tempfile) == 0) {
                   1622:                CtoPstr((char *) p->ioNamePtr);
                   1623:                return TRUE;
                   1624:        }
                   1625:        CtoPstr((char *) p->ioNamePtr);
                   1626:        return FALSE;
                   1627: }
                   1628: 
                   1629: static void check_dir()
                   1630: {
                   1631:        if(cur_vol != 0 - SFSaveDisk || cur_dir != CurDirStore) {
                   1632:                setdir(0 - SFSaveDisk, CurDirStore);
                   1633:                UpdModLine = YES;       /* make sure jove knows the change */
                   1634:                Modechange++;
                   1635:                setCWD(getwd());
                   1636:        }
                   1637: }
                   1638: 
                   1639: char *gfile(namebuf)   /* return a filename to get */
                   1640: char *namebuf;
                   1641: {
                   1642:        SFReply frec;
                   1643:        char ans[FILESIZE];
                   1644:        
                   1645:        SFSaveDisk = 0 - cur_vol;       /* in case a Desk Accessory changed them */
                   1646:        CurDirStore = cur_dir;
                   1647:        SFGetFile(px,0L,Ffilter,TYPES,0L,0L,&frec);
                   1648:        check_dir();    /* see if any change, set if so */
                   1649:        if(frec.good) {
                   1650:                EventRecord theEvent;
                   1651:                while(GetNextEvent(updateMask,&theEvent) == 0);
                   1652:                doUpdate(&theEvent);
                   1653:                PtoCstr((char *)frec.fName);
                   1654:                strcpy(ans,frec.fName);
                   1655:                CtoPstr((char *)frec.fName);
                   1656:                PathParse(ans,namebuf);
                   1657:                return(namebuf);
                   1658:        }
                   1659:        return(char *) 0;       
                   1660: }
                   1661: 
                   1662: char *pfile(namebuf)
                   1663: char *namebuf;
                   1664: {
                   1665:        SFReply frec;
                   1666:        char *t, *nm;
                   1667:        SFSaveDisk = 0 - cur_vol;       /* in case a Desk Accessory changed them */
                   1668:        CurDirStore = cur_dir;
                   1669:        strncpy(namebuf,filename(curbuf),63);
                   1670:        nm = cvt_fnm(namebuf);
                   1671:        CtoPstr(nm);
                   1672:        SFPutFile(px,pmess,nm,0L,&frec);
                   1673:        check_dir();    /* see if any change, set if so */
                   1674:        if(frec.good) {
                   1675:                EventRecord theEvent;
                   1676:                while(GetNextEvent(updateMask,&theEvent) == 0);
                   1677:                doUpdate(&theEvent);
                   1678:                t = (char *)frec.fName;
                   1679:                PtoCstr((char *)frec.fName);
                   1680:                while(*t == ':') t++;   /* convert to unix style */
                   1681:                nm = t;
                   1682:                while(*nm) {
                   1683:                        if(*nm == ':') *nm = '/';
                   1684:                        nm++;
                   1685:                }
                   1686:                PathParse(t,namebuf);
                   1687:                return(namebuf);
                   1688:        }
                   1689:        return(char *) 0;       
                   1690: }      
                   1691: 
                   1692: 
                   1693: /* getArgs() returns an argument list based on documents clicked on by the user. */
                   1694: 
                   1695: int getArgs(avp)
                   1696: char ***avp;
                   1697: {
                   1698:        int argc, nargs, type, old_vol;
                   1699:        long old_dir;
                   1700:        char **argv;
                   1701:        char *pathname; 
                   1702:        AppFile p;
                   1703:        WDPBRec d;
                   1704:        
                   1705:        old_vol = cur_vol;
                   1706:        old_dir = cur_dir;
                   1707:        
                   1708:        CountAppFiles(&type,&nargs);
                   1709:        if(nargs > 0) { /* files to open... */
                   1710:                argv = (char **) malloc((nargs + 2) * sizeof(char *)); 
                   1711:                for(argc = 1; argc <= nargs; argc++) {
                   1712:                        GetAppFiles(argc,&p);
                   1713:                        if(type == 0) {
                   1714:                                PtoCstr((char *)p.fName);
                   1715:                                d.ioCompletion = 0;
                   1716:                                d.ioNamePtr = 0;
                   1717:                                d.ioVRefNum = p.vRefNum;
                   1718:                                d.ioWDIndex = 0;
                   1719:                                PBGetWDInfo(&d,0);
                   1720:                                cur_vol = d.ioWDVRefNum;
                   1721:                                cur_dir = d.ioWDDirID;
                   1722:                                pathname = getwd();
                   1723:                                argv[argc] = malloc(strlen((char *)p.fName) + strlen(pathname) + 2);
                   1724:                                strcpy(argv[argc],pathname);
                   1725:                                strcat(argv[argc],"/");
                   1726:                                strcat(argv[argc],(char *)p.fName);
                   1727:                        }
                   1728:                        ClrAppFiles(argc);
                   1729:                }
                   1730:                if(type != 0) argc = 1;
                   1731:        }
                   1732:        else {
                   1733:                argv = (char **) malloc(2 * sizeof(char*));
                   1734:                argc = 1;
                   1735:        }
                   1736:        argv[0] = "jove";
                   1737: 
                   1738:        argv[argc] = 0;
                   1739:        *avp = argv;
                   1740:        cur_dir = old_dir;
                   1741:        cur_vol = old_vol;      
                   1742:        return(argc);
                   1743: }
                   1744: 
                   1745: /* Limited version of getenv() */
                   1746: 
                   1747: char *getenv(item)
                   1748: char *item;
                   1749: {
                   1750:        char *ret = 0, *str = 0;
                   1751:        
                   1752:        if(strcmp(item,"CWD") == 0) str = getwd();
                   1753:        if(strcmp(item,"HOME") == 0) str = gethome();
                   1754:        if(str) {
                   1755:                ret = malloc(strlen(str) + 1);
                   1756:                strcpy(ret,str);
                   1757:        }
                   1758:        return(ret);
                   1759: }
                   1760: 
                   1761: char *mktemp(name)
                   1762: char *name;
                   1763: {
                   1764:        return name;
                   1765: }
                   1766: 
                   1767: 
                   1768: /* Menu routines. The menus items are set up in a similar manner as keys, and
                   1769:    are bound prior to runtime. See menumaps.txt, which must be run through setmaps.
                   1770:    Unlike keys, menu items may be bound to variables, and to buffers. Buffer binding
                   1771:    is only done at runtime. */ 
                   1772:                
                   1773: static void InitLocalMenus()
                   1774: {
                   1775:        void InitMenu(),
                   1776:                make_edits();
                   1777:        
                   1778:        int i;
                   1779:        for(i = 0; i < NMENUS; i++) {
                   1780:                InitMenu(&Menus[i]);
                   1781:                if(i == 0) make_edits(Menus[i].menu_id + 1);
                   1782:        }
                   1783: }
                   1784: 
                   1785: static void InitMenu(M)
                   1786: struct menu *M;
                   1787: {
                   1788:        int i;
                   1789:        data_obj *d;
                   1790:        char *name;
                   1791: 
                   1792:        if(M->menu_id == 0) return;
                   1793:        M->Mn = NewMenu(M->menu_id,CtoPstr(M->Name));
                   1794:        PtoCstr(M->Name);
                   1795: 
                   1796:        for(i = 0; i < NMENUITEMS; i++) {
                   1797:                d = (M->m[i]);
                   1798:                if(d == 0) break;       /* last item... */ 
                   1799:                switch (d->Type & TYPEMASK) {
                   1800:                        case (STRING) : 
                   1801:                                AppendMenu(M->Mn,CtoPstr(d->Name));
                   1802:                                PtoCstr(d->Name);
                   1803:                                break;
                   1804:                        case (VARIABLE) :
                   1805:                                SetItemMark(M->Mn,i + 1, 0x12);
                   1806:                        case (FUNCTION) :
                   1807:                                CtoPstr(name = ((data_obj *) d)->Name);
                   1808:                                AppendMenu(M->Mn,name);
                   1809:                                PtoCstr(name);
                   1810:                }
                   1811:        }
                   1812:        InsertMenu(M->Mn,0);
                   1813: }
                   1814: 
                   1815: static void ProcMenu(menuno,itemno)
                   1816: int menuno,itemno;
                   1817: {
                   1818:        void MacSetVar();
                   1819:        
                   1820:        int i;
                   1821:        data_obj *d;
                   1822: 
                   1823:        for(i = 0; i < NMENUS && Menus[i].menu_id != menuno; i++);
                   1824:        if(i < NMENUS) {        /* found the menu */
                   1825:                itemno--;
                   1826:                d = Menus[i].m[itemno];
                   1827:                switch(d->Type & TYPEMASK) {
                   1828:                        case FUNCTION :
                   1829:                                ExecCmd((data_obj *) d);
                   1830:                                break;
                   1831:                        case BUFFER :
                   1832:                                        SetABuf(curbuf);
                   1833:                                        tiewind(curwind,(Buffer *) d);
                   1834:                                        SetBuf((Buffer *) d);
                   1835:                                break;
                   1836:                        case VARIABLE :
                   1837:                                        MacSetVar((struct variable *) d,i,itemno);
                   1838:                                break;
                   1839:                        default :
                   1840:                                break;
                   1841:                }
                   1842:                
                   1843:        }
                   1844: }
                   1845: 
                   1846:                
                   1847: 
                   1848:                        
                   1849:        
                   1850: 
                   1851: static void make_edits(menu)   /* add dummy edit menu */
                   1852: int menu;
                   1853: {
                   1854:        MenuHandle M;
                   1855:        int item;
                   1856:        char *fname;
                   1857:        
                   1858:        M = NewMenu((menu),"\pEdit");
                   1859:        AppendMenu(M,"\pUndo/Z;(-;Cut/X;Copy/C;Paste/V;Clear;Select All;(-;Show Clipboard");
                   1860:        InsertMenu(M,0);
                   1861:        DisableItem(M,0);
                   1862: }
                   1863: 
                   1864: void menus_off()
                   1865: {
                   1866:        int i;
                   1867:        
                   1868:        if(Keyonly || EventCmd) return;
                   1869:        DisableItem(SysMenu,0);
                   1870:        for(i = 0; i < NMENUS; i++) 
                   1871:                if(Menus[i].Mn) DisableItem(Menus[i].Mn,0);
                   1872:        Keyonly = 1;
                   1873:        DrawMenuBar();
                   1874: }
                   1875: 
                   1876: void menus_on()
                   1877: {
                   1878:        int i;
                   1879:        
                   1880:        if(Keyonly == 0) return;
                   1881:        EnableItem(SysMenu,0);
                   1882:        for(i = 0; i < NMENUS; i++)
                   1883:                if(Menus[i].Mn) EnableItem(Menus[i].Mn,0);
                   1884:        Keyonly = 0;
                   1885:        DrawMenuBar();
                   1886: }
                   1887: 
                   1888: static char *BufMPrint(b,i)
                   1889: Buffer *b;
                   1890: {
                   1891:        char *p;
                   1892:        char *nm = filename(b);
                   1893:        char t[35];
                   1894:        
                   1895:        if(strlen(nm) > 30) { 
                   1896:                strcpy(t,"...");
                   1897:                strcat(t,nm + strlen(nm) - 30);
                   1898:        }
                   1899:        else strcpy(t,nm);
                   1900:        nm = t;
                   1901:        while(*nm) {
                   1902:                switch(*nm) {   /* ugh... these are metacharacter for Menus */
                   1903:                        case '/' : *nm = ':'; break;
                   1904:                        case '^' :
                   1905:                        case '!' :
                   1906:                        case '<' :
                   1907:                        case '(' :
                   1908:                        case ';' : *nm = '.'; break;    /* that will confuse everybody */
                   1909:                }
                   1910:                nm++;
                   1911:        }
                   1912:        p = sprint("%-2d %-11s \"%-s\"",i,b->b_name,t);
                   1913:        return(p);
                   1914: }
                   1915: 
                   1916: static void SetBufMenu()
                   1917: {
                   1918:        register Buffer *b;
                   1919:        data_obj *d;
                   1920:        int i,j,stop;
                   1921:        struct menu *M;
                   1922: 
                   1923:        Bufchange = 0;
                   1924:        for(i = 0; i < NMENUS && strcmp(Menus[i].Name,"Buffer"); i++);
                   1925:        if(i < NMENUS) {
                   1926:                M = &Menus[i];
                   1927:                for(j = 0; j < NMENUITEMS && (d = Menus[i].m[j]) && (d->Type & TYPEMASK) != BUFFER; j++);
                   1928:                if(j < NMENUITEMS) {
                   1929:                        for(i = j, b = world; i < NMENUITEMS && b != 0; i++, b = b->b_next) {
                   1930:                        
                   1931:                                if(M->m[i] == 0) 
                   1932:                                        AppendMenu(M->Mn,CtoPstr(BufMPrint(b,i-j+1)));  /* add the item */
                   1933:                                else
                   1934:                                        SetItem(M->Mn,i + 1,CtoPstr(BufMPrint(b,i-j+1)));       /* or change it */
                   1935:                                M->m[i] = (data_obj *) b;
                   1936:                        }
                   1937:                        stop = i;
                   1938:                          /* out of buffers? */
                   1939:                        for(;i < NMENUITEMS && M->m[i];i++) {
                   1940:                                DelMenuItem(M->Mn,stop + 1);    /* take off last item */
                   1941:                                M->m[i] = 0;
                   1942:                        }
                   1943:                }
                   1944:        }
                   1945:        return;
                   1946: }
                   1947: 
                   1948: static void MacSetVar(vp,mnu,itm)      /* Set a variable from the menu */
                   1949: struct variable *vp;   /* Liberally taken from SetVar() in extend.c */
                   1950: int mnu,itm;
                   1951: {
                   1952:        void MarkVar();
                   1953:        
                   1954:        char *prompt;
                   1955: 
                   1956:        prompt = sprint("Set %s: ", vp->Name);
                   1957:        switch (vp->v_flags & V_TYPEMASK) {
                   1958:        case V_BASE10:
                   1959:        case V_BASE8:
                   1960:            {
                   1961:                int     value;
                   1962: 
                   1963:                value = ask_int(prompt, ((vp->v_flags & V_TYPEMASK) == V_BASE10)
                   1964:                                          ? 10 : 8);
                   1965:                *(vp->v_value) = value;
                   1966:                break;
                   1967:            }
                   1968:        case V_BOOL:    /* toggle the value */
                   1969:                *(vp->v_value) = (*vp->v_value == ON ? OFF : ON);
                   1970:                MarkVar(vp,mnu,itm);
                   1971:                break;
                   1972:        case V_FILENAME:
                   1973:        case V_STRING:
                   1974:            {
                   1975:                char    *str;
                   1976: 
                   1977:                /* Do_ask() so you can set string to "" if you so desire. */
                   1978:                str = do_ask("\r\n", (int (*)()) 0, (char *) vp->v_value, prompt);
                   1979:                if (str == 0)
                   1980:                        str = NullStr;
                   1981:                strcpy((char *) vp->v_value, str);
                   1982:                /* ... and hope there is enough room. */
                   1983:                break;
                   1984:            }
                   1985:        case V_CHAR:
                   1986:                f_mess(prompt);
                   1987:                *(vp->v_value) = addgetc();
                   1988:                break;          
                   1989:        }
                   1990: 
                   1991:        if (vp->v_flags & V_MODELINE)
                   1992:                UpdModLine = YES;
                   1993:        if (vp->v_flags & V_CLRSCREEN) ClAndRedraw();
                   1994:        if (vp->v_flags & V_TTY_RESET) tty_reset(); /* probably none on a Mac */
                   1995:        return;
                   1996: }
                   1997: 
                   1998: static void MarkModes()
                   1999: {
                   2000:        int mnu,itm,checked;
                   2001:        data_obj *d;
                   2002:        
                   2003:        Modechange = 0;
                   2004:        for(mnu = 0; mnu < NMENUS; mnu++) 
                   2005:                for(itm = 0; itm < NMENUITEMS; itm++) {
                   2006:                        if((d = Menus[mnu].m[itm]) == 0) break;
                   2007:                        if((d->Type & (MAJOR_MODE | MINOR_MODE)) ||
                   2008:                                 ((d->Type & TYPEMASK) == BUFFER)){
                   2009:                                if(d->Type & (MAJOR_MODE))
                   2010:                                        checked = (curbuf->b_major == (d->Type >> 8)) ? 1 : 0;
                   2011:                                else if(d->Type & (MINOR_MODE))
                   2012:                                        checked = (curbuf->b_minor & (d->Type >> 8)) ? 1 : 0;
                   2013:                                else 
                   2014:                                        checked = (d == (data_obj *) curbuf) ? 1 : 0;
                   2015:                                CheckItem(Menus[mnu].Mn, itm + 1, checked);
                   2016:                        }
                   2017:                }
                   2018: }
                   2019:        
                   2020: void MarkVar(vp,mnu,itm)       /* mark a boolean menu item */
                   2021: struct variable *vp;
                   2022: int mnu,itm;
                   2023: {      
                   2024:        int checked;
                   2025:        if(mnu == -1) {         /* we don't know the item... slow */
                   2026:                int found;
                   2027:                for(mnu = 0, found = 0; (mnu < NMENUS) && !found; mnu++) {
                   2028:                        for(itm = 0; (itm < NMENUITEMS); itm++)
                   2029:                                if((struct variable *) (Menus[mnu].m[itm]) == vp) {
                   2030:                                        found++;
                   2031:                                        break;
                   2032:                                }
                   2033:                        if(found) break;
                   2034:                }
                   2035:                if(!found) return;
                   2036:        }
                   2037:        checked = (*(vp->v_value) == ON);
                   2038:        CheckItem(Menus[mnu].Mn, itm + 1, checked);
                   2039: }
                   2040: 
                   2041: static void MarkAllVar()       /* slow, but only do it once */
                   2042: {
                   2043:        int mnu,itm;
                   2044:        data_obj *d;
                   2045:        for(mnu = 0; mnu < NMENUS; mnu++) 
                   2046:                for(itm = 0; itm < NMENUITEMS; itm++) {
                   2047:                        if((d = Menus[mnu].m[itm]) == 0) break;
                   2048:                        if((d->Type & TYPEMASK) == VARIABLE)
                   2049:                                MarkVar((struct variable *)Menus[mnu].m[itm],mnu,itm);
                   2050:                }
                   2051: }
                   2052: 
                   2053: 
                   2054: /* Screen routines and driver. The Macinitosh Text Edit routines are not utilized,
                   2055:    as they are slow and cumbersome for a terminal emulator. Instead, direct QuickDraw
                   2056:    calls are used. The fastest output is obtained writing a line at a time, rather
                   2057:    than on a character basis, so the major output routine is writechr(), which takes
                   2058:    a pascal-style string as an argument. See bufputc() in screen.c. */
                   2059: 
                   2060: void Placur(line,col)
                   2061: int line, col;
                   2062: {
                   2063:        CapCol = col;
                   2064:        CapLine = line;
                   2065:        putcurs(line,col,ON);
                   2066: }
                   2067: 
                   2068: void NPlacur(line,col)
                   2069: int line, col;
                   2070: {
                   2071:        CapCol = col;
                   2072:        CapLine = line;
                   2073:        putcurs(line,col,OFF);
                   2074: }
                   2075: 
                   2076: void i_lines(top, bottom, num)
                   2077: int top, bottom, num;
                   2078: {
                   2079:        Placur(bottom - num + 1, 0);
                   2080:        dellines(num,bottom);
                   2081:        Placur(top, 0);
                   2082:        inslines(num,bottom);
                   2083: }
                   2084: 
                   2085: void d_lines(top, bottom, num)
                   2086: int top, bottom, num;
                   2087: {
                   2088:        Placur(top, 0);
                   2089:        dellines(num,bottom);
                   2090:        Placur(bottom + 1 - num, 0);
                   2091:        inslines(num,bottom);
                   2092: }
                   2093: 
                   2094: 
                   2095: void clr_page()
                   2096: {
                   2097:        void wipescreen();
                   2098:        
                   2099:        wipescreen();
                   2100: }
                   2101: 
                   2102: void clr_eoln()
                   2103: {
                   2104:        void wipeline();
                   2105:        
                   2106:        wipeline();
                   2107: }
                   2108: 
                   2109: void SO_on()
                   2110: {
                   2111:        void HLmode();
                   2112:        
                   2113:        HLmode(1);
                   2114: }
                   2115: 
                   2116: void SO_off()
                   2117: {
                   2118:        void HLmode();
                   2119:        
                   2120:        HLmode(0);
                   2121: }
                   2122: 
                   2123:        
                   2124: /* (ORIGINALLY IN) tn.c   */
                   2125: /* window driver for MacIntosh using windows. */
                   2126: /* K. Mitchum 9/86 */
                   2127: 
                   2128: 
                   2129: 
                   2130: /*#define VARFONT*/
                   2131: #ifdef VARFONT
                   2132: static height,width,theight,twidth,descent;
                   2133: #else
                   2134: #define height HEIGHT
                   2135: #define width WIDTH
                   2136: #define theight THEIGHT
                   2137: #define twidth TWIDTH 
                   2138: #define descent DESCENT
                   2139: #endif
                   2140: 
                   2141: static trow,tcol, insert, tattr, cursor;
                   2142: static Rect cursor_rect;
                   2143: 
                   2144: 
                   2145: static Rect  vRect;
                   2146: static WindowRecord myWindowRec;
                   2147: static Rect myBoundsRect;
                   2148: 
                   2149: 
                   2150: #define active() SetPort(theScreen)
                   2151: /*#define active()*/
                   2152: #define maxadjust(r) OffsetRect(r,0,2);
                   2153: static void tn_init()
                   2154: {
                   2155:        void INSmode(),
                   2156:                init_slate();
                   2157:        
                   2158:        HLmode(0);
                   2159:        INSmode(0);
                   2160:        init_slate();
                   2161:        ShowPen();
                   2162: }
                   2163: 
                   2164: static void wipescreen()       /* clear and home function */
                   2165: {
                   2166:        Rect r;
                   2167:        
                   2168:        active();
                   2169:        SetRect(&r, 0,0,WINDWIDTH,WINDHEIGHT);
                   2170:        EraseRect(&r);
                   2171:        cursor = OFF;
                   2172:        putcurs(0,0);
                   2173:        drawfluff();
                   2174: }
                   2175: 
                   2176: static void putcurs(row,col,vis)
                   2177: unsigned row, col, vis;
                   2178: {
                   2179: /*     if(row > MAXROW || col > MAXCOL) return(ERROR);*/
                   2180: /*     if(row != trow || col != tcol) */{
                   2181:                active();
                   2182:                curset(OFF);
                   2183:                if(row == MAXROW)
                   2184:                        MoveTo(col * width, (row  +1) * height + 2 -descent );
                   2185:                else
                   2186:                        MoveTo(col * width, (row  +1) * height - descent);
                   2187:                trow = row;
                   2188:                tcol = col;
                   2189:                curset(vis);
                   2190:        }
                   2191: }
                   2192: 
                   2193: static void curset(desired)
                   2194: {
                   2195:        if(cursor != desired) {
                   2196:                SetRect(&cursor_rect, tcol * width, (trow) * height , (tcol + 1) * width - 1, (trow +1) * height -1);
                   2197:                if(trow == MAXROW) maxadjust(&cursor_rect);
                   2198:                InvertRect(&cursor_rect);
                   2199:                cursor = desired;
                   2200:        }
                   2201: }
                   2202: 
                   2203: 
                   2204: void putp(p)                   /* put one character, advance cursor */
                   2205: int p;
                   2206: {
                   2207:        static Rect r;
                   2208:        static RgnHandle updateRgn;
                   2209: 
                   2210:        active();
                   2211:        curset(OFF);
                   2212:        if(insert) {
                   2213:                updateRgn = NewRgn();
                   2214:                SetRect(&r, tcol * width, trow * height, WINDWIDTH, (trow +1) * height -1);
                   2215:                if(trow == MAXROW) maxadjust(&r);
                   2216:                ScrollRect(&r, width, 0, updateRgn);
                   2217:                DisposeRgn(updateRgn);
                   2218:        }
                   2219:        if(p == '0') p = 0xAF;  /* slashed zero */
                   2220:        DrawChar(p);
                   2221:        if(tcol >= MAXCOL) putcurs(trow,MAXCOL);
                   2222:        else putcurs(trow,tcol +1);
                   2223: }
                   2224: 
                   2225: static void wipeline()
                   2226: {
                   2227:                static Rect r;
                   2228:                
                   2229:                active();
                   2230:                cursor = OFF;
                   2231:                SetRect(&r, tcol * width, trow * height, WINDWIDTH, (trow +1) * height);
                   2232:                if(trow == MAXROW) maxadjust(&r);
                   2233:                EraseRect(&r);
                   2234:                curset(ON);
                   2235: }
                   2236: 
                   2237: static void delchars()
                   2238: {
                   2239:                static Rect r;
                   2240:                static RgnHandle updateRgn;
                   2241:                
                   2242:                active();
                   2243:                curset(OFF);
                   2244:                updateRgn = NewRgn();
                   2245:                SetRect(&r, tcol * width, trow * height, twidth - width, (trow +1) * height);
                   2246:                if(trow == MAXROW) maxadjust(&r);
                   2247:                ScrollRect(&r, 0 - width, 0, updateRgn);
                   2248:                DisposeRgn(updateRgn);
                   2249:                curset(ON);
                   2250: }
                   2251: 
                   2252: static void dellines(n,bot)
                   2253: int n,bot;
                   2254: {
                   2255:        Rect r;
                   2256:        RgnHandle updateRgn;
                   2257:        
                   2258:        updateRgn = NewRgn();
                   2259:        active();
                   2260:        curset(OFF);
                   2261:        SetRect(&r, 0, ((trow) * height), WINDWIDTH, ((bot + 1) * height));
                   2262:        ScrollRect(&r, 0, 0 - (n * height), updateRgn);
                   2263:        DisposeRgn(updateRgn);
                   2264:        putcurs(trow,0);
                   2265:        
                   2266: }
                   2267: 
                   2268: static void inslines(n,bot)
                   2269: int n,bot;
                   2270: {
                   2271:        Rect r;
                   2272:        RgnHandle updateRgn;
                   2273:        
                   2274:        updateRgn = NewRgn();
                   2275:        active();
                   2276:        curset(OFF);    
                   2277:        SetRect(&r, 0, trow * height, WINDWIDTH, (bot +1) * height);
                   2278:        ScrollRect(&r, 0, (n * height), updateRgn);
                   2279:        DisposeRgn(updateRgn);
                   2280:        putcurs(trow,0);
                   2281: }
                   2282:         
                   2283: static void INSmode(new)
                   2284: int new;
                   2285: {
                   2286:        insert = new;
                   2287: }
                   2288: 
                   2289: static void HLmode(new)
                   2290: int new;
                   2291: {
                   2292:        if(new) tattr = 1;
                   2293:        else tattr = 0;
                   2294: }
                   2295: 
                   2296: void writechr(start)
                   2297: char *start;   /* actually, a Str255 type string */
                   2298: {
                   2299:        static Rect r;
                   2300:        static RgnHandle updateRgn;
                   2301:        register len;
                   2302:        register char save;
                   2303:        
                   2304:        len = (int) start[0];           /* adjusted 6/86 K. M. in td.c*/
                   2305: 
                   2306:        active();
                   2307:        curset(OFF);
                   2308:        if(insert) {
                   2309:                updateRgn = NewRgn();
                   2310:                SetRect(&r, tcol * width, trow * height, twidth - width * len, (trow +1) * height -1);
                   2311:                if(trow == MAXROW) maxadjust(&r);
                   2312:                ScrollRect(&r, width * len, 0, updateRgn);
                   2313:                DisposeRgn(updateRgn);
                   2314:        }
                   2315:        DrawString(start);
                   2316:        
                   2317:        if(tcol >= MAXCOL) putcurs(trow,MAXCOL);
                   2318:        else putcurs(trow,tcol +len);
                   2319: }
                   2320: 
                   2321: 
                   2322: 
                   2323: static void reset(){}
                   2324: static void blanks(){}
                   2325: static void cleanup() {}
                   2326: 
                   2327: 
                   2328: static void init_slate()
                   2329: {
                   2330:        FontInfo f;
                   2331:        
                   2332:        extern char *version;
                   2333:        char *Name = "MacJove ";
                   2334:        char *Title;
                   2335:        
                   2336:        InitGraf(&thePort);
                   2337:        InitWindows();
                   2338:        InitCursor();
                   2339:        InitFonts ();
                   2340:        InitMenus ();
                   2341:        InitDialogs ((ProcPtr) 0);              /* no restart proc */
                   2342:        
                   2343:        tn_left = screenBits.bounds.left + 3;
                   2344:        tn_top =  screenBits.bounds.top + 40;
                   2345: 
                   2346:        tn_rows = (screenBits.bounds.bottom - 3 - tn_top) / HEIGHT;
                   2347:        tn_cols = (screenBits.bounds.right - 3 - tn_left - SCROLLWIDTH) / WIDTH;
                   2348:        tn_right = tn_left + tn_cols * WIDTH + SCROLLWIDTH;
                   2349:        tn_bottom = tn_top + tn_rows * HEIGHT + 2;
                   2350:        tn_cols++;      /* kludge to get jove to use last col */ 
                   2351: 
                   2352:        LI = tn_rows;
                   2353:        CO = tn_cols;
                   2354:        MAXROW = tn_rows -1;
                   2355:        MAXCOL = tn_cols -1;
                   2356:        
                   2357:        SetRect(&myBoundsRect,tn_left,tn_top,tn_right,tn_bottom);
                   2358: 
                   2359:        Title = sprint("%s%s",Name,version);
                   2360:        theScreen = NewWindow(&myWindowRec, &myBoundsRect,CtoPstr(Title),
                   2361:                1,noGrowDocProc,(WindowPtr) -1, 1, (long) 0);
                   2362: 
                   2363: 
                   2364: 
                   2365:        SetPort(theScreen);
                   2366: 
                   2367: /*     SetOrigin(-3,-1);*/
                   2368:        (theScreen)->txFont = FONT;
                   2369:        (theScreen)->txSize = TEXTSIZE;
                   2370:        
                   2371: #ifdef VARFONT 
                   2372:        GetFontInfo(&f);
                   2373:                height = f.ascent+f.descent+f.leading;
                   2374:                width = f.widMax;
                   2375:                twidth = width * tn_cols;
                   2376:                theight = height * tn_rows;
                   2377:                descent = f.descent;
                   2378: #endif
                   2379:        
                   2380: /*     (theScreen)->lineHeight = height;
                   2381:        (theScreen)->fontAscent = ASCENT;*/
                   2382:        theScreen->txMode = patCopy;
                   2383:        theScreen->pnMode = patCopy;
                   2384:        PenNormal();
                   2385:        cursor = OFF;
                   2386: }
                   2387: #endif /* MAC */
                   2388: 
                   2389: 
                   2390: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.