home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume16 / nethck31 / part37 < prev    next >
Encoding:
Internet Message Format  |  1993-01-31  |  58.4 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i045:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part37/108
  5. Message-ID: <4339@master.CNA.TEK.COM>
  6. Date: 30 Jan 93 01:12:05 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2264
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1594
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 45
  14. Archive-name: nethack31/Part37
  15. Supersedes: nethack3p9: Volume 10, Issue 46-102
  16. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 37 (of 108)."
  27. # Contents:  src/mail.c sys/mac/macwin.c1
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:00 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/mail.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/mail.c'\"
  32. else
  33. echo shar: Extracting \"'src/mail.c'\" \(14946 characters\)
  34. sed "s/^X//" >'src/mail.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)mail.c    3.1    92/11/14    */
  36. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#include "hack.h"
  40. X
  41. X#ifdef MAIL
  42. X#include "mail.h"
  43. X/*
  44. X * Notify user when new mail has arrived.  Idea by Merlyn Leroy.
  45. X *
  46. X * The mail daemon can move with less than usual restraint.  It can:
  47. X *    - move diagonally from a door
  48. X *    - use secret and closed doors
  49. X *    - run through a monster ("Gangway!", etc.)
  50. X *    - run over pools & traps
  51. X *
  52. X * Possible extensions:
  53. X *    - Open the file MAIL and do fstat instead of stat for efficiency.
  54. X *      (But sh uses stat, so this cannot be too bad.)
  55. X *    - Examine the mail and produce a scroll of mail named "From somebody".
  56. X *    - Invoke MAILREADER in such a way that only this single letter is read.
  57. X *    - Do something to the text when the scroll is enchanted or cancelled.
  58. X *    - Make the daemon always appear at a stairwell, and have it find a
  59. X *      path to the hero.
  60. X *
  61. X * Note by Olaf Seibert: On the Amiga, we usually don't get mail.  So we go
  62. X *             through most of the effects at 'random' moments.
  63. X */
  64. X
  65. Xstatic boolean FDECL(md_start,(coord *));
  66. Xstatic boolean FDECL(md_stop,(coord *, coord *));
  67. Xstatic boolean FDECL(md_rush,(struct monst *,int,int));
  68. Xstatic void FDECL(newmail, (struct mail_info *));
  69. X
  70. Xextern char *viz_rmin, *viz_rmax;    /* line-of-sight limits (vision.c) */
  71. X
  72. X#ifdef OVL0
  73. X
  74. X# if !defined(UNIX) && !defined(VMS)
  75. Xint mustgetmail = -1;
  76. X# endif
  77. X
  78. X#endif /* OVL0 */
  79. X#ifdef OVLB
  80. X
  81. X# ifdef UNIX
  82. X#  include <sys/stat.h>
  83. X#  include <pwd.h>
  84. X/* DON'T trust all Unices to declare getpwuid() in <pwd.h> */
  85. X#  if !defined(_BULL_SOURCE) && !defined(sgi)
  86. X/* DO trust all SVR4 to typedef uid_t in <sys/types.h> (probably to a long) */
  87. X#   if defined(POSIX_TYPES) || defined(SVR4)
  88. Xextern struct passwd *FDECL(getpwuid,(uid_t));
  89. X#   else 
  90. Xextern struct passwd *FDECL(getpwuid,(int));
  91. X#   endif
  92. X#  endif
  93. Xstatic struct stat omstat,nmstat;
  94. Xstatic char *mailbox = NULL;
  95. Xstatic long laststattime;
  96. X
  97. X# ifdef AMS                /* Just a placeholder for AMS */
  98. X#   define MAILPATH "/dev/null"
  99. X# else
  100. X#  if defined(BSD) || defined(ULTRIX)
  101. X#   define MAILPATH "/usr/spool/mail/"
  102. X#  endif
  103. X#  if defined(SYSV) || defined(HPUX)
  104. X#   define MAILPATH "/usr/mail/"
  105. X#  endif
  106. X# endif /* AMS */
  107. X
  108. Xvoid
  109. Xgetmailstatus()
  110. X{
  111. X    if(!mailbox && !(mailbox = getenv("MAIL"))) {
  112. X#  ifdef MAILPATH
  113. X#   ifdef AMS
  114. X            struct passwd ppasswd;
  115. X
  116. X        (void) memcpy(&ppasswd, getpwuid(getuid()), sizeof(struct passwd));
  117. X        if (ppasswd.pw_dir) {
  118. X             mailbox = (char *) alloc((unsigned) strlen(ppasswd.pw_dir)+sizeof(AMS_MAILBOX));
  119. X             Strcpy(mailbox, ppasswd.pw_dir);
  120. X             Strcat(mailbox, AMS_MAILBOX);
  121. X        } else
  122. X          return;
  123. X#   else
  124. X        mailbox = (char *) alloc(sizeof(MAILPATH)+8);
  125. X        Strcpy(mailbox, MAILPATH);
  126. X        Strcat(mailbox, getpwuid(getuid())->pw_name);
  127. X#  endif /* AMS */
  128. X#  else
  129. X        return;
  130. X#  endif
  131. X    }
  132. X    if(stat(mailbox, &omstat)){
  133. X#  ifdef PERMANENT_MAILBOX
  134. X        pline("Cannot get status of MAIL=\"%s\".", mailbox);
  135. X        mailbox = 0;
  136. X#  else
  137. X        omstat.st_mtime = 0;
  138. X#  endif
  139. X    }
  140. X}
  141. X# endif /* UNIX */
  142. X
  143. X/*
  144. X * Pick coordinates for a starting position for the mail daemon.  Called
  145. X * from newmail() and newphone().
  146. X */
  147. Xstatic boolean
  148. Xmd_start(startp)
  149. X    coord *startp;
  150. X{
  151. X    coord testcc;    /* scratch coordinates */
  152. X    int row;        /* current row we are checking */
  153. X    int lax;        /* if TRUE, pick a position in sight. */
  154. X    int dd;        /* distance to current point */
  155. X    int max_distance;    /* max distance found so far */
  156. X
  157. X    /*
  158. X     * If blind and not telepathic, then it doesn't matter what we pick ---
  159. X     * the hero is not going to see it anyway.  So pick a nearby position.
  160. X     */
  161. X    if (Blind && !Telepat) {
  162. X    if (!enexto(startp, u.ux, u.uy, (struct permonst *) 0))
  163. X        return FALSE;    /* no good posiitons */
  164. X    return TRUE;
  165. X    }
  166. X
  167. X    /*
  168. X     * Arrive at an up or down stairwell if it is in line of sight from the
  169. X     * hero.
  170. X     */
  171. X    if (couldsee(upstair.sx, upstair.sy)) {
  172. X    startp->x = upstair.sx;
  173. X    startp->y = upstair.sy;
  174. X    return TRUE;
  175. X    }
  176. X    if (couldsee(dnstair.sx, dnstair.sy)) {
  177. X    startp->x = dnstair.sx;
  178. X    startp->y = dnstair.sy;
  179. X    return TRUE;
  180. X    }
  181. X
  182. X    /*
  183. X     * Try to pick a location out of sight next to the farthest position away
  184. X     * from the hero.  If this fails, try again, just picking the farthest
  185. X     * position that could be seen.  What we really ought to be doing is
  186. X     * finding a path from a stairwell...
  187. X     *
  188. X     * The arrays viz_rmin[] and viz_rmax[] are set even when blind.  These
  189. X     * are the LOS limits for each row.
  190. X     */
  191. X    lax = 0;    /* be picky */
  192. X    max_distance = -1;
  193. Xretry:
  194. X    for (row = 0; row < ROWNO; row++) {
  195. X    if (viz_rmin[row] < viz_rmax[row]) {
  196. X        /* There are valid positions on this row. */
  197. X        dd = distu(viz_rmin[row],row);
  198. X        if (dd > max_distance) {
  199. X        if (lax) {
  200. X            max_distance = dd;
  201. X            startp->y = row;
  202. X            startp->x = viz_rmin[row];
  203. X            
  204. X        } else if (enexto(&testcc, (xchar)viz_rmin[row], row,
  205. X                        (struct permonst *) 0) &&
  206. X               !cansee(testcc.x, testcc.y) &&
  207. X               couldsee(testcc.x, testcc.y)) {
  208. X            max_distance = dd;
  209. X            *startp = testcc;
  210. X        }
  211. X        }
  212. X        dd = distu(viz_rmax[row],row);
  213. X        if (dd > max_distance) {
  214. X        if (lax) {
  215. X            max_distance = dd;
  216. X            startp->y = row;
  217. X            startp->x = viz_rmax[row];
  218. X            
  219. X        } else if (enexto(&testcc, (xchar)viz_rmax[row], row,
  220. X                        (struct permonst *) 0) &&
  221. X               !cansee(testcc.x,testcc.y) &&
  222. X               couldsee(testcc.x, testcc.y)) {
  223. X
  224. X            max_distance = dd;
  225. X            *startp = testcc;
  226. X        }
  227. X        }
  228. X    }
  229. X    }
  230. X
  231. X    if (max_distance < 0) {
  232. X    if (!lax) {
  233. X        lax = 1;        /* just find a position */
  234. X        goto retry;
  235. X    }
  236. X    return FALSE;
  237. X    }
  238. X
  239. X    return TRUE;
  240. X}
  241. X
  242. X/*
  243. X * Try to choose a stopping point as near as possible to the starting
  244. X * position while still adjacent to the hero.  If all else fails, try
  245. X * enexto().  Use enexto() as a last resort because enexto() chooses
  246. X * its point randomly, which is not what we want.
  247. X */
  248. Xstatic boolean
  249. Xmd_stop(stopp, startp)
  250. X    coord *stopp;    /* stopping position (we fill it in) */
  251. X    coord *startp;    /* starting positon (read only) */
  252. X{
  253. X    int x, y, distance, min_distance = -1;
  254. X
  255. X    for (x = u.ux-1; x <= u.ux+1; x++)
  256. X    for (y = u.uy-1; y <= u.uy+1; y++) {
  257. X        if (!isok(x, y) || (x == u.ux && y == u.uy)) continue;
  258. X
  259. X        if (ACCESSIBLE(levl[x][y].typ) && !MON_AT(x,y)) {
  260. X        distance = dist2(x,y,startp->x,startp->y);
  261. X        if (min_distance < 0 || distance < min_distance ||
  262. X            (distance == min_distance && rn2(2))) {
  263. X            stopp->x = x;
  264. X            stopp->y = y;
  265. X            min_distance = distance;
  266. X        }
  267. X        }
  268. X    }
  269. X
  270. X    /* If we didn't find a good spot, try enexto(). */
  271. X    if (min_distance < 0 &&
  272. X        !enexto(stopp, u.ux, u.uy, &mons[PM_MAIL_DAEMON]))
  273. X    return FALSE;
  274. X
  275. X    return TRUE;
  276. X}
  277. X
  278. X/* Let the mail daemon have a larger vocabulary. */
  279. Xstatic const char NEARDATA *mail_text[] = {
  280. X    "Gangway!",
  281. X    "Look out!",
  282. X    "Pardon me!"
  283. X};
  284. X#define md_exclamations()    (mail_text[rn2(3)])
  285. X
  286. X/*
  287. X * Make the mail daemon run through the dungeon.  The daemon will run over
  288. X * any monsters that are in its path, but will replace them later.  Return
  289. X * FALSE if the md gets stuck in a position where there is a monster.  Return
  290. X * TRUE otherwise.
  291. X */
  292. Xstatic boolean
  293. Xmd_rush(md,tx,ty)
  294. X    struct monst *md;
  295. X    register int tx, ty;        /* destination of mail daemon */
  296. X{
  297. X    struct monst *mon;            /* displaced monster */
  298. X    register int dx, dy;        /* direction counters */
  299. X    int fx = md->mx, fy = md->my;    /* current location */
  300. X    int nfx = fx, nfy = fy,        /* new location */ 
  301. X    d1, d2;                /* shortest distances */
  302. X
  303. X    /*
  304. X     * It is possible that the monster at (fx,fy) is not the md when:
  305. X     * the md rushed the hero and failed, and is now starting back.
  306. X     */
  307. X    if (m_at(fx, fy) == md) {
  308. X    remove_monster(fx, fy);        /* pick up from orig position */
  309. X    newsym(fx, fy);
  310. X    }
  311. X
  312. X    /*
  313. X     * At the beginning and exit of this loop, md is not placed in the
  314. X     * dungeon.
  315. X     */
  316. X    while (1) {
  317. X    /* Find a good location next to (fx,fy) closest to (tx,ty). */
  318. X    d1 = dist2(fx,fy,tx,ty);
  319. X    for (dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
  320. X        if ((dx || dy) && isok(fx+dx,fy+dy) && 
  321. X                       !IS_STWALL(levl[fx+dx][fy+dy].typ)) {
  322. X        d2 = dist2(fx+dx,fy+dy,tx,ty);
  323. X        if (d2 < d1) {
  324. X            d1 = d2;
  325. X            nfx = fx+dx;
  326. X            nfy = fy+dy;
  327. X        }
  328. X        }
  329. X
  330. X    /* Break if the md couldn't find a new position. */
  331. X    if (nfx == fx && nfy == fy) break;
  332. X
  333. X    fx = nfx;            /* this is our new position */
  334. X    fy = nfy;
  335. X
  336. X    /* Break if the md reaches its destination. */
  337. X    if (fx == tx && fy == ty) break;
  338. X
  339. X    if ((mon = m_at(fx,fy)) != 0)    /* save monster at this position */
  340. X        verbalize(md_exclamations());
  341. X    else if (fx == u.ux && fy == u.uy)
  342. X        verbalize("Excuse me.");
  343. X
  344. X    place_monster(md,fx,fy);    /* put md down */
  345. X    newsym(fx,fy);            /* see it */
  346. X    flush_screen(0);        /* make sure md shows up */
  347. X    delay_output();            /* wait a little bit */
  348. X
  349. X    /* Remove md from the dungeon.  Restore original mon, if necessary. */
  350. X    if (mon) {
  351. X        if ((mon->mx != fx) || (mon->my != fy))
  352. X        place_worm_seg(mon, fx, fy);
  353. X        else
  354. X        place_monster(mon, fx, fy);
  355. X    } else
  356. X        remove_monster(fx, fy);
  357. X    newsym(fx,fy);
  358. X    }
  359. X
  360. X    /*
  361. X     * Check for a monster at our stopping position (this is possible, but
  362. X     * very unlikely).  If one exists, then have the md leave in disgust.
  363. X     */
  364. X    if ((mon = m_at(fx, fy)) != 0) {
  365. X    place_monster(md, fx, fy);    /* display md with text below */
  366. X    newsym(fx, fy);
  367. X    verbalize("This place's too crowded.  I'm outta here.");
  368. X
  369. X    if ((mon->mx != fx) || (mon->my != fy))    /* put mon back */
  370. X        place_worm_seg(mon, fx, fy);
  371. X    else
  372. X        place_monster(mon, fx, fy);
  373. X
  374. X    newsym(fx, fy);
  375. X    return FALSE;
  376. X    }
  377. X
  378. X    place_monster(md, fx, fy);    /* place at final spot */
  379. X    newsym(fx, fy);
  380. X    flush_screen(0);
  381. X    delay_output();            /* wait a little bit */
  382. X
  383. X    return TRUE;
  384. X}
  385. X
  386. X/* Deliver a scroll of mail. */
  387. X/*ARGSUSED*/
  388. Xstatic void
  389. Xnewmail(info)
  390. Xstruct mail_info *info;
  391. X{
  392. X    struct monst *md;
  393. X    coord start, stop;
  394. X    boolean message_seen = FALSE;
  395. X
  396. X    /* Try to find good starting and stopping places. */
  397. X    if (!md_start(&start) || !md_stop(&stop,&start)) goto give_up;
  398. X
  399. X    /* Make the daemon.  Have it rush towards the hero. */
  400. X    if (!(md = makemon(&mons[PM_MAIL_DAEMON], start.x, start.y))) goto give_up;
  401. X    if (!md_rush(md, stop.x, stop.y)) goto go_back;
  402. X
  403. X    message_seen = TRUE;
  404. X# ifdef NO_MAILREADER
  405. X    verbalize("Hello, %s!  You have some mail in the outside world.", plname);
  406. X# else
  407. X    verbalize("Hello, %s!  %s.", plname, info->display_txt);
  408. X
  409. X    if (info->message_typ) {
  410. X    struct obj *obj = mksobj(SCR_MAIL, FALSE, FALSE);
  411. X    if (distu(md->mx,md->my) > 2)
  412. X        verbalize("Catch!");
  413. X    display_nhwindow(WIN_MESSAGE, FALSE);
  414. X    if (info->object_nam) {
  415. X        obj = oname(obj, info->object_nam, FALSE);
  416. X        if (info->response_cmd) {    /*(hide extension of the obj name)*/
  417. X        int namelth = info->response_cmd - info->object_nam - 1;
  418. X        if ( namelth <= 0 || namelth >= (int) obj->onamelth )
  419. X            impossible("mail delivery screwed up");
  420. X        else
  421. X            *(ONAME(obj) + namelth) = '\0';
  422. X        /* Note: renaming object will discard the hidden command. */
  423. X        }
  424. X    }
  425. X    obj = hold_another_object(obj, "Oops!",
  426. X                  (const char *)0, (const char *)0);
  427. X    }
  428. X# endif /* NO_MAILREADER */
  429. X
  430. X    /* zip back to starting location */
  431. Xgo_back:
  432. X    (void) md_rush(md, start.x, start.y);
  433. X    mongone(md);
  434. X    /* deliver some classes of messages even if no daemon ever shows up */
  435. Xgive_up:
  436. X    if (!message_seen && info->message_typ == MSG_OTHER)
  437. X    pline("Hark!  \"%s.\"", info->display_txt);
  438. X}
  439. X
  440. X#endif /* OVLB */
  441. X
  442. X# if !defined(UNIX) && !defined(VMS)
  443. X
  444. X#ifdef OVL0
  445. X
  446. Xvoid
  447. Xckmailstatus()
  448. X{
  449. X    if (u.uswallow) return;
  450. X    if (mustgetmail < 0) {
  451. X#ifdef AMIGA
  452. X        mustgetmail=(moves<2000)?(100+rn2(2000)):(2000+rn2(3000));
  453. X#endif
  454. X        return;
  455. X    }
  456. X    if (--mustgetmail <= 0) {
  457. X        static struct mail_info
  458. X            deliver = {MSG_MAIL,"I have some mail for you",0,0};
  459. X        newmail(&deliver);
  460. X        mustgetmail = -1;
  461. X    }
  462. X}
  463. X
  464. X#endif /* OVL0 */
  465. X#ifdef OVLB
  466. X
  467. X/*ARGSUSED*/
  468. Xvoid
  469. Xreadmail(otmp)
  470. Xstruct obj *otmp;
  471. X{
  472. X#ifdef AMIGA
  473. X    char *junk[]={
  474. X    "It reads:  \"Please disregard previous letter.\"",
  475. X    "It reads:  \"Welcome to NetHack 3.1!\"",
  476. X    "It reads:  \"Only Amiga makes it possible.\"",
  477. X    "It reads:  \"CATS have all the answers.\"",
  478. X    "It reads:  \"Report bugs to nethack-bugs@linc.cis.upenn.edu\""
  479. X    };
  480. X
  481. X    pline(junk[rn2(SIZE(junk))]);
  482. X#else
  483. X    pline("It reads:  \"Please disregard previous letter.\"");
  484. X#endif
  485. X}
  486. X
  487. X#endif /* OVLB */
  488. X
  489. X# endif /* !UNIX && !VMS */
  490. X
  491. X# ifdef UNIX
  492. X
  493. X#ifdef OVL0
  494. X
  495. Xvoid
  496. Xckmailstatus()
  497. X{
  498. X    if(!mailbox || u.uswallow
  499. X#  ifdef MAILCKFREQ
  500. X            || moves < laststattime + MAILCKFREQ
  501. X#  endif
  502. X                            )
  503. X        return;
  504. X
  505. X    laststattime = moves;
  506. X    if(stat(mailbox, &nmstat)){
  507. X#  ifdef PERMANENT_MAILBOX
  508. X        pline("Cannot get status of MAIL=\"%s\" anymore.", mailbox);
  509. X        mailbox = 0;
  510. X#  else
  511. X        nmstat.st_mtime = 0;
  512. X#  endif
  513. X    } else if(nmstat.st_mtime > omstat.st_mtime) {
  514. X        if(nmstat.st_size) {
  515. X            static struct mail_info
  516. X                deliver = {MSG_MAIL,"I have some mail for you",0,0};
  517. X            newmail(&deliver);
  518. X        }
  519. X        getmailstatus();    /* might be too late ... */
  520. X    }
  521. X}
  522. X
  523. X#endif /* OVL0 */
  524. X
  525. X#ifdef OVLB
  526. X
  527. X/*ARGSUSED*/
  528. Xvoid
  529. Xreadmail(otmp)
  530. Xstruct obj *otmp;
  531. X{
  532. X#  ifdef DEF_MAILREADER            /* This implies that UNIX is defined */
  533. X    register const char *mr = 0;
  534. X
  535. X    display_nhwindow(WIN_MESSAGE, FALSE);
  536. X    if(!(mr = getenv("MAILREADER")))
  537. X        mr = DEF_MAILREADER;
  538. X
  539. X    if(child(1)){
  540. X        (void) execl(mr, mr, NULL);
  541. X        terminate(1);
  542. X    }
  543. X#  else
  544. X#   ifndef AMS              /* AMS mailboxes are directories */
  545. X    display_file(mailbox, TRUE);
  546. X#   endif /* AMS */
  547. X#  endif /* DEF_MAILREADER */
  548. X
  549. X    /* get new stat; not entirely correct: there is a small time
  550. X       window where we do not see new mail */
  551. X    getmailstatus();
  552. X}
  553. X
  554. X#endif /* OVLB */
  555. X
  556. X# endif /* UNIX */
  557. X
  558. X# ifdef VMS
  559. X
  560. X#ifdef OVL0
  561. X
  562. Xvolatile int broadcasts = 0;
  563. X
  564. Xvoid
  565. Xckmailstatus()
  566. X{
  567. X    struct mail_info *brdcst, *parse_next_broadcast();
  568. X
  569. X    if(u.uswallow) return;
  570. X
  571. X    while (broadcasts > 0) {    /* process all trapped broadcasts [until] */
  572. X    broadcasts--;
  573. X    if ((brdcst = parse_next_broadcast()) != 0) {
  574. X        newmail(brdcst);
  575. X        break;        /* only handle one real message at a time */
  576. X    }
  577. X    }
  578. X}
  579. X
  580. X#endif /* OVL0 */
  581. X
  582. X#ifdef OVLB
  583. X
  584. Xvoid
  585. Xreadmail(otmp)
  586. Xstruct obj *otmp;
  587. X{
  588. X#  ifdef SHELL    /* can't access mail reader without spawning subprocess */
  589. X    char *p, *cmd, buf[BUFSZ], qbuf[BUFSZ];
  590. X
  591. X    /* there should be a command hidden beyond the object name */
  592. X    p = otmp->onamelth ? ONAME(otmp) : "";
  593. X    cmd = (strlen(p) + 1 < otmp->onamelth) ? eos(p) + 1 : (char *) 0;
  594. X    if (!cmd || !*cmd) cmd = "SPAWN";
  595. X
  596. X    Sprintf(qbuf, "System command (%s)", cmd);
  597. X    getlin(qbuf, buf);
  598. X    clear_nhwindow(WIN_MESSAGE);
  599. X    if (*buf != '\033') {
  600. X    for (p = eos(buf); p > buf; *p = '\0')
  601. X        if (*--p != ' ') break;    /* strip trailing spaces */
  602. X    if (*buf) cmd = buf;        /* use user entered command */
  603. X    if (!strcmpi(cmd, "SPAWN") || !strcmp(cmd, "!"))
  604. X        cmd = (char *) 0;        /* interactive escape */
  605. X
  606. X    vms_doshell(cmd, TRUE);
  607. X    (void) sleep(1);
  608. X    }
  609. X#  endif /* SHELL */
  610. X}
  611. X
  612. X#endif /* OVLB */
  613. X
  614. X# endif /* VMS */
  615. X
  616. X#endif /* MAIL */
  617. X
  618. X/*mail.c*/
  619. END_OF_FILE
  620. if test 14946 -ne `wc -c <'src/mail.c'`; then
  621.     echo shar: \"'src/mail.c'\" unpacked with wrong size!
  622. fi
  623. # end of 'src/mail.c'
  624. fi
  625. if test -f 'sys/mac/macwin.c1' -a "${1}" != "-c" ; then 
  626.   echo shar: Will not clobber existing file \"'sys/mac/macwin.c1'\"
  627. else
  628. echo shar: Extracting \"'sys/mac/macwin.c1'\" \(39944 characters\)
  629. sed "s/^X//" >'sys/mac/macwin.c1' <<'END_OF_FILE'
  630. X/*    SCCS Id: @(#)macwin.c    3.1    93/01/24          */
  631. X/* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
  632. X/* NetHack may be freely redistributed.  See license for details. */
  633. X
  634. X/*
  635. X * macwin.c
  636. X */
  637. X
  638. X/*
  639. X * I have to quote X11R5:
  640. X *
  641. X *  "If you think you know what this code is doing, you're probably wrong.
  642. X *   Here be serious and nasty dragons."
  643. X *
  644. X * h+ 92-09-26
  645. X */
  646. X
  647. X#include "hack.h"
  648. X#include "func_tab.h"
  649. X
  650. X#include <osutils.h>
  651. X#include <dialogs.h>
  652. X#include <textedit.h>
  653. X#include <menus.h>
  654. X#ifndef MAC_THINKC5
  655. X#include <sysequ.h>
  656. X#endif
  657. X#include <resources.h>
  658. X#include <desk.h>
  659. X#include <gestaltequ.h>
  660. X#include <balloons.h>
  661. X#include <toolutils.h>
  662. X#include <script.h>
  663. X#include <OSEvents.h>
  664. X#include <Packages.h>
  665. X#include <Sound.h>
  666. X#include <DiskInit.h>
  667. X
  668. XNhWindow * theWindows = (NhWindow *) NULL ;
  669. X
  670. X/*
  671. X * Some useful #defines for the scroll bar width and height
  672. X */
  673. X#define        SBARWIDTH    15
  674. X#define        SBARHEIGHT    14
  675. X
  676. X/*
  677. X * We put a TE on the message window for the "top line" queries.
  678. X * top_line is the TE that holds both the query and the user's
  679. X * response.  The first topl_query_len characters in top_line are
  680. X * the query, the rests are the response.  topl_resp is the valid
  681. X * response to a yn query, while topl_resp[topl_def_idx] is the
  682. X * default response to a yn query.
  683. X */
  684. XTEHandle top_line = nil;
  685. Xint         topl_query_len;
  686. Xint         topl_def_idx = -1;
  687. Xchar     topl_resp[10] = "";
  688. X
  689. X#define CHAR_ANY '\n'
  690. X
  691. X/*
  692. X * inSelect means we have a menu window up for selection or
  693. X * something similar. It makes the window with win number ==
  694. X * inSelect a movable modal (unfortunately without the border)
  695. X * and clicking the close box forces an ESC into the key
  696. X * buffer. Don't forget to set inSelect to WIN_ERR when you're
  697. X * done...
  698. X */
  699. Xwinid inSelect = WIN_ERR ;
  700. X
  701. X/*
  702. X * The key queue - contains 0 for unused or an ascii value.
  703. X * When getting keys, take the first value and shift the
  704. X * queue, shifting in a 0.
  705. X */
  706. X#define QUEUE_LEN 24
  707. Xstatic int keyQueue [ QUEUE_LEN ] ;
  708. X
  709. XBoolean gClickedToMove = 0 ; /* For ObscureCursor */
  710. X
  711. X
  712. X/*
  713. X * Add key to input queue, force means replace last if full
  714. X */
  715. Xvoid
  716. XaddToKeyQueue ( int ch , Boolean force )
  717. X{
  718. X    int i ;
  719. X
  720. X    for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  721. X
  722. X        if ( ! keyQueue [ i ] ) {
  723. X
  724. X            keyQueue [ i ] = ch ;
  725. X            return ;
  726. X        }
  727. X    }
  728. X    if ( force ) {
  729. X
  730. X        keyQueue [ QUEUE_LEN - 1 ] = ch ;
  731. X    }
  732. X}
  733. X
  734. X
  735. X/*
  736. X * Cursor movement
  737. X */
  738. XRgnHandle gMouseRgn = NULL ;
  739. X
  740. X/*
  741. X * _Gestalt madness - we rely heavily on the _Gestalt glue, since we
  742. X * don't check for the trap...
  743. X */
  744. XMacFlags macFlags ;
  745. X
  746. X/*
  747. X * Async flag for keeping track of scrollbars...
  748. X * Used by InvalScrollBar ( )
  749. X */
  750. Xstatic NhWindow * asyDSC = (NhWindow *) NULL ;
  751. X
  752. X/*
  753. X * The font to be used in the text window
  754. X */
  755. Xshort text_wind_font = geneva;
  756. X
  757. X/*
  758. X * Whether to adjust the height of a text window according to its contents
  759. X */
  760. Xboolean full_screen = FALSE;
  761. X
  762. Xchar macPad = 1 ;
  763. X
  764. XHandle mBar ;
  765. XMenuHandle appleMenu ;
  766. XMenuHandle fileMenu ;
  767. XMenuHandle editMenu ;
  768. XMenuHandle extendMenu ;
  769. XMenuHandle miscMenu ;
  770. XMenuHandle helpMenu ;
  771. XMenuHandle commandsMenu ;
  772. XMenuHandle thingsMenu ;
  773. X
  774. X#define NHW_BASE 0
  775. Xwinid BASE_WINDOW ; // Was: , WIN_MAP , WIN_MESSAGE , WIN_INVEN , WIN_STATUS ;
  776. X
  777. Xvoid NDECL(port_help);
  778. X
  779. Xint NDECL(SanePositions);
  780. XBoolean FDECL(RetrieveWinPos, (WindowPtr,short *,short *));
  781. Xvoid NDECL ( InitMac ) ;
  782. Xvoid NDECL(InitRes);
  783. Xvoid FDECL(GeneralKey, ( EventRecord * theEvent , WindowPtr theWindow ));
  784. Xvoid FDECL(HandleKey, ( EventRecord * theEvent ));
  785. Xvoid FDECL(HandleClick, ( EventRecord * theEvent ));
  786. Xvoid FDECL(HandleUpdate, ( EventRecord * theEvent ));
  787. Xvoid FDECL(HandleEvent, ( EventRecord * theEvent ));
  788. Xvoid NDECL(DimMenuBar);
  789. Xvoid NDECL(UndimMenuBar);
  790. Xint FDECL(filter_scroll_key,(const int, NhWindow *));
  791. X
  792. Xvoid SetFrameItem ( DialogPtr , short , short ) ;
  793. Xvoid FlashButton ( DialogPtr , short ) ;
  794. X
  795. Xvoid trans_num_keys ( EventRecord * ) ;
  796. X
  797. X#ifndef MAC_THINKC5
  798. X/*
  799. X * Why aren't these declared when including hack.h - I thought
  800. X * they were...
  801. X */
  802. Xvoid FDECL(putsym, ( winid win , int x , int y , CHAR_P sym ));
  803. X#endif
  804. X
  805. X#define NUM_FUNCS 6
  806. Xstatic void FDECL(macKeyNull, ( EventRecord * , WindowPtr )) ;
  807. Xstatic void FDECL(macKeyMessage, ( EventRecord * , WindowPtr )) ;
  808. Xstatic void FDECL(macKeyStatus, ( EventRecord * , WindowPtr )) ;
  809. Xstatic void FDECL(macKeyMap, ( EventRecord * , WindowPtr )) ;
  810. Xstatic void FDECL(macKeyMenu, ( EventRecord * , WindowPtr )) ;
  811. Xstatic void FDECL(macKeyText, ( EventRecord * , WindowPtr )) ;
  812. X
  813. Xstatic void FDECL(macClickNull, ( EventRecord * , WindowPtr )) ;
  814. Xstatic void FDECL(macClickMessage, ( EventRecord * , WindowPtr )) ;
  815. Xstatic void FDECL(macClickStatus, ( EventRecord * , WindowPtr )) ;
  816. Xstatic void FDECL(macClickMap, ( EventRecord * , WindowPtr )) ;
  817. Xstatic void FDECL(macClickMenu, ( EventRecord * , WindowPtr )) ;
  818. Xstatic void FDECL(macClickText, ( EventRecord * , WindowPtr )) ;
  819. X
  820. Xstatic void FDECL(macUpdateNull, ( EventRecord * , WindowPtr )) ;
  821. Xstatic void FDECL(macUpdateMessage, ( EventRecord * , WindowPtr )) ;
  822. Xstatic void FDECL(macUpdateStatus, ( EventRecord * , WindowPtr )) ;
  823. Xstatic void FDECL(macUpdateMap, ( EventRecord * , WindowPtr )) ;
  824. Xstatic void FDECL(macUpdateMenu, ( EventRecord * , WindowPtr )) ;
  825. Xstatic void FDECL(macUpdateText, ( EventRecord * , WindowPtr )) ;
  826. X
  827. Xstatic void FDECL(macCursorNull, ( EventRecord * , WindowPtr , RgnHandle )) ;
  828. Xstatic void FDECL(macCursorMessage, ( EventRecord * , WindowPtr , RgnHandle )) ;
  829. Xstatic void FDECL(macCursorStatus, ( EventRecord * , WindowPtr , RgnHandle )) ;
  830. Xstatic void FDECL(macCursorMap, ( EventRecord * , WindowPtr , RgnHandle )) ;
  831. Xstatic void FDECL(macCursorMenu, ( EventRecord * , WindowPtr , RgnHandle )) ;
  832. Xstatic void FDECL(macCursorText, ( EventRecord * , WindowPtr , RgnHandle )) ;
  833. X
  834. Xstatic void NDECL(UpdateMenus);
  835. Xstatic void FDECL(DoMenu, (long choise));
  836. X
  837. Xstatic void FDECL (DrawScrollbar, ( NhWindow * , WindowPtr ));
  838. Xstatic void FDECL (InvalScrollBar, ( NhWindow * ));
  839. Xstatic void FDECL(DrawMapCursor,(NhWindow *));
  840. Xstatic void FDECL(DoScrollBar,(Point, short, ControlHandle, NhWindow *, WindowPtr));
  841. Xstatic pascal void FDECL(Up, (ControlHandle, short));
  842. Xstatic pascal void FDECL(Down,(ControlHandle, short));
  843. X
  844. Xtypedef void ( * CbFunc ) ( EventRecord * , WindowPtr ) ;
  845. Xtypedef void ( * CbCursFunc ) ( EventRecord * , WindowPtr , RgnHandle ) ;
  846. X
  847. XCbFunc winKeyFuncs [ NUM_FUNCS ] = {
  848. X    macKeyNull , macKeyMessage , macKeyStatus , macKeyMap , macKeyMenu , macKeyText
  849. X} ;
  850. X
  851. XCbFunc winClickFuncs [ NUM_FUNCS ] = {
  852. X    macClickNull , macClickMessage , macClickStatus , macClickMap , macClickMenu ,
  853. X    macClickText
  854. X} ;
  855. X
  856. XCbFunc winUpdateFuncs [ NUM_FUNCS ] = {
  857. X    macUpdateNull , macUpdateMessage , macUpdateStatus , macUpdateMap ,
  858. X    macUpdateMenu , macUpdateText
  859. X} ;
  860. X
  861. XCbCursFunc winCursorFuncs [ NUM_FUNCS ] = {
  862. X    macCursorNull , macCursorMessage , macCursorStatus , macCursorMap ,
  863. X    macCursorMenu , macCursorText
  864. X} ;
  865. X
  866. X#ifdef applec
  867. X  extern void _DataInit();
  868. X  /* This routine is part of the MPW runtime library. This external
  869. X     reference to it is done so that we can unload its segment, %A5Init,
  870. X     and recover c 250K of memory */
  871. X#endif
  872. X
  873. X
  874. Xvoid
  875. XInitMac( void )
  876. X{
  877. X    int i ;
  878. X    long l ;
  879. X
  880. X#ifdef applec
  881. X    UnloadSeg((Ptr) _DataInit);
  882. X#endif
  883. X
  884. X    SetApplLimit ( 
  885. X                    ( void * ) 
  886. X                    ( 
  887. X                    ( ( long ) GetApplLimit() ) - 40 * 1024L 
  888. X                    ) 
  889. X                 ) ;
  890. X    MaxApplZone ( ) ;
  891. X    for ( i = 0 ; i < 5 ; i ++ )
  892. X        MoreMasters ( ) ;
  893. X
  894. X    InitGraf ( & qd . thePort ) ;
  895. X    InitFonts ( ) ;
  896. X    InitWindows ( ) ;
  897. X    InitMenus ( ) ;
  898. X    InitDialogs ( ( ResumeProcPtr ) 0L ) ;
  899. X    TEInit ( ) ;
  900. X    InitSegMgmt( itworked );    /* itworked is always in the main segment */
  901. X    
  902. X    attemptingto("start up");
  903. X    
  904. X    if ( Gestalt ( gestaltOSAttr , & l ) ) {
  905. X        macFlags . processes = 0 ;
  906. X        macFlags . tempMem = 0 ;
  907. X    } else {
  908. X        macFlags . processes = ( l & ( 1 << gestaltLaunchControl ) ) ? 1 : 0 ;
  909. X        macFlags . tempMem = ( l & ( 1 << gestaltRealTempMemory ) ) ? 1 : 0 ;
  910. X    }
  911. X    if ( Gestalt ( gestaltQuickdrawVersion , & l ) ) {
  912. X        macFlags . color = 0 ;
  913. X    } else {
  914. X        macFlags . color = ( l >= gestalt8BitQD ) ? 1 : 0 ;
  915. X    }
  916. X    if ( Gestalt ( gestaltFindFolderAttr , & l ) ) {
  917. X        macFlags . folders = 0 ;
  918. X    } else {
  919. X        macFlags . folders = ( l & ( 1 << gestaltFindFolderPresent ) ) ? 1 : 0 ;
  920. X    }
  921. X    if ( Gestalt ( gestaltHelpMgrAttr , & l ) ) {
  922. X        macFlags . help = 0 ;
  923. X    } else {
  924. X        macFlags . help = ( l & ( 1 << gestaltHelpMgrPresent ) ) ? 1 : 0 ;
  925. X    }
  926. X    if ( Gestalt ( gestaltFSAttr , & l ) ) {
  927. X        macFlags . fsSpec = 0 ;
  928. X    } else {
  929. X        macFlags . fsSpec = ( l & ( 1 << gestaltHasFSSpecCalls ) ) ? 1 : 0 ;
  930. X    }
  931. X    if ( Gestalt ( gestaltFontMgrAttr , & l ) ) {
  932. X        macFlags . trueType = 0 ;
  933. X    } else {
  934. X        macFlags . trueType = ( l & ( 1 << gestaltOutlineFonts ) ) ? 1 : 0 ;
  935. X    }
  936. X    if ( Gestalt ( gestaltAUXVersion , & l ) ) {
  937. X        macFlags . aux = 0 ;
  938. X    } else {
  939. X        macFlags . aux = ( l >= 0x200 ) ? 1 : 0 ;
  940. X    }
  941. X    if ( Gestalt ( gestaltAliasMgrAttr , & l ) ) {
  942. X        macFlags . alias = 0 ;
  943. X    } else {
  944. X        macFlags . alias = ( l & ( 1 << gestaltAliasMgrPresent ) ) ? 1 : 0 ;
  945. X    }
  946. X    if ( Gestalt ( gestaltStandardFileAttr , & l ) ) {
  947. X        macFlags . standardFile = 0 ;
  948. X    } else {
  949. X        macFlags . standardFile = ( l & ( 1 << gestaltStandardFile58 ) ) ? 1 : 0 ;
  950. X    }
  951. X
  952. X    gMouseRgn = NewRgn ( ) ;
  953. X}
  954. X
  955. X
  956. X#define MAX_HEIGHT 200
  957. X#define MIN_HEIGHT 50
  958. X#define MIN_WIDTH 300
  959. X
  960. X/*
  961. X * This function could be overloaded with any amount of
  962. X * intelligence...
  963. X */
  964. Xint
  965. XSanePositions ( void )
  966. X{
  967. X    short mainTop , mainLeft , mainWidth , mainHeight ;
  968. X    short statTop , statLeft , statWidth , statHeight ;
  969. X    short mesgTop , mesgLeft , mesgWidth , mesgHeight ;
  970. X    short left , top , width , height ;
  971. X    short ix , numText = 0 , numMenu = 0 ;
  972. X    Rect screenArea ;
  973. X    WindowPtr theWindow ;
  974. X    NhWindow * nhWin ;
  975. X
  976. X    screenArea = qd . thePort -> portBits . bounds ;
  977. X    OffsetRect ( & screenArea , - screenArea . left , - screenArea . top ) ;
  978. X
  979. X/* Map Window */
  980. X    nhWin = theWindows + WIN_MAP ;
  981. X    theWindow = nhWin -> theWindow ;
  982. X
  983. X    height = nhWin -> charHeight * NUM_ROWS ;
  984. X    width = nhWin -> charWidth * NUM_COLS ;
  985. X
  986. X    if ( ! RetrievePosition ( kMapWindow , & top , & left ) ) {
  987. X        top = GetMBarHeight ( ) * 2 ;
  988. X        left = ( screenArea . right - width ) / 2 ;
  989. X    }
  990. X
  991. X    mainTop = top ;
  992. X    mainLeft = left ;
  993. X    mainHeight = height ;
  994. X    mainWidth = width ;
  995. X
  996. X/* Status Window */
  997. X    nhWin = theWindows + WIN_STATUS ;
  998. X    theWindow = nhWin -> theWindow ;
  999. X
  1000. X    height = nhWin -> charHeight * NUM_STAT_ROWS ;
  1001. X
  1002. X    if ( ! RetrievePosition ( kStatusWindow , & top , & left ) ) {
  1003. X        top = mainTop + mainHeight + 2 ;
  1004. X        left = mainLeft ;
  1005. X    }
  1006. X
  1007. X    if ( top + height > screenArea . bottom ) {
  1008. X        top = screenArea . bottom - height ;
  1009. X        left += 20 ; /* Edge to the right so we can read it */
  1010. X    }
  1011. X    statTop = top ;
  1012. X    statLeft = left ;
  1013. X    statHeight = height ;
  1014. X    statWidth = width ;
  1015. X
  1016. X/* Message Window */
  1017. X    nhWin = theWindows + WIN_MESSAGE ;
  1018. X    theWindow = nhWin -> theWindow ;
  1019. X
  1020. X    if ( ! RetrievePosition ( kMessageWindow , & top , & left ) ) {
  1021. X        top = statTop + statHeight + 20 ;
  1022. X        left = statLeft ;
  1023. X    }
  1024. X
  1025. X    if ( ! RetrieveSize ( kMessageWindow , top , left , & height , & width ) ) {
  1026. X        height = screenArea . bottom - top - 2 ;
  1027. X        if ( height > MAX_HEIGHT ) {
  1028. X            height = MAX_HEIGHT ;
  1029. X        } else if ( height < MIN_HEIGHT ) {
  1030. X            height = MIN_HEIGHT ;
  1031. X            width = MIN_WIDTH ;
  1032. X            left = screenArea . right - width ;
  1033. X            top = screenArea . bottom - MIN_HEIGHT ;
  1034. X        }
  1035. X    }
  1036. X    mesgTop = top ;
  1037. X    mesgLeft = left ;
  1038. X    mesgHeight = height ;
  1039. X    mesgWidth = width ;
  1040. X
  1041. X/* Move these windows */
  1042. X    MoveWindow ( theWindows [ WIN_STATUS ] . theWindow , statLeft , statTop , 1 ) ;
  1043. X    SizeWindow ( theWindows [ WIN_STATUS ] . theWindow , statWidth , statHeight , 1 ) ;
  1044. X    MoveWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgLeft , mesgTop , 1 ) ;
  1045. X    SizeWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgWidth , mesgHeight , 1 ) ;
  1046. X    MoveWindow ( theWindows [ WIN_MAP ] . theWindow , mainLeft , mainTop , 1 ) ;
  1047. X    SizeWindow ( theWindows [ WIN_MAP ] . theWindow , mainWidth , mainHeight , 1 ) ;
  1048. X
  1049. X/* Handle other windows */
  1050. X    for ( ix = 0 ; ix < NUM_MACWINDOWS ; ix ++ ) {
  1051. X        if ( ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP ) {
  1052. X            if ( theWindow = theWindows [ ix ] . theWindow ) {
  1053. X                if ( ( ( WindowPeek ) theWindow ) -> visible ) {
  1054. X                    if ( theWindows [ ix ] . kind == NHW_MENU ) {
  1055. X                        if ( ! RetrievePosition ( kMenuWindow , & top , & left ) ) {
  1056. X                            top = GetMBarHeight ( ) * 2 ;
  1057. X                            left = 2 ;
  1058. X                        }
  1059. X                        top += ( numMenu * GetMBarHeight ( ) ) ;
  1060. X                        while ( top > screenArea . bottom - MIN_HEIGHT ) {
  1061. X                            top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  1062. X                            left += 20 ;
  1063. X                        }
  1064. X                        numMenu ++ ;
  1065. X                        MoveWindow ( theWindow , left , top , 1 ) ;
  1066. X                    } else {
  1067. X                        if ( ! RetrievePosition ( kTextWindow , & top , & left ) ) {
  1068. X                            top = GetMBarHeight ( ) * 2 ;
  1069. X                            left = screenArea . right - 3 ;
  1070. X                        }
  1071. X                        top += ( numText * GetMBarHeight ( ) ) ;
  1072. X                        while ( top > screenArea . bottom - MIN_HEIGHT ) {
  1073. X                            top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  1074. X                            left -= 20 ;
  1075. X                        }
  1076. X                        numText ++ ;
  1077. X                        MoveWindow ( theWindow , left - ( theWindow -> portRect . right -
  1078. X                            theWindow -> portRect . left ) , top , 1 ) ;
  1079. X                    }
  1080. X                }
  1081. X            }
  1082. X        }
  1083. X    }
  1084. X
  1085. X    InitCursor ( ) ;
  1086. X
  1087. X    return 0 ;
  1088. X}
  1089. X
  1090. X
  1091. Xwinid
  1092. Xmac_create_nhwindow ( int type )
  1093. X{
  1094. X    int i ;
  1095. X    Rect siz ;
  1096. X    NhWindow * aWin ;
  1097. X
  1098. X    if ( type < NHW_BASE || type > NHW_TEXT ) {
  1099. X        error ( "Invalid window type %d in create_nhwindow." , type ) ;
  1100. X        return WIN_ERR ;
  1101. X    }
  1102. X
  1103. X    for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  1104. X        if ( ! theWindows [ i ] . theWindow )
  1105. X            break ;
  1106. X    }
  1107. X    if ( i >= NUM_MACWINDOWS ) {
  1108. X        for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  1109. X            WindowPeek w = ( WindowPeek ) theWindows [ i ] . theWindow ;
  1110. X            if ( w -> visible || i == WIN_INVEN || ( w -> windowKind
  1111. X                != NHW_MENU && w -> windowKind != NHW_TEXT ) )
  1112. X                continue ;
  1113. X            error ( "The window list is getting full, freeing unnecessary window (%d)..." ,
  1114. X                i ) ;
  1115. X            destroy_nhwindow ( i ) ;
  1116. X            goto got1 ;
  1117. X        }
  1118. X        error ( "Out of window ids in create_nhwindow ! (Max = %d)" ,
  1119. X            NUM_MACWINDOWS ) ;
  1120. X        return WIN_ERR ;
  1121. X    }
  1122. X
  1123. Xgot1 :
  1124. X    aWin = & theWindows [ i ] ;
  1125. X    aWin -> theWindow = GetNewWindow ( WIN_BASE_RES + type ,
  1126. X        ( WindowPtr ) 0L , ( WindowPtr ) -1L ) ;
  1127. X    ( ( WindowPeek ) aWin -> theWindow ) -> windowKind = WIN_BASE_KIND
  1128. X        + type ;
  1129. X    aWin -> windowTextLen = 0L ;
  1130. X    aWin -> textBase = 0L ;
  1131. X    aWin -> clear = 0 ; /* Yes, we need to inval the area on a clear */
  1132. X    aWin -> scrollBar = (ControlHandle) NULL ;
  1133. X    switch ( type ) {
  1134. X    case NHW_MAP :
  1135. X        if ( ! ( aWin -> windowText = NewHandle
  1136. X            ( sizeof ( MapData ) ) ) ) {
  1137. X            error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  1138. X                ( long ) sizeof ( MapData ) ) ;
  1139. X            DisposeWindow ( aWin -> theWindow ) ;
  1140. X            aWin -> theWindow = (WindowPtr) NULL ;
  1141. X            return WIN_ERR ;
  1142. X        }
  1143. X        break ;
  1144. X    case NHW_STATUS :
  1145. X        if ( ! ( aWin -> windowText = NewHandle
  1146. X            ( sizeof ( StatusData ) ) ) ) {
  1147. X            error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  1148. X                ( long ) sizeof ( StatusData ) ) ;
  1149. X            DisposeWindow ( aWin -> theWindow ) ;
  1150. X            aWin -> theWindow = (WindowPtr) NULL ;
  1151. X            return WIN_ERR ;
  1152. X        }
  1153. X        break ;
  1154. X    default :
  1155. X        if ( ! ( aWin -> windowText = NewHandle ( TEXT_BLOCK ) ) ) {
  1156. X            error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  1157. X                ( long ) TEXT_BLOCK ) ;
  1158. X            DisposeWindow ( aWin -> theWindow ) ;
  1159. X            aWin -> theWindow = (WindowPtr) NULL ;
  1160. X            return WIN_ERR ;
  1161. X        }
  1162. X        break ;
  1163. X    }
  1164. X
  1165. X    clear_nhwindow ( i ) ;
  1166. X
  1167. X/*HARDCODED*/
  1168. X
  1169. X    SetPort ( aWin -> theWindow ) ;
  1170. X    PenPat ( &qd . black ) ;
  1171. X
  1172. X    switch ( type ) {
  1173. X        case NHW_MAP :
  1174. X        case NHW_STATUS :
  1175. X            GetFNum ( "\pHackFont", & aWin -> fontNum ) ;
  1176. X            aWin -> fontSize = flags.large_font ? 12 : 9 ;
  1177. X            break ;
  1178. X        case NHW_MESSAGE :
  1179. X            GetFNum ( "\pPSHackFont", & aWin -> fontNum ) ;
  1180. X            aWin -> fontSize = flags.large_font ? 12 : 9 ;
  1181. X            break ;
  1182. X        default:
  1183. X            aWin -> fontNum = text_wind_font ;
  1184. X            aWin -> fontSize = 9 ;
  1185. X    }
  1186. X
  1187. X    TextFont ( aWin -> fontNum ) ; 
  1188. X    TextSize ( aWin -> fontSize ) ;
  1189. X
  1190. X    if (type == NHW_MESSAGE && !top_line) {
  1191. X        const Rect out_of_scr = { 10000, 10000, 10100, 10100 };
  1192. X        TextFace(bold);
  1193. X        top_line = TENew(&out_of_scr, &out_of_scr);
  1194. X        TEActivate(top_line);
  1195. X        TextFace(normal);
  1196. X    }
  1197. X
  1198. X    {
  1199. X        FontInfo fi ;
  1200. X        GetFontInfo ( & fi ) ;
  1201. X        aWin -> leading = fi . leading / 2 + fi . descent ;
  1202. X        aWin -> charHeight = fi . ascent + fi . descent + fi . leading ;
  1203. X        aWin -> charWidth = fi . widMax ;
  1204. X    }
  1205. X    SetPt ( & ( theWindows [ i ] . cursor ) , 0 , 0 ) ;
  1206. X
  1207. X    aWin -> kind = type ;
  1208. X    aWin -> keyFunc = winKeyFuncs [ type ] ;
  1209. X    aWin -> clickFunc = winClickFuncs [ type ] ;
  1210. X    aWin -> updateFunc = winUpdateFuncs [ type ] ;
  1211. X    aWin -> cursorFunc = winCursorFuncs [ type ] ;
  1212. X    SetWRefCon ( aWin -> theWindow , ( long ) aWin ) ;
  1213. X
  1214. X    SetRect ( & siz , 0 , 0 , aWin -> charWidth * NUM_COLS ,
  1215. X        aWin -> charHeight * NUM_ROWS ) ;
  1216. X    switch ( type ) {
  1217. X    case NHW_MAP :
  1218. X        OffsetRect ( & siz , 50 , 50 ) ;
  1219. X        break ;
  1220. X    case NHW_BASE :
  1221. X        OffsetRect ( & siz , 20 , 10 ) ;
  1222. X        break ;
  1223. X    default :
  1224. X        siz = aWin -> theWindow -> portRect ;
  1225. X        OffsetRect ( & siz , 30 + rn2 ( 20 ) , 250 + rn2 ( 50 ) ) ;
  1226. X        break ;
  1227. X    }
  1228. X    SizeWindow ( aWin -> theWindow , siz . right - siz . left ,
  1229. X        siz . bottom - siz . top , FALSE ) ;
  1230. X    MoveWindow ( aWin -> theWindow , siz . left , siz . top , FALSE ) ;
  1231. X
  1232. X    if ( type == NHW_MENU || type == NHW_TEXT ) {
  1233. X        Rect r = siz ;
  1234. X        Boolean bool ;
  1235. X        OffsetRect ( & r , - r . left , - r . top ) ;
  1236. X        r . left = r . right - SBARWIDTH ;
  1237. X        r . bottom -= SBARHEIGHT ;
  1238. X        r . top -= 1 ;
  1239. X        r . right += 1 ;
  1240. X        bool = ( r . bottom > r . top + 50 ) ;
  1241. X        aWin -> scrollBar = NewControl ( aWin -> theWindow , & r , (StringPtr)"" ,
  1242. X            bool , 0 , 0 , 0 , 16 , 0L ) ;
  1243. X    }
  1244. X    aWin -> scrollPos = 0 ;
  1245. X    aWin -> cursorDrawn = 0 ;
  1246. X
  1247. X    return i ;
  1248. X}
  1249. X
  1250. X
  1251. Xvoid
  1252. XInitRes ( void )
  1253. X{
  1254. X    Str255 str ;
  1255. X
  1256. X    mBar = GetNewMBar ( 128 ) ;
  1257. X    mustwork(ResError());
  1258. X    SetMenuBar ( mBar ) ;
  1259. X    
  1260. X    appleMenu = GetMHandle ( 128 ) ;
  1261. X    mustwork(ResError());
  1262. X    AppendMenu ( appleMenu , ( ConstStr255Param ) "\002(-" ) ;
  1263. X    AddResMenu ( appleMenu , 'DRVR' ) ;
  1264. X
  1265. X    fileMenu = GetMHandle ( 129 ) ;
  1266. X    mustwork(ResError());
  1267. X    editMenu = GetMHandle ( 130 ) ;
  1268. X    mustwork(ResError());
  1269. X    extendMenu = GetMHandle ( 131 ) ;
  1270. X    mustwork(ResError());
  1271. X    miscMenu = GetMHandle ( 132 ) ;
  1272. X    mustwork(ResError());
  1273. X    commandsMenu = GetMHandle ( 133 ) ;
  1274. X    mustwork ( ResError ( ) ) ;
  1275. X    thingsMenu = GetMHandle ( 134 ) ;
  1276. X    mustwork ( ResError ( ) ) ;
  1277. X
  1278. X    if ( macFlags . help ) {
  1279. X        if ( HMGetHelpMenuHandle ( & helpMenu ) ) {
  1280. X            helpMenu = (MenuHandle) NULL ;
  1281. X        }
  1282. X    }
  1283. X    if ( helpMenu ) {
  1284. X        GetIndString ( str , 128 , 1 ) ;
  1285. X        AppendMenu ( helpMenu , str ) ;
  1286. X    } else AppendMenu ( appleMenu , str ) ;
  1287. X    
  1288. X    DrawMenuBar ( ) ;
  1289. X
  1290. X    return ;
  1291. X}
  1292. X
  1293. X
  1294. Xvoid
  1295. Xmac_init_nhwindows ( void )
  1296. X{
  1297. X    int i ;
  1298. X
  1299. X    InitRes ( ) ;
  1300. X
  1301. X    theWindows = ( NhWindow * ) NewPtr ( NUM_MACWINDOWS *
  1302. X        sizeof ( NhWindow ) ) ;
  1303. X    mustwork(MemError());
  1304. X
  1305. X    for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  1306. X        theWindows [ i ] . theWindow = (WindowPtr) NULL ;
  1307. X    }
  1308. X    for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  1309. X        keyQueue [ i ] = 0 ;
  1310. X    }
  1311. X
  1312. X    BASE_WINDOW = create_nhwindow ( NHW_TEXT ) ;
  1313. X    clear_nhwindow(BASE_WINDOW);
  1314. X    putstr(BASE_WINDOW, 0, "");
  1315. X    putstr(BASE_WINDOW, 0,
  1316. X      "NetHack, Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993");
  1317. X    putstr(BASE_WINDOW, 0,
  1318. X      "         By Stichting Mathematisch Centrum and M. Stephenson.");
  1319. X    putstr(BASE_WINDOW, 0, "         See license for details.");
  1320. X    putstr(BASE_WINDOW, 0, "  ");
  1321. X    display_nhwindow(BASE_WINDOW, FALSE);
  1322. X
  1323. X    flags . window_inited = 1 ;
  1324. X    DimMenuBar ( ) ;
  1325. X}
  1326. X
  1327. X
  1328. Xvoid
  1329. Xmac_nhbell ( void )
  1330. X{
  1331. X    Handle h ;
  1332. X
  1333. X    if ( h = GetNamedResource ( 'snd ' , "\PNetHack Bell" ) ) {
  1334. X
  1335. X        HLock ( h ) ;
  1336. X        SndPlay ( ( SndChannelPtr ) NULL , h , 0 ) ;
  1337. X        ReleaseResource ( h ) ;
  1338. X
  1339. X    } else {
  1340. X
  1341. X        SysBeep ( 30 ) ;
  1342. X    }
  1343. X}
  1344. X
  1345. X
  1346. Xstatic void
  1347. XDrawScrollbar ( NhWindow * aWin , WindowPtr theWindow )
  1348. X{
  1349. X    Rect r2 = theWindow -> portRect ;
  1350. X    Rect r = r2 ;
  1351. X    Boolean vis ;
  1352. X    short val ;
  1353. X
  1354. X    if ( ! aWin -> scrollBar ) {
  1355. X        return ;
  1356. X    }
  1357. X
  1358. X    r2 . left = r2 . right - SBARWIDTH ;
  1359. X    r2 . bottom -= SBARHEIGHT ;
  1360. X    r2 . right += 1 ;
  1361. X    r2 . top -= 1 ;
  1362. X    MoveControl ( aWin -> scrollBar , r2 . left , r2 . top ) ;
  1363. X    SizeControl ( aWin -> scrollBar , r2 . right - r2 . left ,
  1364. X        r2 . bottom - r2 . top ) ;
  1365. X    vis = ( r2 . bottom > r2 . top + 50 ) ;
  1366. X    if ( vis && ! ( * aWin -> scrollBar ) -> contrlVis ) {
  1367. X        ShowControl ( aWin -> scrollBar ) ;
  1368. X    } else if ( ! vis && ( * aWin -> scrollBar ) -> contrlVis ) {
  1369. X        HideControl ( aWin -> scrollBar ) ;
  1370. X    }
  1371. X    if ( aWin -> lin ) {
  1372. X        short max = aWin -> lin - ( r . bottom - r . top ) / aWin ->
  1373. X            charHeight ;
  1374. X        if ( max < 0 ) max = 0 ;
  1375. X        SetCtlMax ( aWin -> scrollBar , max ) ;
  1376. X        if ( max ) HiliteControl ( aWin -> scrollBar , 0 ) ;
  1377. X        else HiliteControl ( aWin -> scrollBar , 255 ) ;
  1378. X    } else {
  1379. X        HiliteControl ( aWin -> scrollBar , 255 ) ;
  1380. X    }
  1381. X    val = GetCtlValue ( aWin -> scrollBar ) ;
  1382. X    if ( val != aWin -> scrollPos ) {
  1383. X        InvalRect ( & ( theWindow -> portRect ) ) ;
  1384. X        aWin -> scrollPos = val ;
  1385. X    }
  1386. X    if ( aWin == asyDSC ) {
  1387. X        asyDSC = (NhWindow *) NULL ;
  1388. X    }
  1389. X}
  1390. X
  1391. X
  1392. Xstatic void
  1393. XInvalScrollBar ( NhWindow * aWin )
  1394. X{
  1395. X    if ( asyDSC && asyDSC != aWin ) {
  1396. X        SetPort ( asyDSC -> theWindow ) ;
  1397. X        DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  1398. X    }
  1399. X    asyDSC = aWin ;
  1400. X}
  1401. X
  1402. X
  1403. Xvoid
  1404. Xmac_clear_nhwindow ( winid win )
  1405. X{
  1406. X    long l ;
  1407. X    register char * start , * stop ;
  1408. X    WindowPtr theWindow ;
  1409. X    NhWindow * aWin = & theWindows [ win ] ;
  1410. X
  1411. X    if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1412. X        error ( "Invalid window %d in clear_nhwindow." , win ) ;
  1413. X        return ;
  1414. X    }
  1415. X    if ( aWin -> clear )
  1416. X        return ;
  1417. X    theWindow = aWin -> theWindow ;
  1418. X    if ( ! theWindow ) {
  1419. X        error ( "Unallocated window %d in clear_nhwindow." , win ) ;
  1420. X        return ;
  1421. X    }
  1422. X    SetPort ( theWindow ) ;
  1423. X    InvalRect ( & ( theWindow -> portRect ) ) ;
  1424. X    switch ( ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ) {
  1425. X    case NHW_MAP :
  1426. X        stop = ( char * ) ( ( MapData * ) ( * aWin -> windowText ) )
  1427. X            -> map ;
  1428. X        start = stop + NUM_COLS * NUM_ROWS ;
  1429. X        while ( start > stop ) * -- start = CHAR_BLANK ;
  1430. X        break ;
  1431. X    case NHW_STATUS :
  1432. X        stop = ( char * ) ( ( StatusData * ) ( * aWin -> windowText ) )
  1433. X            -> map ;
  1434. X        start = stop + NUM_COLS * NUM_STAT_ROWS ;
  1435. X        while ( start > stop ) * -- start = CHAR_BLANK ;
  1436. X        break ;
  1437. X    case NHW_MESSAGE :
  1438. X        l = GetHandleSize ( aWin -> windowText ) ;
  1439. X        if ( l > TEXT_BLOCK * 2 ) {
  1440. X            BlockMove ( * aWin -> windowText + TEXT_BLOCK ,
  1441. X                * aWin -> windowText , l - TEXT_BLOCK ) ;
  1442. X            SetHandleSize ( aWin -> windowText , l - TEXT_BLOCK ) ;
  1443. X            aWin -> windowTextLen -= TEXT_BLOCK ;
  1444. X            if ( aWin -> windowTextLen < 0 ) {
  1445. X                aWin -> windowTextLen = 0 ;
  1446. X            }
  1447. X        }
  1448. X#if 1
  1449. X        aWin->textBase = aWin->windowTextLen;
  1450. X#else
  1451. X        stop = * aWin -> windowText ;
  1452. X        start = stop + aWin -> windowTextLen - 1 ;
  1453. X        while ( -- start > stop ) {
  1454. X            if ( * start == CHAR_CR || * start == CHAR_LF )
  1455. X                break ;
  1456. X        }
  1457. X        if ( start > stop ) {
  1458. X            aWin -> textBase = start - stop + 1 ;
  1459. X        } else {
  1460. X            aWin -> textBase = 0L ;
  1461. X        }
  1462. X#endif
  1463. X        break ;
  1464. X    default :
  1465. X        SetHandleSize ( aWin -> windowText , TEXT_BLOCK ) ;
  1466. X        aWin -> windowTextLen = 0L ;
  1467. X        aWin -> lin = 0 ;
  1468. X        aWin -> wid = 0 ;
  1469. X        aWin -> scrollPos = 0 ;
  1470. X        aWin -> textBase = 0L ;
  1471. X        if ( aWin -> scrollBar ) {
  1472. X            SetCtlMax ( aWin -> scrollBar , 0 ) ;
  1473. X            InvalScrollBar ( aWin ) ;
  1474. X        }
  1475. X        break ;
  1476. X    }
  1477. X    SetPt ( & ( aWin -> cursor ) , 0 , 0 ) ;
  1478. X    aWin -> clear = 1 ;
  1479. X    aWin -> cursorDrawn = 0 ;
  1480. X}
  1481. X
  1482. X
  1483. XBoolean
  1484. XClosingWindowChar(const int c) {
  1485. X    return  c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR ;
  1486. X}
  1487. X
  1488. X
  1489. X#define BTN_IND 2
  1490. X#define BTN_W    40
  1491. X#define BTN_H    (SBARHEIGHT-2)
  1492. X
  1493. Xstatic void
  1494. Xtopl_resp_rect(int resp_idx, Rect *r)
  1495. X{
  1496. X    r->left      = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
  1497. X    r->right  = r->left + BTN_W;
  1498. X    r->bottom = theWindows[WIN_MESSAGE].theWindow->portRect.bottom - 1;
  1499. X    r->top      = r->bottom - BTN_H;
  1500. X}
  1501. X
  1502. X
  1503. XBoolean
  1504. Xin_topl_mode(void)
  1505. X{
  1506. X    return top_line &&
  1507. X           (*top_line)->viewRect.left < theWindows[WIN_MESSAGE].theWindow->portRect.right;
  1508. X}
  1509. X
  1510. X
  1511. Xvoid
  1512. Xenter_topl_mode(char *query)
  1513. X{
  1514. X    if (!top_line || in_topl_mode())
  1515. X        Debugger();
  1516. X    (*top_line)->viewRect.left = 0;
  1517. X
  1518. X    topl_query_len = strlen(query);
  1519. X    (*top_line)->selStart = topl_query_len;
  1520. X    (*top_line)->selEnd      = topl_query_len;
  1521. X    PtrToXHand(query, (*top_line)->hText, topl_query_len);
  1522. X    TECalText(top_line);
  1523. X
  1524. X    display_nhwindow(WIN_MESSAGE, FALSE);
  1525. X    putstr(WIN_MESSAGE, ATR_BOLD, query);
  1526. X}
  1527. X
  1528. X
  1529. Xvoid
  1530. Xleave_topl_mode(char *answer)
  1531. X{
  1532. X    int ans_len = (*top_line)->teLength - topl_query_len;
  1533. X    NhWindow *aWin = theWindows + WIN_MESSAGE;
  1534. X    char tmp[3] = "  ";
  1535. X
  1536. X    if (!in_topl_mode())
  1537. X        Debugger();
  1538. X    (*top_line)->viewRect.left += 10000;
  1539. X
  1540. X    BlockMove(*(*top_line)->hText + topl_query_len, answer, ans_len);
  1541. X    answer[ans_len] = '\0';
  1542. X
  1543. X    if ( aWin -> windowTextLen > 0 &&
  1544. X         ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  1545. X        -- aWin -> windowTextLen ;
  1546. X        -- aWin -> lin ;
  1547. X    }
  1548. X    if (strlen(answer) <= 1) {
  1549. X        if (answer[0]) tmp[0] = answer[0];
  1550. X        putstr(WIN_MESSAGE, ATR_BOLD, tmp);
  1551. X    } else
  1552. X        putstr(WIN_MESSAGE, ATR_BOLD, answer);
  1553. X}
  1554. X
  1555. X/*
  1556. X * TESetSelect flushes out all the pending key strokes.  I hate it.
  1557. X */
  1558. Xstatic void
  1559. Xtopl_set_select(short selStart, short selEnd)
  1560. X{
  1561. X    TEDeactivate(top_line);
  1562. X    (*top_line)->selStart = selStart;
  1563. X    (*top_line)->selEnd      = selEnd;
  1564. X    TEActivate(top_line);
  1565. X}
  1566. X
  1567. X
  1568. Xstatic void
  1569. Xtopl_replace(char *new_ans)
  1570. X{
  1571. X    topl_set_select(topl_query_len, (*top_line)->teLength);
  1572. X    TEDelete(top_line);
  1573. X    TEInsert(new_ans, strlen(new_ans), top_line);
  1574. X}
  1575. X
  1576. X
  1577. XBoolean
  1578. Xtopl_key(unsigned char ch)
  1579. X{
  1580. X    switch (ch) {
  1581. X        case CHAR_ESC:
  1582. X            topl_replace("\x1b");
  1583. X            return false;
  1584. X        case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  1585. X            return false;
  1586. X
  1587. X        case 0x1f & 'P':
  1588. X            nh_doprev_message();
  1589. X            return true;
  1590. X        case '\x1e'/* up arrow */:
  1591. X            topl_set_select(topl_query_len, topl_query_len);
  1592. X            return true;
  1593. X        case CHAR_BS: case '\x1c'/* left arrow */:
  1594. X            if ((*top_line)->selEnd > topl_query_len)
  1595. X                TEKey(ch, top_line);
  1596. X            return true;
  1597. X        default:
  1598. X            TEKey(ch, top_line);
  1599. X            return true;
  1600. X    }
  1601. X}
  1602. X
  1603. X
  1604. XBoolean
  1605. Xtopl_ext_key(unsigned char ch)
  1606. X{
  1607. X    switch (ch) {
  1608. X        case CHAR_ESC:
  1609. X            topl_replace("\x1b");
  1610. X            return false;
  1611. X        case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  1612. X            return false;
  1613. X
  1614. X        case 0x1f & 'P':
  1615. X            nh_doprev_message();
  1616. X            return true;
  1617. X        case CHAR_BS:
  1618. X            topl_replace("");
  1619. X            return true;
  1620. X        default: {
  1621. X            int com_index = -1, oindex = 0;
  1622. X            TEInsert(&ch, 1, top_line);
  1623. X            while(extcmdlist[oindex].ef_txt != NULL){
  1624. X                if(!strncmpi(*(*top_line)->hText + topl_query_len,
  1625. X                             extcmdlist[oindex].ef_txt,
  1626. X                             (*top_line)->teLength - topl_query_len))
  1627. X                    if(com_index == -1) /* No matches yet*/
  1628. X                        com_index = oindex;
  1629. X                    else /* More than 1 match */
  1630. X                        com_index = -2;
  1631. X                oindex++;
  1632. X            }
  1633. X            if(com_index >= 0)
  1634. X                topl_replace(extcmdlist[com_index].ef_txt);
  1635. X            return true;
  1636. X        }
  1637. X    }
  1638. X}
  1639. X
  1640. X
  1641. Xvoid
  1642. Xtopl_flash_resp(int resp_idx)
  1643. X{
  1644. X    long dont_care;
  1645. X    Rect frame;
  1646. X    SetPort(theWindows[WIN_MESSAGE].theWindow);
  1647. X    topl_resp_rect(resp_idx, &frame);
  1648. X    InsetRect(&frame, 1, 1);
  1649. X    InvertRect(&frame);
  1650. X    Delay(GetDblTime() / 2, &dont_care);
  1651. X    InvertRect(&frame);
  1652. X}
  1653. X
  1654. X
  1655. Xvoid
  1656. Xtopl_set_def(int new_def_idx)
  1657. X{
  1658. X    Rect frame;
  1659. X    SetPort(theWindows[WIN_MESSAGE].theWindow);
  1660. X    topl_resp_rect(topl_def_idx, &frame);
  1661. X    InvalRect(&frame);
  1662. X    topl_def_idx = new_def_idx;
  1663. X    topl_resp_rect(new_def_idx, &frame);
  1664. X    InvalRect(&frame);
  1665. X}
  1666. X
  1667. X
  1668. Xvoid
  1669. Xtopl_set_resp(char *resp, char def)
  1670. X{
  1671. X    char *loc;
  1672. X    Rect frame;
  1673. X    int r_len, r_len1;
  1674. X
  1675. X    if (!resp) {
  1676. X        static char any_str[2] = { CHAR_ANY, '\0' };
  1677. X        resp = any_str;
  1678. X        def = CHAR_ANY;
  1679. X    }
  1680. X
  1681. X    r_len1 = strlen(resp);
  1682. X    r_len  = strlen(topl_resp);
  1683. X    if (r_len < r_len1)
  1684. X        r_len = r_len1;
  1685. X    topl_resp_rect(0, &frame);
  1686. X    frame.right = (BTN_IND + BTN_W) * r_len;
  1687. X    InvalRect(&frame);
  1688. X
  1689. X    strcpy(topl_resp, resp);
  1690. X    loc = strchr (resp, def);
  1691. X    topl_def_idx = loc ? loc - resp : -1;
  1692. X}
  1693. X
  1694. X
  1695. Xstatic char
  1696. Xtopl_resp_key(char ch)
  1697. X{
  1698. X    if (strlen(topl_resp) > 0) {
  1699. X        char *loc = strchr(topl_resp, ch);
  1700. X
  1701. X        if (!loc)
  1702. X            if (ch == '\x9'/* tab */) {
  1703. X                topl_set_def(topl_def_idx <= 0 ? strlen(topl_resp)-1 : topl_def_idx-1);
  1704. X                ch = '\0';
  1705. X
  1706. X            } else if (ch == CHAR_ESC) {
  1707. X                loc = strchr(topl_resp, 'q');
  1708. X                if (!loc) {
  1709. X                    loc = strchr(topl_resp, 'n');
  1710. X                    if (!loc && topl_def_idx >= 0)
  1711. X                        loc = topl_resp + topl_def_idx;
  1712. X                }
  1713. X
  1714. X            } else if (ch == (0x1f & 'P')) {
  1715. X                nh_doprev_message();
  1716. X                ch = '\0';
  1717. X
  1718. X            } else if (topl_def_idx >= 0) {
  1719. X                if ( ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF ||
  1720. X                     ch == CHAR_BLANK || topl_resp[topl_def_idx] == CHAR_ANY )
  1721. X                    loc = topl_resp + topl_def_idx;
  1722. X
  1723. X                else if (strchr(topl_resp, '#')) {
  1724. X                    if (digit(ch)) {
  1725. X                        topl_set_def(strchr(topl_resp, '#') - topl_resp);
  1726. X                        TEKey(ch, top_line);
  1727. X                        ch = '\0';
  1728. X
  1729. X                    } else if (topl_resp[topl_def_idx] == '#')
  1730. X                        if (ch == '\x1e'/* up arrow */) {
  1731. X                            topl_set_select(topl_query_len, topl_query_len);
  1732. X                            ch = '\0';
  1733. X                        } else if (ch == '\x1d'/* right arrow */ ||
  1734. X                                   ch == '\x1f'/* down arrow */ ||
  1735. X                                   (ch == CHAR_BS || ch == '\x1c'/* left arrow */) &&
  1736. X                                        (*top_line)->selEnd > topl_query_len) {
  1737. X                            TEKey(ch, top_line);
  1738. X                            ch = '\0';
  1739. X                        }
  1740. X                }
  1741. X            }
  1742. X
  1743. X        if (loc) {
  1744. X            topl_flash_resp(loc - topl_resp);
  1745. X            if (*loc != CHAR_ANY)
  1746. X                ch = *loc;
  1747. X            TEKey(ch, top_line);
  1748. X        }
  1749. X    }
  1750. X
  1751. X    return ch;
  1752. X}
  1753. X
  1754. X
  1755. X/*
  1756. X * display/select/update the window.
  1757. X * If f is true, this window should be "modal" - don't return
  1758. X * until presumed seen.
  1759. X */
  1760. Xvoid
  1761. Xmac_display_nhwindow ( winid win , BOOLEAN_P f )
  1762. X{
  1763. X    WindowPtr theWindow ;
  1764. X    NhWindow * aWin = & theWindows [ win ] ;
  1765. X
  1766. X    if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1767. X        error ( "Invalid window %d in display_nhwindow." , win ) ;
  1768. X        return ;
  1769. X    }
  1770. X    theWindow = aWin -> theWindow ;
  1771. X    if ( ! theWindow ) {
  1772. X        error ( "Unallocated window %d in display_nhwindow." , win ) ;
  1773. X        return ;
  1774. X    }
  1775. X
  1776. X    if ( f && inSelect == WIN_ERR && ( win == BASE_WINDOW || win == WIN_MESSAGE ) ) {
  1777. X        if ( win == WIN_MESSAGE )
  1778. X            topl_set_resp ( NULL , 0 ) ;
  1779. X        /* The following piece of code prevents the "-- More --" prompt to be on a new
  1780. X           line by itself.  I comment it out because the result looks ugly to me. */
  1781. X#ifdef 0
  1782. X        if ( aWin -> windowTextLen > 0 &&
  1783. X             ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  1784. X            -- aWin -> windowTextLen ;
  1785. X            -- aWin -> lin ;
  1786. X        }
  1787. X#endif
  1788. X        putstr ( win , ATR_INVERSE , "-- More --" ) ;
  1789. X    }
  1790. X
  1791. X    if ( ! ( ( WindowPeek ) theWindow ) -> visible ) {
  1792. X        const Rect scr_r   = (*GetGrayRgn())->rgnBBox,
  1793. X                   win_ind = { 20, 2, 3, 3 };
  1794. X        const Point scr_sz = { scr_r.bottom - scr_r.top, scr_r.right - scr_r.left },
  1795. X                    wp_sz  = { theWindow->portRect.bottom - theWindow->portRect.top,
  1796. X                               theWindow->portRect.right  - theWindow->portRect.left };
  1797. X        const short max_h = scr_sz.v - win_ind.top    - win_ind.bottom,
  1798. X                    max_w = scr_sz.h - win_ind.left - win_ind.right;
  1799. X        const char cr = CHAR_CR;
  1800. X
  1801. X        long line_start = 0, line_end;
  1802. X        short w = wp_sz.h,
  1803. X              h = full_screen ? aWin->lin * aWin->charHeight : wp_sz.v;
  1804. X        Point pos = { theWindow->portRect.top, theWindow->portRect.left };
  1805. X        SetPort(theWindow);
  1806. X        LocalToGlobal(&pos);
  1807. X
  1808. X        HLock(aWin->windowText);
  1809. X        while (line_start < aWin->windowTextLen) {
  1810. X            short line_w;
  1811. X            line_end = Munger(aWin->windowText, line_start, &cr, 1, nil, 0);
  1812. X            if (line_end < 0)
  1813. X                line_end = aWin->windowTextLen;
  1814. X            line_w = TextWidth(*aWin->windowText, line_start, line_end - line_start) +
  1815. X                     (SBARWIDTH + 2);
  1816. X            if (w < line_w)
  1817. X                w = line_w;
  1818. X            line_start = line_end + 1;
  1819. X        }
  1820. X        HUnlock(aWin->windowText);
  1821. X
  1822. X        if (h > max_h) h = max_h;
  1823. X        if (w > max_w) w = max_w;
  1824. X        SizeWindow(theWindow, w, h, FALSE);
  1825. X
  1826. X        if ( ! ( ( WindowPeek ) theWindow ) -> visible ) {
  1827. X            short top , left ;
  1828. X            if ( ! RetrieveWinPos ( theWindow , & top , & left ) ) {
  1829. X                if (pos.v + h + win_ind.bottom > scr_r.bottom)
  1830. X                    pos.v = scr_r.bottom - h - win_ind.bottom;
  1831. X                if (pos.h + w + win_ind.right  > scr_r.right)
  1832. X                    pos.h = scr_r.right     - w - win_ind.right;
  1833. X                top = pos . v ;
  1834. X                left = pos . h ;
  1835. X            }
  1836. X            MoveWindow(theWindow, left, top, FALSE);
  1837. X        }
  1838. X
  1839. X        SelectWindow ( theWindow ) ;
  1840. X        ShowWindow ( theWindow ) ;
  1841. X    }
  1842. X
  1843. X    SetPort ( theWindow ) ;
  1844. X    if ( aWin -> scrollBar ) {
  1845. X        InvalScrollBar ( aWin ) ;
  1846. X    }
  1847. X
  1848. X    if ( f && inSelect == WIN_ERR ) {
  1849. X        int ch ;
  1850. X
  1851. X        inSelect = win ;
  1852. X        do {
  1853. X            ch = nhgetch ( ) ;
  1854. X        } while ( ! ClosingWindowChar ( ch ) ) ;
  1855. X        inSelect = WIN_ERR ;
  1856. X
  1857. X        if ( win == WIN_MESSAGE )
  1858. X            topl_set_resp ( "" , '\0' ) ;
  1859. X        else
  1860. X            HideWindow ( theWindow ) ;
  1861. X
  1862. X    } else {
  1863. X        wait_synch ( ) ;
  1864. X    }
  1865. X}
  1866. X
  1867. X
  1868. Xvoid
  1869. Xmac_destroy_nhwindow ( winid win )
  1870. X{
  1871. X    WindowPtr theWindow ;
  1872. X    NhWindow * aWin = & theWindows [ win ] ;
  1873. X    int kind , visible ;
  1874. X
  1875. X    if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1876. X        if ( flags . window_inited )
  1877. X            error ( "Invalid window number %d (Max %d) in destroy_nhwindow." ,
  1878. X                win , NUM_MACWINDOWS ) ;
  1879. X        return ;
  1880. X    }
  1881. X    theWindow = aWin -> theWindow ;
  1882. X    if ( ! theWindow ) {
  1883. X        error ( "Not allocated window number %d in destroy_nhwindow." ,
  1884. X            win ) ;
  1885. X        return ;
  1886. X    }
  1887. X
  1888. X    /*
  1889. X     * Check special windows.
  1890. X     * The base window should never go away.
  1891. X     * The other "standard" windows should not go away
  1892. X     * unless we've exitted nhwindows.
  1893. X     */
  1894. X    if ( win == BASE_WINDOW ) {
  1895. X        return ;
  1896. X    }
  1897. X    if ( win == WIN_INVEN || win == WIN_STATUS || win == WIN_MAP ||
  1898. X        win == WIN_MESSAGE ) {
  1899. X        if ( flags . window_inited ) {
  1900. X            if ( flags . tombstone && killer ) {
  1901. X                /* Prepare for the coming of the tombstone window. */
  1902. X                mono_font ( ) ;
  1903. X                full_screen = TRUE ;
  1904. X            }
  1905. X            return ;
  1906. X        }
  1907. X    }
  1908. X
  1909. X    kind = ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ;
  1910. X    visible = ( ( WindowPeek ) theWindow ) -> visible ;
  1911. X
  1912. X    if ( ! visible || ( kind != NHW_MENU && kind != NHW_TEXT ) ) {
  1913. X        DisposeWindow ( theWindow ) ;
  1914. X        if ( aWin -> windowText ) {
  1915. X            DisposHandle ( aWin -> windowText ) ;
  1916. X        }
  1917. X        aWin -> theWindow = (WindowPtr) NULL ;
  1918. X        aWin -> windowText = (Handle) NULL ;
  1919. X    }
  1920. X}
  1921. X
  1922. X
  1923. Xvoid
  1924. Xmac_number_pad ( int pad )
  1925. X{
  1926. X    macPad = pad ;
  1927. X}
  1928. X
  1929. X
  1930. Xvoid
  1931. Xtrans_num_keys(EventRecord *theEvent)
  1932. X{
  1933. X    if (macPad) {
  1934. X        Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
  1935. X        if (h) {
  1936. X            short *ab = (short *)*h;
  1937. X            int i = ab[0];
  1938. X            while (i) {
  1939. X                if ((theEvent->message & keyCodeMask) == (ab[i] & keyCodeMask)) {
  1940. X                    theEvent->message = ab[i];
  1941. X                    break;
  1942. X                }
  1943. X                --i;
  1944. X            }
  1945. X        }
  1946. X    }
  1947. X}
  1948. X
  1949. X
  1950. X/*
  1951. X * Note; theWindow may very well be NULL here, since keyDown may call
  1952. X * it when theres no window !!!
  1953. X */
  1954. Xvoid
  1955. XGeneralKey ( EventRecord * theEvent , WindowPtr theWindow )
  1956. X{
  1957. X    int i ;
  1958. X
  1959. X    trans_num_keys ( theEvent ) ;
  1960. X
  1961. X    addToKeyQueue ( topl_resp_key ( theEvent -> message & 0xff ) , 1 ) ;
  1962. X}
  1963. X
  1964. X
  1965. Xstatic void
  1966. XmacKeyNull ( EventRecord * theEvent , WindowPtr theWindow )
  1967. X{
  1968. X    GeneralKey ( theEvent , theWindow ) ;
  1969. X}
  1970. X
  1971. X
  1972. Xstatic void
  1973. XmacKeyMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1974. X{
  1975. X    GeneralKey ( theEvent , theWindow ) ;
  1976. X}
  1977. X
  1978. X
  1979. Xstatic void
  1980. XmacKeyStatus ( EventRecord * theEvent , WindowPtr theWindow )
  1981. X{
  1982. X    GeneralKey ( theEvent , theWindow ) ;
  1983. X}
  1984. X
  1985. X
  1986. Xstatic void
  1987. XmacKeyMap ( EventRecord * theEvent , WindowPtr theWindow )
  1988. X{
  1989. X    GeneralKey ( theEvent , theWindow ) ;
  1990. X}
  1991. X
  1992. X
  1993. Xstatic void
  1994. XmacKeyMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1995. X{
  1996. X    if ( filter_scroll_key ( theEvent -> message & 0xff ,
  1997. X        ( NhWindow * ) GetWRefCon ( theWindow ) ) ) {
  1998. X        GeneralKey ( theEvent , theWindow ) ;
  1999. X    }
  2000. X}
  2001. X
  2002. X
  2003. Xstatic void
  2004. XmacKeyText ( EventRecord * theEvent , WindowPtr theWindow )
  2005. X{
  2006. X    char c = filter_scroll_key ( theEvent -> message & 0xff ,
  2007. X                                 ( NhWindow * ) GetWRefCon ( theWindow ) ) ;
  2008. X    if ( c )
  2009. X        if ( inSelect == WIN_ERR && ClosingWindowChar ( c ) ) {
  2010. X            HideWindow ( theWindow ) ;
  2011. X            destroy_nhwindow ( ( NhWindow * ) GetWRefCon ( theWindow ) - theWindows ) ;
  2012. X        } else {
  2013. X            GeneralKey ( theEvent , theWindow ) ;
  2014. X        }
  2015. X}
  2016. X
  2017. X
  2018. Xstatic void
  2019. XmacClickNull ( EventRecord * theEvent , WindowPtr theWindow )
  2020. X{
  2021. X    if ( ! theEvent || ! theWindow ) {
  2022. X        Debugger ( ) ;
  2023. X    }
  2024. X}
  2025. X
  2026. X
  2027. Xstatic void
  2028. XmacClickMessage ( EventRecord * theEvent , WindowPtr theWindow )
  2029. X{
  2030. X    int r_idx = 0;
  2031. X    Point mouse = theEvent->where;
  2032. X    GlobalToLocal(&mouse);
  2033. X    while (topl_resp[r_idx]) {
  2034. X        Rect frame;
  2035. X        topl_resp_rect(r_idx, &frame);
  2036. X        InsetRect(&frame, 1, 1);
  2037. X        if (PtInRect(mouse, &frame)) {
  2038. X
  2039. X            Boolean in_btn = true;
  2040. X            InvertRect(&frame);
  2041. X            while (WaitMouseUp()) {
  2042. X                SystemTask();
  2043. X                GetMouse(&mouse);
  2044. X                if (PtInRect(mouse, &frame) != in_btn) {
  2045. X                    in_btn = !in_btn;
  2046. X                    InvertRect(&frame);
  2047. X                }
  2048. X            }
  2049. X            if (in_btn) {
  2050. X                InvertRect(&frame);
  2051. X                addToKeyQueue ( topl_resp [ r_idx ] , 1 ) ;
  2052. X            }
  2053. X            return;
  2054. X
  2055. X        }
  2056. X        ++r_idx;
  2057. X    }
  2058. X}
  2059. X
  2060. X
  2061. Xstatic void
  2062. XmacClickStatus ( EventRecord * theEvent , WindowPtr theWindow )
  2063. X{
  2064. X    if ( ! theEvent || ! theWindow ) {
  2065. X        Debugger ( ) ;
  2066. X    }
  2067. X}
  2068. X
  2069. X
  2070. Xstatic void
  2071. XmacClickMap ( EventRecord * theEvent , WindowPtr theWindow )
  2072. X{
  2073. X    if ( ! theEvent || ! theWindow ) {
  2074. X        Debugger ( ) ;
  2075. X    }
  2076. X    {
  2077. X        NhWindow * nhw = ( NhWindow * ) GetWRefCon ( theWindow ) ;
  2078. X        Point where ;
  2079. X        short posX , posY ;
  2080. X        short sector ;
  2081. X        char theDirectionChar [ 18 ] = {
  2082. X            ' ' , 'k' , 'u' , 'l' , 'n' , 'j' , 'b' , 'h' , 'y' ,
  2083. X            'o' , 'K' , 'U' , 'L' , 'N' , 'J' , 'B' , 'H' , 'Y' ,
  2084. X        } ;
  2085. X
  2086. X        where = theEvent -> where ;
  2087. X        GlobalToLocal ( & where ) ;
  2088. X        posX = where . h / nhw -> charWidth ;
  2089. X        posY = where . v / nhw -> charHeight ;
  2090. X
  2091. X    /* 0 is ON, 1 is top, then clockwise */
  2092. X        sector = clickSector ( u . ux , u . uy , posX , posY ) ;
  2093. X        if ( theEvent -> modifiers & shiftKey ) {
  2094. X            sector += 9 ;
  2095. X        }
  2096. X        addToKeyQueue ( theDirectionChar [ sector ] , 0 ) ;
  2097. X
  2098. X        gClickedToMove = 1 ;
  2099. X    }
  2100. X}
  2101. X
  2102. Xstatic amtToScroll = 0 ;
  2103. Xstatic NhWindow * winToScroll = (NhWindow *) NULL ;
  2104. X
  2105. Xstatic pascal void
  2106. XUp ( ControlHandle theBar , short part )
  2107. X{
  2108. X    EventRecord fake ;
  2109. X    short now = GetCtlValue ( theBar ) ;
  2110. X    short min = GetCtlMin ( theBar ) ;
  2111. X    Rect r ;
  2112. X    RgnHandle rgn = NewRgn ( ) ;
  2113. X
  2114. X    if ( ! part ) {
  2115. X        return ;
  2116. X    }
  2117. X
  2118. X    if ( now - min < amtToScroll ) {
  2119. X        amtToScroll = now - min ;
  2120. X    }
  2121. X    if ( ! amtToScroll ) {
  2122. X        return ;
  2123. X    }
  2124. X    SetCtlValue ( theBar , now - amtToScroll ) ;
  2125. X    winToScroll -> scrollPos = now - amtToScroll ;
  2126. X    r = winToScroll -> theWindow -> portRect ;
  2127. X    r . right -= 15 ;
  2128. X    ScrollRect ( & r , 0 , amtToScroll * winToScroll -> charHeight , rgn ) ;
  2129. X    if ( rgn ) {
  2130. X        InvalRgn ( rgn ) ;
  2131. X        r . top = r . bottom - 16 ;
  2132. X        r . left = r . right ;
  2133. X        r . right += 15 ;
  2134. X        InvalRect ( & r ) ;
  2135. X        BeginUpdate ( winToScroll -> theWindow ) ;
  2136. X    }
  2137. X    winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  2138. X    if ( rgn ) {
  2139. X        EndUpdate ( winToScroll -> theWindow ) ;
  2140. X        DisposeRgn ( rgn ) ;
  2141. X    }
  2142. X}
  2143. X
  2144. X
  2145. Xstatic pascal void
  2146. XDown ( ControlHandle theBar , short part )
  2147. X{
  2148. X    EventRecord fake ;
  2149. X    short now = GetCtlValue ( theBar ) ;
  2150. X    short max = GetCtlMax ( theBar ) ;
  2151. X    Rect r ;
  2152. X    RgnHandle rgn = NewRgn ( ) ;
  2153. X
  2154. X    if ( ! part ) {
  2155. X        return ;
  2156. X    }
  2157. X
  2158. X    if ( max - now < amtToScroll ) {
  2159. X        amtToScroll = max - now ;
  2160. X    }
  2161. X    if ( ! amtToScroll ) {
  2162. X        return ;
  2163. X    }
  2164. X    SetCtlValue ( theBar , now + amtToScroll ) ;
  2165. X    winToScroll -> scrollPos = now + amtToScroll ;
  2166. X    r = winToScroll -> theWindow -> portRect ;
  2167. X    r . right -= 15 ;
  2168. X    ScrollRect ( & r , 0 , - amtToScroll * winToScroll -> charHeight , rgn ) ; 
  2169. X    if ( rgn ) {
  2170. X        InvalRgn ( rgn ) ;
  2171. X        r . top = r . bottom - 16 ;
  2172. X        r . left = r . right ;
  2173. X        r . right += 15 ;
  2174. X        InvalRect ( & r ) ;
  2175. X        BeginUpdate ( winToScroll -> theWindow ) ;
  2176. X    }
  2177. X    winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  2178. X    if ( rgn ) {
  2179. X        EndUpdate ( winToScroll -> theWindow ) ;
  2180. X        DisposeRgn ( rgn ) ;
  2181. X    }
  2182. X}
  2183. X
  2184. X
  2185. Xstatic void
  2186. XDoScrollBar ( Point p , short code , ControlHandle theBar , NhWindow * aWin ,
  2187. X    WindowPtr theWindow )
  2188. X{
  2189. X    pascal void ( * func ) ( ControlHandle , short ) = 0 ;
  2190. X
  2191. X    winToScroll = aWin ;
  2192. X    switch ( code ) {
  2193. X    case inUpButton :
  2194. X        func = Up ;
  2195. X        amtToScroll = 1 ;
  2196. X        break ;
  2197. X    case inDownButton :
  2198. X        func = Down ;
  2199. X        amtToScroll = 1 ;
  2200. X        break ;
  2201. X    case inPageUp :
  2202. X        func = Up ;
  2203. X        amtToScroll = ( theWindow -> portRect . bottom - theWindow ->
  2204. X            portRect . top ) / aWin -> charHeight ;
  2205. X        break ;
  2206. X    case inPageDown :
  2207. X        func = Down ;
  2208. X        amtToScroll = ( theWindow -> portRect . bottom - theWindow ->
  2209. X            portRect . top ) / aWin -> charHeight ;
  2210. X        break ;
  2211. X    default :
  2212. X        break ;
  2213. X    }
  2214. X
  2215. X    ( void ) TrackControl ( theBar , p , ( ProcPtr ) func );
  2216. X    if ( ! func ) {
  2217. X        if ( aWin -> scrollPos != GetCtlValue ( theBar ) ) {
  2218. X            aWin -> scrollPos = GetCtlValue ( theBar ) ;
  2219. X            InvalRect ( & ( theWindow -> portRect ) ) ;
  2220. X        }
  2221. X    }
  2222. X}
  2223. X
  2224. X
  2225. Xint
  2226. Xfilter_scroll_key(const int ch, NhWindow *aWin)
  2227. X{
  2228. X    if (aWin->scrollBar && GetCtlValue(aWin->scrollBar) < GetCtlMax(aWin->scrollBar)) {
  2229. X        winToScroll = aWin;
  2230. X        SetPort(aWin->theWindow);
  2231. X        if (ch == CHAR_BLANK) {
  2232. X            amtToScroll = ( aWin->theWindow->portRect.bottom
  2233. X                          - aWin->theWindow->portRect.top ) / aWin->charHeight;
  2234. X            Down(aWin->scrollBar, inPageDown);
  2235. X            return 0;
  2236. X        }
  2237. X        if (ch == CHAR_CR || ch == CHAR_LF) {
  2238. X            amtToScroll = 1;
  2239. X            Down(aWin->scrollBar, inDownButton);
  2240. X            return 0;
  2241. X        }
  2242. X    }
  2243. X    return ch;
  2244. X}
  2245. X
  2246. X
  2247. END_OF_FILE
  2248. if test 39944 -ne `wc -c <'sys/mac/macwin.c1'`; then
  2249.     echo shar: \"'sys/mac/macwin.c1'\" unpacked with wrong size!
  2250. fi
  2251. # end of 'sys/mac/macwin.c1'
  2252. fi
  2253. echo shar: End of archive 37 \(of 108\).
  2254. cp /dev/null ark37isdone
  2255. MISSING=""
  2256. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2257. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2258. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2259. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2260. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2261. 101 102 103 104 105 106 107 108 ; do
  2262.     if test ! -f ark${I}isdone ; then
  2263.     MISSING="${MISSING} ${I}"
  2264.     fi
  2265. done
  2266. if test "${MISSING}" = "" ; then
  2267.     echo You have unpacked all 108 archives.
  2268.     echo "Now execute 'rebuild.sh'"
  2269.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2270. else
  2271.     echo You still need to unpack the following archives:
  2272.     echo "        " ${MISSING}
  2273. fi
  2274. ##  End of shell archive.
  2275. exit 0
  2276.