]> granicus.if.org Git - nethack/commitdiff
command queue handling in getobj, yn_function
authorPatR <rankin@nethack.org>
Tue, 19 Apr 2022 20:53:40 +0000 (13:53 -0700)
committerPatR <rankin@nethack.org>
Tue, 19 Apr 2022 20:53:40 +0000 (13:53 -0700)
Mostly attempting to clean up potential error handling but I don't
have any error cases to test with.  Doesn't seem to break anything
when there aren't any errors....

src/cmd.c
src/invent.c

index 5ada7c8be789876fa22830d55d71559a0cba9902..957b874f0a56426ad2a36e5e7ac796a3289c8716 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -5464,7 +5464,7 @@ char
 yn_function(const char *query, const char *resp, char def)
 {
     char res = '\033', qbuf[QBUFSZ];
-    struct _cmd_queue *cmdq = cmdq_pop();
+    struct _cmd_queue cq, *cmdq;
 #ifdef DUMPLOG
     unsigned idx = g.saved_pline_index;
     /* buffer to hold query+space+formatted_single_char_response */
@@ -5481,15 +5481,24 @@ yn_function(const char *query, const char *resp, char def)
         Strcpy(&qbuf[QBUFSZ - 1 - 3], "...");
         query = qbuf;
     }
-    if (cmdq) {
-        if (cmdq->typ == CMDQ_KEY)
-            res = cmdq->key;
+
+    if ((cmdq = cmdq_pop()) != 0) {
+        cq = *cmdq;
+        free(cmdq);
+    } else {
+        cq.typ = CMDQ_USER_INPUT;
+        cq.key = '\0'; /* lint suppression */
+    }
+
+    if (cq.typ != CMDQ_USER_INPUT) {
+        if (cq.typ == CMDQ_KEY)
+            res = cq.key;
         else
             cmdq_clear(); /* 'res' is ESC */
     } else {
         res = (*windowprocs.win_yn_function)(query, resp, def);
     }
-    free(cmdq);
+
 #ifdef DUMPLOG
     if (idx == g.saved_pline_index) {
         /* when idx is still the same as g.saved_pline_index, the interface
index 0be6565f7b401246509384a6a8f35bd35b158bd8..48f8e049030982744ec19a04e693fd0c25ddc156 100644 (file)
@@ -1489,9 +1489,10 @@ any_obj_ok(struct obj *obj)
  * case.
  */
 struct obj *
-getobj(const char *word,
-       int (*obj_ok)(OBJ_P), /* callback */
-       unsigned int ctrlflags)
+getobj(
+    const char *word,       /* usually a direct verb such as "drop" */
+    int (*obj_ok)(OBJ_P),   /* callback to classify an object's suitability */
+    unsigned int ctrlflags) /* some control to fine-tune the behavior */
 {
     register struct obj *otmp;
     register char ilet = 0;
@@ -1504,41 +1505,47 @@ getobj(const char *word,
             allownone = FALSE;
     int inaccess = 0; /* counts GETOBJ_EXCLUDE_INACCESS items to decide
                        * between "you don't have anything to <foo>"
-                       * versus "you don't have anything _else_ to <foo>" */
+                       * versus "you don't have anything _else_ to <foo>"
+                       * (also used for GETOBJ_EXCLUDE_NONINVENT) */
     long cnt;
     boolean cntgiven = FALSE;
     boolean msggiven = FALSE;
     boolean oneloop = FALSE;
     Loot *sortedinvent, *srtinv;
+    struct _cmd_queue cq, *cmdq;
 
-    struct _cmd_queue *cmdq = cmdq_pop();
-
-    if (cmdq && cmdq->typ != CMDQ_USER_INPUT) {
-        int v;
-
-        /* it's not a key, abort */
-        if (cmdq->typ != CMDQ_KEY) {
-            free(cmdq);
-            return (struct obj *) 0;
-        }
-        for (otmp = g.invent; otmp; otmp = otmp->nobj)
-            if (otmp->invlet == cmdq->key) {
-                v = (*obj_ok)(otmp);
-                if (v == GETOBJ_SUGGEST || v == GETOBJ_DOWNPLAY)
-                    break;
-            }
-        if (!otmp) {
-            v = (*obj_ok)((struct obj *) 0);
-            if (v == GETOBJ_SUGGEST || v == GETOBJ_DOWNPLAY)
-                otmp = (struct obj *) &cg.zeroobj; /* cast away const */
-        }
-        free(cmdq);
-        if (!otmp)
-            cmdq_clear();
-        return otmp;
-    }
-    if (cmdq)
+    if ((cmdq = cmdq_pop()) != 0) {
+        cq = *cmdq;
         free(cmdq);
+        /* user-input means pick something interactively now, with more
+           in the command queue for after that; if not user-input, it
+           has to be a key here */
+        if (cq.typ != CMDQ_USER_INPUT) {
+            otmp = 0; /* in case of non-key or lookup failure */
+            if (cq.typ == CMDQ_KEY) {
+                int v;
+
+                if (cq.key == '-') {
+                    /* check whether the hands/self choice is suitable */
+                    v = (*obj_ok)((struct obj *) 0);
+                    if (v == GETOBJ_SUGGEST || v == GETOBJ_DOWNPLAY)
+                        otmp = (struct obj *) &cg.zeroobj;
+                } else {
+                    /* there could be more than one match if key is '#';
+                       take first one which passes the obj_ok callback */
+                    for (otmp = g.invent; otmp; otmp = otmp->nobj)
+                        if (otmp->invlet == cq.key) {
+                            v = (*obj_ok)(otmp);
+                            if (v == GETOBJ_SUGGEST || v == GETOBJ_DOWNPLAY)
+                                break;
+                        }
+                }
+            }
+            if (!otmp)        /* didn't find what we were looking for, */
+                cmdq_clear(); /* so discard any other queued commands  */
+            return otmp;
+        } /* !CMDQ_USER_INPUT */
+    } /* cmdq */
 
     /* is "hands"/"self" a valid thing to do this action on? */
     switch ((*obj_ok)((struct obj *) 0)) {