]> granicus.if.org Git - nethack/commitdiff
releasing inventory window(s)
authorPatR <rankin@nethack.org>
Tue, 3 Nov 2015 02:14:57 +0000 (18:14 -0800)
committerPatR <rankin@nethack.org>
Tue, 3 Nov 2015 02:14:57 +0000 (18:14 -0800)
This should address the issue that the problem patch to display_pickinv()
was trying to deal with:  releasing the inventory window before exiting
the program so Pasi's memory checker doesn't think it's a memory leak.

Not related, but in the same file:
The older qsort comparison routines are tagged with CFDECLSPEC to deal
with some C vs C++ interaction issue.  I added that to the relatively
recently added 'sortloot' qsort compare callback.

I also changed worn_wield_only(), although it isn't actually called.
(display_minventory() has provisions to call it, but both of the latter's
callers pass in MINV_ALL so allow_all() gets used instead.)

include/extern.h
src/end.c
src/invent.c
src/save.c

index 8d6fda3d2944150881e97ea2dedf08f3017d3c78..7e5195cc8a1e7a113f60987ea7ebbe9d19b878ed 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1446336781 2015/11/01 00:13:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.511 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1446516834 2015/11/03 02:13:54 $  $NHDT-Branch: master $:$NHDT-Revision: 1.513 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -910,8 +910,8 @@ E boolean NDECL(wearing_armor);
 E boolean FDECL(is_worn, (struct obj *));
 E struct obj *FDECL(g_at, (int, int));
 E struct obj *FDECL(getobj, (const char *, const char *));
-E int FDECL(ggetobj,
-            (const char *, int (*)(OBJ_P), int, BOOLEAN_P, unsigned *));
+E int FDECL(ggetobj, (const char *, int (*)(OBJ_P), int,
+                      BOOLEAN_P, unsigned *));
 E int FDECL(askchain, (struct obj **, const char *, int, int (*)(OBJ_P),
                        int (*)(OBJ_P), int, const char *));
 E void FDECL(fully_identify_obj, (struct obj *));
@@ -945,6 +945,7 @@ E char *FDECL(let_to_name, (CHAR_P, BOOLEAN_P, BOOLEAN_P));
 E void NDECL(free_invbuf);
 E void NDECL(reassign);
 E int NDECL(doorganize);
+E void NDECL(free_pickinv_cache);
 E int FDECL(count_unpaid, (struct obj *));
 E int FDECL(count_buc, (struct obj *, int));
 E long FDECL(count_contents, (struct obj *, BOOLEAN_P, BOOLEAN_P, BOOLEAN_P));
index 0500bc4d871dd22d9a780edf09849c2669190812..c8560b21771ce1e17c83497e6fd19cbce346a9a1 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 end.c   $NHDT-Date: 1434408399 2015/06/15 22:46:39 $  $NHDT-Branch: master $:$NHDT-Revision: 1.100 $ */
+/* NetHack 3.6 end.c   $NHDT-Date: 1446510332 2015/11/03 00:25:32 $  $NHDT-Branch: master $:$NHDT-Revision: 1.102 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -214,7 +214,7 @@ NH_panictrace_libc()
     for (x = 0; x < count; x++) {
         raw_printf("[%lu] %s", (unsigned long) x, info[x]);
     }
-    /* free(info);     Don't risk it. */
+    /* free(info);   -- Don't risk it. */
     return TRUE;
 #else
     return FALSE;
@@ -273,22 +273,23 @@ NH_panictrace_gdb()
 /*
  * The order of these needs to match the macros in hack.h.
  */
-static NEARDATA const char *deaths[] =
-    { /* the array of death */
-      "died", "choked", "poisoned", "starvation", "drowning", "burning",
-      "dissolving under the heat and pressure", "crushed", "turned to stone",
-      "turned into slime", "genocided", "panic", "trickery", "quit",
-      "escaped", "ascended"
-    };
-
-static NEARDATA const char *ends[] = { /* "when you..." */
-                                       "died", "choked", "were poisoned",
-                                       "starved", "drowned", "burned",
-                                       "dissolved in the lava",
-                                       "were crushed", "turned to stone",
-                                       "turned into slime", "were genocided",
-                                       "panicked", "were tricked", "quit",
-                                       "escaped", "ascended"
+static NEARDATA const char *deaths[] = {
+    /* the array of death */
+    "died", "choked", "poisoned", "starvation", "drowning", "burning",
+    "dissolving under the heat and pressure", "crushed", "turned to stone",
+    "turned into slime", "genocided", "panic", "trickery", "quit",
+    "escaped", "ascended"
+};
+
+static NEARDATA const char *ends[] = {
+    /* "when you %s" */
+    "died", "choked", "were poisoned",
+    "starved", "drowned", "burned",
+    "dissolved in the lava",
+    "were crushed", "turned to stone",
+    "turned into slime", "were genocided",
+    "panicked", "were tricked", "quit",
+    "escaped", "ascended"
 };
 
 static boolean Schroedingers_cat = FALSE;
@@ -366,8 +367,8 @@ done2()
 
 #ifndef NO_SIGNAL
 /*ARGSUSED*/
-STATIC_PTR void done_intr(
-    sig_unused) /* called as signal() handler, so sent at least one arg */
+STATIC_PTR void
+done_intr(sig_unused) /* called as signal() handler, so sent at least 1 arg */
 int sig_unused UNUSED;
 {
     done_stopprint++;
@@ -396,10 +397,11 @@ struct monst *mtmp;
 int how;
 {
     char buf[BUFSZ];
-    struct permonst *mptr = mtmp->data, *champtr = (mtmp->cham >= LOW_PM)
-                                                       ? &mons[mtmp->cham]
-                                                       : mptr;
-    boolean distorted = (boolean)(Hallucination && canspotmon(mtmp)),
+    struct permonst *mptr = mtmp->data,
+                    *champtr = ((mtmp->cham >= LOW_PM)
+                                   ? &mons[mtmp->cham]
+                                   : mptr);
+    boolean distorted = (boolean) (Hallucination && canspotmon(mtmp)),
             mimicker = (mtmp->m_ap_type == M_AP_MONSTER),
             imitator = (mptr != champtr || mimicker);
 
@@ -452,8 +454,9 @@ int how;
             Strcpy(shape, an(fakenm));
         /* omit "called" to avoid excessive verbosity */
         Sprintf(eos(buf),
-                alt ? "%s in %s form" : mimicker ? "%s disguised as %s"
-                                                 : "%s imitating %s",
+                alt ? "%s in %s form"
+                    : mimicker ? "%s disguised as %s"
+                               : "%s imitating %s",
                 realnm, shape);
         mptr = mtmp->data; /* reset for mimicker case */
     } else if (mptr == &mons[PM_GHOST]) {
@@ -462,9 +465,8 @@ int how;
             Sprintf(eos(buf), " of %s", MNAME(mtmp));
     } else if (mtmp->isshk) {
         const char *shknm = shkname(mtmp),
-                   *honorific = shkname_is_pname(mtmp) ? "" : mtmp->female
-                                                                  ? "Ms. "
-                                                                  : "Mr. ";
+                   *honorific = shkname_is_pname(mtmp) ? ""
+                                   : mtmp->female ? "Ms. " : "Mr. ";
 
         Sprintf(eos(buf), "%s%s, the shopkeeper", honorific, shknm);
         killer.format = KILLED_BY;
@@ -925,7 +927,7 @@ int how;
     }
 
 /*
- *     The game is now over...
+ *      The game is now over...
  */
 
 die:
@@ -1092,6 +1094,8 @@ die:
     /* clean up unneeded windows */
     if (have_windows) {
         wait_synch();
+        if (WIN_INVEN != WIN_ERR)
+            destroy_nhwindow(WIN_INVEN),  WIN_INVEN = WIN_ERR;
         display_nhwindow(WIN_MESSAGE, TRUE);
         destroy_nhwindow(WIN_MAP),  WIN_MAP = WIN_ERR;
 #ifndef STATUS_VIA_WINDOWPORT
@@ -1130,8 +1134,8 @@ die:
     }
 
     if (how == ESCAPED || how == ASCENDED) {
-        register struct monst *mtmp;
-        register struct obj *otmp;
+        struct monst *mtmp;
+        struct obj *otmp;
         register struct val_list *val;
         register int i;
 
index 79f8e921ac7262e56ccf69a7d7e1f53d3314afe3..5309d3b8d143c4e6258f4ad089a646eb99b14e1b 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 invent.c        $NHDT-Date: 1445388918 2015/10/21 00:55:18 $  $NHDT-Branch: master $:$NHDT-Revision: 1.175 $ */
+/* NetHack 3.6 invent.c        $NHDT-Date: 1446516832 2015/11/03 02:13:52 $  $NHDT-Branch: master $:$NHDT-Revision: 1.178 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -7,7 +7,7 @@
 #define NOINVSYM '#'
 #define CONTAINED_SYM '>' /* designator for inside a container */
 
-STATIC_DCL int FDECL(sortloot_cmp, (struct obj *, struct obj *));
+STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
 STATIC_DCL void NDECL(reorder_invent);
 STATIC_DCL boolean FDECL(mergable, (struct obj *, struct obj *));
 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
@@ -40,11 +40,13 @@ static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
  * suddenly become a choice for all the inventory-class commands, which
  * would probably cause mass confusion.  the test for inventory venom
  * is only WIZARD and not wizard because the wizard can leave venom lying
- * around on a bones level for normal players to find.
+ * around on a bones level for normal players to find.  [Note to the
+ * confused:  'WIZARD' used to be a compile-time conditional so this was
+ * guarded by #ifdef WIZARD/.../#endif.]
  */
 static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
 
-int
+STATIC_OVL int CFDECLSPEC
 sortloot_cmp(obj1, obj2)
 struct obj *obj1;
 struct obj *obj2;
@@ -104,7 +106,9 @@ struct obj *obj2;
         return val2 - val1; /* Because bigger is better. */
     }
 
-    return 0; /* They're identical, as far as we're concerned. */
+    /* They're identical, as far as we're concerned,
+       but we want to force a determistic order between them. */
+    return (obj1->o_id > obj2->o_id) ? 1 : -1;
 }
 
 struct obj **
@@ -316,18 +320,17 @@ struct obj **potmp, **pobj;
                 setnotworn(otmp);
             setworn(otmp, wmask);
             setnotworn(obj);
-        }
 #if 0
         /* (this should not be necessary, since items
             already in a monster's inventory don't ever get
             merged into other objects [only vice versa]) */
-        else if (obj->owornmask && mcarried(otmp)) {
+        else if (obj->owornmask && mcarried(otmp)) {
             if (obj == MON_WEP(otmp->ocarry)) {
-            MON_WEP(otmp->ocarry) = otmp;
-            otmp->owornmask = W_WEP;
+                MON_WEP(otmp->ocarry) = otmp;
+                otmp->owornmask = W_WEP;
             }
-        }
 #endif /*0*/
+        }
 
         /* handle puddings a bit differently; absorption will
          * free the other object automatically so we can just
@@ -335,11 +338,11 @@ struct obj **potmp, **pobj;
         if (Is_pudding(obj)) {
             pudding_merge_message(otmp, obj);
             obj_absorb(potmp, pobj);
-            return (1);
+            return 1;
         }
 
         obfree(obj, otmp); /* free(obj), bill->otmp */
-        return (1);
+        return 1;
     }
     return 0;
 }
@@ -477,7 +480,7 @@ added:
     addinv_core2(obj);
     carry_obj_effects(obj); /* carrying affects the obj */
     update_inventory();
-    return (obj);
+    return obj;
 }
 
 /*
@@ -595,8 +598,8 @@ void
 useup(obj)
 register struct obj *obj;
 {
-    /*  Note:  This works correctly for containers because they */
-    /*    (containers) don't merge.                        */
+    /* Note:  This works correctly for containers because they (containers)
+       don't merge. */
     if (obj->quan > 1L) {
         obj->in_use = FALSE; /* no longer in use */
         obj->quan--;
@@ -763,12 +766,13 @@ register int type;
 
     for (otmp = invent; otmp; otmp = otmp->nobj)
         if (otmp->otyp == type)
-            return (otmp);
-    return ((struct obj *) 0);
+            return  otmp;
+    return (struct obj *) 0;
 }
 
-/** Fictional and not-so-fictional currencies.
- * http://concord.wikia.com/wiki/List_of_Fictional_Currencies */
+/* Fictional and not-so-fictional currencies.
+ * http://concord.wikia.com/wiki/List_of_Fictional_Currencies
+ */
 static const char *const currencies[] = {
     "Altarian Dollar",       /* The Hitchhiker's Guide to the Galaxy */
     "Ankh-Morpork Dollar",   /* Discworld */
@@ -812,8 +816,8 @@ have_lizard()
 
     for (otmp = invent; otmp; otmp = otmp->nobj)
         if (otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
-            return (TRUE);
-    return (FALSE);
+            return  TRUE;
+    return FALSE;
 }
 
 /* 3.6.0 tribute */
@@ -825,7 +829,7 @@ u_have_novel()
     for (otmp = invent; otmp; otmp = otmp->nobj)
         if (otmp->otyp == SPE_NOVEL)
             return otmp;
-    return (struct obj *)0;
+    return (struct obj *) 0;
 }
 
 struct obj *
@@ -837,12 +841,12 @@ register struct obj *objchn;
 
     while (objchn) {
         if (objchn->o_id == id)
-            return (objchn);
+            return objchn;
         if (Has_contents(objchn) && (temp = o_on(id, objchn->cobj)))
             return temp;
         objchn = objchn->nobj;
     }
-    return ((struct obj *) 0);
+    return (struct obj *) 0;
 }
 
 boolean
@@ -854,8 +858,8 @@ int x, y;
 
     for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
         if (obj == otmp)
-            return (TRUE);
-    return (FALSE);
+            return TRUE;
+    return FALSE;
 }
 
 struct obj *
@@ -863,12 +867,13 @@ g_at(x, y)
 register int x, y;
 {
     register struct obj *obj = level.objects[x][y];
+
     while (obj) {
         if (obj->oclass == COIN_CLASS)
             return obj;
         obj = obj->nexthere;
     }
-    return ((struct obj *) 0);
+    return (struct obj *) 0;
 }
 
 /* compact a string of inventory letters by dashing runs of letters */
@@ -936,9 +941,9 @@ const char *action;
 
 /*
  * getobj returns:
- *     struct obj *xxx:        object to do something with.
- *     (struct obj *) 0        error return: no object.
- *     &zeroobj                explicitly no object (as in w-).
+ *      struct obj *xxx:        object to do something with.
+ *      (struct obj *) 0        error return: no object.
+ *      &zeroobj                explicitly no object (as in w-).
 !!!! test if gold can be used in unusual ways (eaten etc.)
 !!!! may be able to remove "usegold"
  */
@@ -1147,7 +1152,7 @@ register const char *let, *word;
 
     if (!foo && !allowall && !allownone) {
         You("don't have anything %sto %s.", foox ? "else " : "", word);
-        return ((struct obj *) 0);
+        return (struct obj *) 0;
     }
     for (;;) {
         cnt = 0;
@@ -1189,18 +1194,19 @@ register const char *let, *word;
         if (index(quitchars, ilet)) {
             if (flags.verbose)
                 pline1(Never_mind);
-            return ((struct obj *) 0);
+            return (struct obj *) 0;
         }
         if (ilet == '-') {
             if (!allownone) {
-                char *suf = NULL;
+                char *suf = (char *) 0;
+
                 strcpy(buf, word);
-                if ((bp = strstr(buf, " on the "))
-                    != NULL) { /* rub on the stone[s] */
+                if ((bp = strstr(buf, " on the ")) != 0) {
+                    /* rub on the stone[s] */
                     *bp = '\0';
                     suf = (bp + 1);
                 }
-                if ((bp = strstr(buf, " or ")) != NULL) {
+                if ((bp = strstr(buf, " or ")) != 0) {
                     *bp = '\0';
                     bp = (rn2(2) ? buf : (bp + 4));
                 } else
@@ -1283,12 +1289,12 @@ register const char *let, *word;
         if (!otmp) {
             You("don't have that object.");
             if (in_doagain)
-                return ((struct obj *) 0);
+                return (struct obj *) 0;
             continue;
         } else if (cnt < 0 || otmp->quan < cnt) {
             You("don't have that many!  You have only %ld.", otmp->quan);
             if (in_doagain)
-                return ((struct obj *) 0);
+                return (struct obj *) 0;
             continue;
         }
         break;
@@ -1296,7 +1302,7 @@ register const char *let, *word;
     if (!allowall && let && !index(let, otmp->oclass)
         && !(usegold && otmp->oclass == COIN_CLASS)) {
         silly_thing(word, otmp);
-        return ((struct obj *) 0);
+        return (struct obj *) 0;
     }
     if (allowcnt == 2) { /* cnt given */
         if (cnt == 0)
@@ -1310,7 +1316,7 @@ register const char *let, *word;
                 otmp->corpsenm = (int) cnt;
         }
     }
-    return (otmp);
+    return otmp;
 }
 
 void
@@ -1354,15 +1360,15 @@ struct obj *otmp;
 
 STATIC_PTR int
 ckvalidcat(otmp)
-register struct obj *otmp;
+struct obj *otmp;
 {
     /* use allow_category() from pickup.c */
-    return ((int) allow_category(otmp));
+    return (int) allow_category(otmp);
 }
 
 STATIC_PTR int
 ckunpaid(otmp)
-register struct obj *otmp;
+struct obj *otmp;
 {
     return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
 }
@@ -1435,7 +1441,7 @@ unsigned *resultflags;
     takeoff = ident = allflag = m_seen = FALSE;
     if (!invent) {
         You("have nothing to %s.", word);
-        return (0);
+        return 0;
     }
     add_valid_menu_class(0); /* reset */
     if (taking_off(word)) {
@@ -1478,7 +1484,7 @@ unsigned *resultflags;
                 ilets);
         getlin(qbuf, buf);
         if (buf[0] == '\033')
-            return (0);
+            return 0;
         if (index(buf, 'i')) {
             if (display_inventory((char *) 0, TRUE) == '\033')
                 return 0;
@@ -1563,14 +1569,16 @@ unsigned *resultflags;
         }
     }
 
-    if (m_seen)
+    if (m_seen) {
         return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
-    else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag)
+    } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
         return 0;
-    else /*!!!! if (allowgold == 2 && !oletct)
-        !!!! return 1;  you dropped gold (or at least tried to) 
-            !!!! test gold dropping
-    else*/ {
+#if 0
+    /* !!!! test gold dropping */
+    } else if (allowgold == 2 && !oletct) {
+        return 1; /* you dropped gold (or at least tried to)  */
+#endif
+    } else {
         int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
         /*
          * askchain() has already finished the job in this case
@@ -1625,10 +1633,10 @@ nextclass:
      * (dropping a burning potion of oil while levitating creates
      * an explosion which can destroy inventory items), so simple
      * list traversal
-     * for (otmp = *objchn; otmp; otmp = otmp2) {
-     *     otmp2 = otmp->nobj;
-     *     ...
-     * }
+     *  for (otmp = *objchn; otmp; otmp = otmp2) {
+     *      otmp2 = otmp->nobj;
+     *      ...
+     *  }
      * is inadequate here.  Use each object's bypass bit to keep
      * track of which list elements have already been processed.
      */
@@ -1721,11 +1729,11 @@ nextclass:
         pline("No applicable objects.");
 ret:
     bypass_objlist(*objchn, FALSE);
-    return (cnt);
+    return cnt;
 }
 
 /*
- *     Object identification routines:
+ *      Object identification routines:
  */
 
 /* make an object actually be identified; no display updating */
@@ -1860,9 +1868,10 @@ learn_unseen_invent()
     update_inventory();
 }
 
+/* should of course only be called for things in invent */
 STATIC_OVL char
-obj_to_let(obj) /* should of course only be called for things in invent */
-register struct obj *obj;
+obj_to_let(obj)
+struct obj *obj;
 {
     if (!flags.invlet_constant) {
         obj->invlet = NOINVSYM;
@@ -1878,7 +1887,7 @@ register struct obj *obj;
 void
 prinv(prefix, obj, quan)
 const char *prefix;
-register struct obj *obj;
+struct obj *obj;
 long quan;
 {
     if (!prefix)
@@ -1911,8 +1920,8 @@ long quan;       /* if non-0, print this quantity, not obj->quan */
 
     /*
      * If let is:
-     * *  Then obj == null and we are printing a total amount.
-     * >  Then the object is contained and doesn't have an inventory letter.
+     *  *  Then obj == null and we are printing a total amount.
+     *  >  Then the object is contained and doesn't have an inventory letter.
      */
     if (cost != 0 || let == '*') {
         /* if dot is true, we're doing Iu, otherwise Ix */
@@ -1960,7 +1969,7 @@ struct obj *list, **last_found;
                 if (list == *last_found)
                     *last_found = (struct obj *) 0;
             } else
-                return (*last_found = list);
+                return ((*last_found = list));
         }
         if (Has_contents(list)) {
             if ((obj = find_unpaid(list->cobj, last_found)) != 0)
@@ -1971,6 +1980,22 @@ struct obj *list, **last_found;
     return (struct obj *) 0;
 }
 
+/* for perm_invent when operating on a partial inventory display, so that
+   the persistent one doesn't get shrunk during filtering for item selection
+   then regrown to full inventory, possibly being resized in the process */
+static winid cached_pickinv_win = WIN_ERR;
+
+/* #ifdef FREE_ALL_MEMORY */
+void
+free_pickinv_cache()
+{
+    if (cached_pickinv_win != WIN_ERR) {
+        destroy_nhwindow(cached_pickinv_win);
+        cached_pickinv_win = WIN_ERR;
+    }
+}
+/* #endif */
+
 /*
  * Internal function used by display_inventory and getobj that can display
  * inventory and return a count as well as a letter. If out_cnt is not null,
@@ -1987,31 +2012,31 @@ long *out_cnt;
     char *invlet = flags.inv_order;
     int i, n, classcount;
     winid win;                        /* windows being used */
-    static winid local_win = WIN_ERR; /* window for partial menus */
     anything any;
     menu_item *selected;
     struct obj **oarray;
 
-    /* overridden by global flag */
-    if (flags.perm_invent) {
-        win = (lets && *lets) ? local_win : WIN_INVEN;
-        /* create the first time used */
-        if (win == WIN_ERR)
-            win = local_win = create_nhwindow(NHW_MENU);
+    if (flags.perm_invent && lets && *lets) {
+        /* partial inventory in perm_invent setting; don't operate on
+           full inventory window, use an alternate one instead; create
+           the first time needed and keep it for re-use as needed later */
+        if (cached_pickinv_win == WIN_ERR)
+            cached_pickinv_win = create_nhwindow(NHW_MENU);
+        win = cached_pickinv_win;
     } else
         win = WIN_INVEN;
 
     /*
-    Exit early if no inventory -- but keep going if we are doing
-    a permanent inventory update.  We need to keep going so the
-    permanent inventory window updates itself to remove the last
-    item(s) dropped.  One down side:  the addition of the exception
-    for permanent inventory window updates _can_ pop the window
-    up when it's not displayed -- even if it's empty -- because we
-    don't know at this level if its up or not.  This may not be
-    an issue if empty checks are done before hand and the call
-    to here is short circuited away.
-    */
+     * Exit early if no inventory -- but keep going if we are doing
+     * a permanent inventory update.  We need to keep going so the
+     * permanent inventory window updates itself to remove the last
+     * item(s) dropped.  One down side:  the addition of the exception
+     * for permanent inventory window updates _can_ pop the window
+     * up when it's not displayed -- even if it's empty -- because we
+     * don't know at this level if its up or not.  This may not be
+     * an issue if empty checks are done before hand and the call
+     * to here is short circuited away.
+     */
     if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
         pline("Not carrying anything.");
         return 0;
@@ -2117,7 +2142,7 @@ nextclass:
  */
 char
 display_inventory(lets, want_reply)
-register const char *lets;
+const char *lets;
 boolean want_reply;
 {
     return display_pickinv(lets, want_reply, (long *) 0);
@@ -2535,8 +2560,7 @@ dotypeinv()
         if (oclass == COIN_CLASS)
             return doprgold();
         if (index(types, c) > index(types, '\033')) {
-            /* '> ESC' => "hidden choice", something known not to be carried
-             */
+            /* '> ESC' => hidden choice, something known not to be carried */
             const char *which = 0;
 
             switch (c) {
@@ -2690,7 +2714,7 @@ boolean picked_some;
         } else {
             You("%s no objects here.", verb);
         }
-        return (!!Blind);
+        return !!Blind;
     }
     if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
         There("is %s here.",
@@ -2722,7 +2746,7 @@ boolean picked_some;
             dfeature = 0; /* ice already identified */
         if (!can_reach_floor(TRUE)) {
             pline("But you can't reach it!");
-            return (0);
+            return 0;
         }
     }
 
@@ -2736,7 +2760,7 @@ boolean picked_some;
         read_engr_at(u.ux, u.uy); /* Eric Backus */
         if (!skip_objects && (Blind || !dfeature))
             You("%s no objects here.", verb);
-        return (!!Blind);
+        return !!Blind;
     }
     /* we know there is something here */
 
@@ -2806,10 +2830,10 @@ boolean picked_some;
             feel_cockatrice(otmp, FALSE);
         read_engr_at(u.ux, u.uy); /* Eric Backus */
     }
-    return (!!Blind);
+    return !!Blind;
 }
 
-/* explicitly look at what is here, including all objects */
+/* the ':' command - explicitly look at what is here, including all objects */
 int
 dolook()
 {
@@ -2862,8 +2886,9 @@ struct obj *obj;
     return;
 }
 
+/* returns TRUE if obj  & otmp can be merged */
 STATIC_OVL boolean
-mergable(otmp, obj) /* returns TRUE if obj  & otmp can be merged */
+mergable(otmp, obj)
 register struct obj *otmp, *obj;
 {
     int objnamelth = 0, otmpnamelth = 0;
@@ -2882,7 +2907,7 @@ register struct obj *otmp, *obj;
         || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
         || obj->greased != otmp->greased || obj->oeroded != otmp->oeroded
         || obj->oeroded2 != otmp->oeroded2 || obj->bypass != otmp->bypass)
-        return (FALSE);
+        return FALSE;
 
     if (obj->nomerge) /* explicitly marked to prevent merge */
         return FALSE;
@@ -2894,7 +2919,7 @@ register struct obj *otmp, *obj;
 
     if (obj->oclass == FOOD_CLASS
         && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
-        return (FALSE);
+        return FALSE;
 
     if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
         if (obj->corpsenm != otmp->corpsenm)
@@ -2910,7 +2935,7 @@ register struct obj *otmp, *obj;
     /* allow candle merging only if their ages are close */
     /* see begin_burn() for a reference for the magic "25" */
     if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
-        return (FALSE);
+        return FALSE;
 
     /* burning potions of oil never merge */
     if (obj->otyp == POT_OIL && obj->lamplit)
@@ -2943,6 +2968,7 @@ register struct obj *otmp, *obj;
         return FALSE;
 }
 
+/* the '$' command */
 int
 doprgold()
 {
@@ -2957,6 +2983,7 @@ doprgold()
     return 0;
 }
 
+/* the ')' command */
 int
 doprwep()
 {
@@ -2994,15 +3021,21 @@ boolean report_uskin;
     }
 }
 
+/* the '[' command */
 int
 doprarm()
 {
+    char lets[8];
+    register int ct = 0;
+    /*
+     * Note:  players sometimes get here by pressing a function key which
+     * transmits ''ESC [ <something>'' rather than by pressing '[';
+     * there's nothing we can--or should-do about that here.
+     */
+
     if (!wearing_armor()) {
         noarmor(TRUE);
     } else {
-        char lets[8];
-        register int ct = 0;
-
         if (uarmu)
             lets[ct++] = obj_to_let(uarmu);
         if (uarm)
@@ -3023,6 +3056,7 @@ doprarm()
     return 0;
 }
 
+/* the '=' command */
 int
 doprring()
 {
@@ -3042,6 +3076,7 @@ doprring()
     return 0;
 }
 
+/* the '"' command */
 int
 dopramulet()
 {
@@ -3064,6 +3099,7 @@ struct obj *obj;
                       || (obj->otyp == LEASH && obj->leashmon));
 }
 
+/* the '(' command */
 int
 doprtool()
 {
@@ -3236,27 +3272,27 @@ reassign()
 
 /* #adjust command
  *
- *     User specifies a 'from' slot for inventory stack to move,
- *     then a 'to' slot for its destination.  Open slots and those
- *     filled by compatible stacks are listed as likely candidates
- *     but user can pick any inventory letter (including 'from').
- *     All compatible items found are gathered into the 'from'
- *     stack as it is moved.  If the 'to' slot isn't empty and
- *     doesn't merge, then its stack is swapped to the 'from' slot.
+ *      User specifies a 'from' slot for inventory stack to move,
+ *      then a 'to' slot for its destination.  Open slots and those
+ *      filled by compatible stacks are listed as likely candidates
+ *      but user can pick any inventory letter (including 'from').
+ *      All compatible items found are gathered into the 'from'
+ *      stack as it is moved.  If the 'to' slot isn't empty and
+ *      doesn't merge, then its stack is swapped to the 'from' slot.
  *
- *     If the user specifies a count when choosing the 'from' slot,
- *     and that count is less than the full size of the stack,
- *     then the stack will be split.  The 'count' portion is moved
- *     to the destination, and the only candidate for merging with
- *     it is the stack already at the 'to' slot, if any.  When the
- *     destination is non-empty but won't merge, whatever is there
- *     will be moved to an open slot; if there isn't any open slot
- *     available, the adjustment attempt fails.
+ *      If the user specifies a count when choosing the 'from' slot,
+ *      and that count is less than the full size of the stack,
+ *      then the stack will be split.  The 'count' portion is moved
+ *      to the destination, and the only candidate for merging with
+ *      it is the stack already at the 'to' slot, if any.  When the
+ *      destination is non-empty but won't merge, whatever is there
+ *      will be moved to an open slot; if there isn't any open slot
+ *      available, the adjustment attempt fails.
  *
- *     Splitting has one special case:  if 'to' slot is non-empty
- *     and is compatible with 'from' in all respects except for
- *     user-assigned names, the 'count' portion being moved is
- *     effectively renamed so that it will merge with 'to' stack.
+ *      Splitting has one special case:  if 'to' slot is non-empty
+ *      and is compatible with 'from' in all respects except for
+ *      user-assigned names, the 'count' portion being moved is
+ *      effectively renamed so that it will merge with 'to' stack.
  */
 int
 doorganize() /* inventory organizer by Del Lamb */
@@ -3281,7 +3317,7 @@ doorganize() /* inventory organizer by Del Lamb */
     allowall[1] = ALL_CLASSES;
     allowall[2] = '\0';
     if (!(obj = getobj(allowall, "adjust")))
-        return (0);
+        return 0;
 
     /* figure out whether user gave a split count to getobj() */
     splitting = bumped = 0;
@@ -3440,7 +3476,7 @@ doorganize() /* inventory organizer by Del Lamb */
     if (splitting)
         clear_splitobjs(); /* reset splitobj context */
     update_inventory();
-    return (0);
+    return 0;
 }
 
 /* common to display_minventory and display_cinventory */
@@ -3466,15 +3502,25 @@ const char *hdr, *txt;
     return;
 }
 
-/* query_objlist callback: return things that could possibly be worn/wielded
- */
+/* query_objlist callback: return things that are worn or wielded */
 STATIC_OVL boolean
 worn_wield_only(obj)
 struct obj *obj;
 {
-    return (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS
-            || obj->oclass == AMULET_CLASS || obj->oclass == RING_CLASS
-            || obj->oclass == TOOL_CLASS);
+#if 1
+    /* check for things that *are* worn or wielded (only used for monsters,
+       so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
+    return (boolean) (obj->owornmask != 0L);
+#else
+    /* this used to check for things that *might* be worn or wielded,
+       but that's not particularly interesting */
+    if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
+        return TRUE;
+    return (boolean) (obj->oclass == WEAPON_CLASS
+                      || obj->oclass == ARMOR_CLASS
+                      || obj->oclass == AMULET_CLASS
+                      || obj->oclass == RING_CLASS);
+#endif
 }
 
 /*
@@ -3485,8 +3531,8 @@ struct obj *obj;
  * By default, only worn and wielded items are displayed.  The caller
  * can pick one.  Modifier flags are:
  *
- *     MINV_NOLET      - nothing selectable
- *     MINV_ALL        - display all inventory
+ *      MINV_NOLET      - nothing selectable
+ *      MINV_ALL        - display all inventory
  */
 struct obj *
 display_minventory(mon, dflags, title)
index e1c737dec6d8324fcf858dd8c3b7565a69594c60..cb080ef788c1c2739aebeb8c32b8732ad68f9c8f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 save.c  $NHDT-Date: 1432536532 2015/05/25 06:48:52 $  $NHDT-Branch: master $:$NHDT-Revision: 1.88 $ */
+/* NetHack 3.6 save.c  $NHDT-Date: 1446516854 2015/11/03 02:14:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.91 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1387,10 +1387,14 @@ freedynamicdata()
     if (iflags.wc_tile_file)
         free(iflags.wc_tile_file);
     free_autopickup_exceptions();
+
+    /* miscellaneous */
+    free_pickinv_cache();
 #endif /* FREE_ALL_MEMORY */
 #ifdef STATUS_VIA_WINDOWPORT
     status_finish();
 #endif
+
     sysopt_release(); /* SYSCF strings */
     return;
 }