home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / Editors / mjovesrc.zoo / mac.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  59KB  |  2,957 lines

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