Index: /trunk/Ohana/src/opihi/cmd.basic/macro.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.basic/macro.c	(revision 11006)
+++ /trunk/Ohana/src/opihi/cmd.basic/macro.c	(revision 11007)
@@ -1,12 +1,3 @@
 # include "basic.h"
-
-static Command macro_command[] = {
-  {"create", macro_create, "create a macro *"},
-  {"delete", macro_delete, "delete a macro *"},
-  {"list",   macro_list_f, "list a macro *"},
-  {"edit",   macro_edit,   "edit a macro <not working yet!> *"},
-  {"read",   macro_read,   "read a macro from a file <not working yet!> *"},
-  {"write",  macro_write,  "write a macro to a file <not working yet!> *"}
-};
 
 int macro (int argc, char **argv) {
@@ -27,17 +18,14 @@
   }
 
-  N = sizeof (macro_command) / sizeof (Command);
+  CommandF *cmd;
 
-  /* find the macro sub-command which matches from the list. */
-  /* if sub-command is not found, assume this is creating a new macro */
-  for (i = 0; i < N; i++) {
-    if (!strcmp (macro_command[i].name, argv[1])) {
-      status = (*macro_command[i].func) (argc - 1, argv + 1);
-      return (status);
-    }
+  cmd = find_macro_command (argv[1]);
+  if (cmd != NULL) {
+    status = (*cmd) (argc - 1, argv + 1);
+  } else {
+    /* sub-command was not found, pass argv[1..N] to macro_create */
+    status = macro_create (argc, argv);
   }
 
-  /* sub-command was not found, pass argv[1..N] to macro_create */
-  status = macro_create (argc, argv);
   return (status);
 }
Index: /trunk/Ohana/src/opihi/cmd.data/book_commands.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/book_commands.c	(revision 11006)
+++ /trunk/Ohana/src/opihi/cmd.data/book_commands.c	(revision 11007)
@@ -220,5 +220,5 @@
 
   int where, N;
-  char *varName;
+  char *varName, *keyName, *keyValue;
   Book *book;
   Page *page;
@@ -231,6 +231,15 @@
   }
 
+  keyName = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    keyName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    keyValue = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
   if (argc != 3) {
-    gprint (GP_ERR, "USAGE: book getpage (book) (where) [-var var]\n");
+    gprint (GP_ERR, "USAGE: book getpage (book) (where) [-var var] [-key key value]\n");
     return FALSE;
   }
@@ -244,5 +253,9 @@
   }
 
-  page = GetPage (book, where);
+  if (keyName == NULL) {
+    page = GetPage (book, where);
+  } else {
+    page = GetPageRestricted (book, where, keyName, keyValue);
+  }
   if (page == NULL) {
     gprint (GP_ERR, "page %s in book %s not found\n", argv[2], argv[1]);
Index: /trunk/Ohana/src/opihi/include/data.h
===================================================================
--- /trunk/Ohana/src/opihi/include/data.h	(revision 11006)
+++ /trunk/Ohana/src/opihi/include/data.h	(revision 11007)
@@ -50,4 +50,5 @@
 Page *FindPage (Book *book, char *name);
 Page *GetPage (Book *book, int where);
+Page *GetPageRestricted (Book *book, int where, char *keyName, char *keyValue);
 Page *CreatePage (Book *book, char *name);
 int DeletePage (Book *book, Page *page);
Index: /trunk/Ohana/src/opihi/lib.data/page.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.data/page.c	(revision 11006)
+++ /trunk/Ohana/src/opihi/lib.data/page.c	(revision 11007)
@@ -24,5 +24,5 @@
 }
 
-/* return the given book */
+/* return the given page */
 Page *GetPage (Book *book, int where) {
 
@@ -33,4 +33,46 @@
   if (where >= book[0].Npages) return NULL;
   return (book[0].pages[where]);
+}
+
+/* return the given page with key restrictions */
+Page *GetPageRestricted (Book *book, int where, char *keyName, char *keyValue) {
+
+  int i;
+  int N, Nout;
+  char *value;
+
+  if (where < 0) where += book[0].Npages;
+  if (where < 0) return NULL;
+  if (where >= book[0].Npages) return NULL;
+
+  if (where >= 0) {
+    N = -1;
+    for (i = 0; (i < book[0].Npages) && (N < where); i++) {
+      value = BookGetWord (book[0].pages[i], keyName);
+      if ((value == NULL) && !strcmp (keyValue, "NULL")) {
+	N++;
+	Nout = i;
+      } 
+      if ((value != NULL) && !strcmp (keyValue, value)) {
+	N++;
+	Nout = i;
+      }
+    }
+  } else {
+    N = 0;
+    for (i = book[0].Npages - 1; (i >= 0) && (N > where); i--) {
+      value = BookGetWord (book[0].pages[i], keyName);
+      if ((value == NULL) && !strcmp (keyValue, "NULL")) {
+	N--;
+      } 
+      if ((value != NULL) && !strcmp (keyValue, value)) {
+	N--;
+      }
+    }
+  }
+
+  if (N != where) return NULL;
+
+  return (book[0].pages[Nout]);
 }
 
Index: /trunk/Ohana/src/opihi/lib.shell/ListOps.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/ListOps.c	(revision 11006)
+++ /trunk/Ohana/src/opihi/lib.shell/ListOps.c	(revision 11007)
@@ -111,7 +111,8 @@
   char *comm;
   char *this_macro;
-
-  comm = thisword (line);
-  if (comm == (char *) NULL) return (FALSE);
+  CommandF *cmd;
+
+  comm = thisword (line);
+  if (comm == NULL) return (FALSE);
 
   status = !strcmp (comm, "macro");
@@ -120,21 +121,14 @@
   
   this_macro = thisword (nextword (line));
-
-  if (this_macro == (char *)NULL) return (FALSE);
-
-  N = sizeof (in_macro) / sizeof (Command);
-
-  /* find the macro sub-command which matches from the list. */
-  /* if sub-command is not found, assume this is creating a new macro */
-  for (i = 0; i < N; i++) {
-    if (!strcmp (in_macro[i].name, this_macro)) {
-      free (this_macro);
-      return (FALSE);
-    }
-  }
-
+  if (this_macro == NULL) return (FALSE);
+
+  cmd = find_macro_command (this_macro);
   free (this_macro);
+
+  if (cmd == NULL) {
+    return (FALSE);
+  }
+
   return (TRUE);
-
 }
 
Index: /trunk/Ohana/src/opihi/lib.shell/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/Makefile	(revision 11006)
+++ /trunk/Ohana/src/opihi/lib.shell/Makefile	(revision 11007)
@@ -22,4 +22,5 @@
 $(SDIR)/macro_delete.$(ARCH).o          \
 $(SDIR)/macro_edit.$(ARCH).o            \
+$(SDIR)/macro_funcs.$(ARCH).o           \
 $(SDIR)/macro_exec.$(ARCH).o            \
 $(SDIR)/macro_list.$(ARCH).o            \
Index: /trunk/Ohana/src/opihi/lib.shell/macro_funcs.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/macro_funcs.c	(revision 11007)
+++ /trunk/Ohana/src/opihi/lib.shell/macro_funcs.c	(revision 11007)
@@ -0,0 +1,26 @@
+# include "basic.h"
+
+static Command macro_command[] = {
+  {"create", macro_create, "create a macro *"},
+  {"delete", macro_delete, "delete a macro *"},
+  {"list",   macro_list_f, "list a macro *"},
+  {"edit",   macro_edit,   "edit a macro <not working yet!> *"},
+  {"read",   macro_read,   "read a macro from a file <not working yet!> *"},
+  {"write",  macro_write,  "write a macro to a file <not working yet!> *"}
+};
+
+CommandF *find_macro_command (char *name) {
+
+  int i, N;
+
+  N = sizeof (macro_command) / sizeof (Command);
+
+  /* find the macro sub-command which matches from the list. */
+  for (i = 0; i < N; i++) {
+    if (!strcmp (macro_command[i].name, name)) {
+      return (macro_command[i].func);
+    }
+  }
+
+  return NULL;
+}
