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