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

  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: v16i060:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part52/108
  5. Message-ID: <4363@master.CNA.TEK.COM>
  6. Date: 1 Feb 93 19:43:02 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2031
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1610
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 60
  14. Archive-name: nethack31/Part52
  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 52 (of 108)."
  27. # Contents:  src/display.c sys/vms/gnutermcap.c
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:07 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/display.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/display.c'\"
  32. else
  33. echo shar: Extracting \"'src/display.c'\" \(35153 characters\)
  34. sed "s/^X//" >'src/display.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)display.c    3.1    92/10/25    */
  36. X/* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
  37. X/* and Dave Cohrs, 1990.                      */
  38. X/* NetHack may be freely redistributed.  See license for details. */
  39. X
  40. X/*
  41. X *            THE NEW DISPLAY CODE
  42. X *
  43. X * The old display code has been broken up into three parts: vision, display,
  44. X * and drawing.  Vision decides what locations can and cannot be physically
  45. X * seen by the hero.  Display decides _what_ is displayed at a given location.
  46. X * Drawing decides _how_ to draw a monster, fountain, sword, etc.
  47. X *
  48. X * The display system uses information from the vision system to decide
  49. X * what to draw at a given location.  The routines for the vision system
  50. X * can be found in vision.c and vision.h.  The routines for display can
  51. X * be found in this file (display.c) and display.h.  The drawing routines
  52. X * are part of the window port.  See doc/window.doc for the drawing
  53. X * interface.
  54. X *
  55. X * The display system deals with an abstraction called a glyph.  Anything
  56. X * that could possibly be displayed has a unique glyph identifier.
  57. X *
  58. X * What is seen on the screen is a combination of what the hero remembers
  59. X * and what the hero currently sees.  Objects and dungeon features (walls
  60. X * doors, etc) are remembered when out of sight.  Monsters and temporary
  61. X * effects are not remembered.  Each location on the level has an
  62. X * associated glyph.  This is the hero's _memory_ of what he or she has
  63. X * seen there before.
  64. X *
  65. X * Display rules:
  66. X *
  67. X *    If the location is in sight, display in order:
  68. X *        visible monsters
  69. X *        visible objects
  70. X *        known traps
  71. X *        background
  72. X *
  73. X *    If the location is out of sight, display in order:
  74. X *        sensed monsters (telepathy)
  75. X *        memory
  76. X *
  77. X *
  78. X *
  79. X * Here is a list of the major routines in this file to be used externally:
  80. X *
  81. X * newsym
  82. X *
  83. X * Possibly update the screen location (x,y).  This is the workhorse routine.
  84. X * It is always correct --- where correct means following the in-sight/out-
  85. X * of-sight rules.  **Most of the code should use this routine.**  This
  86. X * routine updates the map and displays monsters.
  87. X *
  88. X *
  89. X * map_background
  90. X * map_object
  91. X * map_trap
  92. X * unmap_object
  93. X *
  94. X * If you absolutely must override the in-sight/out-of-sight rules, there
  95. X * are two possibilities.  First, you can mess with vision to force the
  96. X * location in sight then use newsym(), or you can  use the map_* routines.
  97. X * The first has not been tried [no need] and the second is used in the
  98. X * detect routines --- detect object, magic mapping, etc.  The map_*
  99. X * routines *change* what the hero remembers.  All changes made by these
  100. X * routines will be sticky --- they will survive screen redraws.  Do *not*
  101. X * use these for things that only temporarily change the screen.  These
  102. X * routines are also used directly by newsym().  unmap_object is used to
  103. X * clear a remembered object when/if detection reveals it isn't there.
  104. X *
  105. X *
  106. X * show_glyph
  107. X *
  108. X * This is direct (no processing in between) buffered access to the screen.
  109. X * Temporary screen effects are run through this and its companion,
  110. X * flush_screen().  There is yet a lower level routine, print_glyph(),
  111. X * but this is unbuffered and graphic dependent (i.e. it must be surrounded
  112. X * by graphic set-up and tear-down routines).  Do not use print_glyph().
  113. X *
  114. X *
  115. X * see_monsters
  116. X * see_objects
  117. X *
  118. X * These are only used when something affects all of the monsters or
  119. X * objects.  For objects, the only thing is hallucination.  For monsters,
  120. X * there are hallucination and changing from/to blindness, etc.
  121. X *
  122. X *
  123. X * tmp_at
  124. X *
  125. X * This is a useful interface for displaying temporary items on the screen.
  126. X * Its interface is different than previously, so look at it carefully.
  127. X *
  128. X *
  129. X *
  130. X * Parts of the rm structure that are used:
  131. X *
  132. X *    typ    - What is really there.
  133. X *    glyph    - What the hero remembers.  This will never be a monster.
  134. X *          Monsters "float" above this.
  135. X *    lit    - True if the position is lit.  An optimization for
  136. X *          lit/unlit rooms.
  137. X *    waslit    - True if the position was *remembered* as lit.
  138. X *    seen    - Set to true when the location is seen or felt as it really
  139. X *          is.  This is used primarily for walls, which look like stone
  140. X *          if seen from the outside of a room.  However, this is
  141. X *          also used as a guide for blind heros.  If the hero has
  142. X *          seen or felt a room feature underneath a boulder, when the
  143. X *          boulder is moved, the hero should see it again.  This is
  144. X *          also used as an indicator for unmapping detected objects.
  145. X *
  146. X *    doormask   - Additional information for the typ field.
  147. X *    horizontal - Indicates whether the wall or door is horizontal or
  148. X *             vertical.
  149. X */
  150. X#include "hack.h"
  151. X
  152. Xstatic void FDECL(display_monster,(XCHAR_P,XCHAR_P,struct monst *,int,XCHAR_P));
  153. Xstatic int FDECL(swallow_to_glyph, (int, int));
  154. X
  155. X#ifdef INVISIBLE_OBJECTS
  156. X/*
  157. X * vobj_at()
  158. X *
  159. X * Returns a pointer to an object if the hero can see an object at the
  160. X * given location.  This takes care of invisible objects.  NOTE, this
  161. X * assumes that the hero is not blind and on top of the object pile.
  162. X * It does NOT take into account that the location is out of sight, or,
  163. X * say, one can see blessed, etc.
  164. X */
  165. Xstruct obj *
  166. Xvobj_at(x,y)
  167. X    xchar x,y;
  168. X{
  169. X    register struct obj *obj = level.objects[x][y];
  170. X
  171. X    while (obj) {
  172. X    if (!obj->oinvis || See_invisible) return obj;
  173. X    obj = obj->nexthere;
  174. X    }
  175. X    return ((struct obj *) 0);
  176. X}
  177. X#endif    /* else vobj_at() is defined in display.h */
  178. X
  179. X/*
  180. X * The routines map_background(), map_object(), and map_trap() could just
  181. X * as easily be:
  182. X *
  183. X *    map_glyph(x,y,glyph,show)
  184. X *
  185. X * Which is called with the xx_to_glyph() in the call.  Then I can get
  186. X * rid of 3 routines that don't do very much anyway.  And then stop
  187. X * having to create fake objects and traps.  However, I am reluctant to
  188. X * make this change.
  189. X */
  190. X
  191. X/*
  192. X * map_background()
  193. X *
  194. X * Make the real background part of our map.  This routine assumes that
  195. X * the hero can physically see the location.  Update the screen if directed.
  196. X */
  197. Xvoid
  198. Xmap_background(x, y, show)
  199. X    register xchar x,y;
  200. X    register int  show;
  201. X{
  202. X    register int glyph = back_to_glyph(x,y);
  203. X
  204. X    if (level.flags.hero_memory)
  205. X    levl[x][y].glyph = glyph;
  206. X    if (show) show_glyph(x,y, glyph);
  207. X}
  208. X
  209. X/*
  210. X * map_trap()
  211. X *
  212. X * Map the trap and print it out if directed.  This routine assumes that the
  213. X * hero can physically see the location.
  214. X */
  215. Xvoid
  216. Xmap_trap(trap, show)
  217. X    register struct trap *trap;
  218. X    register int     show;
  219. X{
  220. X    register int x = trap->tx, y = trap->ty;
  221. X    register int glyph = trap_to_glyph(trap);
  222. X
  223. X    if (level.flags.hero_memory)
  224. X    levl[x][y].glyph = glyph;
  225. X    if (show) show_glyph(x, y, glyph);
  226. X}
  227. X
  228. X/*
  229. X * map_object()
  230. X *
  231. X * Map the given object.  This routine assumes that the hero can physically
  232. X * see the location of the object.  Update the screen if directed.
  233. X */
  234. Xvoid
  235. Xmap_object(obj, show)
  236. X    register struct obj *obj;
  237. X    register int    show;
  238. X{
  239. X    register int x = obj->ox, y = obj->oy;
  240. X    register int glyph = obj_to_glyph(obj);
  241. X
  242. X    if (level.flags.hero_memory)
  243. X    levl[x][y].glyph = glyph;
  244. X    if (show) show_glyph(x, y, glyph);
  245. X}
  246. X
  247. X/*
  248. X * unmap_object()
  249. X *
  250. X * Remove something from the map when detection reveals that it isn't
  251. X * there any more.  Replace it with background or known trap, but not
  252. X * with any other remembered object.  No need to update the display;
  253. X * a full update is imminent.
  254. X *
  255. X * This isn't quite correct due to overloading of the seen bit.  But
  256. X * it works well enough for now.
  257. X */
  258. Xvoid
  259. Xunmap_object(x, y)
  260. X    register int x, y;
  261. X{
  262. X    register struct trap *trap;
  263. X
  264. X    if (!level.flags.hero_memory) return;
  265. X
  266. X    if ((trap = t_at(x,y)) != 0 && trap->tseen && !covers_traps(x,y))
  267. X    map_trap(trap, 0);
  268. X    else if (levl[x][y].seen) {
  269. X    struct rm *lev = &levl[x][y];
  270. X
  271. X    map_background(x, y, 0);
  272. X
  273. X    /* turn remembered dark room squares dark */
  274. X    if (!lev->waslit && lev->glyph == cmap_to_glyph(S_room) &&
  275. X                                lev->typ == ROOM)
  276. X        lev->glyph = cmap_to_glyph(S_stone);
  277. X    } else 
  278. X    levl[x][y].glyph = cmap_to_glyph(S_stone);    /* default val */
  279. X}
  280. X
  281. X
  282. X/*
  283. X * map_location()
  284. X *
  285. X * Make whatever at this location show up.  This is only for non-living
  286. X * things.  This will not handle feeling invisible objects correctly.
  287. X */
  288. X#define map_location(x,y,show)                        \
  289. X{                                    \
  290. X    register struct obj   *obj;                        \
  291. X    register struct trap  *trap;                    \
  292. X                                    \
  293. X    if ((obj = vobj_at(x,y)) && !covers_objects(x,y))            \
  294. X    map_object(obj,show);                        \
  295. X    else if ((trap = t_at(x,y)) && trap->tseen && !covers_traps(x,y))    \
  296. X    map_trap(trap,show);                        \
  297. X    else                                \
  298. X    map_background(x,y,show);                    \
  299. X}
  300. X
  301. X
  302. X/*
  303. X * display_monster()
  304. X *
  305. X * Note that this is *not* a map_XXXX() function!  Monsters sort of float
  306. X * above everything.
  307. X *
  308. X * Yuck.  Display body parts by recognizing that the display position is
  309. X * not the same as the monster position.  Currently the only body part is
  310. X * a worm tail.
  311. X *  
  312. X */
  313. Xstatic void
  314. Xdisplay_monster(x, y, mon, in_sight, worm_tail)
  315. X    register xchar x, y;    /* display position */
  316. X    register struct monst *mon;    /* monster to display */
  317. X    int in_sight;        /* TRUE if the monster is physically seen */
  318. X    register xchar worm_tail;    /* mon is actually a worm tail */
  319. X{
  320. X    register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING);
  321. X    register int sensed = mon_mimic &&
  322. X    (Protection_from_shape_changers || sensemon(mon));
  323. X
  324. X    /*
  325. X     * We must do the mimic check first.  If the mimic is mimicing something,
  326. X     * and the location is in sight, we have to change the hero's memory
  327. X     * so that when the position is out of sight, the hero remembers what
  328. X     * the mimic was mimicing.
  329. X     */
  330. X
  331. X    if (mon_mimic && in_sight) {
  332. X    switch (mon->m_ap_type) {
  333. X        default:
  334. X        impossible("display_monster:  bad m_ap_type value [ = %d ]",
  335. X                            (int) mon->m_ap_type);
  336. X        case M_AP_NOTHING:
  337. X        show_glyph(x, y, mon_to_glyph(mon));
  338. X        break;
  339. X
  340. X        case M_AP_FURNITURE: {
  341. X        /*
  342. X         * This is a poor man's version of map_background().  I can't
  343. X         * use map_background() because we are overriding what is in
  344. X         * the 'typ' field.  Maybe have map_background()'s parameters
  345. X         * be (x,y,glyph) instead of just (x,y).
  346. X         *
  347. X         * mappearance is currently set to an S_ index value in
  348. X         * makemon.c.
  349. X         */
  350. X        register int glyph = cmap_to_glyph(mon->mappearance);
  351. X        levl[x][y].glyph = glyph;
  352. X        if (!sensed) show_glyph(x,y, glyph);
  353. X        break;
  354. X        }
  355. X
  356. X        case M_AP_OBJECT: {
  357. X        struct obj obj;    /* Make a fake object to send    */
  358. X                /* to map_object().        */
  359. X        obj.ox = x;
  360. X        obj.oy = y;
  361. X        obj.otyp = mon->mappearance;
  362. X        obj.corpsenm = PM_TENGU;    /* if mimicing a corpse */
  363. X        map_object(&obj,!sensed);
  364. X        break;
  365. X        }
  366. X
  367. X        case M_AP_MONSTER:
  368. X        show_glyph(x,y, monnum_to_glyph(what_mon(mon->mappearance)));
  369. X        break;
  370. X    }
  371. X    
  372. X    }
  373. X
  374. X    /* If the mimic is unsucessfully mimicing something, display the monster */
  375. X    if (!mon_mimic || sensed) {
  376. X    if (mon->mtame) {
  377. X        if (worm_tail)
  378. X        show_glyph(x,y, petnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)));
  379. X        else    
  380. X        show_glyph(x,y, pet_to_glyph(mon));
  381. X    } else {
  382. X        if (worm_tail)
  383. X        show_glyph(x,y, monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)));
  384. X        else    
  385. X        show_glyph(x,y, mon_to_glyph(mon));
  386. X    }
  387. X    }
  388. X}
  389. X
  390. X/*
  391. X * feel_location()
  392. X *
  393. X * Feel the given location.  This assumes that the hero is blind and that
  394. X * the given position is either the hero's or one of the eight squares
  395. X * adjacent to the hero (except for a boulder push).
  396. X */
  397. Xvoid
  398. Xfeel_location(x, y)
  399. X    xchar x, y;
  400. X{
  401. X    struct rm *lev = &(levl[x][y]);
  402. X    struct obj *boulder;
  403. X    register struct monst *mon;
  404. X
  405. X    /* The hero can't feel non pool locations while under water. */
  406. X    if (Underwater && !Is_waterlevel(&u.uz) && ! is_pool(x,y))
  407. X    return;
  408. X
  409. X    /* If the hero is not in a corridor, then she will feel the wall as a */
  410. X    /* wall.  It doesn't matter if the hero is levitating or not.      */
  411. X    if ((IS_WALL(lev->typ) || lev->typ == SDOOR) &&
  412. X                        levl[u.ux][u.uy].typ != CORR)
  413. X    lev->seen = 1;
  414. X
  415. X    if (Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
  416. X    /*
  417. X     * Levitation Rules.  It is assumed that the hero can feel the state
  418. X     * of the walls around herself and can tell if she is in a corridor,
  419. X     * room, or doorway.  Boulders are felt because they are large enough.
  420. X     * Anything else is unknown because the hero can't reach the ground.
  421. X     * This makes things difficult.
  422. X     *
  423. X     * Check (and display) in order:
  424. X     *
  425. X     *    + Stone, walls, and closed doors.
  426. X     *    + Boulders.  [see a boulder before a doorway]
  427. X     *    + Doors.
  428. X     *    + Room/water positions
  429. X     *    + Everything else (hallways!)
  430. X     */
  431. X    if (IS_ROCK(lev->typ) || (IS_DOOR(lev->typ) &&
  432. X                (lev->doormask & (D_LOCKED | D_CLOSED)))) {
  433. X        map_background(x, y, 1);
  434. X    } else if (boulder = sobj_at(BOULDER,x,y)) {
  435. X        map_object(boulder, 1);
  436. X    } else if (IS_DOOR(lev->typ)) {
  437. X        map_background(x, y, 1);
  438. X    } else if (IS_ROOM(lev->typ) || IS_POOL(lev->typ)) {
  439. X        /*
  440. X         * An open room or water location.  Normally we wouldn't touch
  441. X         * this, but we have to get rid of remembered boulder symbols.
  442. X         * This will only occur in rare occations when the hero goes
  443. X         * blind and doesn't find a boulder where expected (something
  444. X         * came along and picked it up).  We know that there is not a
  445. X         * boulder at this location.  Show fountains, pools, etc.
  446. X         * underneath if already seen.  Otherwise, show the appropriate
  447. X         * floor symbol.
  448. X         *
  449. X         * This isn't quite correct.  If the boulder was on top of some
  450. X         * other objects they should be seen once the boulder is removed.
  451. X         * However, we have no way of knowing that what is there now
  452. X         * was there then.  So we let the hero have a lapse of memory.
  453. X         * We could also just display what is currently on the top of the
  454. X         * object stack (if anything).
  455. X         */
  456. X        if (lev->glyph == objnum_to_glyph(BOULDER)) {
  457. X        if (lev->typ != ROOM && lev->seen) {
  458. X            map_background(x, y, 1);
  459. X        } else {
  460. X            lev->glyph = lev->waslit ? cmap_to_glyph(S_room) :
  461. X                           cmap_to_glyph(S_stone);
  462. X            show_glyph(x,y,lev->glyph);
  463. X        }
  464. X        }
  465. X    } else {
  466. X        /* We feel it (I think hallways are the only things left). */
  467. X        map_background(x, y, 1);
  468. X        /* Corridors are never felt as lit (unless remembered that way) */
  469. X        /* (lit_corridor only).                        */
  470. X        if (lev->typ == CORR &&
  471. X            lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit)
  472. X        show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
  473. X    }
  474. X    } else {
  475. X    map_location(x, y, 1);
  476. X
  477. X    if (Punished) {
  478. X        /*
  479. X         * A ball or chain is only felt if it is first on the object
  480. X         * location list.  Otherwise, we need to clear the felt bit ---
  481. X         * something has been dropped on the ball/chain.  If the bit is
  482. X         * not cleared, then when the ball/chain is moved it will drop
  483. X         * the wrong glyph.
  484. X         */
  485. X        if (uchain->ox == x && uchain->oy == y) {
  486. X        if (level.objects[x][y] == uchain)
  487. X            u.bc_felt |= BC_CHAIN;
  488. X        else
  489. X            u.bc_felt &= ~BC_CHAIN;    /* do not feel the chain */
  490. X        }
  491. X        if (!carried(uball) && uball->ox == x && uball->oy == y) {
  492. X        if (level.objects[x][y] == uball)
  493. X            u.bc_felt |= BC_BALL;
  494. X        else
  495. X            u.bc_felt &= ~BC_BALL;    /* do not feel the ball */
  496. X        }
  497. X    }
  498. X
  499. X    /* Floor spaces are dark if unlit.  Corridors are dark if unlit. */
  500. X    if (lev->typ == ROOM &&
  501. X            lev->glyph == cmap_to_glyph(S_room) && !lev->waslit)
  502. X        show_glyph(x,y, lev->glyph = cmap_to_glyph(S_stone));
  503. X    else if (lev->typ == CORR &&
  504. X            lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit)
  505. X        show_glyph(x,y, lev->glyph = cmap_to_glyph(S_corr));
  506. X    }
  507. X    /* draw monster on top if we can sense it */
  508. X    if ((x != u.ux || y != u.uy) && (mon = m_at(x,y)) && sensemon(mon))
  509. X    display_monster(x,y,mon,1,((x != mon->mx)  || (y != mon->my)));
  510. X}
  511. X
  512. X/*
  513. X * newsym()
  514. X *
  515. X * Possibly put a new glyph at the given location.
  516. X */
  517. Xvoid
  518. Xnewsym(x,y)
  519. X    register xchar x,y;
  520. X{
  521. X    register struct monst *mon;
  522. X    register struct rm *lev = &(levl[x][y]);
  523. X    register int see_it;
  524. X    register xchar worm_tail;
  525. X
  526. X    /* only permit updating the hero when swallowed */
  527. X    if (u.uswallow) {
  528. X    if (x == u.ux && y == u.uy) display_self();
  529. X    return;
  530. X    }
  531. X    if (Underwater && !Is_waterlevel(&u.uz)) {
  532. X    /* don't do anything unless (x,y) is an adjacent underwater position */
  533. X    int dx, dy;
  534. X    if (!is_pool(x,y)) return;
  535. X    dx = x - u.ux;    if (dx < 0) dx = -dx;
  536. X    dy = y - u.uy;    if (dy < 0) dy = -dy;
  537. X    if (dx > 1 || dy > 1) return;
  538. X    }
  539. X
  540. X    /* Can physically see the location. */
  541. X    if (cansee(x,y)) {
  542. X    lev->waslit = (lev->lit!=0);    /* remember lit condition */
  543. X
  544. X    if (x == u.ux && y == u.uy) {
  545. X        if (canseeself()) {
  546. X        map_location(x,y,0);    /* map *under* self */
  547. X        display_self();
  548. X        } else
  549. X        /* we can see what is there */
  550. X        map_location(x,y,1);
  551. X    }
  552. X    else if ((mon = m_at(x,y)) &&
  553. X         ((see_it = mon_visible(mon)) || sensemon(mon))) {
  554. X        map_location(x,y,0);     /* map under the monster */
  555. X            worm_tail = ((x != mon->mx)  || (y != mon->my));
  556. X        display_monster(x,y,mon,see_it,worm_tail);
  557. X    }
  558. X    else
  559. X        map_location(x,y,1);    /* map the location */
  560. X    }
  561. X
  562. X    /* Can't see the location. */
  563. X    else {
  564. X    if (x == u.ux && y == u.uy) {
  565. X        feel_location(u.ux, u.uy);        /* forces an update */
  566. X
  567. X        if (canseeself()) display_self();
  568. X    }
  569. X    else if ((mon = m_at(x,y)) && sensemon(mon) &&
  570. X                     !((x != mon->mx)  || (y != mon->my))) {
  571. X        /* Monsters are printed every time. */
  572. X        display_monster(x,y,mon,0,0);
  573. X    }
  574. X    /*
  575. X     * If the location is remembered as being both dark (waslit is false)
  576. X     * and lit (glyph is a lit room or lit corridor) then it was either:
  577. X     *
  578. X     *    (1) A dark location that the hero could see through night
  579. X     *        vision.
  580. X     *
  581. X     *    (2) Darkened while out of the hero's sight.  This can happen
  582. X     *        when cursed scroll of light is read.
  583. X     *
  584. X     * In either case, we have to manually correct the hero's memory to
  585. X     * match waslit.  Deciding when to change waslit is non-trivial.
  586. X     *
  587. X     *  Note:  If flags.lit_corridor is set, then corridors act like room
  588. X     *       squares.  That is, they light up if in night vision range.
  589. X     *       If flags.lit_corridor is not set, then corridors will
  590. X     *       remain dark unless lit by a light spell.
  591. X     *
  592. X     * These checks and changes must be here and not in back_to_glyph().
  593. X     * They are dependent on the position being out of sight.
  594. X     */
  595. X    else if (!lev->waslit) {
  596. X        if (flags.lit_corridor && lev->glyph == cmap_to_glyph(S_litcorr) &&
  597. X                                lev->typ == CORR)
  598. X        show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
  599. X        else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM)
  600. X        show_glyph(x, y, lev->glyph = cmap_to_glyph(S_stone));
  601. X        else
  602. X        goto show_mem;
  603. X    } else {
  604. Xshow_mem:
  605. X        show_glyph(x, y, lev->glyph);
  606. X    }
  607. X    }
  608. X}
  609. X
  610. X
  611. X/*
  612. X * shieldeff()
  613. X *
  614. X * Put magic shield pyrotechnics at the given location.  This *could* be
  615. X * pulled into a platform dependent routine for fancier graphics if desired.
  616. X */
  617. Xvoid
  618. Xshieldeff(x,y)
  619. X    xchar x,y;
  620. X{
  621. X    register int i;
  622. X
  623. X    if (cansee(x,y)) {    /* Don't see anything if can't see the location */
  624. X    for (i = 0; i < SHIELD_COUNT; i++) {
  625. X        show_glyph(x, y, cmap_to_glyph(shield_static[i]));
  626. X        flush_screen(1);    /* make sure the glyph shows up */
  627. X        delay_output();
  628. X    }
  629. X    newsym(x,y);        /* restore the old information */
  630. X    }
  631. X}
  632. X
  633. X
  634. X/*
  635. X * tmp_at()
  636. X *
  637. X * Temporarily place glyphs on the screen.  Do not call delay_output().  It
  638. X * is up to the caller to decide if it wants to wait [presently, everyone
  639. X * but explode() wants to delay].
  640. X *
  641. X * Call:
  642. X *    (DISP_BEAM,   glyph)    open, initialize glyph
  643. X *    (DISP_FLASH,  glyph)    open, initialize glyph
  644. X *    (DISP_CHANGE, glyph)    change glyph
  645. X *    (DISP_END,    0)    close & clean up (second argument doesn't
  646. X *                matter)
  647. X *    (x, y)            display the glyph at the location
  648. X *
  649. X * DISP_BEAM  - Display the given glyph at each location, but do not erase
  650. X *        any until the close call.
  651. X * DISP_FLASH - Display the given glyph at each location, but erase the
  652. X *        previous location's glyph.
  653. X */
  654. Xvoid
  655. Xtmp_at(x, y)
  656. X    int x, y;
  657. X{
  658. X    static coord saved[COLNO];    /* prev positions, only for DISP_BEAM */
  659. X    static int sidx = 0;    /* index of saved previous positions */
  660. X    static int sx = -1, sy;    /* previous position, only for DISP_FLASH */
  661. X    static int status;        /* either DISP_BEAM or DISP_FLASH */
  662. X    static int glyph;        /* glyph to use when printing */
  663. X
  664. X    switch (x) {
  665. X    case DISP_BEAM:
  666. X    case DISP_FLASH:
  667. X        status = x;
  668. X        glyph  = y;
  669. X        flush_screen(0);    /* flush buffered glyphs */
  670. X        break;
  671. X
  672. X    case DISP_CHANGE:
  673. X        glyph = y;
  674. X        break;
  675. X
  676. X    case DISP_END:
  677. X        if (status == DISP_BEAM) {
  678. X        register int i;
  679. X
  680. X        /* Erase (reset) from source to end */
  681. X        for (i = 0; i < sidx; i++)
  682. X            newsym(saved[i].x,saved[i].y);
  683. X        sidx = 0;
  684. X        
  685. X        } else if (sx >= 0) {    /* DISP_FLASH (called at least once) */
  686. X        newsym(sx,sy);    /* reset the location */
  687. X        sx = -1;    /* reset sx to an illegal pos for next time */
  688. X        }
  689. X        break;
  690. X
  691. X    default:    /* do it */
  692. X        if (!cansee(x,y)) break;
  693. X
  694. X        if (status == DISP_BEAM) {
  695. X        saved[sidx  ].x = x;    /* save pos for later erasing */
  696. X        saved[sidx++].y = y;
  697. X        }
  698. X
  699. X        else {    /* DISP_FLASH */
  700. X        if (sx >= 0)        /* not first call */
  701. X            newsym(sx,sy);    /* update the old position */
  702. X
  703. X        sx = x;        /* save previous pos for next call */
  704. X        sy = y;
  705. X        }
  706. X
  707. X        show_glyph(x,y,glyph);    /* show it */
  708. X        flush_screen(0);        /* make sure it shows up */
  709. X        break;
  710. X    } /* end case */
  711. X}
  712. X
  713. X
  714. X/*
  715. X * swallowed()
  716. X *
  717. X * The hero is swallowed.  Show a special graphics sequence for this.  This
  718. X * bypasses all of the display routines and messes with buffered screen
  719. X * directly.  This method works because both vision and display check for
  720. X * being swallowed.
  721. X */
  722. Xvoid
  723. Xswallowed(first)
  724. X    int first;
  725. X{
  726. X    static xchar lastx, lasty;    /* last swallowed position */
  727. X    int swallower;
  728. X
  729. X    if (first)
  730. X    cls();
  731. X    else {
  732. X    register int x, y;
  733. X
  734. X    /* Clear old location */
  735. X    for (y = lasty-1; y <= lasty+1; y++)
  736. X        if(isok(lastx,y)) {
  737. X        for (x = lastx-1; x <= lastx+1; x++)
  738. X            show_glyph(x,y,cmap_to_glyph(S_stone));
  739. X        }
  740. X    }
  741. X
  742. X    swallower = monsndx(u.ustuck->data);
  743. X    /*
  744. X     *  Display the hero surrounded by the monster's stomach.
  745. X     */
  746. X    if(isok(u.ux, u.uy-1)) {
  747. X    show_glyph(u.ux-1, u.uy-1, swallow_to_glyph(swallower, S_sw_tl));
  748. X    show_glyph(u.ux  , u.uy-1, swallow_to_glyph(swallower, S_sw_tc));
  749. X    show_glyph(u.ux+1, u.uy-1, swallow_to_glyph(swallower, S_sw_tr));
  750. X    }
  751. X
  752. X    show_glyph(u.ux-1, u.uy  , swallow_to_glyph(swallower, S_sw_ml));
  753. X    display_self();
  754. X    show_glyph(u.ux+1, u.uy  , swallow_to_glyph(swallower, S_sw_mr));
  755. X
  756. X    if(isok(u.ux, u.uy+1)) {
  757. X    show_glyph(u.ux-1, u.uy+1, swallow_to_glyph(swallower, S_sw_bl));
  758. X    show_glyph(u.ux  , u.uy+1, swallow_to_glyph(swallower, S_sw_bc));
  759. X    show_glyph(u.ux+1, u.uy+1, swallow_to_glyph(swallower, S_sw_br));
  760. X    }
  761. X
  762. X    /* Update the swallowed position. */
  763. X    lastx = u.ux;
  764. X    lasty = u.uy;
  765. X}
  766. X
  767. X/*
  768. X * under_water()
  769. X *
  770. X * Similar to swallowed() in operation.  Shows hero when underwater
  771. X * except when in water level.  Special routines exist for that.
  772. X */
  773. Xvoid
  774. Xunder_water(mode)
  775. X    int mode;
  776. X{
  777. X    static xchar lastx, lasty;
  778. X    static boolean dela;
  779. X    register int x, y;
  780. X
  781. X    /* swallowing has a higher precedence than under water */
  782. X    if (Is_waterlevel(&u.uz) || u.uswallow) return;
  783. X
  784. X    /* full update */
  785. X    if (mode == 1 || dela) {
  786. X    cls();
  787. X    dela = FALSE;
  788. X    }   
  789. X    /* delayed full update */
  790. X    else if (mode == 2) {
  791. X    dela = TRUE;
  792. X    return;
  793. X    }
  794. X    /* limited update */
  795. X    else {
  796. X    for (y = lasty-1; y <= lasty+1; y++)
  797. X        for (x = lastx-1; x <= lastx+1; x++)
  798. X        if (isok(x,y)) 
  799. X            show_glyph(x,y,cmap_to_glyph(S_stone));
  800. X    }
  801. X    for (x = u.ux-1; x <= u.ux+1; x++)
  802. X    for (y = u.uy-1; y <= u.uy+1; y++)
  803. X        if (isok(x,y) && is_pool(x,y)) {
  804. X        if (Blind && !(x == u.ux && y == u.uy))
  805. X            show_glyph(x,y,cmap_to_glyph(S_stone));
  806. X        else    
  807. X            newsym(x,y);
  808. X        }
  809. X    lastx = u.ux;
  810. X    lasty = u.uy;
  811. X}
  812. X
  813. X
  814. X/* ========================================================================= */
  815. X
  816. X/*
  817. X * Loop through all of the monsters and update them.  Called when:
  818. X *    + going blind & telepathic
  819. X *    + regaining sight & telepathic
  820. X *    + hallucinating
  821. X *    + doing a full screen redraw
  822. X *    + see invisible times out or a ring of see invisible is taken off
  823. X *    + when a potion of see invisible is quaffed or a ring of see
  824. X *      invisible is put on
  825. X *    + gaining telepathy when blind [givit() in eat.c, pleased() in pray.c]
  826. X *    + losing telepathy while blind [xkilled() in mon.c, attrcurse() in
  827. X *      sit.c]
  828. X */
  829. Xvoid
  830. Xsee_monsters()
  831. X{
  832. X    register struct monst *mon;
  833. X    for (mon = fmon; mon; mon = mon->nmon) {
  834. X    newsym(mon->mx,mon->my);
  835. X    if (mon->wormno) see_wsegs(mon);
  836. X    }
  837. X}
  838. X
  839. X/*
  840. X * Block/unblock light depending on what a mimic is mimicing and if it's
  841. X * invisible or not.  Should be called only when the state of See_invisible
  842. X * changes.
  843. X */
  844. Xvoid
  845. Xset_mimic_blocking()
  846. X{
  847. X    register struct monst *mon;
  848. X    for (mon = fmon; mon; mon = mon->nmon)
  849. X    if(mon->minvis &&
  850. X       ((mon->m_ap_type == M_AP_FURNITURE &&
  851. X          (mon->mappearance == S_vcdoor || mon->mappearance == S_hcdoor))||
  852. X        (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER))) {
  853. X        if(See_invisible)
  854. X        block_point(mon->mx, mon->my);
  855. X        else
  856. X        unblock_point(mon->mx, mon->my);
  857. X    }
  858. X}
  859. X
  860. X/*
  861. X * Loop through all of the object *locations* and update them.  Called when
  862. X *    + hallucinating.
  863. X */
  864. Xvoid
  865. Xsee_objects()
  866. X{
  867. X    register struct obj *obj;
  868. X    for(obj = fobj; obj; obj = obj->nobj)
  869. X    if (vobj_at(obj->ox,obj->oy) == obj) newsym(obj->ox, obj->oy);
  870. X}
  871. X
  872. X/*
  873. X * Put the cursor on the hero.  Flush all accumulated glyphs before doing it.
  874. X */
  875. Xvoid
  876. Xcurs_on_u()
  877. X{
  878. X    flush_screen(1);    /* Flush waiting glyphs & put cursor on hero */
  879. X}
  880. X
  881. Xint
  882. Xdoredraw()
  883. X{
  884. X    docrt();
  885. X    return 0;
  886. X}
  887. X
  888. Xvoid
  889. Xdocrt()
  890. X{
  891. X    register int x,y;
  892. X    register struct rm *lev;
  893. X
  894. X    if (!u.ux) return; /* display isn't ready yet */
  895. X
  896. X    if (u.uswallow) {
  897. X    swallowed(1);
  898. X    return;
  899. X    }
  900. X    if (Underwater && !Is_waterlevel(&u.uz)) {
  901. X    under_water(1);
  902. X    return;
  903. X    }
  904. X
  905. X    /* shut down vision */
  906. X    vision_recalc(2);
  907. X
  908. X    /*
  909. X     * This routine assumes that cls() does the following:
  910. X     *      + fills the physical screen with the symbol for rock
  911. X     *      + clears the glyph buffer
  912. X     */
  913. X    cls();
  914. X
  915. X    /* display memory */
  916. X    for (x = 1; x < COLNO; x++) {
  917. X    lev = &levl[x][0];
  918. X    for (y = 0; y < ROWNO; y++, lev++)
  919. X        if (lev->glyph != cmap_to_glyph(S_stone))
  920. X        show_glyph(x,y,lev->glyph);
  921. X    }
  922. X
  923. X    /* see what is to be seen */
  924. X    vision_recalc(0);
  925. X
  926. X    /* overlay with monsters */
  927. X    see_monsters();
  928. X
  929. X    flags.botlx = 1;    /* force a redraw of the bottom line */
  930. X}
  931. X
  932. X
  933. X/* ========================================================================= */
  934. X/* Glyph Buffering (3rd screen) ============================================ */
  935. X
  936. Xtypedef struct {
  937. X    xchar new;        /* perhaps move this bit into the rm strucure. */
  938. X    int   glyph;
  939. X} gbuf_entry;
  940. X
  941. Xstatic gbuf_entry gbuf[ROWNO][COLNO];
  942. Xstatic char gbuf_start[ROWNO];
  943. Xstatic char gbuf_stop[ROWNO];
  944. X
  945. X/*
  946. X * Store the glyph in the 3rd screen for later flushing.
  947. X */
  948. Xvoid
  949. Xshow_glyph(x,y,glyph)
  950. X    xchar x,y;
  951. X    int   glyph;
  952. X{
  953. X    /*
  954. X     * Check for bad positions and glyphs.
  955. X     */
  956. X    if (x <= 0 || x >= COLNO || y < 0 || y >= ROWNO) {
  957. X    const char *text;
  958. X    int  offset;
  959. X
  960. X    /* column 0 is invalid, but it's often used as a flag, so ignore it */
  961. X    if (x == 0) return;
  962. X
  963. X    /*
  964. X     *  This assumes an ordering of the offsets.  See display.h for
  965. X     *  the definition.
  966. X     */
  967. X    if (glyph >= GLYPH_SWALLOW_OFF) {        /* swallow border */
  968. X        text = "swallow border";    offset = glyph - GLYPH_SWALLOW_OFF;
  969. X    }else if (glyph >= GLYPH_ZAP_OFF) {        /* zap beam */
  970. X        text = "zap beam";        offset = glyph - GLYPH_ZAP_OFF;
  971. X    } else if (glyph >= GLYPH_CMAP_OFF) {        /* cmap */
  972. X        text = "cmap_index";    offset = glyph - GLYPH_CMAP_OFF;
  973. X    } else if (glyph >= GLYPH_TRAP_OFF) {        /* trap */
  974. X        text = "trap";        offset = glyph - GLYPH_TRAP_OFF;
  975. X    } else if (glyph >= GLYPH_OBJ_OFF) {        /* object */
  976. X        text = "object";        offset = glyph - GLYPH_OBJ_OFF;
  977. X    } else if (glyph >= GLYPH_BODY_OFF) {        /* a corpse */
  978. X        text = "corpse";        offset = glyph - GLYPH_BODY_OFF;
  979. X    } else {                    /* a monster */
  980. X        text = "monster";        offset = glyph;
  981. X    }
  982. X
  983. X    impossible("show_glyph:  bad pos %d %d with glyph %d [%s %d].",
  984. X                        x, y, glyph, text, offset);
  985. X    return;
  986. X    }
  987. X
  988. X    if (glyph >= MAX_GLYPH) {
  989. X    impossible("show_glyph:  bad glyph %d [max %d] at (%d,%d).",
  990. X                    glyph, MAX_GLYPH, x, y);
  991. X    return;
  992. X    }
  993. X
  994. X    if (gbuf[y][x].glyph != glyph) {
  995. X    gbuf[y][x].glyph = glyph;
  996. X    gbuf[y][x].new   = 1;
  997. X    if (gbuf_start[y] > x) gbuf_start[y] = x;
  998. X    if (gbuf_stop[y]  < x) gbuf_stop[y]  = x;
  999. X    }
  1000. X}
  1001. X
  1002. X
  1003. X/*
  1004. X * Reset the changed glyph borders so that none of the 3rd screen has
  1005. X * changed.
  1006. X */
  1007. X#define reset_glyph_bbox()            \
  1008. X    {                        \
  1009. X    int i;                    \
  1010. X                        \
  1011. X    for (i = 0; i < ROWNO; i++) {        \
  1012. X        gbuf_start[i] = COLNO-1;        \
  1013. X        gbuf_stop[i]  = 0;            \
  1014. X    }                    \
  1015. X    }
  1016. X
  1017. X
  1018. Xstatic gbuf_entry nul_gbuf = { 0, cmap_to_glyph(S_stone) };
  1019. X/*
  1020. X * Turn the 3rd screen into stone.
  1021. X */
  1022. Xvoid
  1023. Xclear_glyph_buffer()
  1024. X{
  1025. X    register int x, y;
  1026. X    register gbuf_entry *gptr;
  1027. X
  1028. X    for (y = 0; y < ROWNO; y++) {
  1029. X    gptr = &gbuf[y][0];
  1030. X    for (x = COLNO; x; x--) {
  1031. X        *gptr++ = nul_gbuf;
  1032. X    }
  1033. X    }
  1034. X    reset_glyph_bbox();
  1035. X}
  1036. X
  1037. X/*
  1038. X * Assumes that the indicated positions are filled with S_stone glyphs.
  1039. X */
  1040. Xvoid
  1041. Xrow_refresh(start,stop,y)
  1042. X    int start,stop,y;
  1043. X{
  1044. X    register int x;
  1045. X
  1046. X    for (x = start; x <= stop; x++)
  1047. X    if (gbuf[y][x].glyph != cmap_to_glyph(S_stone))
  1048. X        print_glyph(WIN_MAP,x,y,gbuf[y][x].glyph);
  1049. X}
  1050. X
  1051. Xvoid
  1052. Xcls()
  1053. X{
  1054. X    display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
  1055. X    flags.botlx = 1;        /* force update of botl window */
  1056. X    clear_nhwindow(WIN_MAP);    /* clear physical screen */
  1057. X
  1058. X    clear_glyph_buffer();    /* this is sort of an extra effort, but OK */
  1059. X}
  1060. X
  1061. X/*
  1062. X * Synch the third screen with the display.
  1063. X */
  1064. Xvoid
  1065. Xflush_screen(cursor_on_u)
  1066. X    int cursor_on_u;
  1067. X{
  1068. X    /* Prevent infinite loops on errors:
  1069. X     *        flush_screen->print_glyph->impossible->pline->flush_screen
  1070. X     */
  1071. X    static   boolean flushing = 0;
  1072. X    register int x,y;
  1073. X
  1074. X    if (flushing) return;    /* if already flushing then return */
  1075. X    flushing = 1;
  1076. X
  1077. X    for (y = 0; y < ROWNO; y++) {
  1078. X    register gbuf_entry *gptr = &gbuf[y][x = gbuf_start[y]];
  1079. X    for (; x <= gbuf_stop[y]; gptr++, x++)
  1080. X        if (gptr->new) {
  1081. X        print_glyph(WIN_MAP,x,y,gptr->glyph);
  1082. X        gptr->new = 0;
  1083. X        }
  1084. X    }
  1085. X
  1086. X    if (cursor_on_u) curs(WIN_MAP, u.ux,u.uy); /* move cursor to the hero */
  1087. X    display_nhwindow(WIN_MAP, FALSE);
  1088. X    reset_glyph_bbox();
  1089. X    flushing = 0;
  1090. X    if(flags.botl || flags.botlx) bot();
  1091. X}
  1092. X
  1093. X/* ========================================================================= */
  1094. X
  1095. X/*
  1096. X * back_to_glyph()
  1097. X *
  1098. X * Use the information in the rm structure at the given position to create
  1099. X * a glyph of a background.
  1100. X *
  1101. X * I had to add a field in the rm structure (horizontal) so that we knew
  1102. X * if open doors and secret doors were horizontal or vertical.  Previously,
  1103. X * the screen symbol had the horizontal/vertical information set at
  1104. X * level generation time.
  1105. X *
  1106. X * I used the 'ladder' field (really doormask) for deciding if stairwells
  1107. X * were up or down.  I didn't want to check the upstairs and dnstairs
  1108. X * variables.
  1109. X */
  1110. Xint
  1111. Xback_to_glyph(x,y)
  1112. X    xchar x,y;
  1113. X{
  1114. X    int idx;
  1115. X    struct rm *ptr = &(levl[x][y]);
  1116. X
  1117. X    switch (ptr->typ) {
  1118. X    case SCORR:
  1119. X    case STONE:        idx = S_stone;      break;
  1120. X    case ROOM:        idx = S_room;      break;
  1121. X    case CORR:
  1122. X        idx = (ptr->waslit || flags.lit_corridor) ? S_litcorr : S_corr;
  1123. X        break;
  1124. X    case HWALL:    idx = ptr->seen ? S_hwall  : S_stone;   break;
  1125. X    case VWALL:    idx = ptr->seen ? S_vwall  : S_stone;   break;
  1126. X    case TLCORNER:    idx = ptr->seen ? S_tlcorn : S_stone;    break;
  1127. X    case TRCORNER:    idx = ptr->seen ? S_trcorn : S_stone;    break;
  1128. X    case BLCORNER:    idx = ptr->seen ? S_blcorn : S_stone;    break;
  1129. X    case BRCORNER:    idx = ptr->seen ? S_brcorn : S_stone;    break;
  1130. X    case CROSSWALL:    idx = ptr->seen ? S_crwall : S_stone;    break;
  1131. X    case TUWALL:    idx = ptr->seen ? S_tuwall : S_stone;    break;
  1132. X    case TDWALL:    idx = ptr->seen ? S_tdwall : S_stone;    break;
  1133. X    case TLWALL:    idx = ptr->seen ? S_tlwall : S_stone;    break;
  1134. X    case TRWALL:    idx = ptr->seen ? S_trwall : S_stone;    break;
  1135. X    case SDOOR:
  1136. X        if (ptr->seen)
  1137. X        idx = (ptr->horizontal) ? S_hwall : S_vwall;
  1138. X        else
  1139. X        idx = S_stone;
  1140. X        break;
  1141. X    case DOOR:
  1142. X        if (ptr->doormask) {
  1143. X        if (ptr->doormask & D_BROKEN)
  1144. X            idx = S_ndoor;
  1145. X        else if (ptr->doormask & D_ISOPEN)
  1146. X            idx = (ptr->horizontal) ? S_hodoor : S_vodoor;
  1147. X        else            /* else is closed */
  1148. X            idx = (ptr->horizontal) ? S_hcdoor : S_vcdoor;
  1149. X        } else
  1150. X        idx = S_ndoor;
  1151. X        break;
  1152. X    case POOL:
  1153. X    case MOAT:        idx = S_pool;      break;
  1154. X    case STAIRS:
  1155. X        idx = (ptr->ladder & LA_DOWN) ? S_dnstair : S_upstair;
  1156. X        break;
  1157. X    case LADDER:
  1158. X        idx = (ptr->ladder & LA_DOWN) ? S_dnladder : S_upladder;
  1159. X        break;
  1160. X    case FOUNTAIN:        idx = S_fountain; break;
  1161. X    case SINK:        idx = S_sink;     break;
  1162. X    case ALTAR:        idx = S_altar;    break;
  1163. X    case THRONE:        idx = S_throne;   break;
  1164. X    case LAVAPOOL:        idx = S_lava;      break;
  1165. X    case ICE:        idx = S_ice;      break;
  1166. X    case AIR:        idx = S_air;      break;
  1167. X    case CLOUD:        idx = S_cloud;      break;
  1168. X    case WATER:        idx = S_water;      break;
  1169. X    case DBWALL:
  1170. X        idx = (ptr->horizontal) ? S_hcdbridge : S_vcdbridge;
  1171. X        break;
  1172. X    case DRAWBRIDGE_UP:
  1173. X        switch(ptr->drawbridgemask & DB_UNDER) {
  1174. X        case DB_MOAT:  idx = S_pool; break;
  1175. X        case DB_LAVA:  idx = S_lava; break;
  1176. X        case DB_ICE:   idx = S_ice;  break;
  1177. X        case DB_FLOOR: idx = S_room; break;
  1178. X        default:
  1179. X        impossible("Strange db-under: %d",
  1180. X               ptr->drawbridgemask & DB_UNDER);
  1181. X        idx = S_room; /* something is better than nothing */
  1182. X        break;
  1183. X        }
  1184. X        break;
  1185. X    case DRAWBRIDGE_DOWN:
  1186. X        idx = (ptr->horizontal) ? S_hodbridge : S_vodbridge;
  1187. X        break;
  1188. X    default:
  1189. X        impossible("back_to_glyph:  unknown level type [ = %d ]",ptr->typ);
  1190. X        idx = S_room;
  1191. X        break;
  1192. X    }
  1193. X
  1194. X    return cmap_to_glyph(idx);
  1195. X}
  1196. X
  1197. X
  1198. X/*
  1199. X * swallow_to_glyph()
  1200. X *
  1201. X * Convert a monster number and a swallow location into the correct glyph.
  1202. X * If you don't want a patchwork monster while hallucinating, decide on
  1203. X * a random monster in swallowed() and don't use what_mon() here.
  1204. X */
  1205. Xstatic int
  1206. Xswallow_to_glyph(mnum, loc)
  1207. X    int mnum;
  1208. X    int loc;
  1209. X{
  1210. X    if (loc < S_sw_tl || S_sw_br < loc) {
  1211. X    impossible("swallow_to_glyph: bad swallow location");
  1212. X    loc = S_sw_br;
  1213. X    }
  1214. X    return ((int) (what_mon(mnum)<<3) | (loc - S_sw_tl)) + GLYPH_SWALLOW_OFF;
  1215. X}
  1216. X
  1217. X
  1218. X
  1219. X/*
  1220. X * zapdir_to_glyph()
  1221. X *
  1222. X * Change the given zap direction and beam type into a glyph.  Each beam
  1223. X * type has four glyphs, one for each of the symbols below.  The order of
  1224. X * the zap symbols [0-3] as defined in rm.h are:
  1225. X *
  1226. X *    |  S_vbeam    ( 0, 1) or ( 0,-1)
  1227. X *    -  S_hbeam    ( 1, 0) or (-1,    0)
  1228. X *    \  S_lslant    ( 1, 1) or (-1,-1)
  1229. X *    /  S_rslant    (-1, 1) or ( 1,-1)
  1230. X */
  1231. Xint
  1232. Xzapdir_to_glyph(dx, dy, beam_type)
  1233. X    register int dx, dy;
  1234. X    int beam_type;
  1235. X{
  1236. X    if (beam_type >= NUM_ZAP) {
  1237. X    impossible("zapdir_to_glyph:  illegal beam type");
  1238. X    beam_type = 0;
  1239. X    }
  1240. X    dx = (dx == dy) ? 2 : (dx && dy) ? 3 : dx ? 1 : 0;
  1241. X
  1242. X    return ((int) ((beam_type << 2) | dx)) + GLYPH_ZAP_OFF;
  1243. X}
  1244. X
  1245. X
  1246. X/*
  1247. X * Utility routine for dowhatis() used to find out the glyph displayed at
  1248. X * the location.  This isn't necessarily the same as the glyph in the levl
  1249. X * structure, so we must check the "third screen".
  1250. X */
  1251. Xint
  1252. Xglyph_at(x, y)
  1253. X    xchar x,y;
  1254. X{
  1255. X    if(x < 0 || y < 0 || x >= COLNO || y >= ROWNO)
  1256. X    return cmap_to_glyph(S_room);            /* XXX */
  1257. X    return gbuf[y][x].glyph;
  1258. X}
  1259. X
  1260. X/*display.c*/
  1261. END_OF_FILE
  1262. if test 35153 -ne `wc -c <'src/display.c'`; then
  1263.     echo shar: \"'src/display.c'\" unpacked with wrong size!
  1264. fi
  1265. # end of 'src/display.c'
  1266. fi
  1267. if test -f 'sys/vms/gnutermcap.c' -a "${1}" != "-c" ; then 
  1268.   echo shar: Will not clobber existing file \"'sys/vms/gnutermcap.c'\"
  1269. else
  1270. echo shar: Extracting \"'sys/vms/gnutermcap.c'\" \(18405 characters\)
  1271. sed "s/^X//" >'sys/vms/gnutermcap.c' <<'END_OF_FILE'
  1272. X/* Work-alike for termcap, plus extra features.
  1273. X   Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  1274. X
  1275. X               NO WARRANTY
  1276. X
  1277. X  BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  1278. XNO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
  1279. XWHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  1280. XRICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
  1281. XWITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
  1282. XBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1283. XFITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
  1284. XAND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
  1285. XDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  1286. XCORRECTION.
  1287. X
  1288. X IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  1289. XSTALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  1290. XWHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
  1291. XLIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
  1292. XOTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  1293. XUSE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
  1294. XDATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
  1295. XA FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
  1296. XPROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  1297. XDAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  1298. X
  1299. X        GENERAL PUBLIC LICENSE TO COPY
  1300. X
  1301. X  1. You may copy and distribute verbatim copies of this source file
  1302. Xas you receive it, in any medium, provided that you conspicuously and
  1303. Xappropriately publish on each copy a valid copyright notice "Copyright
  1304. X(C) 1986 Free Software Foundation, Inc."; and include following the
  1305. Xcopyright notice a verbatim copy of the above disclaimer of warranty
  1306. Xand of this License.  You may charge a distribution fee for the
  1307. Xphysical act of transferring a copy.
  1308. X
  1309. X  2. You may modify your copy or copies of this source file or
  1310. Xany portion of it, and copy and distribute such modifications under
  1311. Xthe terms of Paragraph 1 above, provided that you also do the following:
  1312. X
  1313. X    a) cause the modified files to carry prominent notices stating
  1314. X    that you changed the files and the date of any change; and
  1315. X
  1316. X    b) cause the whole of any work that you distribute or publish,
  1317. X    that in whole or in part contains or is a derivative of this
  1318. X    program or any part thereof, to be licensed at no charge to all
  1319. X    third parties on terms identical to those contained in this
  1320. X    License Agreement (except that you may choose to grant more extensive
  1321. X    warranty protection to some or all third parties, at your option).
  1322. X
  1323. X    c) You may charge a distribution fee for the physical act of
  1324. X    transferring a copy, and you may at your option offer warranty
  1325. X    protection in exchange for a fee.
  1326. X
  1327. XMere aggregation of another unrelated program with this program (or its
  1328. Xderivative) on a volume of a storage or distribution medium does not bring
  1329. Xthe other program under the scope of these terms.
  1330. X
  1331. X  3. You may copy and distribute this program (or a portion or derivative
  1332. Xof it, under Paragraph 2) in object code or executable form under the terms
  1333. Xof Paragraphs 1 and 2 above provided that you also do one of the following:
  1334. X
  1335. X    a) accompany it with the complete corresponding machine-readable
  1336. X    source code, which must be distributed under the terms of
  1337. X    Paragraphs 1 and 2 above; or,
  1338. X
  1339. X    b) accompany it with a written offer, valid for at least three
  1340. X    years, to give any third party free (except for a nominal
  1341. X    shipping charge) a complete machine-readable copy of the
  1342. X    corresponding source code, to be distributed under the terms of
  1343. X    Paragraphs 1 and 2 above; or,
  1344. X
  1345. X    c) accompany it with the information you received as to where the
  1346. X    corresponding source code may be obtained.  (This alternative is
  1347. X    allowed only for noncommercial distribution and only if you
  1348. X    received the program in object code or executable form alone.)
  1349. X
  1350. XFor an executable file, complete source code means all the source code for
  1351. Xall modules it contains; but, as a special exception, it need not include
  1352. Xsource code for modules which are standard libraries that accompany the
  1353. Xoperating system on which the executable file runs.
  1354. X
  1355. X  4. You may not copy, sublicense, distribute or transfer this program
  1356. Xexcept as expressly provided under this License Agreement.  Any attempt
  1357. Xotherwise to copy, sublicense, distribute or transfer this program is void and
  1358. Xyour rights to use the program under this License agreement shall be
  1359. Xautomatically terminated.  However, parties who have received computer
  1360. Xsoftware programs from you with this License Agreement will not have
  1361. Xtheir licenses terminated so long as such parties remain in full compliance.
  1362. X
  1363. X  5. If you wish to incorporate parts of this program into other free
  1364. Xprograms whose distribution conditions are different, write to the Free
  1365. XSoftware Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
  1366. Xworked out a simple rule that can be stated here, but we will often permit
  1367. Xthis.  We will be guided by the two goals of preserving the free status of
  1368. Xall derivatives of our free software and of promoting the sharing and reuse of
  1369. Xsoftware.
  1370. X
  1371. X
  1372. XIn other words, you are welcome to use, share and improve this program.
  1373. XYou are forbidden to forbid anyone else to use, share and improve
  1374. Xwhat you give them.   Help stamp out software-hoarding!  */
  1375. X
  1376. X
  1377. X
  1378. X/* BUFSIZE is the initial size allocated for the buffer
  1379. X   for reading the termcap file.
  1380. X   It is not a limit.
  1381. X   Make it large normally for speed.
  1382. X   Make it variable when debugging, so can exercise
  1383. X   increasing the space dynamically.  */
  1384. X
  1385. X#ifdef emacs
  1386. X#include "config.h"
  1387. X#endif
  1388. X
  1389. X#ifndef BUFSIZE
  1390. X#ifdef DEBUG
  1391. X#define BUFSIZE bufsize
  1392. X
  1393. Xint bufsize = 128;
  1394. X#else
  1395. X#define BUFSIZE 2048
  1396. X#endif
  1397. X#endif
  1398. X
  1399. X#ifndef emacs
  1400. Xstatic
  1401. Xmemory_out ()
  1402. X{
  1403. X  write (2, "Virtual memory exhausted\n", 25);
  1404. X  exit (1);
  1405. X}
  1406. X
  1407. Xstatic int
  1408. Xxmalloc (size)
  1409. X     int size;
  1410. X{
  1411. X  register tem = malloc (size);
  1412. X  if (!tem)
  1413. X    memory_out ();
  1414. X  return tem;
  1415. X}
  1416. X
  1417. Xstatic int
  1418. Xxrealloc (ptr, size)
  1419. X     int ptr;
  1420. X     int size;
  1421. X{
  1422. X  register tem = realloc (ptr, size);
  1423. X  if (!tem)
  1424. X    memory_out ();
  1425. X  return tem;
  1426. X}
  1427. X#endif /* not emacs */
  1428. X
  1429. X/* Looking up capabilities in the entry already found */
  1430. X
  1431. X/* The pointer to the data made by tgetent is left here
  1432. X   for tgetnum, tgetflag and tgetstr to find.  */
  1433. X
  1434. Xstatic char *term_entry;
  1435. X
  1436. Xstatic char *tgetst1 ();
  1437. X
  1438. X/* This is the main subroutine that is used to search
  1439. X   an entry for a particular capability */
  1440. X
  1441. Xstatic char *
  1442. Xfind_capability (bp, cap)
  1443. X     register char *bp, *cap;
  1444. X{
  1445. X  for (; *bp; bp++)
  1446. X    if (bp[0] == ':'
  1447. X    && bp[1] == cap[0]
  1448. X    && bp[2] == cap[1])
  1449. X      return &bp[4];
  1450. X  return 0;
  1451. X}
  1452. X
  1453. Xint
  1454. Xtgetnum (cap)
  1455. X     char *cap;
  1456. X{
  1457. X  register char *ptr = find_capability (term_entry, cap);
  1458. X  if (!ptr || ptr[-1] != '#')
  1459. X    return -1;
  1460. X  return atoi (ptr);
  1461. X}
  1462. X
  1463. Xint
  1464. Xtgetflag (cap)
  1465. X     char *cap;
  1466. X{
  1467. X  register char *ptr = find_capability (term_entry, cap);
  1468. X  return 0 != ptr && ptr[-1] == ':';
  1469. X}
  1470. X
  1471. X/* Look up a string-valued capability `cap'.
  1472. X   If `area' is nonzero, it points to a pointer to a block in which
  1473. X   to store the string.  That pointer is advanced over the space used.
  1474. X   If `area' is zero, space is allocated with `malloc'.  */
  1475. X
  1476. Xchar *
  1477. Xtgetstr (cap, area)
  1478. X     char *cap;
  1479. X     char **area;
  1480. X{
  1481. X  register char *ptr = find_capability (term_entry, cap);
  1482. X  if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
  1483. X    return 0;
  1484. X  return tgetst1 (ptr, area);
  1485. X}
  1486. X
  1487. X/* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
  1488. X   gives meaning of character following \, or a space if no special meaning.
  1489. X   Eight characters per line within the string.  */
  1490. X
  1491. Xstatic char esctab[]
  1492. X  = " \007\010  \033\014 \
  1493. X      \012 \
  1494. X  \015 \011 \013 \
  1495. X        ";
  1496. X
  1497. X/* Given a pointer to a string value inside a termcap entry (`ptr'),
  1498. X   copy the value and process \ and ^ abbreviations.
  1499. X   Copy into block that *area points to,
  1500. X   or to newly allocated storage if area is 0.  */
  1501. X
  1502. Xstatic char *
  1503. Xtgetst1 (ptr, area)
  1504. X     char *ptr;
  1505. X     char **area;
  1506. X{
  1507. X  register char *p, *r;
  1508. X  register int c;
  1509. X  register int size;
  1510. X  char *ret;
  1511. X  register int c1;
  1512. X
  1513. X  if (!ptr)
  1514. X    return 0;
  1515. X
  1516. X  /* `ret' gets address of where to store the string */
  1517. X  if (!area)
  1518. X    {
  1519. X      /* Compute size of block needed (may overestimate) */
  1520. X      p = ptr;
  1521. X      while ((c = *p++) && c != ':' && c != '\n');
  1522. X      ret = (char *) xmalloc (p - ptr + 1);
  1523. X    }
  1524. X  else
  1525. X    ret = *area;
  1526. X
  1527. X  /* Copy the string value, stopping at null or colon.  */
  1528. X  /* Also process ^ and \ abbreviations.  */
  1529. X  p = ptr;
  1530. X  r = ret;
  1531. X  while ((c = *p++) && c != ':' && c != '\n')
  1532. X    {
  1533. X      if (c == '^')
  1534. X    c = *p++ & 037;
  1535. X      else if (c == '\\')
  1536. X    {
  1537. X      c = *p++;
  1538. X      if (c >= '0' && c <= '7')
  1539. X        {
  1540. X          c -= '0';
  1541. X          size = 0;
  1542. X
  1543. X          while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
  1544. X        {
  1545. X          c *= 8;
  1546. X          c += c1 - '0';
  1547. X          p++;
  1548. X        }
  1549. X        }
  1550. X      else if (c >= 0100 && c < 0200)
  1551. X        {
  1552. X          c1 = esctab[(c & ~040) - 0100];
  1553. X          if (c1 != ' ')
  1554. X        c = c1;
  1555. X        }
  1556. X    }
  1557. X      *r++ = c;
  1558. X    }
  1559. X  *r = 0;
  1560. X  /* Update *area */
  1561. X  if (area)
  1562. X    *area = r + 1;
  1563. X  return ret;
  1564. X}
  1565. X
  1566. X/* Outputting a string with padding */
  1567. X
  1568. Xshort ospeed;
  1569. Xchar PC;
  1570. X
  1571. X/* Actual baud rate if positive;
  1572. X   - baud rate / 100 if negative.  */
  1573. X
  1574. Xstatic short speeds[] =
  1575. X  {
  1576. X#ifdef VMS
  1577. X    0, 50, 75, 110, 134, 150, -3, -6, -12, -18,
  1578. X    -20, -24, -36, -48, -72, -96, -192
  1579. X#else /* not VMS */
  1580. X    0, 50, 75, 110, 135, 150, -2, -3, -6, -12,
  1581. X    -18, -24, -48, -96, -192, -384
  1582. X#endif /* not VMS */
  1583. X  };
  1584. X
  1585. Xtputs (string, nlines, outfun)
  1586. X     register char *string;
  1587. X     int nlines;
  1588. X     register int (*outfun) ();
  1589. X{
  1590. X  register int padcount = 0;
  1591. X
  1592. X  if (string == (char *) 0)
  1593. X    return;
  1594. X  while (*string >= '0' && *string <= '9')
  1595. X    {
  1596. X      padcount += *string++ - '0';
  1597. X      padcount *= 10;
  1598. X    }
  1599. X  if (*string == '.')
  1600. X    {
  1601. X      string++;
  1602. X      padcount += *string++ - '0';
  1603. X    }
  1604. X  if (*string == '*')
  1605. X    {
  1606. X      string++;
  1607. X      padcount *= nlines;
  1608. X    }
  1609. X  while (*string)
  1610. X    (*outfun) (*string++);
  1611. X
  1612. X  /* padcount is now in units of tenths of msec.  */
  1613. X  padcount *= speeds[ospeed];
  1614. X  padcount += 500;
  1615. X  padcount /= 1000;
  1616. X  if (speeds[ospeed] < 0)
  1617. X    padcount = -padcount;
  1618. X  else
  1619. X    {
  1620. X      padcount += 50;
  1621. X      padcount /= 100;
  1622. X    }
  1623. X
  1624. X  while (padcount-- > 0)
  1625. X    (*outfun) (PC);
  1626. X}
  1627. X
  1628. X/* Finding the termcap entry in the termcap data base */
  1629. X
  1630. Xstruct buffer
  1631. X  {
  1632. X    char *beg;
  1633. X    int size;
  1634. X    char *ptr;
  1635. X    int ateof;
  1636. X    int full;
  1637. X  };
  1638. X
  1639. X/* Forward declarations of static functions */
  1640. X
  1641. Xstatic int scan_file ();
  1642. Xstatic char *gobble_line ();
  1643. Xstatic int compare_contin ();
  1644. Xstatic int name_match ();
  1645. X
  1646. X#ifdef VMS
  1647. X
  1648. X#include <rmsdef.h>
  1649. X#include <fab.h>
  1650. X#include <nam.h>
  1651. X
  1652. Xstatic int
  1653. Xlegal_filename_p (fn)
  1654. X     char *fn;
  1655. X{
  1656. X  struct FAB fab = cc$rms_fab;
  1657. X  struct NAM nam = cc$rms_nam;
  1658. X  char esa[NAM$C_MAXRSS];
  1659. X
  1660. X  fab.fab$l_fna = fn;
  1661. X  fab.fab$b_fns = strlen(fn);
  1662. X  fab.fab$l_nam = &nam;
  1663. X  fab.fab$l_fop = FAB$M_NAM;
  1664. X
  1665. X  nam.nam$l_esa = esa;
  1666. X  nam.nam$b_ess = sizeof esa;
  1667. X
  1668. X  return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
  1669. X}
  1670. X
  1671. X#endif /* VMS */
  1672. X
  1673. X/* Find the termcap entry data for terminal type `name'
  1674. X   and store it in the block that `bp' points to.
  1675. X   Record its address for future use.
  1676. X
  1677. X   If `bp' is zero, space is dynamically allocated.  */
  1678. X
  1679. Xint
  1680. Xtgetent (bp, name)
  1681. X     char *bp, *name;
  1682. X{
  1683. X  register char *tem;
  1684. X  register int fd;
  1685. X  struct buffer buf;
  1686. X  register char *bp1;
  1687. X  char *bp2;
  1688. X  char *term;
  1689. X  int malloc_size = 0;
  1690. X  register int c;
  1691. X  char *tcenv;            /* TERMCAP value, if it contais :tc=.  */
  1692. X  char *indirect = 0;        /* Terminal type in :tc= in TERMCAP value.  */
  1693. X  int filep;
  1694. X
  1695. X  tem = (char *) getenv ("TERMCAP");
  1696. X  if (tem && *tem == 0) tem = 0;
  1697. X
  1698. X#ifdef VMS
  1699. X  filep = tem && legal_filename_p (tem);
  1700. X#else
  1701. X  filep = tem && (*tem == '/');
  1702. X#endif /* VMS */
  1703. X
  1704. X  /* If tem is non-null and starts with / (in the un*x case, that is),
  1705. X     it is a file name to use instead of /etc/termcap.
  1706. X     If it is non-null and does not start with /,
  1707. X     it is the entry itself, but only if
  1708. X     the name the caller requested matches the TERM variable.  */
  1709. X
  1710. X  if (tem && !filep && !strcmp (name, getenv ("TERM")))
  1711. X    {
  1712. X      indirect = tgetst1 (find_capability (tem, "tc"), 0);
  1713. X      if (!indirect)
  1714. X    {
  1715. X      if (!bp)
  1716. X        bp = tem;
  1717. X      else
  1718. X        strcpy (bp, tem);
  1719. X      goto ret;
  1720. X    }
  1721. X      else
  1722. X    {            /* we will need to read /etc/termcap */
  1723. X      tcenv = tem;
  1724. X       tem = 0;
  1725. X    }
  1726. X    }
  1727. X  else
  1728. X    indirect = (char *) 0;
  1729. X
  1730. X  if (!tem)
  1731. X#ifdef VMS
  1732. X    tem = "emacs_library:[etc]termcap.dat";
  1733. X#else
  1734. X    tem = "/etc/termcap";
  1735. X#endif
  1736. X
  1737. X  /* Here we know we must search a file and tem has its name.  */
  1738. X
  1739. X  fd = open (tem, 0, 0);
  1740. X  if (fd < 0)
  1741. X    return -1;
  1742. X
  1743. X  buf.size = BUFSIZE;
  1744. X  buf.beg = (char *) xmalloc (buf.size);
  1745. X  term = indirect ? indirect : name;
  1746. X
  1747. X  if (!bp)
  1748. X    {
  1749. X      malloc_size = indirect ? strlen (tcenv) + 1 : buf.size;
  1750. X      bp = (char *) xmalloc (malloc_size);
  1751. X    }
  1752. X  bp1 = bp;
  1753. X
  1754. X  if (indirect)            /* copy the data from the environment variable */
  1755. X    {
  1756. X      strcpy (bp, tcenv);
  1757. X      bp1 += strlen (tcenv);
  1758. X    }
  1759. X
  1760. X  while (term)
  1761. X    {
  1762. X      /* Scan file, reading it via buf, till find start of main entry */
  1763. X      if (scan_file (term, fd, &buf) == 0)
  1764. X    return 0;
  1765. X
  1766. X      /* Free old `term' if appropriate.  */
  1767. X      if (term != name)
  1768. X    free (term);
  1769. X
  1770. X      /* If `bp' is malloc'd by us, make sure it is big enough.  */
  1771. X      if (malloc_size)
  1772. X    {
  1773. X      malloc_size = bp1 - bp + buf.size;
  1774. X      tem = (char *) xrealloc (bp, malloc_size);
  1775. X      bp1 += tem - bp;
  1776. X      bp = tem;
  1777. X    }
  1778. X
  1779. X      bp2 = bp1;
  1780. X
  1781. X      /* Copy the line of the entry from buf into bp.  */
  1782. X      tem = buf.ptr;
  1783. X      while ((*bp1++ = c = *tem++) && c != '\n')
  1784. X    /* Drop out any \ newline sequence. */
  1785. X    if (c == '\\' && *tem == '\n')
  1786. X      {
  1787. X        bp1--;
  1788. X        tem++;
  1789. X      }
  1790. X      *bp1 = 0;
  1791. X
  1792. X      /* Does this entry refer to another terminal type's entry?  */
  1793. X      /* If something is found, copy it into heap and null-terminate it */
  1794. X      term = tgetst1 (find_capability (bp2, "tc"), 0);
  1795. X    }
  1796. X
  1797. X  close (fd);
  1798. X  free (buf.beg);
  1799. X
  1800. X  if (malloc_size)
  1801. X    {
  1802. X      bp = (char *) xrealloc (bp, bp1 - bp + 1);
  1803. X    }
  1804. X
  1805. X ret:
  1806. X  term_entry = bp;
  1807. X  if (malloc_size)
  1808. X    return (int) bp;
  1809. X  return 1;
  1810. X}
  1811. X
  1812. X/* Given file open on `fd' and buffer `bufp',
  1813. X   scan the file from the beginning until a line is found
  1814. X   that starts the entry for terminal type `string'.
  1815. X   Returns 1 if successful, with that line in `bufp',
  1816. X   or returns 0 if no entry found in the file.  */
  1817. X
  1818. Xstatic int
  1819. Xscan_file (string, fd, bufp)
  1820. X     char *string;
  1821. X     int fd;
  1822. X     register struct buffer *bufp;
  1823. X{
  1824. X  register char *tem;
  1825. X  register char *end;
  1826. X
  1827. X  bufp->ptr = bufp->beg;
  1828. X  bufp->full = 0;
  1829. X  bufp->ateof = 0;
  1830. X  *bufp->ptr = 0;
  1831. X
  1832. X  lseek (fd, 0L, 0);
  1833. X
  1834. X  while (!bufp->ateof)
  1835. X    {
  1836. X      /* Read a line into the buffer */
  1837. X      end = 0;
  1838. X      do
  1839. X    {
  1840. X      /* if it is continued, append another line to it,
  1841. X         until a non-continued line ends */
  1842. X      end = gobble_line (fd, bufp, end);
  1843. X    }
  1844. X      while (!bufp->ateof && end[-2] == '\\');
  1845. X
  1846. X      if (*bufp->ptr != '#'
  1847. X      && name_match (bufp->ptr, string))
  1848. X    return 1;
  1849. X
  1850. X      /* Discard the line just processed */
  1851. X      bufp->ptr = end;
  1852. X    }
  1853. X  return 0;
  1854. X}
  1855. X
  1856. X/* Return nonzero if NAME is one of the names specified
  1857. X   by termcap entry LINE.  */
  1858. X
  1859. Xstatic int
  1860. Xname_match (line, name)
  1861. X     char *line, *name;
  1862. X{
  1863. X  register char *tem;
  1864. X
  1865. X  if (!compare_contin (line, name))
  1866. X    return 1;
  1867. X  /* This line starts an entry.  Is it the right one?  */
  1868. X  for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
  1869. X    if (*tem == '|' && !compare_contin (tem + 1, name))
  1870. X      return 1;
  1871. X
  1872. X  return 0;
  1873. X}
  1874. X
  1875. Xstatic int
  1876. Xcompare_contin (str1, str2)
  1877. X     register char *str1, *str2;
  1878. X{
  1879. X  register int c1, c2;
  1880. X  while (1)
  1881. X    {
  1882. X      c1 = *str1++;
  1883. X      c2 = *str2++;
  1884. X      while (c1 == '\\' && *str1 == '\n')
  1885. X    {
  1886. X      str1++;
  1887. X      while ((c1 = *str1++) == ' ' || c1 == '\t');
  1888. X    }
  1889. X      if (c2 == '\0')        /* end of type being looked up */
  1890. X    {
  1891. X      if (c1 == '|' || c1 == ':') /* If end of name in data base, */
  1892. X        return 0;        /* we win. */
  1893. X      else
  1894. X        return 1;
  1895. X        }
  1896. X      else if (c1 != c2)
  1897. X    return 1;
  1898. X    }
  1899. X}
  1900. X
  1901. X/* Make sure that the buffer <- `bufp' contains a full line
  1902. X   of the file open on `fd', starting at the place `bufp->ptr'
  1903. X   points to.  Can read more of the file, discard stuff before
  1904. X   `bufp->ptr', or make the buffer bigger.
  1905. X
  1906. X   Returns the pointer to after the newline ending the line,
  1907. X   or to the end of the file, if there is no newline to end it.
  1908. X
  1909. X   Can also merge on continuation lines.  If `append_end' is
  1910. X   nonzero, it points past the newline of a line that is
  1911. X   continued; we add another line onto it and regard the whole
  1912. X   thing as one line.  The caller decides when a line is continued.  */
  1913. X
  1914. Xstatic char *
  1915. Xgobble_line (fd, bufp, append_end)
  1916. X     int fd;
  1917. X     register struct buffer *bufp;
  1918. X     char *append_end;
  1919. X{
  1920. X  register char *end;
  1921. X  register int nread;
  1922. X  register char *buf = bufp->beg;
  1923. X  register char *tem;
  1924. X
  1925. X  if (append_end == 0)
  1926. X    append_end = bufp->ptr;
  1927. X
  1928. X  while (1)
  1929. X    {
  1930. X      end = append_end;
  1931. X      while (*end && *end != '\n') end++;
  1932. X      if (*end)
  1933. X        break;
  1934. X      if (bufp->ateof)
  1935. X    return buf + bufp->full;
  1936. X      if (bufp->ptr == buf)
  1937. X    {
  1938. X      if (bufp->full == bufp->size)
  1939. X        {
  1940. X          bufp->size *= 2;
  1941. X          tem = (char *) xrealloc (buf, bufp->size);
  1942. X          bufp->ptr += tem - buf;
  1943. X          append_end += tem - buf;
  1944. X          bufp->beg = buf = tem;
  1945. X        }
  1946. X    }
  1947. X      else
  1948. X    {
  1949. X      append_end -= bufp->ptr - buf;
  1950. X      bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf);
  1951. X      bufp->ptr = buf;
  1952. X    }
  1953. X      if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
  1954. X    bufp->ateof = 1;
  1955. X      bufp->full += nread;
  1956. X      if (bufp->full != bufp->size)
  1957. X    buf[bufp->full] = 0;
  1958. X    }
  1959. X  return end + 1;
  1960. X}
  1961. X
  1962. X#ifdef TEST
  1963. X
  1964. X#include <stdio.h>
  1965. X
  1966. Xmain (argc, argv)
  1967. X     int argc;
  1968. X     char **argv;
  1969. X{
  1970. X  char *term;
  1971. X  char *buf;
  1972. X
  1973. X  term = argv[1];
  1974. X  printf ("TERM: %s\n", term);
  1975. X
  1976. X  buf = (char *) tgetent (0, term);
  1977. X  if ((int) buf <= 0)
  1978. X    {
  1979. X      printf ("No entry.\n");
  1980. X      return 0;
  1981. X    }
  1982. X
  1983. X  printf ("Entry: %s\n", buf);
  1984. X
  1985. X  tprint ("cm");
  1986. X  tprint ("AL");
  1987. X
  1988. X  printf ("co: %d\n", tgetnum ("co"));
  1989. X  printf ("am: %d\n", tgetflag ("am"));
  1990. X}
  1991. X
  1992. Xtprint (cap)
  1993. X     char *cap;
  1994. X{
  1995. X  char *x = tgetstr (cap, 0);
  1996. X  register char *y;
  1997. X
  1998. X  printf ("%s: ", cap);
  1999. X  if (x)
  2000. X    {
  2001. X      for (y = x; *y; y++)
  2002. X    if (*y <= ' ' || *y == 0177)
  2003. X      printf ("\\%0o", *y);
  2004. X    else
  2005. X      putchar (*y);
  2006. X      free (x);
  2007. X    }
  2008. X  else
  2009. X    printf ("none");
  2010. X  putchar ('\n');
  2011. X}
  2012. X
  2013. X#endif /* TEST */
  2014. END_OF_FILE
  2015. if test 18405 -ne `wc -c <'sys/vms/gnutermcap.c'`; then
  2016.     echo shar: \"'sys/vms/gnutermcap.c'\" unpacked with wrong size!
  2017. fi
  2018. # end of 'sys/vms/gnutermcap.c'
  2019. fi
  2020. echo shar: End of archive 52 \(of 108\).
  2021. cp /dev/null ark52isdone
  2022. MISSING=""
  2023. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2024. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2025. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2026. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2027. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2028. 101 102 103 104 105 106 107 108 ; do
  2029.     if test ! -f ark${I}isdone ; then
  2030.     MISSING="${MISSING} ${I}"
  2031.     fi
  2032. done
  2033. if test "${MISSING}" = "" ; then
  2034.     echo You have unpacked all 108 archives.
  2035.     echo "Now execute 'rebuild.sh'"
  2036.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2037. else
  2038.     echo You still need to unpack the following archives:
  2039.     echo "        " ${MISSING}
  2040. fi
  2041. ##  End of shell archive.
  2042. exit 0
  2043.