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 */

Defined functions

AdjustScrollBar defined in line 1061; used 2 times
BufMPrint defined in line 1888; used 2 times
CheckEvents defined in line 1330; used 2 times
DScroll defined in line 1125; used 1 times
Ffilter defined in line 1616; used 1 times
HLmode defined in line 2289; used 5 times
INSmode defined in line 2283; used 2 times
InitBinds defined in line 63; used 2 times
InitCM defined in line 128; used 3 times
InitEvents defined in line 98; used 2 times
InitLocalMenus defined in line 1773; used 2 times
InitMenu defined in line 1785; used 2 times
InitSysMenu defined in line 1381; used 2 times
MacInit defined in line 111; used 2 times
MacSetVar defined in line 1948; used 2 times
MakeScrollBar defined in line 1044; used 2 times
MarkAllVar defined in line 2041; never used
MarkModes defined in line 1998; used 2 times
MarkVar defined in line 2020; used 4 times
NPage defined in line 1141; used 1 times
NPlacur defined in line 2068; used 2 times
PPage defined in line 1148; used 1 times
ProcFilter defined in line 953; used 1 times
ProcMenu defined in line 1815; used 2 times
RemoveScrollBar defined in line 1116; used 2 times
ResetTerm defined in line 132; used 2 times
SO_off defined in line 2116; used 3 times
SO_on defined in line 2109; used 3 times
SetBufMenu defined in line 1916; used 2 times
SetScrollBar defined in line 1081; used 1 times
UScroll defined in line 1133; used 1 times
UnsetTerm defined in line 134; used 2 times
about_j defined in line 806; used 1 times
abs defined in line 541; used 5 times
blanks defined in line 2324; never used
chdir defined in line 625; used 6 times
check_dir defined in line 1629; used 2 times
cleanup defined in line 2325; never used
clr_eoln defined in line 2102; used 1 times
clr_page defined in line 2095; used 1 times
con_read defined in line 518; used 1 times
con_write defined in line 510; used 1 times
ctol defined in line 1168; used 1 times
curset defined in line 2193; used 10 times
cvt_err defined in line 191; used 15 times
cvt_fnm defined in line 228; used 5 times
d_lines defined in line 2085; used 2 times
delchars defined in line 2237; never used
dellines defined in line 2252; used 3 times
doActivate defined in line 1497; used 2 times
doGoAway defined in line 1231; used 2 times
doMouse defined in line 1407; used 3 times
doSysClick defined in line 1458; used 2 times
doSysMenu defined in line 1425; used 2 times
doUpdate defined in line 1467; used 4 times
doWind defined in line 1180; used 2 times
do_creat defined in line 322; used 2 times
do_display defined in line 869; used 1 times
do_events defined in line 979; used 2 times
do_list defined in line 896; used 2 times
docontrols defined in line 1015; used 2 times
dodivider defined in line 1090; used 2 times
dokeyDown defined in line 1533; used 3 times
dorecover defined in line 149; never used
drawfluff defined in line 1105; used 4 times
dummy defined in line 141; used 1 times
findtext defined in line 1262; used 1 times
fsetup defined in line 172; used 8 times
getArgs defined in line 1695; used 2 times
getdir defined in line 594; used 1 times
gethome defined in line 765; used 5 times
getwd defined in line 738; used 5 times
gfile defined in line 1639; used 3 times
i_lines defined in line 2076; used 2 times
init_slate defined in line 2328; used 2 times
inslines defined in line 2268; used 3 times
isetup defined in line 181; used 6 times
ltoc defined in line 1157; used 1 times
make_edits defined in line 1851; used 2 times
makedisplay defined in line 830; used 2 times
makelist defined in line 886; used 2 times
menus_on defined in line 1876; used 3 times
pfile defined in line 1662; used 2 times
printbind defined in line 917; used 2 times
ptoxy defined in line 1283; used 1 times
putcurs defined in line 2176; used 10 times
putp defined in line 2204; used 2 times
rawchkc defined in line 1593; used 3 times
rawgetc defined in line 1576; used 1 times
reset defined in line 2323; never used
rtowind defined in line 1238; used 1 times
scandir defined in line 663; used 3 times
setdir defined in line 607; used 2 times
tn_init defined in line 2153; used 2 times
windtol defined in line 1251; used 1 times
wipeline defined in line 2225; used 2 times
wipescreen defined in line 2164; used 2 times
writechr defined in line 2296; used 1 times

Defined variables

Bufchange defined in line 54; used 2 times
CmdDb defined in line 38; used 3 times
CurrentVol defined in line 1608; never used
EventCmd defined in line 51; used 6 times
Joverc defined in line 41; never used
Keyonly defined in line 52; used 7 times
ListHandle defined in line 886; used 2 times
Macmode defined in line 53; used 1 times
Modechange defined in line 55; used 3 times
SysMenu defined in line 1308; used 7 times
Windchange defined in line 56; used 2 times
WindowPtr defined in line 830; used 26 times
charbuf defined in line 1526; used 3 times
cur_dir defined in line 164; used 13 times
cur_vol defined in line 163; used 17 times
cur_vref defined in line 165; never used
d_tempfile defined in line 40; used 1 times
descent defined in line 2132; never used
errno defined in line 50; used 78 times
firsttime defined in line 1306; used 2 times
ft defined in line 170; used 18 times
height defined in line 2132; never used
npos defined in line 1155; used 5 times
p_tempfile defined in line 39; never used
pmess defined in line 1614; used 1 times
sig defined in line 144; used 1 times
theight defined in line 2132; never used
twidth defined in line 2132; never used
width defined in line 2132; never used
window defined in line 94; used 33 times

Defined struct's

ftab defined in line 167; never used

Defined macros

ApplLimit defined in line 1345; used 2 times
DHEIGHT defined in line 793; used 1 times
DLOGNAME defined in line 786; used 1 times
DONE_ITEM defined in line 788; never used
DWIDTH defined in line 792; used 1 times
EVENTLIST defined in line 1008; never used
HeapEnd defined in line 1344; used 2 times
INITC defined in line 1007; used 1 times
LIST_ITEM defined in line 789; used 1 times
MAXC defined in line 1006; used 4 times
MINC defined in line 1005; used 2 times
NEVENTS defined in line 1305; used 1 times
NFILES defined in line 157; used 5 times
NMEVENTS defined in line 1394; used 1 times
NOFUNC defined in line 1304; used 13 times
SYS_ID defined in line 1303; used 2 times
TYPES defined in line 1611; used 1 times
Ticks defined in line 1332; used 2 times
_mac defined in line 13; never used
active defined in line 2150; used 8 times
descent defined in line 2138; used 5 times
height defined in line 2134; used 20 times
maxadjust defined in line 2152; used 5 times
theight defined in line 2136; used 1 times
track defined in line 1184; used 1 times
twidth defined in line 2137; used 3 times
width defined in line 2135; used 15 times
Last modified: 1988-03-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 11847
Valid CSS Valid XHTML 1.0 Strict