Index: trunk/Ohana/src/opihi/cmd.data/book_commands.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/book_commands.c	(revision 14068)
+++ trunk/Ohana/src/opihi/cmd.data/book_commands.c	(revision 14070)
@@ -83,7 +83,8 @@
 int book_npages (int argc, char **argv) {
 
-  int N;
+  int i, N, Npages;
   Book *book;
   char *varName;
+  char *Key, *Value, *value;
 
   varName = NULL;
@@ -93,88 +94,4 @@
     remove_argument (N, &argc, argv);
   }
-
-  if (argc != 2) {
-    gprint (GP_ERR, "USAGE: book npages (book)\n");
-    FREE (varName);
-    return FALSE;
-  }
-
-  book = FindBook (argv[1]);
-  if (book == NULL) {
-    gprint (GP_ERR, "book %s not found\n", argv[1]);
-    FREE (varName);
-    return FALSE;
-  }
-
-  if (varName) {
-    set_int_variable (varName, book[0].Npages);
-  } else {
-    gprint (GP_ERR, "%d pages\n", book[0].Npages);
-  }
-  FREE (varName);
-  return TRUE;
-}
-
-int book_getbook (int argc, char **argv) {
-
-  int where, N;
-  char *varName;
-  Book *book;
-
-  varName = NULL;
-  if ((N = get_argument (argc, argv, "-var"))) {
-    remove_argument (N, &argc, argv);
-    varName = strcreate (argv[N]);
-    remove_argument (N, &argc, argv);
-  }
-
-  if (argc != 2) {
-    gprint (GP_ERR, "USAGE: book getbook (where) [-var var]\n");
-    FREE (varName);
-    return FALSE;
-  }
-
-  where = atoi (argv[1]);
-  book = GetBook (where);
-  if (book == NULL) {
-    gprint (GP_ERR, "book %s not found\n", argv[1]);
-    FREE (varName);
-    return FALSE;
-  }
-
-  if (varName) {
-    set_str_variable (varName, book[0].name);
-  } else {
-    gprint (GP_ERR, "%s\n", book[0].name);
-  }
-  FREE (varName);
-  return TRUE;
-}
-
-int book_newpage (int argc, char **argv) {
-
-  Book *book;
-
-  if (argc != 3) {
-    gprint (GP_ERR, "USAGE: book newpage (book) (page)\n");
-    return FALSE;
-  }
-
-  book = FindBook (argv[1]);
-  if (book == NULL) {
-    gprint (GP_ERR, "book %s not found\n", argv[1]);
-    return FALSE;
-  }
-  
-  CreatePage (book, argv[2]);
-  return TRUE;
-}
-
-int book_delpage (int argc, char **argv) {
-
-  int i, N;
-  Page *page;
-  Book *book;
-  char *Key, *Value, *value;
 
   Key = NULL;
@@ -185,4 +102,113 @@
     remove_argument (N, &argc, argv);
     Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book npages (book) [-var result] [-key name value]\n");
+    gprint (GP_ERR, "  reports the number of pages (optionally limited to those matching the key)\n");
+    FREE (varName);
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+
+  Npages = book[0].Npages;
+  if (Key) {
+    /* count only matching key */
+    Npages = 0;
+    for (i = 0; i < book[0].Npages; i++) {
+      value = BookGetWord (book[0].pages[i], Key);
+      if (value == NULL) continue;
+      if (!strcmp(value, Value)) Npages ++;
+    }
+  }
+
+  if (varName) {
+    set_int_variable (varName, Npages);
+  } else {
+    gprint (GP_ERR, "%d pages\n", Npages);
+  }
+  FREE (Key);
+  FREE (Value);
+  FREE (varName);
+  return TRUE;
+}
+
+int book_getbook (int argc, char **argv) {
+
+  int where, N;
+  char *varName;
+  Book *book;
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book getbook (where) [-var var]\n");
+    FREE (varName);
+    return FALSE;
+  }
+
+  where = atoi (argv[1]);
+  book = GetBook (where);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+
+  if (varName) {
+    set_str_variable (varName, book[0].name);
+  } else {
+    gprint (GP_ERR, "%s\n", book[0].name);
+  }
+  FREE (varName);
+  return TRUE;
+}
+
+int book_newpage (int argc, char **argv) {
+
+  Book *book;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: book newpage (book) (page)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+  
+  CreatePage (book, argv[2]);
+  return TRUE;
+}
+
+int book_delpage (int argc, char **argv) {
+
+  int i, N;
+  Page *page;
+  Book *book;
+  char *Key, *Value, *value;
+
+  Key = NULL;
+  Value = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
   }
 
