📄 mac.c
字号:
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * * is provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ***************************************************************************//* (C) 1986, 1987, 1988 Ken Mitchum. This code is intended only for use with Jove. */#include "tune.h"#ifdef MAC#include <MacTypes.h>#include "jove.h"#include <QuickDraw.h>#include <WindowMgr.h>#include <FontMgr.h>#include <ListMgr.h>#include <EventMgr.h>#include <ControlMgr.h>#include <DialogMgr.h>#include <ResourceMgr.h>#include <ToolboxUtil.h>#include <HFS.h>#include <StdFilePkg.h>#include <MenuMgr.h>#include <pascal.h>#include <errno.h>#include <SegmentLdr.h>#include "mac.h"#include "termcap.h"extern struct menu Menus[NMENUS];private EventRecord the_Event;private void SetBounds proto((void));private void Set_std proto((void));private void Reset_std proto((void));private bool is_dir proto((char *));private bool findtext proto((void));/* keycodes (from Inside MacIntosh I-251). because of changes withthe MacPlus, there are some duplicate codes between cursor keys andkeypad keys. these can be deciphered by the corresponding charactercodes, which are different. this table simply translates a keycodeinto a character code that is appropriate. */#define NOKEY (-1)#define RET 0x0D#define TAB 0x09#define BACKSP 0x08#define ENTERL NOKEY /* left enter key absent on MacPlus */#define COMMAND NOKEY /* will be no translation anyway for these */#define SHIFT NOKEY#define CAPSLOCK NOKEY#define OPTION NOKEY#define PADDOT '.' /* PAD period */#define PAD0 '0'#define PAD1 '1'#define PAD2 '2'#define PAD3 '3'#define PAD4 '4'#define PAD5 '5'#define PAD6 '6'#define PAD7 '7'#define PAD8 '8'#define PAD9 '9'#define LEFTCURS 'B' /* jove only, make like commands */#define RIGHTCURS 'F'#define UPCURS 'P'#define DOWNCURS 'N'#define PADENTER RET#define PADMINUS '-'#define CLEAR 0private char nsh_keycodes[] = { 'a','s','d','f','h', /* 0 - 4 */ 'g','z','x','c','v', /* 5 - 9 */ NOKEY,'b','q','w','e', /* 10 - 14 */ 'r','y','t','1','2', /* 15 - 19 */ '3','4','6','5','=', /* 20 - 24 */ '9','7','-','8','0', /* 25 - 29 */ ']','O','u','[','i', /* 30 - 34 */ 'p',RET,'l','j','\'', /* 35 - 39 */ 'k',';','\\',',','/', /* 40 - 44 */ 'n','m','.',TAB,NOKEY, /* 45 - 49 */ '`',BACKSP,ENTERL,NOKEY,NOKEY, /* 50 - 54 */ COMMAND,SHIFT,CAPSLOCK,OPTION, NOKEY, /* 55 - 59 */ NOKEY,NOKEY,NOKEY,NOKEY,NOKEY, /* 60 - 64 */ PADDOT,RIGHTCURS,NOKEY,NOKEY,NOKEY, /* 65 - 69 */ LEFTCURS,CLEAR,DOWNCURS,NOKEY,NOKEY, /* 70 - 74 */ NOKEY,PADENTER,UPCURS,PADMINUS,NOKEY, /* 75 - 79 */ NOKEY,NOKEY,PAD0,PAD1,PAD2, /* 80 - 84 */ PAD3,PAD4,PAD5,PAD6,PAD7, /* 85 - 89 */ NOKEY,PAD8,PAD9};private char sh_keycodes[] = { 'A','S','D','F','H', /* 0 - 4 */ 'G','Z','X','C','V', /* 5 - 9 */ NOKEY,'B','Q','W','E', /* 10 - 14 */ 'R','Y','T','!','@', /* 15 - 19 */ '#','$','^','%','+', /* 20 - 24 */ '(','&','_','*',')', /* 25 - 29 */ '}','O','U','{','I', /* 30 - 34 */ 'P',RET,'L','J','\'', /* 35 - 39 */ 'K',';','|','<','?', /* 40 - 44 */ 'N','M','>',TAB,NOKEY, /* 45 - 49 */ '~',BACKSP,ENTERL,NOKEY,NOKEY, /* 50 - 54 */ COMMAND,SHIFT,CAPSLOCK,OPTION, NOKEY, /* 55 - 59 */ NOKEY,NOKEY,NOKEY,NOKEY,NOKEY, /* 60 - 64 */ PADDOT,RIGHTCURS,NOKEY,NOKEY,NOKEY, /* 65 - 69 */ LEFTCURS,CLEAR,DOWNCURS,NOKEY,NOKEY, /* 70 - 74 */ NOKEY,PADENTER,UPCURS,PADMINUS,NOKEY, /* 75 - 79 */ NOKEY,NOKEY,PAD0,PAD1,PAD2, /* 80 - 84 */ PAD3,PAD4,PAD5,PAD6,PAD7, /* 85 - 89 */ NOKEY,PAD8,PAD9};/* tn.h Modified for variable screen size 11/21/87. K. Mitchum */#define SCREENSIZE (wc->w_rows * ROWSIZE)#define FONT monaco#define TEXTSIZE 9#define HEIGHT 11#define WIDTH 6#define DESCENT 2#define TWIDTH CO * WIDTH#define THEIGHT LI * HEIGHT/* window specs */#define SCROLLWIDTH 16 /* width of scroll bar control in pixels */#define WINDWIDTH (wc->w_width - SCROLLWIDTH + 1) /* local coordinates */#define WINDHEIGHT (wc->w_height) /* local coordinates */#define MAXROW (LI - 1)#define MAXCOL (CO - 1)/* for keyboard routines */#define MCHARS 32 /* must be power of two */#define NMASK MCHARS (-1) /* circular buffer *//***************************************************//* these normally reside in "tune.c" which we don't use */char *CmdDb; /* see InitMac() */char *p_tempfile = ".jrecXXX";char *d_tempfile = ".joveXXX";char *Joverc = ".joverc";void putcurs(),curset(),putp(),dellines(),inslines();private Rect LimitRect; /* bounds we can't move past */struct wind_config { int w_width; /* pixel width of the Mac window */ int w_height; int w_rows; /* rows of characters which fit the window */ int w_cols;} wc_std, wc_user, *wc;private WindowPtr theScreen;int errno;bool Windchange, EventCmd, Keyonly, Bufchange, Modechange, Macmode = OFF;/* Initialization Routines. */voidInitBinds(){ struct cmd *c; data_obj **p; int i; p = MainKeys; for (i= 0; i < NCHARS; i++) { c = (struct cmd *) *p; c->c_map = F_MAINMAP; c->c_key = i; p++; } p = EscKeys; for (i= 0; i < NCHARS; i++) { c = (struct cmd *) *p; c->c_map = F_PREF1MAP; c->c_key = i; p++; } p = CtlxKeys; for (i= 0; i < NCHARS; i++) { c = (struct cmd *) *p; c->c_map = F_PREF2MAP; c->c_key = i; p++; }}private WindowPtr window;private Rect r;private CursHandle cross;voidInitEvents(){ void InitSysMenu(); window = theScreen; InitSysMenu(); SetRect(&r,window->portRect.left, window->portRect.top, window->portRect.right - SCROLLWIDTH, window->portRect.bottom - SCROLLWIDTH); cross = GetCursor(crossCursor);}voidMacInit(){ char *gethome(); void tn_init(); tn_init(); getdir(); gethome(); /* before anyone changes it */ CmdDb = malloc(strlen(gethome()) + 10); /* ??? better check for CmdDb == NULL -- DHR */ strcpy(CmdDb,gethome()); strcat(CmdDb,"/cmds.doc"); InitBinds();}/* dummy routines. */int dummy() {}SIGRESULT(*signal(sig,func)) proto((int))int sig;SIGRESULT (*func) proto((int));{ return &dummy;}void dorecover() {}/* Surrogate unix-style file i/o routines for Jove. These replace the routines distributed in the libraries. They work with Jove, but may not be general enough for other purposes. */#include <io.h>#define NFILES 10/* #define fsetup(p) { \ * (p).ioCompletion = 0; \ * (p).ioVRefNum = cur_vol; \ * (p).ioDirID = cur_dir; \ * (p).ioFVersNum = 0; \ * } * #define isetup(p) {(p).ioCompletion = 0; (p).ioVRefNum = cur_vol;} */private int cur_vol; /* Disk or volume number */private long cur_dir; /* Directory number */private int cur_vref; /* ugh.. Vref for volume + directory */struct ftab { int inuse; /* 0 = closed 1 = binary 2 = text*/ int refnum; /* Mac file reference number */} ft[NFILES];private voidfsetup(p)HParmBlkPtr p;{ byte_zero(p,sizeof(HParamBlockRec)); p->fileParam.ioVRefNum = cur_vol; p->fileParam.ioDirID = cur_dir; p->fileParam.ioFVersNum = 0;}private voidisetup(p)HIOParam *p;{ byte_zero(p,sizeof(HIOParam)); p->ioVRefNum = cur_vol;}/* Kludge to convert Macintosh error codes to something like Unix. */private intcvt_err(err) /* some of these don't make sense... */int err;{ switch(err) { case noErr: errno = 0; return 0; case dirFulErr: case dskFulErr: errno = ENOSPC; break; case nsvErr: case mFulErr: case tmfoErr: case fnfErr: default: errno = ENOENT; break; case ioErr: errno = EIO; break; case bdNamErr: case opWrErr: case paramErr: errno = EINVAL; break; case fnOpnErr: /* dubious... */ case rfNumErr: errno = EBADF; break; case eofErr: /* ditto */ case posErr: errno = ESPIPE; break; case wPrErr: errno = EROFS; break; case fLckdErr: case permErr: errno = EACCES; break; case fBsyErr: errno = EBUSY; break; case dupFNErr: errno = EEXIST; break; case gfpErr: case volOffLinErr: case volOnLinErr: case nsDrvErr: errno = ENODEV; break; case noMacDskErr: case extFSErr: errno = EIO; break; case fsRnErr: case badMDBErr: case wrPermErr: errno = EPERM; break; } return -1;}private char *cvt_fnm(file)char *file;{ static char nm[255]; char *t; if (*file == '/') strcpy(nm,file + 1); /* full path */ else { if (strchr(file + 1, '/') != NULL) strcpy(nm,"/"); /* make a partial pathname */ else *nm = '\0'; strcat(nm,file); } t = nm; while (*t) { if (*t == '/') *t = ':'; t++; } return nm;}intcreat(name,perm) /* permission mode is irrelevant on a Mac */char *name;int perm;{ int fd, err; char *nm; HParamBlockRec p; if (is_dir(name)) { errno = EACCES; return -1; } nm = cvt_fnm(name); /* convert filename to Mac type name */ CtoPstr(nm); for (fd = 0; fd < NFILES && ft[fd].inuse; fd++) ; if (fd == NFILES) { errno = EMFILE; return -1; } fsetup(&p); /* try to delete it, whether it is there or not. */ p.fileParam.ioNamePtr = (StringPtr) nm; if ((err = PBHDelete(&p,0)) != noErr && err != fnfErr) return cvt_err(err); if (do_creat(&p,nm) != 0) return -1; else { ft[fd].inuse++; ft[fd].refnum = p.ioParam.ioRefNum; return fd + 1; }}intopen(name,mode)char *name;int mode;{ int fd, err; char *nm; HParamBlockRec p; if (is_dir(name)) { errno = EACCES; return -1; } nm = cvt_fnm(name); /* convert filename to Mac type name */ CtoPstr(nm); for (fd = 0; fd < NFILES && ft[fd].inuse; fd++) ; if (fd == NFILES) { errno = EMFILE; return -1; } fsetup(&p); switch (mode & 3) { case O_RDONLY: p.ioParam.ioPermssn = fsRdPerm; break; case O_WRONLY: p.ioParam.ioPermssn = fsWrPerm; break; case O_RDWR: p.ioParam.ioPermssn = fsRdWrPerm; break; } p.ioParam.ioNamePtr = (StringPtr) nm; p.ioParam.ioMisc = 0; if ((err = PBHOpen(&p,0)) != noErr && err != fnfErr) return cvt_err(err); if (err == noErr && mode & O_CREAT && mode & O_EXCL) { PBClose(&p,0); errno = EEXIST; return -1; } if (err == fnfErr) { if (mode & O_CREAT) { if (do_creat(&p,nm) != 0) return -1; } else { errno = ENOENT; return -1; } } ft[fd].inuse++; ft[fd].refnum = p.ioParam.ioRefNum; p.ioParam.ioPosMode = (mode & O_APPEND)? fsFromLEOF : fsFromStart; p.ioParam.ioPosOffset = 0; if ((err = PBSetFPos(&p,0)) != noErr) { ft[fd].inuse = 0; return cvt_err(err); } errno = 0; return fd + 1;}private intdo_creat(p,nm)HParmBlkPtr p;char *nm;{ int err; fsetup(p); p->fileParam.ioNamePtr = (StringPtr) nm; if ((err = PBHCreate(p,0)) != noErr) return cvt_err(err); fsetup(p); p->fileParam.ioNamePtr = (StringPtr) nm; p->fileParam.ioFDirIndex = 0; if ((err = PBHGetFInfo(p,0)) != noErr) return cvt_err(err); p->fileParam.ioDirID = cur_dir; p->fileParam.ioFlFndrInfo.fdType = 'TEXT'; p->fileParam.ioFlFndrInfo.fdCreator = 'JV01'; p->fileParam.ioFlFndrInfo.fdFlags = 0; p->fileParam.ioFVersNum = 0; if ((err = PBHSetFInfo(p,0)) != noErr) return cvt_err(err); fsetup(p); p->ioParam.ioNamePtr = (StringPtr) nm; p->ioParam.ioPermssn = fsRdWrPerm; p->ioParam.ioMisc = 0; if (cvt_err(PBHOpen(p,0))) return -1; return 0;}intclose(fd)int fd;{ int err; HParamBlockRec p; fsetup(&p); p.ioParam.ioRefNum = ft[--fd].refnum; ft[fd].inuse = 0;#ifdef NEVER if (cvt_err(PBFlushFile(&p,0)) < 0) return -1; fsetup(&p);#endif if (cvt_err(PBClose(&p,0)) < 0) return -1; fsetup(&p); p.ioParam.ioNamePtr = NULL; if (cvt_err(PBFlushVol(&p,0)) < 0) return -1; return 0; /* ??? added by DHR */}/* Raw read, except '\n' is translated to '\r'. * Surely this could be done better by having '\n' stand for '\015' * as it is done in OS-9. */intread(fd,buf,n)int fd;char *buf;unsigned n;{ int err; IOParam p; if (fd == 0) return con_read(buf,n); if (ft[--fd].inuse == 0) { errno = EBADF; return -1; } isetup(&p); p.ioRefNum = ft[fd].refnum; p.ioBuffer = buf; p.ioReqCount = n; p.ioPosMode = fsFromMark; p.ioPosOffset = 0; if ((err = PBRead(&p,0)) != noErr && err != eofErr) return cvt_err(err); while (n--) { if (*buf == '\r') *buf = '\n'; /* convert from Mac style */ buf++; } errno = 0; return p.ioActCount;}/* Raw write, except '\n' is translated to '\r'. * Surely this could be done better by having '\n' stand for '\015' * as it is done in OS-9. */intwrite(fd,buf,n)int fd;const char *buf;unsigned n;{#ifdef NEVER int err; IOParam p; char *obuf, *s; if (fd == 0) return con_write(buf,n); s = obuf = malloc(n + 1); if (obuf == NULL) return -1; /* shouldn't happen... */ if (ft[--fd].inuse == 0) { errno = EBADF; free(obuf); return -1; } isetup(&p); p.ioRefNum = ft[fd].refnum; p.ioBuffer = obuf; p.ioReqCount = (long) n; p.ioPosMode = fsFromMark; p.ioPosOffset = 0L; while (n--) { if (*buf == '\n') *s = '\r'; /* make it look like Mac files */ else *s = *buf; buf++; s++; } if ((err = PBWrite(&p,0)) != noErr) { free(obuf); return -1; } free(obuf); return (int) p.ioActCount;#else /* ??? This version is untested! -- DHR * It avoids a malloc for every file write! */ if (fd == 0) { return con_write(buf,n); } else { IOParam p; const char *ebuf = buf + n; p.ioRefNum = ft[fd].refnum; p.ioPosMode = fsFromMark; while (buf != ebuf) { int err; if (*buf == '\n') { p.ioReqCount = 1 p.ioBuffer = "\r"; } else { const char *p = buf while (p != ebuf && *p != '\n') p++; p.ioReqCount = p-buf; p.ioBuffer = buf; } p.ioPosOffset = 0L; /* bidirectional */ if ((err = PBWrite(&p,0)) != noErr) return cvt_err(err); buf += p.ioActCount; } return n; }#endif}longlseek(fd,offset,type) /* The Mac version of this doesn't allocate new space. */int fd;long offset;unsigned type;{ int err; long cur_mark, eof, new_mark; IOParam p; if (ft[--fd].inuse == 0) { errno = EBADF; return -1; } isetup(&p); p.ioRefNum = ft[fd].refnum; if ((err = PBGetFPos(&p,0)) != noErr) return cvt_err(err); cur_mark = p.ioPosOffset; isetup(&p); p.ioRefNum = ft[fd].refnum; if ((err = PBGetEOF(&p,0)) != noErr) return cvt_err(err); eof = (long) p.ioMisc; switch(type) { case 0: new_mark = offset; break; case 1: new_mark = offset + cur_mark; break; case 2: new_mark = offset + eof; break; } if (new_mark > eof) { /* need more space in file */ isetup(&p); p.ioRefNum = ft[fd].refnum; p.ioMisc = (Ptr) new_mark; if ((err = PBSetEOF(&p,0)) != noErr) return cvt_err(err);#ifdef NEVER if ((err = PBAllocContig(&p,0)) != noErr) return cvt_err(err);#endif } isetup(&p); p.ioRefNum = ft[fd].refnum; p.ioPosOffset = new_mark; p.ioPosMode = fsFromStart; if ((err = PBSetFPos(&p,0)) != noErr) return cvt_err(err); errno = 0; return p.ioPosOffset;}intunlink(name)char *name;{ int fd, err; char *nm; HParamBlockRec p; nm = cvt_fnm(name); /* convert filename to Mac type name */ CtoPstr(nm); fsetup(&p); /* try to delete it, whether it is there or not. */ p.fileParam.ioNamePtr = (StringPtr) nm; if ((err = PBHDelete(&p,0)) != noErr && err != fnfErr) return cvt_err(err); return 0; /* ??? added by DHR */}/* Console read and write routines */private intcon_write(buf,size)char *buf;unsigned size;{ while (size--) putp(*buf++); return size;}private intcon_read(buf,size)char *buf;unsigned size;{ unsigned n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -