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 ;
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: 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: 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: 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: 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: 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 :
1829: ExecCmd((data_obj *) d);
1830: break;
1831: case :
1832: SetABuf(curbuf);
1833: tiewind(curwind,(Buffer *) d);
1834: SetBuf((Buffer *) d);
1835: break;
1836: case :
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: 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: 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: 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 */