home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume16 / nethack31 / patch2w < prev    next >
Internet Message Format  |  1993-06-16  |  58KB

  1. Path: uunet!gatech!news-feed-1.peachnet.edu!emory!ogicse!news.tek.com!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v17i098:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Patch2w/33
  5. Message-ID: <1v8is9$j65@ying.cna.tek.com>
  6. Date: 11 Jun 93 00:16:09 GMT
  7. Article-I.D.: ying.1v8is9$j65
  8. Organization: Tektronix, Inc, Redmond, OR, USA
  9. Lines: 2196
  10. Approved: billr@saab.CNA.TEK.COM
  11. NNTP-Posting-Host: saab.cna.tek.com
  12. Xref: uunet comp.sources.games:1761
  13.  
  14. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  15. Posting-number: Volume 17, Issue 98
  16. Archive-name: nethack31/Patch2w
  17. Patch-To: nethack31: Volume 16, Issue 1-116
  18. Environment: Amiga, Atari, Mac, MS-DOS, Windows-NT, OS2, Unix, VMS, X11
  19.  
  20.  
  21.  
  22. #! /bin/sh
  23. # This is a shell archive.  Remove anything before this line, then unpack
  24. # it by saving it into a file and typing "sh file".  To overwrite existing
  25. # files, type "sh file -c".  You can also feed this as standard input via
  26. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  27. # will see the following message at the end:
  28. #        "End of archive 23 (of 33)."
  29. # Contents:  src/ball.c sys/mac/mactty.c
  30. # Wrapped by billr@saab on Thu Jun 10 16:55:06 1993
  31. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  32. if test -f 'src/ball.c' -a "${1}" != "-c" ; then 
  33.   echo shar: Renaming existing file \"'src/ball.c'\" to \"'src/ball.c.orig'\"
  34.   mv -f 'src/ball.c' 'src/ball.c.orig'
  35. fi
  36. echo shar: Extracting \"'src/ball.c'\" \(16324 characters\)
  37. sed "s/^X//" >'src/ball.c' <<'END_OF_FILE'
  38. X/*    SCCS Id: @(#)ball.c    3.1    93/05/15    */
  39. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  40. X/* NetHack may be freely redistributed.  See license for details. */
  41. X
  42. X/* Ball & Chain =============================================================*/
  43. X
  44. X#include "hack.h"
  45. X
  46. Xstatic int NDECL(bc_order);
  47. Xstatic void NDECL(litter);
  48. X
  49. Xvoid
  50. Xballfall()
  51. X{
  52. X    boolean gets_hit;
  53. X
  54. X    gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy)) &&
  55. X            ((uwep == uball)? FALSE : (boolean)rn2(5)));
  56. X    if (carried(uball)) {
  57. X        pline("Startled, you drop the iron ball.");
  58. X        if (uwep == uball)
  59. X            setuwep((struct obj *)0);
  60. X        if (uwep != uball)
  61. X            freeinv(uball);
  62. X    }
  63. X    if(gets_hit){
  64. X        int dmg = rn1(7,25);
  65. X        pline("The iron ball falls on your %s.",
  66. X            body_part(HEAD));
  67. X        if (uarmh)
  68. X            if(is_metallic(uarmh)) {
  69. X            pline("Fortunately, you are wearing a hard helmet.");
  70. X            dmg = 3;
  71. X            } else if (flags.verbose)
  72. X            Your("%s does not protect you.", xname(uarmh));
  73. X        losehp(dmg, "Crunched in the head by an iron ball",
  74. X            NO_KILLER_PREFIX);
  75. X    }
  76. X}
  77. X
  78. X/*
  79. X *  To make this work, we have to mess with the hero's mind.  The rules for
  80. X *  ball&chain are:
  81. X *
  82. X *    1. If the hero can see them, fine.
  83. X *    2. If the hero can't see either, it isn't seen.
  84. X *    3. If either is felt it is seen.
  85. X *    4. If either is felt and moved, it disappears.
  86. X *
  87. X *  If the hero can see, then when a move is done, the ball and chain are
  88. X *  first picked up, the positions under them are corrected, then they
  89. X *  are moved after the hero moves.  Not too bad.
  90. X *
  91. X *  If the hero is blind, then she can "feel" the ball and/or chain at any
  92. X *  time.  However, when the hero moves, the felt ball and/or chain become
  93. X *  unfelt and whatever was felt "under" the ball&chain appears.  Pretty
  94. X *  nifty, but it requires that the ball&chain "remember" what was under
  95. X *  them --- i.e. they pick-up glyphs when they are felt and drop them when
  96. X *  moved (and felt).  When swallowed, the ball&chain are pulled completely
  97. X *  off of the dungeon, but are still on the object chain.  They are placed
  98. X *  under the hero when she is expelled.
  99. X */
  100. X
  101. X/*
  102. X * from you.h
  103. X *    int u.bglyph        glyph under the ball
  104. X *    int u.cglyph        glyph under the chain
  105. X *    int u.bc_felt        mask for ball/chain being felt
  106. X *    #define BC_BALL  0x01    bit mask in u.bc_felt for ball
  107. X *    #define BC_CHAIN 0x02    bit mask in u.bc_felt for chain
  108. X *    int u.bc_order        ball & chain order
  109. X *
  110. X * u.bc_felt is also manipulated in display.c and read.c, the others only
  111. X * in this file.  None of these variables are valid unless the player is
  112. X * Blind.
  113. X */
  114. X
  115. X/* values for u.bc_order */
  116. X#define BCPOS_DIFFER    0    /* ball & chain at different positions */
  117. X#define BCPOS_CHAIN    1    /* chain on top of ball */
  118. X#define BCPOS_BALL    2    /* ball on top of chain */
  119. X
  120. X
  121. X
  122. X/*
  123. X *  Place the ball & chain under the hero.  Make sure that the ball & chain
  124. X *  variables are set (actually only needed when blind, but what the heck).
  125. X *  It is assumed that when this is called, the ball and chain are NOT
  126. X *  attached to the object list.
  127. X *
  128. X *  Should not be called while swallowed.
  129. X */
  130. Xvoid
  131. Xplacebc()
  132. X{
  133. X    if (!uchain || !uball) {
  134. X    impossible("Where are your ball and chain?");
  135. X    return;
  136. X    }
  137. X
  138. X    (void) flooreffects(uchain, u.ux, u.uy, "");    /* chain might rust */
  139. X    uchain->nobj = fobj;        /* put chain on object list */
  140. X    fobj = uchain;
  141. X
  142. X    if (carried(uball))        /* the ball is carried */
  143. X    u.bc_order = BCPOS_DIFFER;
  144. X    else {
  145. X    /* ball might rust -- already checked when carried */
  146. X    (void) flooreffects(uball, u.ux, u.uy, "");
  147. X    uball->nobj = fobj;        /* put ball on object list */
  148. X    fobj = uball;
  149. X
  150. X    place_object(uball, u.ux, u.uy);
  151. X    u.bc_order = BCPOS_CHAIN;
  152. X    }
  153. X
  154. X    place_object(uchain, u.ux, u.uy);
  155. X
  156. X    u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph;   /* pick up glyph */
  157. X
  158. X    newsym(u.ux,u.uy);
  159. X}
  160. X
  161. Xvoid
  162. Xunplacebc()
  163. X{
  164. X    if (u.uswallow) return;    /* ball&chain not placed while swallowed */
  165. X
  166. X    if (!carried(uball)) {
  167. X    freeobj(uball);
  168. X    if (Blind && (u.bc_felt & BC_BALL))        /* drop glyph */
  169. X        levl[uball->ox][uball->oy].glyph = u.bglyph;
  170. X
  171. X    newsym(uball->ox,uball->oy);
  172. X    }
  173. X    freeobj(uchain);
  174. X    if (Blind && (u.bc_felt & BC_CHAIN))        /* drop glyph */
  175. X    levl[uchain->ox][uchain->oy].glyph = u.cglyph;
  176. X
  177. X    newsym(uchain->ox,uchain->oy);
  178. X    u.bc_felt = 0;                    /* feel nothing */
  179. X}
  180. X
  181. X
  182. X/*
  183. X *  Return the stacking of the hero's ball & chain.  This assumes that the
  184. X *  hero is being punished.
  185. X */
  186. Xstatic int
  187. Xbc_order()
  188. X{
  189. X    struct obj *obj;
  190. X
  191. X    if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)
  192. X        || u.uswallow)
  193. X    return BCPOS_DIFFER;
  194. X
  195. X    for (obj = level.objects[uball->ox][uball->oy]; obj; obj = obj->nexthere) {
  196. X    if (obj == uchain) return BCPOS_CHAIN;
  197. X    if (obj == uball) return BCPOS_BALL;
  198. X    }
  199. X    impossible("bc_order:  ball&chain not in same location!");
  200. X    return BCPOS_DIFFER;
  201. X}
  202. X
  203. X/*
  204. X *  set_bc()
  205. X *
  206. X *  The hero is either about to go blind or already blind and just punished.
  207. X *  Set up the ball and chain variables so that the ball and chain are "felt".
  208. X */
  209. Xvoid
  210. Xset_bc(already_blind)
  211. Xint already_blind;
  212. X{
  213. X    int ball_on_floor = !carried(uball);
  214. X
  215. X    u.bc_order = bc_order();                /* get the order */
  216. X    u.bc_felt = ball_on_floor ? BC_BALL|BC_CHAIN : BC_CHAIN;    /* felt */
  217. X
  218. X    if (already_blind || u.uswallow) {
  219. X    u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;
  220. X    return;
  221. X    }
  222. X
  223. X    /*
  224. X     *  Since we can still see, remove the ball&chain and get the glyph that
  225. X     *  would be beneath them.  Then put the ball&chain back.  This is pretty
  226. X     *  disgusting, but it will work.
  227. X     */
  228. X    remove_object(uchain);
  229. X    if (ball_on_floor) remove_object(uball);
  230. X
  231. X    newsym(uchain->ox, uchain->oy);
  232. X    u.cglyph = levl[uchain->ox][uchain->oy].glyph;
  233. X
  234. X    if (u.bc_order == BCPOS_DIFFER) {        /* different locations */
  235. X    place_object(uchain, uchain->ox, uchain->oy);
  236. X    newsym(uchain->ox, uchain->oy);
  237. X    if (ball_on_floor) {
  238. X        newsym(uball->ox, uball->oy);        /* see under ball */
  239. X        u.bglyph = levl[uball->ox][uball->oy].glyph;
  240. X        place_object(uball,  uball->ox, uball->oy);
  241. X        newsym(uball->ox, uball->oy);        /* restore ball */
  242. X    }
  243. X    } else {
  244. X    u.bglyph = u.cglyph;
  245. X    if (u.bc_order == BCPOS_CHAIN) {
  246. X        place_object(uball,  uball->ox, uball->oy);
  247. X        place_object(uchain, uchain->ox, uchain->oy);
  248. X    } else {
  249. X        place_object(uchain, uchain->ox, uchain->oy);
  250. X        place_object(uball,  uball->ox, uball->oy);
  251. X    }
  252. X    newsym(uball->ox, uball->oy);
  253. X    }
  254. X}
  255. X
  256. X
  257. X/*
  258. X *  move_bc()
  259. X *
  260. X *  Move the ball and chain.  This is called twice for every move.  The first
  261. X *  time to pick up the ball and chain before the move, the second time to
  262. X *  place the ball and chain after the move.  If the ball is carried, this
  263. X *  function should never have BC_BALL as part of its control.
  264. X *
  265. X *  Should not be called while swallowed.
  266. X */
  267. Xvoid
  268. Xmove_bc(before, control, ballx, bally, chainx, chainy)
  269. Xint   before, control;
  270. Xxchar ballx, bally, chainx, chainy;    /* only matter !before */
  271. X{
  272. X    if (Blind) {
  273. X    /*
  274. X     *  The hero is blind.  Time to work hard.  The ball and chain that
  275. X     *  are attached to the hero are very special.  The hero knows that
  276. X     *  they are attached, so when they move, the hero knows that they
  277. X     *  aren't at the last position remembered.  This is complicated
  278. X     *  by the fact that the hero can "feel" the surrounding locations
  279. X     *  at any time, hence, making one or both of them show up again.
  280. X     *  So, we have to keep track of which is felt at any one time and
  281. X     *  act accordingly.
  282. X     */
  283. X    if (!before) {
  284. X        if ((control & BC_CHAIN) && (control & BC_BALL)) {
  285. X        /*
  286. X         *  Both ball and chain moved.  If felt, drop glyph.
  287. X         */
  288. X        if (u.bc_felt & BC_BALL)
  289. X            levl[uball->ox][uball->oy].glyph = u.bglyph;
  290. X        if (u.bc_felt & BC_CHAIN)
  291. X            levl[uchain->ox][uchain->oy].glyph = u.cglyph;
  292. X        u.bc_felt = 0;
  293. X
  294. X        /* Pick up glyph at new location. */
  295. X        u.bglyph = levl[ballx][bally].glyph;
  296. X        u.cglyph = levl[chainx][chainy].glyph;
  297. X
  298. X        movobj(uball,ballx,bally);
  299. X        movobj(uchain,chainx,chainy);
  300. X        } else if (control & BC_BALL) {
  301. X        if (u.bc_felt & BC_BALL) {
  302. X            if (u.bc_order == BCPOS_DIFFER) {    /* ball by itself */
  303. X            levl[uball->ox][uball->oy].glyph = u.bglyph;
  304. X            } else if (u.bc_order == BCPOS_BALL) {
  305. X            if (u.bc_felt & BC_CHAIN) {   /* know chain is there */
  306. X                map_object(uchain, 0);
  307. X            } else {
  308. X                levl[uball->ox][uball->oy].glyph = u.bglyph;
  309. X            }
  310. X            }
  311. X            u.bc_felt &= ~BC_BALL;    /* no longer feel the ball */
  312. X        }
  313. X
  314. X        /* Pick up glyph at new position. */
  315. X        u.bglyph = (ballx != chainx || bally != chainy) ?
  316. X                    levl[ballx][bally].glyph : u.cglyph;
  317. X
  318. X        movobj(uball,ballx,bally);
  319. X        } else if (control & BC_CHAIN) {
  320. X        if (u.bc_felt & BC_CHAIN) {
  321. X            if (u.bc_order == BCPOS_DIFFER) {
  322. X            levl[uchain->ox][uchain->oy].glyph = u.cglyph;
  323. X            } else if (u.bc_order == BCPOS_CHAIN) {
  324. X            if (u.bc_felt & BC_BALL) {
  325. X                map_object(uball, 0);
  326. X            } else {
  327. X                levl[uchain->ox][uchain->oy].glyph = u.cglyph;
  328. X            }
  329. X            }
  330. X            u.bc_felt &= ~BC_CHAIN;
  331. X        }
  332. X        /* Pick up glyph at new position. */
  333. X        u.cglyph = (ballx != chainx || bally != chainy) ?
  334. X                    levl[chainx][chainy].glyph : u.bglyph;
  335. X
  336. X        movobj(uchain,chainx,chainy);
  337. X        }
  338. X
  339. X        u.bc_order = bc_order();    /* reset the order */
  340. X    }
  341. X
  342. X    } else {
  343. X    /*
  344. X     *  The hero is not blind.  To make this work correctly, we need to
  345. X     *  pick up the ball and chain before the hero moves, then put them
  346. X     *  in their new positions after the hero moves.
  347. X     */
  348. X    if (before) {
  349. X        if (!control) {
  350. X        /*
  351. X         * Neither ball nor chain is moving, so remember which was
  352. X         * on top until !before.  Use the variable u.bc_order
  353. X         * since it is only valid when blind.
  354. X         */
  355. X        u.bc_order = bc_order();
  356. X        }
  357. X
  358. X        remove_object(uchain);
  359. X        newsym(uchain->ox, uchain->oy);
  360. X        if (!carried(uball)) {
  361. X        remove_object(uball);
  362. X        newsym(uball->ox,  uball->oy);
  363. X        }
  364. X    } else {
  365. X        int on_floor = !carried(uball);
  366. X
  367. X        if ((control & BC_CHAIN) ||
  368. X                (!control && u.bc_order == BCPOS_CHAIN)) {
  369. X        /* If the chain moved or nothing moved & chain on top. */
  370. X        if (on_floor) place_object(uball,  ballx, bally);
  371. X        place_object(uchain, chainx, chainy);    /* chain on top */
  372. X        } else {
  373. X        place_object(uchain, chainx, chainy);
  374. X        if (on_floor) place_object(uball,  ballx, bally);
  375. X                                /* ball on top */
  376. X        }
  377. X        newsym(chainx, chainy);
  378. X        if (on_floor) newsym(ballx, bally);
  379. X    }
  380. X    }
  381. X}
  382. X
  383. X/* return TRUE if ball could be dragged
  384. X *
  385. X *  Should not be called while swallowed.
  386. X */
  387. Xboolean
  388. Xdrag_ball(x, y, bc_control, ballx, bally, chainx, chainy)
  389. Xxchar x, y;
  390. Xint *bc_control;
  391. Xxchar *ballx, *bally, *chainx, *chainy;
  392. X{
  393. X    struct trap *t = (struct trap *)0;
  394. X
  395. X    *ballx  = uball->ox;
  396. X    *bally  = uball->oy;
  397. X    *chainx = uchain->ox;
  398. X    *chainy = uchain->oy;
  399. X    *bc_control = 0;
  400. X
  401. X    if (dist2(x, y, uchain->ox, uchain->oy) <= 2) {    /* nothing moved */
  402. X        move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
  403. X        return TRUE;
  404. X    }
  405. X
  406. X    if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 ||
  407. X        (uball->ox == uchain->ox && uball->oy == uchain->oy)) {
  408. X        *bc_control = BC_CHAIN;
  409. X        move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
  410. X        *chainx = u.ux;
  411. X        *chainy = u.uy;
  412. X        return TRUE;
  413. X    }
  414. X
  415. X    if (near_capacity() > SLT_ENCUMBER) {
  416. X        You("cannot %sdrag the heavy iron ball.",
  417. X                invent ? "carry all that and also " : "");
  418. X        nomul(0);
  419. X        return FALSE;
  420. X    }
  421. X
  422. X    if ((is_pool(uchain->ox, uchain->oy) &&
  423. X            /* water not mere continuation of previous water */
  424. X            (levl[uchain->ox][uchain->oy].typ == POOL ||
  425. X             !is_pool(uball->ox, uball->oy) ||
  426. X             levl[uball->ox][uball->oy].typ == POOL))
  427. X        || ((t = t_at(uchain->ox, uchain->oy)) &&
  428. X            (t->ttyp == PIT ||
  429. X             t->ttyp == SPIKED_PIT ||
  430. X             t->ttyp == TRAPDOOR)) ) {
  431. X
  432. X        if (Levitation) {
  433. X        You("feel a tug from the iron ball.");
  434. X        if (t) t->tseen = 1;
  435. X        } else {
  436. X        struct monst *victim;
  437. X
  438. X        You("are jerked back by the iron ball!");
  439. X        if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
  440. X            int tmp;
  441. X
  442. X            tmp = -2 + Luck + find_mac(victim);
  443. X
  444. X            if (victim->msleep) {
  445. X            victim->msleep = 0;
  446. X            tmp += 2;
  447. X            }
  448. X            if (!victim->mcanmove) {
  449. X            tmp += 4;
  450. X            if (!rn2(10)) {
  451. X                victim->mcanmove = 1;
  452. X                victim->mfrozen = 0;
  453. X            }
  454. X            }
  455. X            if (tmp >= rnd(20))
  456. X            (void) hmon(victim,uball,1); 
  457. X            else 
  458. X            miss(xname(uball), victim);
  459. X
  460. X        }         /* now check again in case mon died */
  461. X        if (!m_at(uchain->ox, uchain->oy)) {
  462. X            u.ux = uchain->ox;
  463. X            u.uy = uchain->oy;
  464. X            newsym(u.ux0, u.uy0);
  465. X        }
  466. X        nomul(0);
  467. X
  468. X        *bc_control = BC_BALL;
  469. X        move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
  470. X        *ballx = uchain->ox;
  471. X        *bally = uchain->oy;
  472. X        move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
  473. X        spoteffects();
  474. X        return FALSE;
  475. X        } 
  476. X    }
  477. X
  478. X    *bc_control = BC_BALL|BC_CHAIN;;
  479. X    nomul(-2);
  480. X    nomovemsg = "";
  481. X
  482. X    move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
  483. X    *ballx  = uchain->ox;
  484. X    *bally  = uchain->oy;
  485. X    *chainx = u.ux;
  486. X    *chainy = u.uy;
  487. X    return TRUE;
  488. X}
  489. X
  490. X/*
  491. X *  drop_ball()
  492. X *
  493. X *  The punished hero drops or throws her iron ball.  If the hero is
  494. X *  blind, we must reset the order and glyph.  Check for side effects.
  495. X *  This routine expects the ball to be already placed.
  496. X *
  497. X *  Should not be called while swallowed.
  498. X */
  499. Xvoid
  500. Xdrop_ball(x, y)
  501. Xxchar x, y;
  502. X{
  503. X    if (Blind) {
  504. X    u.bc_order = bc_order();            /* get the order */
  505. X                            /* pick up glyph */
  506. X    u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;
  507. X    }
  508. X
  509. X    if (x != u.ux || y != u.uy) {
  510. X    struct trap *t;
  511. X    const char *pullmsg = "The ball pulls you out of the %s!";
  512. X
  513. X    if (u.utrap && u.utraptype != TT_INFLOOR) {
  514. X        switch(u.utraptype) {
  515. X        case TT_PIT:
  516. X        pline(pullmsg, "pit");
  517. X        break;
  518. X        case TT_WEB:
  519. X        pline(pullmsg, "web");
  520. X        pline("The web is destroyed!");
  521. X        deltrap(t_at(u.ux,u.uy));
  522. X        break;
  523. X        case TT_LAVA:
  524. X        pline(pullmsg, "lava");
  525. X        break;
  526. X        case TT_BEARTRAP: {
  527. X        register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
  528. X        pline(pullmsg, "bear trap");
  529. X        Your("%s %s is severely damaged.",
  530. X                    (side == LEFT_SIDE) ? "left" : "right",
  531. X                    body_part(LEG));
  532. X        set_wounded_legs(side, rn1(1000, 500));
  533. X        losehp(2, "leg damage from being pulled out of a bear trap",
  534. X                    KILLED_BY);
  535. X        break;
  536. X          }
  537. X        }
  538. X        u.utrap = 0;
  539. X        fill_pit(u.ux, u.uy);
  540. X    }
  541. X
  542. X    u.ux0 = u.ux;
  543. X    u.uy0 = u.uy;
  544. X    if (!Levitation && !MON_AT(x, y) && !u.utrap &&
  545. X                (is_pool(x, y) ||
  546. X                 ((t = t_at(x, y)) &&
  547. X                  (t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
  548. X                   t->ttyp == TRAPDOOR)))) {
  549. X        u.ux = x;
  550. X        u.uy = y;
  551. X    } else {
  552. X        u.ux = x - u.dx;
  553. X        u.uy = y - u.dy;
  554. X    }
  555. X    vision_full_recalc = 1;    /* hero has moved, recalculate vision later */
  556. X
  557. X    if (Blind) {
  558. X        /* drop glyph under the chain */
  559. X        if (u.bc_felt & BC_CHAIN)
  560. X        levl[uchain->ox][uchain->oy].glyph = u.cglyph;
  561. X        u.bc_felt  = 0;        /* feel nothing */
  562. X        /* pick up new glyph */
  563. X        u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;
  564. X    }
  565. X    movobj(uchain,u.ux,u.uy);    /* has a newsym */
  566. X    if (Blind) {
  567. X        u.bc_order = bc_order();
  568. X    }
  569. X    newsym(u.ux0,u.uy0);        /* clean up old position */
  570. X    spoteffects();
  571. X    }
  572. X}
  573. X
  574. X
  575. Xstatic void
  576. Xlitter()
  577. X{
  578. X    struct obj *otmp = invent, *nextobj;
  579. X    int capacity = weight_cap();
  580. X
  581. X    while (otmp) {
  582. X        nextobj = otmp->nobj;
  583. X        if ((otmp != uball) && (rnd(capacity) <= otmp->owt)) {
  584. X            if (otmp == uwep)
  585. X                setuwep((struct obj *)0);
  586. X            if ((otmp != uwep) && (canletgo(otmp, ""))) {
  587. X                Your("%s you down the stairs.",
  588. X                     aobjnam(otmp, "follow"));
  589. X                dropx(otmp);
  590. X            }
  591. X        }
  592. X        otmp = nextobj;
  593. X    }
  594. X}
  595. X
  596. Xvoid
  597. Xdrag_down()
  598. X{
  599. X    boolean forward;
  600. X    uchar dragchance = 3;
  601. X
  602. X    /* 
  603. X     *    Assume that the ball falls forward if:
  604. X     *
  605. X     *    a) the character is wielding it, or
  606. X     *    b) the character has both hands available to hold it (i.e. is 
  607. X     *       not wielding any weapon), or 
  608. X     *    c) (perhaps) it falls forward out of his non-weapon hand
  609. X     */
  610. X
  611. X    forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
  612. X
  613. X    if (carried(uball)) 
  614. X        You("lose your grip on the iron ball.");
  615. X
  616. X    if (forward) {
  617. X        if(rn2(6)) {
  618. X            pline("The iron ball drags you downstairs!");
  619. X            losehp(rnd(6), "dragged downstairs by an iron ball",
  620. X                NO_KILLER_PREFIX);
  621. X            litter();
  622. X        }
  623. X    } else {
  624. X        if(rn2(2)) {
  625. X            pline("The iron ball smacks into you!");
  626. X            losehp(rnd(20), "iron ball collision", KILLED_BY_AN);
  627. X            exercise(A_STR, FALSE);
  628. X            dragchance -= 2;
  629. X        } 
  630. X        if( (int) dragchance >= rnd(6)) {
  631. X            pline("The iron ball drags you downstairs!");
  632. X            losehp(rnd(3), "dragged downstairs by an iron ball",
  633. X                NO_KILLER_PREFIX);
  634. X            exercise(A_STR, FALSE);
  635. X            litter();
  636. X        }
  637. X    }
  638. X}
  639. X
  640. X/*ball.c*/
  641. END_OF_FILE
  642. if test 16324 -ne `wc -c <'src/ball.c'`; then
  643.     echo shar: \"'src/ball.c'\" unpacked with wrong size!
  644. fi
  645. # end of 'src/ball.c'
  646. if test -f 'sys/mac/mactty.c' -a "${1}" != "-c" ; then 
  647.   echo shar: Renaming existing file \"'sys/mac/mactty.c'\" to \"'sys/mac/mactty.c.orig'\"
  648.   mv -f 'sys/mac/mactty.c' 'sys/mac/mactty.c.orig'
  649. fi
  650. echo shar: Extracting \"'sys/mac/mactty.c'\" \(36517 characters\)
  651. sed "s/^X//" >'sys/mac/mactty.c' <<'END_OF_FILE'
  652. X/*    SCCS Id: @(#)mactty.c    3.1    93/03/01            */
  653. X/* Copyright (c) Jon W{tte 1993.                    */
  654. X/* NetHack may be freely redistributed.  See license for details.    */
  655. X
  656. X/*
  657. X * mactty.c
  658. X *
  659. X * This file contains the actual code for the tty library. For a 
  660. X * description, see the file mactty.h, which contains all you
  661. X * need to know to use the library.
  662. X */
  663. X
  664. X#include "mttypriv.h"
  665. X
  666. X#if PRINTF_TTY
  667. X# include <stdio.h>
  668. X# include <stdarg.h>
  669. X#endif
  670. X
  671. Xextern void dprintf ( char * , ... ) ;
  672. Xstatic void select_onscreen_window ( tty_record * record ) ;
  673. Xstatic void select_offscreen_port ( tty_record * record ) ;
  674. X
  675. X#define MEMORY_MARGIN 30000
  676. X
  677. X
  678. X/*
  679. X * Error code returned when it's probably our fault, or
  680. X * bad parameters.
  681. X */
  682. X#define general_failure 1
  683. X
  684. X/*
  685. X * How long lines do we support for input?
  686. X */
  687. X#define IB_LIMIT 80
  688. X
  689. X/*
  690. X * Convenience macro for most functions - put last in declaration
  691. X */
  692. X#define RECORD(record) \
  693. Xtty_record * record ; \
  694. X    if ( ! window ) { \
  695. X        dprintf ( "*** NULL Window ***" ) ; \
  696. X        return general_failure ; \
  697. X    } \
  698. X    record = ( tty_record * ) GetWRefCon ( window ) ; \
  699. X    if ( ! record ) { \
  700. X        return general_failure ; \
  701. X    }
  702. X
  703. X/*
  704. X * Simple macro for deciding wether we draw at once or delay
  705. X */
  706. X#define DRAW_DIRECT ( 0L != ( TA_ALWAYS_REFRESH & record -> \
  707. X    attribute [ TTY_ATTRIB_FLAGS ] ) )
  708. X
  709. X
  710. X/*
  711. X * Module variable used as return value for various calls.
  712. X */
  713. Xstatic short s_err = 0 ;
  714. X
  715. X/*
  716. X * Table of special characters. Zero is ALWAYS special; it means
  717. X * end of string and would be MISSED if it was not included here.
  718. X */
  719. Xstatic const unsigned char s_cooked_controls [ ] = {
  720. X    1,    0,    0,    0,    0,    0,    0,    1,    1,    0,    1,    0,    0,    1,    0,    0,
  721. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  722. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  723. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  724. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  725. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  726. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  727. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  728. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  729. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  730. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  731. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  732. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  733. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  734. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  735. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  736. X} ;
  737. X
  738. Xstatic const unsigned char s_raw_controls [ ] = {
  739. X    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  740. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  741. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  742. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  743. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  744. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  745. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  746. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  747. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  748. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  749. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  750. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  751. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  752. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  753. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  754. X    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  755. X} ;
  756. X
  757. Xstatic const unsigned char * s_control = s_cooked_controls ;
  758. X
  759. X
  760. X/*
  761. X * Memory-related error
  762. X */
  763. Xstatic short
  764. Xmem_err ( void ) {
  765. X    if ( MemError ( ) ) {
  766. X        return MemError ( ) ;
  767. X    }
  768. X    return general_failure ;
  769. X}
  770. X
  771. X
  772. X/*
  773. X * Make a rectangle empty
  774. X */
  775. Xstatic void
  776. Xempty_rect ( Rect * r ) {
  777. X
  778. X    r -> right = -20000 ;
  779. X    r -> left = 20000 ;
  780. X    r -> top = 20000 ;
  781. X    r -> bottom = -20000 ;
  782. X}
  783. X
  784. X
  785. X/*
  786. X * Union twp rect together
  787. X */
  788. Xstatic void
  789. Xunion_rect ( Rect * r1 , Rect * r2 , Rect * dest ) {
  790. X
  791. X    if ( r1 -> left < r2 -> left ) {
  792. X        dest -> left = r1 -> left ;
  793. X    } else {
  794. X        dest -> left = r2 -> left ;
  795. X    }
  796. X
  797. X    if ( r1 -> top < r2 -> top ) {
  798. X        dest -> top = r1 -> top ;
  799. X    } else {
  800. X        dest -> top = r2 -> top ;
  801. X    }
  802. X
  803. X    if ( r1 -> bottom > r2 -> bottom ) {
  804. X        dest -> bottom = r1 -> bottom ;
  805. X    } else {
  806. X        dest -> bottom = r2 -> bottom ;
  807. X    }
  808. X
  809. X    if ( r1 -> right > r2 -> right ) {
  810. X        dest -> right = r1 -> right ;
  811. X    } else {
  812. X        dest -> right = r2 -> right ;
  813. X    }
  814. X}
  815. X
  816. X
  817. X/*
  818. X * Dispose a pointer using the set memory-allocator
  819. X */
  820. Xstatic short
  821. Xdispose_ptr ( tty_record * record , void * ptr ) {
  822. Xpascal short ( * func ) ( WindowPtr window , void * ptr ) =
  823. X    ( pascal short ( * ) ( WindowPtr , void * ) )
  824. X    record -> attribute [ TTY_FREE_MEMORY_FUNCTION ] ;
  825. X
  826. X    if ( ! ptr ) {
  827. X        return noErr ; /* Silently accept disposing NULLs */
  828. X    }
  829. X    if ( func ) {
  830. X        s_err = ( * func ) ( record -> its_window , ptr ) ;
  831. X    } else {
  832. X        DisposePtr ( ptr ) ;
  833. X        s_err = MemError ( ) ;
  834. X    }
  835. X    return s_err ;
  836. X}
  837. X
  838. X
  839. X/*
  840. X * Allocate a pointer using the set memory-allocator
  841. X */
  842. Xstatic short
  843. Xalloc_ptr ( tty_record * record , void * * ptr , long size ) {
  844. Xpascal short ( * func ) ( WindowPtr window , void * * ptr , long ) =
  845. X    ( pascal short ( * ) ( WindowPtr , void * * , long ) )
  846. X    record -> attribute [ TTY_ALLOCATE_MEMORY_FUNCTION ] ;
  847. X
  848. X    if ( func ) {
  849. X        s_err = ( * func ) ( record -> its_window , ptr , size ) ;
  850. X    } else {
  851. X        * ptr = NewPtr ( size ) ;
  852. X        s_err = * ptr ? noErr : mem_err ( ) ;
  853. X    }
  854. X    return s_err ;
  855. X}
  856. X
  857. X
  858. X/*
  859. X * Set up a GWorld in the record
  860. X */
  861. Xstatic short
  862. Xallocate_offscreen_world ( tty_record * record ) {
  863. XGWorldPtr gw = NULL ;
  864. XGWorldFlags world_flags = clipPix ;
  865. Xlong mem_here , mem_there , other , required_mem ;
  866. XPoint p = { 0 , 0 } ;
  867. XRect r_screen ;
  868. XGDHandle gdh ;
  869. X
  870. X    select_onscreen_window ( record ) ;
  871. X    LocalToGlobal ( & p ) ;
  872. X    r_screen = record -> its_bits . bounds ;
  873. X    OffsetRect ( & r_screen , p . h , p . v ) ;
  874. X
  875. X    gdh = GetMaxDevice ( & r_screen ) ;
  876. X    required_mem = ( long ) ( * ( ( * gdh ) -> gdPMap ) ) -> pixelSize *
  877. X        ( ( long ) record -> its_bits . bounds . right *
  878. X        record -> its_bits . bounds . bottom ) >> 3 ;
  879. X
  880. X    PurgeSpace ( & other , & mem_here ) ;
  881. X    if ( other < mem_here + MEMORY_MARGIN ) {
  882. X        mem_here = other - MEMORY_MARGIN ;
  883. X    }
  884. X    dprintf ( "Heap %ld Required %ld" , mem_here , required_mem ) ;
  885. X    if ( required_mem > mem_here ) {
  886. X        mem_there = required_mem ;
  887. X        if ( required_mem > MFMaxMem ( & mem_there ) ) {
  888. X            dprintf ( "No memory" ) ;
  889. X            return memFullErr ;
  890. X        }
  891. X        world_flags |= useTempMem ;
  892. X    }
  893. X    s_err = NewGWorld ( & gw , 16 , & r_screen , NULL , NULL , world_flags ) ;
  894. X    if ( ! s_err ) {
  895. X        record -> offscreen_world = gw ;
  896. X        select_offscreen_port ( record ) ;
  897. X        SetOrigin ( 0 , 0 ) ;
  898. X        dprintf ( "New GWorld @ %lx;dm %lx CGrafPtr" , gw , gw ) ;
  899. X    }
  900. X    return s_err ;
  901. X}
  902. X
  903. X
  904. X/*
  905. X * Done with GWorld, release data
  906. X */
  907. Xstatic short
  908. Xdeallocate_gworld ( tty_record * record ) {
  909. X    if ( record -> offscreen_world ) {
  910. X        DisposeGWorld ( record -> offscreen_world ) ;
  911. X        record -> offscreen_world = NULL ;
  912. X    }
  913. X    return noErr ;
  914. X}
  915. X
  916. X
  917. X/*
  918. X * Save the current port/world in a safe place for later retrieval
  919. X */
  920. Xstatic void
  921. Xsave_port ( tty_record * record , void * save ) {
  922. XGWorldPtr gw ;
  923. XGDHandle gh ;
  924. XGrafPtr gp ;
  925. X
  926. X    if ( record -> uses_gworld ) {
  927. X        GetGWorld ( & gw , & gh ) ;
  928. X        * ( GWorldPtr * ) save = gw ;
  929. X    } else {
  930. X        GetPort ( & gp ) ;
  931. X        * ( GrafPtr * ) save = gp ;
  932. X    }
  933. X}
  934. X
  935. X
  936. X/*
  937. X * Restore current port/world after a save
  938. X */
  939. Xstatic void
  940. Xuse_port ( tty_record * record , void * port ) {
  941. X    if ( record -> uses_gworld ) {
  942. X    PixMapHandle pix_map ;
  943. X
  944. X        SetGWorld ( ( GWorldPtr ) port , NULL ) ;
  945. X        if ( port == record -> offscreen_world ) {
  946. X            pix_map = GetGWorldPixMap ( record -> offscreen_world ) ;
  947. X            if ( pix_map ) {
  948. X                LockPixels ( pix_map ) ;
  949. X            }
  950. X        } else {
  951. X            pix_map = GetGWorldPixMap ( record -> offscreen_world ) ;
  952. X            if ( pix_map ) {
  953. X                UnlockPixels ( pix_map ) ;
  954. X            }
  955. X        }
  956. X    } else {
  957. X        SetPort ( ( GrafPtr ) port ) ;
  958. X    }
  959. X}
  960. X
  961. X
  962. X/*
  963. X * Use offscreen drawing - lock the pixels through use_port
  964. X */
  965. Xstatic void
  966. Xselect_offscreen_port ( tty_record * record ) {
  967. X    if ( record -> uses_gworld ) {
  968. X        use_port ( record , record -> offscreen_world ) ;
  969. X    } else {
  970. X        use_port ( record , record -> offscreen_port ) ;
  971. X    }
  972. X}
  973. X
  974. X
  975. X/*
  976. X * Use the window - unlock pixels
  977. X */
  978. Xstatic void
  979. Xselect_onscreen_window ( tty_record * record ) {
  980. X    if ( record -> uses_gworld ) {
  981. X        use_port ( record , record -> its_window_world ) ;
  982. X        SetPort ( record -> its_window ) ;
  983. X    } else {
  984. X        use_port ( record , record -> its_window ) ;
  985. X    }
  986. X}
  987. X
  988. X
  989. X/*
  990. X * Do bits copy depending on if we're using color or not
  991. X */
  992. Xstatic void
  993. Xcopy_bits ( tty_record * record , Rect * bounds , short xfer_mode , RgnHandle mask_rgn ) {
  994. XRGBColor old_fore , old_back ;
  995. XRGBColor rgb_black = { 0 , 0 , 0 } ;
  996. XRGBColor rgb_white = { 0xffff , 0xffff , 0xffff } ;
  997. X
  998. X    if ( record -> uses_gworld ) {
  999. X    GWorldFlags pix_state = GetPixelsState ( GetGWorldPixMap ( record -> offscreen_world ) ) ;
  1000. X
  1001. X        LockPixels ( GetGWorldPixMap ( record -> offscreen_world ) ) ;
  1002. X        GetForeColor ( & old_fore ) ;
  1003. X        GetBackColor ( & old_back ) ;
  1004. X        RGBForeColor ( & rgb_black ) ;
  1005. X        RGBBackColor ( & rgb_white ) ;
  1006. X        CopyBits ( ( BitMap * ) & ( record -> offscreen_world -> portPixMap ) ,
  1007. X            & ( record -> its_window -> portBits ) , bounds , bounds , xfer_mode ,
  1008. X            mask_rgn ) ;
  1009. X        RGBForeColor ( & old_fore ) ;
  1010. X        RGBBackColor ( & old_back ) ;
  1011. X        SetPixelsState ( GetGWorldPixMap ( record -> offscreen_world ) , pix_state ) ;
  1012. X    } else {
  1013. X        CopyBits ( & ( record -> its_bits ) , & ( record -> its_window -> portBits ) ,
  1014. X            bounds , bounds , xfer_mode , mask_rgn ) ;
  1015. X    }
  1016. X}
  1017. X
  1018. X
  1019. X/*
  1020. X * Fill an area with the background color
  1021. X */
  1022. Xstatic void
  1023. Xerase_rect ( tty_record * record , Rect * area ) {
  1024. X#if defined(applec)
  1025. X# pragma unused(record)
  1026. X#endif
  1027. X
  1028. X    EraseRect ( area ) ;
  1029. X}
  1030. X
  1031. X
  1032. X/*
  1033. X * Get rid of offscreen bitmap
  1034. X */
  1035. Xstatic short
  1036. Xfree_bits ( tty_record * record ) {
  1037. X    if ( record -> uses_gworld ) {
  1038. X        s_err = deallocate_gworld ( record ) ;
  1039. X    } else {
  1040. X        if ( record -> offscreen_port ) {
  1041. X            ClosePort ( record -> offscreen_port ) ;
  1042. X            s_err = dispose_ptr ( record , record -> offscreen_port ) ;
  1043. X            if ( ! s_err ) {
  1044. X                record -> offscreen_port = NULL ;
  1045. X            } else {
  1046. X                return s_err ;
  1047. X            }
  1048. X        }
  1049. X        s_err = dispose_ptr ( record , record -> its_bits . baseAddr ) ;
  1050. X        if ( ! s_err ) {
  1051. X            record -> its_bits . baseAddr = NULL ;
  1052. X        }
  1053. X    }
  1054. X    return s_err ;
  1055. X}
  1056. X
  1057. X
  1058. X/*
  1059. X * Snatch a window from the resource fork. Create the record.
  1060. X * Otherwise, do nothing.
  1061. X */
  1062. Xpascal short
  1063. Xcreate_tty ( WindowPtr * window , short resource_id , Boolean in_color ) {
  1064. Xtty_record * record ;
  1065. XBoolean was_allocated = !! * window ;
  1066. X
  1067. X    if ( in_color ) {
  1068. X        * window = GetNewCWindow ( resource_id , ( Ptr ) * window , ( WindowPtr ) -1L ) ;
  1069. X    } else {
  1070. X        * window = GetNewWindow ( resource_id , ( Ptr ) * window , ( WindowPtr ) -1L ) ;
  1071. X    }
  1072. X    if ( ! * window ) {
  1073. X        return mem_err ( ) ;
  1074. X    }
  1075. X
  1076. X    record = ( tty_record * ) NewPtrClear ( sizeof ( tty_record ) ) ;
  1077. X    if ( ! record ) {
  1078. X        if ( was_allocated ) {
  1079. X            CloseWindow ( * window ) ;
  1080. X        } else {
  1081. X            DisposeWindow ( * window ) ;
  1082. X        }
  1083. X        return mem_err ( ) ;
  1084. X    }
  1085. X    record -> its_window = * window ;
  1086. X    SetWRefCon ( * window , ( long ) record ) ;
  1087. X    record -> was_allocated = was_allocated ;
  1088. X    record -> its_bits . baseAddr = NULL ;
  1089. X#if TTY_INPUT
  1090. X    record -> input_buffer = NULL ;
  1091. X#endif
  1092. X
  1093. X/*
  1094. X * Wee need to keep the window world around if we switch worlds
  1095. X */
  1096. X    record -> offscreen_world = NULL ;
  1097. X    record -> uses_gworld = in_color ;
  1098. X    if ( in_color ) {
  1099. X    GDHandle gh ;
  1100. X
  1101. X        SetPort ( * window ) ;
  1102. X        GetGWorld ( & ( record -> its_window_world ) , & gh ) ;
  1103. X    } else {
  1104. X        record -> its_window_world = NULL ;
  1105. X    }
  1106. X
  1107. X#if CLIP_RECT_ONLY
  1108. X    empty_rect ( & ( record -> invalid_rect ) ) ;
  1109. X#else
  1110. X    record -> invalid_part = NewRgn ( ) ;
  1111. X    if ( ! record -> invalid_part ) {
  1112. X    short err = mem_err ( ) ;
  1113. X
  1114. X        err = destroy_tty ( * window ) ;
  1115. X        return err ;
  1116. X    }
  1117. X#endif
  1118. X
  1119. X    return noErr ;
  1120. X}
  1121. X
  1122. X
  1123. X/*
  1124. X * Initialize the struct so it actually works as a tty.
  1125. X */
  1126. Xpascal short
  1127. Xinit_tty_name ( WindowPtr window , unsigned char * font_name , short font_size ,
  1128. X    short x_size , short y_size ) {
  1129. Xshort font_num = 0 ;
  1130. X
  1131. X    GetFNum ( font_name , & font_num ) ;
  1132. X    if ( ! font_num ) {
  1133. X        return general_failure ;
  1134. X    }
  1135. X    return init_tty_number ( window , font_num , font_size , x_size , y_size ) ;
  1136. X}
  1137. X
  1138. X
  1139. Xpascal short
  1140. Xinit_tty_number ( WindowPtr window , short font_number , short font_size ,
  1141. X    short x_size , short y_size ) {
  1142. XRECORD ( record ) ;
  1143. X
  1144. X    record -> font_number = font_number ;
  1145. X    record -> font_size = font_size ;
  1146. X    record -> x_size = x_size ;
  1147. X    record -> y_size = y_size ;
  1148. X
  1149. X    record -> offscreen_port = NULL ;
  1150. X    record -> attribute [ TTY_ATTRIB_BACKGROUND ] = 0xffffff ; /* White */
  1151. X
  1152. X#if TTY_INPUT
  1153. X    record -> input_buffer_len = 0 ;
  1154. X    record -> input_buffer_limit = IB_LIMIT ;
  1155. X    s_err = alloc_ptr ( record , & ( record -> input_buffer ) , IB_LIMIT ) ;
  1156. X    if ( s_err ) {
  1157. X        return s_err ;
  1158. X    }
  1159. X#endif
  1160. X
  1161. X    return force_tty_coordinate_system_recalc ( window ) ;
  1162. X}
  1163. X
  1164. X
  1165. X/*
  1166. X * Done with a window - destroy it. Release the memory only if
  1167. X * it wasn't allocated when we got it!
  1168. X */
  1169. Xpascal short
  1170. Xdestroy_tty ( WindowPtr window ) {
  1171. XBoolean close_flag ;
  1172. XRECORD ( record ) ;
  1173. X
  1174. X    s_err = free_bits ( record ) ;
  1175. X#if TTY_INPUT
  1176. X    if ( ! s_err ) {
  1177. X        s_err = dispose_ptr ( record -> input_buffer ) ;
  1178. X        if ( ! s_err ) {
  1179. X            record -> input_buffer = NULL ;
  1180. X        }
  1181. X    }
  1182. X#endif
  1183. X    if ( ! s_err ) {
  1184. X        close_flag = record -> was_allocated ;
  1185. X        DisposePtr ( ( Ptr ) record ) ;
  1186. X        s_err = MemError ( ) ;
  1187. X        if ( close_flag ) {
  1188. X            CloseWindow ( window ) ;
  1189. X        } else {
  1190. X            DisposeWindow ( window ) ;
  1191. X        }
  1192. X    }
  1193. X    
  1194. X    return s_err ;
  1195. X}
  1196. X
  1197. X
  1198. X/*
  1199. X * Use a new font for drawing.
  1200. X */
  1201. Xpascal short
  1202. Xset_tty_font_name ( WindowPtr window , unsigned char * font_name ) {
  1203. XRECORD ( record ) ;
  1204. X
  1205. X    record -> font_number = 0 ;
  1206. X    GetFNum ( font_name , & ( record -> font_number ) ) ;
  1207. X
  1208. X    return ! record -> font_number ;
  1209. X}
  1210. X
  1211. X
  1212. Xpascal short
  1213. Xset_tty_font_number ( WindowPtr window , short font_number ) {
  1214. XRECORD ( record ) ;
  1215. X
  1216. X    record -> font_number = font_number ;
  1217. X
  1218. X    return noErr ;
  1219. X}
  1220. X
  1221. X
  1222. Xpascal short
  1223. Xset_tty_font_size ( WindowPtr window , short font_size ) {
  1224. XRECORD ( record ) ;
  1225. X
  1226. X    record -> font_size = font_size ;
  1227. X
  1228. X    return noErr ;
  1229. X}
  1230. X
  1231. X
  1232. Xstatic void
  1233. Xdo_set_port_font ( tty_record * record ) {
  1234. X
  1235. X    PenNormal ( ) ;
  1236. X    TextFont ( record -> font_number ) ;
  1237. X    TextFace ( 0 ) ;
  1238. X    TextSize ( record -> font_size ) ;
  1239. X    if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_OVERSTRIKE ) ) {
  1240. X        TextMode ( srcOr ) ;
  1241. X    } else {
  1242. X        TextMode ( srcCopy ) ;
  1243. X    }
  1244. X}
  1245. X
  1246. X
  1247. X/*
  1248. X * Fill in some fields from some other fields that may have changed
  1249. X */
  1250. Xstatic void
  1251. Xcalc_font_sizes ( tty_record * record ) {
  1252. XFontInfo font_info ;
  1253. X
  1254. X    do_set_port_font ( record ) ;
  1255. X
  1256. X    GetFontInfo ( & font_info ) ;
  1257. X    record -> char_width = font_info . widMax ;
  1258. X    record -> ascent_height = font_info . ascent + font_info . leading ;
  1259. X    record -> row_height = record -> ascent_height + font_info . descent ;
  1260. X}
  1261. X
  1262. X
  1263. X/*
  1264. X * Allocate memory for the bitmap holding the tty window
  1265. X */
  1266. Xstatic short
  1267. Xalloc_bits ( tty_record * record ) {
  1268. Xvoid * old_port ;
  1269. X
  1270. X    save_port ( record , & old_port ) ;
  1271. X    SetRect ( & record -> its_bits . bounds , 0 , 0 ,
  1272. X        record -> char_width * record -> x_size ,
  1273. X        record -> row_height * record -> y_size ) ;
  1274. X
  1275. X/*
  1276. X * Clear two highest and lowest bit - not a color pixMap, and even in size
  1277. X */
  1278. X    record -> its_bits . rowBytes = ( ( record -> its_bits . bounds . right + 15 )
  1279. X        >> 3 ) & 0x1ffe ;
  1280. X
  1281. X    if ( record -> uses_gworld ) {
  1282. X        s_err = allocate_offscreen_world ( record ) ;
  1283. X    } else {
  1284. X        s_err = alloc_ptr ( record , ( void * * ) & ( record -> its_bits . baseAddr ) ,
  1285. X            record -> its_bits . rowBytes * record -> its_bits . bounds . bottom ) ;
  1286. X        if ( ! s_err ) {
  1287. X            s_err = alloc_ptr ( record , ( void * * ) & ( record -> offscreen_port ) ,
  1288. X                sizeof ( GrafPort ) ) ;
  1289. X        }
  1290. X        if ( ! s_err ) {
  1291. X            OpenPort ( record -> offscreen_port ) ;
  1292. X            SetPort ( record -> offscreen_port ) ;
  1293. X            ClipRect ( & ( record -> its_bits . bounds ) ) ;
  1294. X            SetPortBits ( & ( record -> its_bits ) ) ;
  1295. X        }
  1296. X    }
  1297. X    use_port ( record , old_port ) ;
  1298. X
  1299. X    return s_err ;
  1300. X}
  1301. X
  1302. X
  1303. Xstatic void
  1304. Xupdate_offscreen_info ( tty_record * record ) {
  1305. X
  1306. X    select_offscreen_port ( record ) ;
  1307. X    do_set_port_font ( record ) ;
  1308. X}
  1309. X
  1310. X
  1311. X/*
  1312. X * Recalculate the window based on new size, font, extent values,
  1313. X * and re-allocate the bitmap.
  1314. X */
  1315. Xpascal short
  1316. Xforce_tty_coordinate_system_recalc ( WindowPtr window ) {
  1317. XRECORD ( record ) ;
  1318. X
  1319. X    if ( s_err = free_bits ( record ) ) {
  1320. X        return s_err ;
  1321. X    }
  1322. X    select_onscreen_window ( record ) ;
  1323. X    calc_font_sizes ( record ) ;
  1324. X
  1325. X    if ( s_err = alloc_bits ( record ) ) {
  1326. X/*
  1327. X * Catastrophe! We could not allocate memory for the bitmap! Things may go very
  1328. X * much downhill from here!
  1329. X */
  1330. X         dprintf ( "alloc_bits returned NULL in force_tty_coordinate_system_recalc!" ) ;
  1331. X        return s_err ;
  1332. X    }
  1333. X
  1334. X    update_offscreen_info ( record ) ;
  1335. X    return clear_tty ( window ) ;
  1336. X}
  1337. X
  1338. X
  1339. X/*
  1340. X * Update TTY according to new color environment for the window
  1341. X */
  1342. Xpascal short
  1343. Xtty_environment_changed ( WindowPtr window ) {
  1344. XPoint p = { 0 , 0 } ;
  1345. XRect r_screen ;
  1346. XRECORD ( record ) ;
  1347. X
  1348. X    if ( record -> uses_gworld ) {
  1349. X        select_onscreen_window ( record ) ;
  1350. X        r_screen = record -> its_bits . bounds ;
  1351. X        LocalToGlobal ( & p )  ;
  1352. X        OffsetRect ( & r_screen , p . h , p . v ) ;
  1353. X        UpdateGWorld ( & ( record -> offscreen_world ) , 0 , & r_screen ,
  1354. X            NULL , NULL , stretchPix ) ;
  1355. X        select_offscreen_port ( record ) ;
  1356. X        SetOrigin ( 0 , 0 ) ;
  1357. X    }
  1358. X    return s_err ;
  1359. X}
  1360. X
  1361. X
  1362. X/*
  1363. X * Read a lot of interesting and useful information from the current tty
  1364. X */
  1365. Xpascal short
  1366. Xget_tty_metrics ( WindowPtr window , short * x_size , short * y_size ,
  1367. X    short * x_size_pixels , short * y_size_pixels , short * font_number ,
  1368. X    short * font_size , short * char_width , short * row_height ) {
  1369. XRECORD ( record ) ;
  1370. X
  1371. X/*
  1372. X * First, test that we actually have something to draw to...
  1373. X */
  1374. X    if ( ( ( NULL == record -> its_bits . baseAddr ) && ! record -> uses_gworld ) ||
  1375. X        ( ( NULL == record -> offscreen_world ) && record -> uses_gworld ) ) {
  1376. X        return general_failure ;
  1377. X    }
  1378. X
  1379. X    * x_size = record -> x_size ;
  1380. X    * y_size = record -> y_size ;
  1381. X    * x_size_pixels = record -> its_bits . bounds . right ;
  1382. X    * y_size_pixels = record -> its_bits . bounds . bottom ;
  1383. X    * font_number = record -> font_number ;
  1384. X    * font_size = record -> font_size ;
  1385. X    * char_width = record -> char_width ;
  1386. X    * row_height = record -> row_height ;
  1387. X
  1388. X    return noErr ;
  1389. X}
  1390. X
  1391. X
  1392. X/*
  1393. X * Map a position on the map to screen coordinates
  1394. X */
  1395. Xstatic void
  1396. Xpos_rect ( tty_record * record , Rect * r , short x_pos , short y_pos ,
  1397. X    short x_end , short y_end ) {
  1398. X    SetRect ( r , x_pos * ( record -> char_width ) , y_pos * ( record -> row_height ) ,
  1399. X        ( 1 + x_end ) * ( record -> char_width ) , ( 1 + y_end ) *
  1400. X        ( record -> row_height ) ) ;
  1401. X}
  1402. X
  1403. X
  1404. Xstatic void
  1405. Xaccumulate_rect ( tty_record * record , Rect * rect ) {
  1406. X#if CLIP_RECT_ONLY
  1407. X    union_rect ( rect , & ( record -> invalid_rect ) , & ( record -> invalid_rect ) ) ;
  1408. X#else
  1409. XRgnHandle rh = NewRgn ( ) ;
  1410. X
  1411. X    RectRgn ( rh , rect ) ;
  1412. X    UnionRgn ( record -> invalid_part , rh , record -> invalid_part ) ;
  1413. X    DisposeRgn ( rh ) ;
  1414. X#endif
  1415. X}
  1416. X
  1417. X
  1418. X/*
  1419. X * Invert the specified position
  1420. X */
  1421. Xstatic void
  1422. Xcurs_pos ( tty_record * record , short x_pos , short y_pos , short to_state ) {
  1423. XRect r ;
  1424. X
  1425. X    if ( record -> curs_state == to_state ) {
  1426. X        return ;
  1427. X    }
  1428. X    record -> curs_state = to_state ;
  1429. X    pos_rect ( record , & r , x_pos , y_pos , x_pos , y_pos ) ;
  1430. X
  1431. X    if ( DRAW_DIRECT ) {
  1432. X    void * old_port ;
  1433. X
  1434. X        save_port ( record , & old_port ) ;
  1435. X        select_onscreen_window ( record ) ;
  1436. X        InvertRect ( & r ) ;
  1437. X        use_port ( record , old_port ) ;
  1438. X    } else {
  1439. X        accumulate_rect ( record , & r ) ;
  1440. X    }
  1441. X}
  1442. X
  1443. X
  1444. X/*
  1445. X * Move the cursor (both as displayed and where drawing goes)
  1446. X * HOWEVER: The cursor is NOT stored in the bitmap!
  1447. X */
  1448. Xpascal short
  1449. Xmove_tty_cursor ( WindowPtr window , short x_pos , short y_pos ) {
  1450. XRECORD ( record ) ;
  1451. X
  1452. X    select_onscreen_window ( record ) ;
  1453. X    if ( record -> x_curs == x_pos && record -> y_curs == y_pos ) {
  1454. X        return noErr ;
  1455. X    }
  1456. X    if ( record -> x_size <= x_pos || x_pos < 0 ||
  1457. X        record -> y_size <= y_pos || y_pos < 0 ) {
  1458. X        return general_failure ;
  1459. X    }
  1460. X    curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
  1461. X    record -> x_curs = x_pos ;
  1462. X    record -> y_curs = y_pos ;
  1463. X    curs_pos ( record , x_pos , y_pos , 1 ) ;
  1464. X
  1465. X    return noErr ;
  1466. X}
  1467. X
  1468. X
  1469. X/*
  1470. X * Get the current cursor position. Note that the cursor may not be
  1471. X * displayed there yet; it depends on wether you've called update_tty()
  1472. X * or have the window in TA_ALWAYS_REFRESH mode.
  1473. X */
  1474. Xpascal short
  1475. Xget_tty_cursor ( WindowPtr window , short * x_pos , short * y_pos ) {
  1476. XRECORD ( record ) ;
  1477. X
  1478. X    * x_pos = record -> x_curs ;
  1479. X    * y_pos = record -> y_curs ;
  1480. X
  1481. X    return noErr ;
  1482. X}
  1483. X
  1484. X
  1485. X/*
  1486. X * Update the screen to match the current bitmap, after adding stuff
  1487. X * with add_tty_char etc.
  1488. X */
  1489. Xpascal short
  1490. Xupdate_tty ( WindowPtr window ) {
  1491. XRect r ;
  1492. XRECORD ( record ) ;
  1493. X
  1494. X#if CLIP_RECT_ONLY
  1495. X    if ( record -> invalid_rect . right <= record -> invalid_rect . left ||
  1496. X        record -> invalid_rect . bottom <= record -> invalid_rect . top ) {
  1497. X        return noErr ;
  1498. X    }
  1499. X    r = record -> invalid_rect ;
  1500. X#else
  1501. X    if ( EmptyRgn ( record -> invalid_part ) ) {
  1502. X        return noErr ;
  1503. X    }
  1504. X    r = ( * ( record -> invalid_part ) ) -> rgnBBox ;
  1505. X#endif
  1506. X    select_onscreen_window ( record ) ;
  1507. X#if CLIP_RECT_ONLY
  1508. X    copy_bits ( record , & r , srcCopy , NULL ) ;
  1509. X    empty_rect ( & ( record -> invalid_rect ) ) ;
  1510. X#else
  1511. X    copy_bits ( record , & r , srcCopy , NULL ) ;
  1512. X    SetEmptyRgn ( record -> invalid_part ) ;
  1513. X#endif
  1514. X    if ( record -> curs_state ) {
  1515. X
  1516. X        pos_rect ( record , & r , record -> x_curs , record -> y_curs ,
  1517. X            record -> x_curs , record -> y_curs ) ;
  1518. X        InvertRect ( & r ) ;
  1519. X    }
  1520. X
  1521. X    return noErr ;
  1522. X}
  1523. X
  1524. X
  1525. X/*
  1526. X * Add a single character. It is drawn directly if the correct flag is set,
  1527. X * else deferred to the next update event or call of update_tty()
  1528. X */
  1529. Xpascal short
  1530. Xadd_tty_char ( WindowPtr window , short character ) {
  1531. Xchar s [ 2 ] ;
  1532. X
  1533. X    s [ 0 ] = character ;
  1534. X    s [ 1 ] = 0 ;
  1535. X    return add_tty_string ( window , s ) ;
  1536. X}
  1537. X
  1538. X
  1539. X/*
  1540. X * Low level add to screen
  1541. X */
  1542. Xstatic void
  1543. Xdo_add_string ( tty_record * record , char * str , short len ) {
  1544. XRect r ;
  1545. Xregister int x_pos , count = len ;
  1546. X
  1547. X    if ( len < 1 ) {
  1548. X        return ;
  1549. X    }
  1550. X    select_offscreen_port ( record ) ;
  1551. X
  1552. X    if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_MOVE_EACH_CHAR ) ) {
  1553. X        x_pos = record -> x_curs ;
  1554. X        while ( count -- ) {
  1555. X            MoveTo ( x_pos * record -> char_width , record -> y_curs *
  1556. X                record -> row_height + record -> ascent_height ) ;
  1557. X            DrawChar ( * ( str ++ ) ) ;
  1558. X        }
  1559. X    } else {
  1560. X        MoveTo ( record -> x_curs * record -> char_width , record -> y_curs *
  1561. X            record -> row_height + record -> ascent_height ) ;
  1562. X        DrawText ( str , 0 , len ) ;
  1563. X    }
  1564. X
  1565. X    pos_rect ( record , & r , record -> x_curs , record -> y_curs ,
  1566. X        record -> x_curs + len - 1 , record -> y_curs ) ;
  1567. X    if ( DRAW_DIRECT ) {
  1568. X        select_onscreen_window ( record ) ;
  1569. X        copy_bits ( record , & r , srcCopy , NULL ) ;
  1570. X    } else {
  1571. X        accumulate_rect ( record , & r ) ;
  1572. X    }
  1573. X}
  1574. X
  1575. X
  1576. X/*
  1577. X * Low-level cursor handling routine
  1578. X */
  1579. Xstatic void
  1580. Xdo_add_cursor ( tty_record * record , short x_pos ) {
  1581. X
  1582. X    record -> x_curs = x_pos ;
  1583. X    if ( record -> x_curs >= record -> x_size ) {
  1584. X        if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_WRAP_AROUND ) ) {
  1585. X            record -> y_curs ++ ;
  1586. X            record -> x_curs = 0 ;
  1587. X            if ( record -> y_curs >= record -> y_size ) {
  1588. X                if ( 0L != ( record -> attribute [ TTY_ATTRIB_FLAGS ] &
  1589. X                    TA_INHIBIT_VERT_SCROLL ) ) {
  1590. X                    record -> y_curs = record -> y_size ;
  1591. X                } else {
  1592. X                    scroll_tty ( record -> its_window , 0 , 1 + record -> y_curs -
  1593. X                        record -> y_size ) ;
  1594. X                }
  1595. X            }
  1596. X        } else {
  1597. X            record -> x_curs = record -> x_size ;
  1598. X        }
  1599. X    }
  1600. X}
  1601. X
  1602. X
  1603. X/*
  1604. X * Beep
  1605. X */
  1606. Xstatic void
  1607. Xdo_tty_beep ( tty_record * record ) {
  1608. X    if ( record -> attribute [ TTY_BEEP_FUNCTION ] ) {
  1609. X    pascal void ( * tty_beep ) ( WindowPtr ) = ( pascal void ( * ) ( WindowPtr ) )
  1610. X        record -> attribute [ TTY_BEEP_FUNCTION ] ;
  1611. X        ( * tty_beep ) ( record -> its_window ) ;
  1612. X    } else {
  1613. X        SysBeep ( 20 ) ;
  1614. X    }
  1615. X}
  1616. X
  1617. X
  1618. X/*
  1619. X * Do control character
  1620. X */
  1621. Xstatic void
  1622. Xdo_control ( tty_record * record , short character ) {
  1623. Xstatic int recurse = 0 ;
  1624. X
  1625. X/*
  1626. X * Check recursion because nl_add_cr and cr_add_nl may both be set and call each other
  1627. X */
  1628. X    recurse ++ ;
  1629. X    if ( recurse > 2 ) {
  1630. X        return ;
  1631. X    }
  1632. X    switch ( character ) {
  1633. X    case 10 :
  1634. X        record -> y_curs ++ ;
  1635. X        if ( record -> y_curs >= record -> y_size ) {
  1636. X            scroll_tty ( record -> its_window , 0 , 1 + record -> y_curs -
  1637. X                record -> y_size ) ;
  1638. X        }
  1639. X        if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_NL_ADD_CR ) ) {
  1640. X            do_control ( record , 13 ) ;
  1641. X        }
  1642. X        break ;
  1643. X    case 13 :
  1644. X        record -> x_curs = 0 ;
  1645. X        if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_CR_ADD_NL ) ) {
  1646. X            do_control ( record , 10 ) ;
  1647. X        }
  1648. X        break ;
  1649. X    case 7 :
  1650. X        do_tty_beep ( record ) ;
  1651. X        break ;
  1652. X    case 8 :
  1653. X        if ( record -> x_curs > 0 ) {
  1654. X            record -> x_curs -- ;
  1655. X        }
  1656. X        break ;
  1657. X    default :
  1658. X        break ;
  1659. X    }
  1660. X    recurse -- ;
  1661. X}
  1662. X
  1663. X
  1664. X/*
  1665. X * Add a null-terminated string of characters
  1666. X */
  1667. Xpascal short
  1668. Xadd_tty_string ( WindowPtr window , const char * string ) {
  1669. Xregister const unsigned char * start_c ;
  1670. Xregister const unsigned char * the_c ;
  1671. Xregister short max_x , pos_x ;
  1672. XRECORD ( record ) ;
  1673. X
  1674. X    select_onscreen_window ( record ) ;
  1675. X    curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
  1676. X
  1677. X    the_c = ( const unsigned char * ) string ;
  1678. X    max_x = record -> x_size ;
  1679. X    while ( 1 ) {
  1680. X        start_c = the_c ;
  1681. X        pos_x = record -> x_curs ;
  1682. X        if ( ( 0L == ( record -> attribute [ TTY_ATTRIB_FLAGS ] & TA_WRAP_AROUND ) ) &&
  1683. X            pos_x >= max_x ) { /* Optimize away drawing across border without wrap */
  1684. X            break ;
  1685. X        }
  1686. X        while ( pos_x < max_x && ! s_control [ * the_c ] ) {
  1687. X            the_c ++ ;
  1688. X            pos_x ++ ;
  1689. X        }
  1690. X        do_add_string ( record , ( char * ) start_c , the_c - start_c ) ;
  1691. X        do_add_cursor ( record , pos_x ) ;
  1692. X        if ( ! * the_c ) {
  1693. X            break ;
  1694. X        }
  1695. X        if ( s_control [ * the_c ] ) {
  1696. X            do_control ( record , * the_c ) ;
  1697. X            the_c ++ ;
  1698. X        }
  1699. X    }
  1700. X    select_onscreen_window ( record ) ;
  1701. X    curs_pos ( record , record -> x_curs , record -> y_curs , 1 ) ;
  1702. X
  1703. X    ShowWindow ( window ) ;
  1704. X
  1705. X    return noErr ;
  1706. X}
  1707. X
  1708. X
  1709. X/*
  1710. X * Do a c-style printf - the result shouldn't be too long...
  1711. X */
  1712. Xshort
  1713. Xprintf_tty ( WindowPtr window , const char * fmt , ... ) {
  1714. Xstatic char buf [ 256 ] ;
  1715. Xva_list list ;
  1716. X
  1717. X    va_start ( list , fmt ) ;
  1718. X    vsprintf ( buf , fmt , list ) ;
  1719. X    va_end ( list ) ;
  1720. X
  1721. X    return add_tty_string ( window , buf ) ;
  1722. X}
  1723. X
  1724. X
  1725. X/*
  1726. X * Read or change attributes for the tty. Note that some attribs may
  1727. X * very well clear and reallocate the bitmap when changed, whereas
  1728. X * others (color, highlight, ...) are guaranteed not to.
  1729. X */
  1730. Xpascal short
  1731. Xget_tty_attrib ( WindowPtr window , tty_attrib attrib , long * value ) {
  1732. XRECORD ( record ) ;
  1733. X
  1734. X    if ( attrib < 0 || attrib >= TTY_NUMBER_ATTRIBUTES ) {
  1735. X        return general_failure ;
  1736. X    }
  1737. X    * value = record -> attribute [ attrib ] ;
  1738. X
  1739. X    return noErr ;
  1740. X}
  1741. X
  1742. X
  1743. Xpascal short
  1744. Xset_tty_attrib ( WindowPtr window , tty_attrib attrib , long value ) {
  1745. Xlong old_value ;
  1746. XRGBColor rgb_color ;
  1747. XRECORD ( record ) ;
  1748. X
  1749. X    if ( attrib < 0 || attrib >= TTY_NUMBER_ATTRIBUTES ) {
  1750. X        return general_failure ;
  1751. X    }
  1752. X    old_value = record -> attribute [ attrib ] ;
  1753. X    if ( old_value == value ) {
  1754. X        return noErr ;
  1755. X    }
  1756. X    record -> attribute [ attrib ] = value ;
  1757. X    /*
  1758. X     * Presently, no attributes generate a new bitmap.
  1759. X     */
  1760. X    switch ( attrib ) {
  1761. X    case TTY_ATTRIB_CURSOR :
  1762. X/*
  1763. X * Check if we should change tables
  1764. X */
  1765. X        if ( 0L != ( value & TA_RAW_OUTPUT ) ) {
  1766. X            s_control = s_raw_controls ;
  1767. X        } else {
  1768. X            s_control = s_cooked_controls ;
  1769. X        }
  1770. X        break ;
  1771. X    case TTY_ATTRIB_FLAGS :
  1772. X/*
  1773. X * Check if we should flush the output going from cached to draw-direct
  1774. X */
  1775. X        if ( 0L != ( value & TA_ALWAYS_REFRESH ) ) {
  1776. X            update_tty ( window ) ;
  1777. X        }
  1778. X        break ;
  1779. X    case TTY_ATTRIB_FOREGROUND :
  1780. X/*
  1781. X * Set foreground color
  1782. X */
  1783. X         TA_TO_RGB ( value , rgb_color ) ;
  1784. X        select_offscreen_port ( record ) ;
  1785. X        RGBForeColor ( & rgb_color ) ;
  1786. X        select_onscreen_window ( record ) ;
  1787. X        RGBForeColor ( & rgb_color ) ;
  1788. X        break ;
  1789. X    case TTY_ATTRIB_BACKGROUND :
  1790. X/*
  1791. X * Set background color
  1792. X */
  1793. X         TA_TO_RGB ( value , rgb_color ) ;
  1794. X        select_offscreen_port ( record ) ;
  1795. X        RGBBackColor ( & rgb_color ) ;
  1796. X        select_onscreen_window ( record ) ;
  1797. X        RGBBackColor ( & rgb_color ) ;
  1798. X        break ;
  1799. X    default :
  1800. X        break ;
  1801. X    }
  1802. X    return noErr ;
  1803. X}
  1804. X
  1805. X
  1806. X/*
  1807. X * Scroll the window. Positive is up/left. scroll_tty ( window , 0 , 1 ) is a line feed.
  1808. X * Scroll flushes the accumulated update area by calling update_tty().
  1809. X */
  1810. Xpascal short
  1811. Xscroll_tty ( WindowPtr window , short delta_x , short delta_y ) {
  1812. XRgnHandle rgn ;
  1813. XRECORD ( record ) ;
  1814. X
  1815. X    select_onscreen_window ( record ) ;
  1816. X    s_err = update_tty ( window ) ;
  1817. X
  1818. X    rgn = NewRgn ( ) ;
  1819. X
  1820. X    select_offscreen_port ( record ) ;
  1821. X    ScrollRect ( & ( record -> its_bits . bounds ) , - delta_x * record -> char_width ,
  1822. X        - delta_y * record -> row_height , rgn ) ;
  1823. X    EraseRgn ( rgn ) ;
  1824. X    SetEmptyRgn ( rgn ) ;
  1825. X
  1826. X    select_onscreen_window ( record ) ;
  1827. X    ScrollRect ( & ( record -> its_bits . bounds ) , - delta_x * record -> char_width ,
  1828. X        - delta_y * record -> row_height , rgn ) ;
  1829. X    EraseRgn ( rgn ) ;
  1830. X    DisposeRgn ( rgn ) ;
  1831. X
  1832. X    record -> y_curs -= delta_y ;
  1833. X    record -> x_curs -= delta_x ;
  1834. X
  1835. X    return noErr ;
  1836. X}
  1837. X
  1838. X
  1839. X/*
  1840. X * Clear the screen. Immediate.
  1841. X */
  1842. Xpascal short
  1843. Xclear_tty ( WindowPtr window ) {
  1844. XRECORD ( record ) ;
  1845. X
  1846. X    select_offscreen_port ( record ) ;
  1847. X    erase_rect ( record , & ( record -> its_bits . bounds ) ) ;
  1848. X    select_onscreen_window ( record ) ;
  1849. X    curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
  1850. X    erase_rect ( record , & ( record -> its_bits . bounds ) ) ;
  1851. X#if CLIP_RECT_ONLY
  1852. X    empty_rect ( & ( record -> invalid_rect ) ) ;
  1853. X#else
  1854. X    SetEmptyRgn ( record -> invalid_part ) ;
  1855. X#endif
  1856. X    curs_pos ( record , record -> x_curs , record -> y_curs , 1 ) ;
  1857. X
  1858. X    return noErr ;
  1859. X}
  1860. X
  1861. X
  1862. X/*
  1863. X * Resize the area - clears and reallocates the bitmap.
  1864. X */
  1865. Xpascal short
  1866. Xresize_tty_area ( WindowPtr window , short x_size , short y_size ) {
  1867. XRECORD ( record ) ;
  1868. X
  1869. X    record -> x_size = x_size ;
  1870. X    record -> y_size = y_size ;
  1871. X
  1872. X    return force_tty_coordinate_system_recalc ( window ) ;
  1873. X}
  1874. X
  1875. X
  1876. X/*
  1877. X * Echo to the user if echo mode on
  1878. X */
  1879. Xstatic void
  1880. Xdo_add_input_character ( tty_record * record , unsigned char character ) {
  1881. X    if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_ECHO_INPUT ) ) {
  1882. X        add_tty_char ( record -> its_window , character ) ;
  1883. X    }
  1884. X}
  1885. X
  1886. X
  1887. X#if TTY_INPUT
  1888. X/*
  1889. X * Add a key in the queue.
  1890. X */
  1891. Xstatic short
  1892. Xdo_add_key ( tty_record * record , long message ) {
  1893. X    if ( record -> input_buffer_len >= record -> input_buffer_limit ) {
  1894. X        do_tty_beep ( record ) ;
  1895. X        return general_failure ;
  1896. X    } else {
  1897. X/*
  1898. X * If input is cooked, we should fix up this here line to allow line editting...
  1899. X */
  1900. X        record -> input_buffer [ record -> input_buffer_len ++ ] = message & 0xff ;
  1901. X        do_add_input_character ( record , message & 0xff ) ;
  1902. X        return noErr ;
  1903. X    }
  1904. X}
  1905. X#endif
  1906. X
  1907. X
  1908. X/*
  1909. X * Add a key in the queue.
  1910. X */
  1911. Xstatic short
  1912. Xdo_cmd_key ( tty_record * record , EventRecord * event ) {
  1913. X    pascal void ( * callback ) ( EventRecord * event , WindowPtr window ) =
  1914. X        ( pascal void ( * ) ( EventRecord * , WindowPtr ) )
  1915. X        record -> attribute [ TTY_COMMAND_KEY_CALLBACK ] ;
  1916. X
  1917. X    if ( callback ) {
  1918. X        ( * callback ) ( event , record -> its_window ) ;
  1919. X        return noErr ;
  1920. X    }
  1921. X    return general_failure ;
  1922. X}
  1923. X
  1924. X
  1925. X/*
  1926. X * Handle a tty event:
  1927. X * Updates, pertaining to our window.
  1928. X * Key downs, entered into the queue (if we are frontmost)
  1929. X */
  1930. Xpascal short
  1931. Xhandle_tty_event ( WindowPtr window , EventRecord * event ) {
  1932. XRECORD ( record ) ;
  1933. X
  1934. X    update_tty ( window ) ;
  1935. X
  1936. X    if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_BLINKING_CURSOR ) ) {
  1937. X        if ( event -> when > record -> last_cursor + GetCaretTime ( ) ) {
  1938. X            curs_pos ( record , record -> x_curs , record -> y_curs ,
  1939. X                ! record -> curs_state ) ;
  1940. X            record -> last_cursor = event -> when ;
  1941. X        }
  1942. X    }
  1943. X
  1944. X    switch ( event -> what ) {
  1945. X    case updateEvt :
  1946. X        if ( event -> message == ( long ) window ) {
  1947. X            BeginUpdate ( window ) ;
  1948. X            erase_rect ( record , & ( record -> its_bits . bounds ) ) ;
  1949. X            tty_environment_changed ( window ) ;
  1950. X            s_err = image_tty ( window ) ;
  1951. X            EndUpdate ( window ) ;
  1952. X            return s_err ;
  1953. X        }
  1954. X        break ;
  1955. X#if TTY_INPUT
  1956. X    case keyDown :
  1957. X    case autoKey :
  1958. X        if ( FrontWindow ( ) == window ) {
  1959. X            if ( event -> modifiers & cmdKey ) {
  1960. X                return do_cmd_key ( record , event ) ;
  1961. X            } else {
  1962. X                return do_add_key ( record , event -> message ) ;
  1963. X            }
  1964. X        }
  1965. X        break ;
  1966. X#endif
  1967. X    deafult :
  1968. X        break ;
  1969. X    }
  1970. X
  1971. X    return general_failure ;
  1972. X}
  1973. X
  1974. X
  1975. X/*
  1976. X * Draw an image of the tty - used for update events and can be called
  1977. X * for screen dumps.
  1978. X */
  1979. Xpascal short
  1980. Ximage_tty ( WindowPtr window ) {
  1981. XRect r ;
  1982. XRECORD ( record ) ;
  1983. X
  1984. X    select_onscreen_window ( record ) ;
  1985. X    copy_bits ( record , & ( record -> its_bits . bounds ) , srcCopy , NULL ) ;
  1986. X    if ( record -> curs_state ) {
  1987. X
  1988. X        pos_rect ( record , & r , record -> x_curs , record -> y_curs ,
  1989. X            record -> x_curs , record -> y_curs ) ;
  1990. X        InvertRect ( & r ) ;
  1991. X    }
  1992. X
  1993. X    return noErr ;
  1994. X}
  1995. X
  1996. X
  1997. X#if TTY_INPUT
  1998. X
  1999. X/*
  2000. X * Read a character depending on the input mode
  2001. X */
  2002. Xpascal short
  2003. Xgetchar_tty ( WindowPtr window , short * character ) {
  2004. XRECORD ( record ) ;
  2005. X
  2006. X    if ( 0L != ( record -> attribute [ TTY_ATTRIB_CURSOR ] & TA_RAW_INPUT ) ) {
  2007. X        while ( ! record -> input_buffer_len ) {
  2008. X        EventRecord er ;
  2009. X
  2010. X            WaitNextEvent ( -1 , & er , GetCaretTime ( ) , NULL ) ;
  2011. X            if ( handle_tty_event ( window , & er ) ) {
  2012. X                switch ( er . what ) {
  2013. X                default :
  2014. X                    break ;
  2015. X                }
  2016. X            }
  2017. X        }
  2018. X        * character = 
  2019. X    } else {
  2020. X
  2021. X    }
  2022. X}
  2023. X
  2024. X#endif /* TTY_INPUT */
  2025. X
  2026. X#if EXTENDED_SUPPORT
  2027. X/*
  2028. X * Delete or insert operations used by many terminals can bottleneck through
  2029. X * here. Note that the order of executin for row/colum insertions is NOT
  2030. X * specified. Negative values for num_ mean delete, zero means no effect.
  2031. X */
  2032. Xpascal short
  2033. Xmangle_tty_rows_columns ( WindowPtr window , short from_row , short num_rows ,
  2034. X    short from_column , short num_columns ) {
  2035. XRect r ;
  2036. XRgnHandle rh = NewRgn ( ) ;
  2037. XRECORD ( record ) ;
  2038. X
  2039. X    update_tty ( window ) ; /* Always make sure screen is OK */
  2040. X    curs_pos ( record , record -> x_curs , record -> y_curs , 0 ) ;
  2041. X
  2042. X    if ( num_rows ) {
  2043. X        pos_rect ( record , & r , 0 , from_row , record -> x_size - 1 ,
  2044. X            record -> y_size - 1 ) ;
  2045. X        select_offscreen_port ( record ) ;
  2046. X        ScrollRect ( & r , 0 , num_rows * record -> row_height , rh ) ;
  2047. X        EraseRgn ( rh ) ;
  2048. X        SetEmptyRgn ( rh ) ;
  2049. X        select_onscreen_window ( record ) ;
  2050. X        ScrollRect ( & r , 0 , num_rows * record -> row_height , rh ) ;
  2051. X        EraseRgn ( rh ) ;
  2052. X        SetEmptyRgn ( rh ) ;
  2053. X    }
  2054. X    if ( num_columns ) {
  2055. X        pos_rect ( record , & r , from_column , 0 , record -> x_size - 1 ,
  2056. X            record -> y_size - 1 ) ;
  2057. X        select_offscreen_port ( record ) ;
  2058. X        ScrollRect ( & r , num_columns * record -> char_width , 0 , rh ) ;
  2059. X        EraseRgn ( rh ) ;
  2060. X        SetEmptyRgn ( rh ) ;
  2061. X        select_onscreen_window ( record ) ;
  2062. X        ScrollRect ( & r , num_columns * record -> char_width , 0 , rh ) ;
  2063. X        EraseRgn ( rh ) ;
  2064. X        SetEmptyRgn ( rh ) ;
  2065. X    }
  2066. X    DisposeRgn ( rh ) ;
  2067. X    if ( record -> x_curs >= from_column ) {
  2068. X        record -> x_curs += num_columns ;
  2069. X    }
  2070. X    if ( record -> y_curs >= from_row ) {
  2071. X        record -> y_curs += num_rows ;
  2072. X    }
  2073. X    curs_pos ( record , record -> x_curs , record -> y_curs , 1 ) ;
  2074. X
  2075. X    return noErr ;
  2076. X}
  2077. X
  2078. X
  2079. X/*
  2080. X * Clear an area
  2081. X */
  2082. Xpascal short
  2083. Xclear_tty_window ( WindowPtr window , short from_x , short from_y ,
  2084. X    short to_x , short to_y ) {
  2085. XRect r ;
  2086. XRECORD ( record ) ;
  2087. X
  2088. X    if ( from_x > to_x || from_y > to_y ) {
  2089. X        return general_failure ;
  2090. X    }
  2091. X    pos_rect ( record , & r , from_x , from_y , to_x , to_y ) ;
  2092. X    select_offscreen_port ( record ) ;
  2093. X    erase_rect ( record , & r ) ;
  2094. X    accumulate_rect ( record , & r ) ;
  2095. X    if ( DRAW_DIRECT ) {
  2096. X        update_tty ( window ) ;
  2097. X    }
  2098. X}
  2099. X
  2100. X
  2101. X/*
  2102. X * Frame an area in an aesthetically pleasing way.
  2103. X */
  2104. Xpascal short
  2105. Xframe_tty_window ( WindowPtr window , short from_x , short from_y ,
  2106. X    short to_x , short to_y , short frame_fatness ) {
  2107. XRect r ;
  2108. XRECORD ( record ) ;
  2109. X
  2110. X    if ( from_x > to_x || from_y > to_y ) {
  2111. X        return general_failure ;
  2112. X    }
  2113. X    pos_rect ( record , & r , from_x , from_y , to_x , to_y ) ;
  2114. X    select_offscreen_port ( record ) ;
  2115. X    PenSize ( frame_fatness , frame_fatness ) ;
  2116. X    FrameRect ( & r ) ;
  2117. X    PenNormal ( ) ;
  2118. X    accumulate_rect ( record , & r ) ;
  2119. X    if ( DRAW_DIRECT ) {
  2120. X        update_tty ( window ) ;
  2121. X    }
  2122. X}
  2123. X
  2124. X
  2125. X/*
  2126. X * Highlighting a specific part of the tty window
  2127. X */
  2128. Xpascal short
  2129. Xinvert_tty_window ( WindowPtr window , short from_x , short from_y ,
  2130. X    short to_x , short to_y ) {
  2131. XRect r ;
  2132. XRECORD ( record ) ;
  2133. X
  2134. X    if ( from_x > to_x || from_y > to_y ) {
  2135. X        return general_failure ;
  2136. X    }
  2137. X    pos_rect ( record , & r , from_x , from_y , to_x , to_y ) ;
  2138. X    select_offscreen_port ( record ) ;
  2139. X    InvertRect ( & r ) ;
  2140. X    accumulate_rect ( record , & r ) ;
  2141. X    if ( DRAW_DIRECT ) {
  2142. X        update_tty ( window ) ;
  2143. X    }
  2144. X}
  2145. X
  2146. X
  2147. Xstatic void
  2148. Xcanonical_rect ( Rect * r , short x1 , short y1 , short x2 , short y2 ) {
  2149. X    if ( x1 < x2 ) {
  2150. X        if ( y1 < y2 ) {
  2151. X            SetRect ( r , x1 , x2 , y1 , y2 ) ;
  2152. X        } else {
  2153. X            SetRect ( r , x1 , x2 , y2 , y1 ) ;
  2154. X        }
  2155. X    } else {
  2156. X        if ( y1 < y2 ) {
  2157. X            SetRect ( r , x2 , x1 , y1 , y2 ) ;
  2158. X        } else {
  2159. X            SetRect ( r , x2 , x1 , y2 , y1 ) ;
  2160. X        }
  2161. X    }
  2162. X}
  2163. X
  2164. X
  2165. X/*
  2166. X * Line drawing - very device dependent
  2167. X */
  2168. Xpascal short
  2169. Xdraw_tty_line ( WindowPtr window , short from_x , short from_y ,
  2170. X    short to_x , short to_y ) {
  2171. XRect r ;
  2172. XRECORD ( record ) ;
  2173. X
  2174. X    select_offscreen_port ( record ) ;
  2175. X    MoveTo ( from_x , from_y ) ;
  2176. X    LineTo ( to_x , to_y ) ;
  2177. X    canonical_rect ( & r , from_x , from_y , to_x , to_y ) ;
  2178. X    accumulate_rect ( record , & r ) ;
  2179. X    if ( DRAW_DIRECT ) {
  2180. X        update_tty ( window ) ;
  2181. X    }
  2182. X}
  2183. X
  2184. X
  2185. X#endif /* EXTENDED_SUPPORT */
  2186. END_OF_FILE
  2187. if test 36517 -ne `wc -c <'sys/mac/mactty.c'`; then
  2188.     echo shar: \"'sys/mac/mactty.c'\" unpacked with wrong size!
  2189. fi
  2190. # end of 'sys/mac/mactty.c'
  2191. echo shar: End of archive 23 \(of 33\).
  2192. cp /dev/null ark23isdone
  2193. MISSING=""
  2194. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  2195.     if test ! -f ark${I}isdone ; then
  2196.     MISSING="${MISSING} ${I}"
  2197.     fi
  2198. done
  2199. if test "${MISSING}" = "" ; then
  2200.     echo You have unpacked all 33 archives.
  2201.     echo "Now execute ./patchit.sh"
  2202.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2203. else
  2204.     echo You still need to unpack the following archives:
  2205.     echo "        " ${MISSING}
  2206. fi
  2207. ##  End of shell archive.
  2208. exit 0
  2209.