Adding Special 'Stacking' Operators

diff --git a/MagickWand/operation.c b/MagickWand/operation.c
index 34b33aa..80ea212 100644
--- a/MagickWand/operation.c
+++ b/MagickWand/operation.c
@@ -50,7 +50,9 @@
 #include "MagickWand/studio.h"
 #include "MagickWand/MagickWand.h"
 #include "MagickWand/magick-wand-private.h"
+#include "MagickWand/magick-cli-private.h"
 #include "MagickWand/operation.h"
+#include "MagickWand/wand.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/thread-private.h"
 #include "MagickCore/string-private.h"
@@ -72,7 +74,7 @@
 */
 static MagickBooleanType MonitorProgress(const char *text,
   const MagickOffsetType offset,const MagickSizeType extent,
-  void *wand_unused(client_data))
+  void *wand_unused(cli_wandent_data))
 {
   char
     message[MaxTextExtent],
@@ -149,6 +151,8 @@
   specifications (or direct floating point numbers).  The number of floats
   needed to represent a color varies depending on teh current channel
   setting.
+
+  This really should be in MagickCore, so that other API's can make use of it.
 */
 static Image *SparseColorOption(const Image *image,
   const SparseColorMethod method,const char *arguments,
@@ -223,7 +227,7 @@
   number_arguments=x;
   if ( error ) {
     (void) ThrowMagickException(exception,GetMagickModule(),
-               OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
+               OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
                "Invalid number of Arguments");
     return( (Image *)NULL);
   }
@@ -246,7 +250,7 @@
     if ( token[0] == '\0' ) break;
     if ( isalpha((int) token[0]) || token[0] == '#' ) {
       (void) ThrowMagickException(exception,GetMagickModule(),
-            OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
+            OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
             "Color found, instead of X-coord");
       error = MagickTrue;
       break;
@@ -257,7 +261,7 @@
     if ( token[0] == '\0' ) break;
     if ( isalpha((int) token[0]) || token[0] == '#' ) {
       (void) ThrowMagickException(exception,GetMagickModule(),
-            OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
+            OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
             "Color found, instead of Y-coord");
       error = MagickTrue;
       break;
@@ -332,7 +336,7 @@
   }
   if ( number_arguments != x && !error ) {
     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
+      "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
     sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
     return( (Image *)NULL);
   }
@@ -351,30 +355,172 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   W a n d S e t t i n g O p t i o n I n f o                                 %
++   A c q u i r e W a n d C L I                                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WandSettingOptionInfo() applies a single settings option into a CLI wand
-%  holding the image_info, draw_info, quantize_info structures that will be
-%  used when processing the images also found within the wand.
+%  AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
+%  Wand). The given image_info and exception is included as is if provided.
 %
-%  These options do no require images to be present in the wand for them to be
-%  able to be set, in which case they will be applied to
+%  Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
+%  needed.
+%
+%  The format of the NewMagickWand method is:
+% 
+%      MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
+%           ExceptionInfo *exception)
+%
+*/
+WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
+    ExceptionInfo *exception)
+{
+  MagickCLI
+    *cli_wand;
+
+  /* precaution - as per NewMagickWand() */
+  {
+     size_t depth = MAGICKCORE_QUANTUM_DEPTH;
+     const char *quantum = GetMagickQuantumDepth(&depth);
+     if (depth != MAGICKCORE_QUANTUM_DEPTH)
+       ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
+  }
+
+  /* allocate memory for MgaickCLI */
+  cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
+  if (cli_wand == (MagickCLI *) NULL)
+    {
+      ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
+        GetExceptionMessage(errno));
+      return((MagickCLI *)NULL);
+    }
+
+  /* Initialize Wand Part of MagickCLI
+     FUTURE: this is a repeat of code from NewMagickWand()
+     However some parts may be given fro man external source!
+  */
+  cli_wand->wand.id=AcquireWandId();
+  (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
+           "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
+  cli_wand->wand.images=NewImageList();
+  if ( image_info == (ImageInfo *)NULL)
+    cli_wand->wand.image_info=AcquireImageInfo();
+  else
+    cli_wand->wand.image_info=image_info;
+  if ( exception == (ExceptionInfo *)NULL)
+    cli_wand->wand.exception=AcquireExceptionInfo();
+  else
+    cli_wand->wand.exception=exception;
+  cli_wand->wand.debug=IsEventLogging();
+  cli_wand->wand.signature=WandSignature;
+
+  /* Initialize CLI Part of MagickCLI */
+  cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
+  cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
+  cli_wand->image_list_stack=(Stack *)NULL;
+  cli_wand->image_info_stack=(Stack *)NULL;
+  cli_wand->signature=WandSignature;
+
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+  return(cli_wand);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   D e s t r o y W a n d C L I                                               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  DestroyMagickCLI() destorys everything in a CLI wand, including image_info
+%  and any exceptions, if still present in the wand.
+%
+%  The format of the NewMagickWand method is:
+% 
+%    MagickWand *DestroyMagickCLI()
+%            Exception *exception)
+%
+*/
+WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
+{
+  Stack
+    *node;
+
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+
+  /* Destroy CLI part of MagickCLI */
+  if (cli_wand->draw_info != (DrawInfo *) NULL )
+    cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
+  if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
+    cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
+  while(cli_wand->image_list_stack != (Stack *)NULL)
+    {
+      node=cli_wand->image_list_stack;
+      cli_wand->image_list_stack=node->next;
+      (void) DestroyImageList((Image *)node->data);
+      (void) RelinquishMagickMemory(node);
+    }
+  while(cli_wand->image_info_stack != (Stack *)NULL)
+    {
+      node=cli_wand->image_info_stack;
+      cli_wand->image_info_stack=node->next;
+      (void) DestroyImageInfo((ImageInfo *)node->data);
+      (void) RelinquishMagickMemory(node);
+    }
+  cli_wand->signature=(~WandSignature);
+
+  /* Destroy Wand part MagickCLI */
+  cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
+  if (cli_wand->wand.image_info != (ImageInfo *) NULL )
+    cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
+  if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
+    cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
+  RelinquishWandId(cli_wand->wand.id);
+  cli_wand->wand.signature=(~WandSignature);
+
+  return((MagickCLI *)NULL);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   C L I S e t t i n g O p t i o n I n f o                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  CLISettingOptionInfo() applies a single settings option into a CLI wand
+%  holding the image_info, draw_info, quantize_info structures that will be
+%  used when processing the images.
+%
+%  These options do no require images to be present in the CLI wand for them
+%  to be able to be set, in which case they will generally be applied to image
+%  that are read in later
 %
 %  Options handled by this function are listed in CommandOptions[] of
 %  "option.c" that is one of "SettingOptionFlags" option flags.
 %
 %  The format of the WandSettingOptionInfo method is:
 %
-%    void WandSettingOptionInfo(MagickWand *wand,const char *option,
+%    void CLISettingOptionInfo(MagickCLI *cli_wand,const char *option,
 %               const char *arg)
 %
 %  A description of each parameter follows:
 %
-%    o wand: structure holding settings to be applied
+%    o cli_wand: structure holding settings to be applied
 %
 %    o option: The option string to be set
 %
@@ -384,9 +530,9 @@
 %
 % Example usage...
 %
-%    WandSettingOptionInfo(wand, "background", MagickTrue, "Red");
-%    WandSettingOptionInfo(wand, "adjoin", "true");
-%    WandSettingOptionInfo(wand, "adjoin", NULL);
+%    CLISettingOptionInfo(cli_wand, "background", MagickTrue, "Red");
+%    CLISettingOptionInfo(cli_wand, "adjoin", "true");
+%    CLISettingOptionInfo(cli_wand, "adjoin", NULL);
 %
 % Or for handling command line arguments EG: +/-option ["arg"]
 %
@@ -396,25 +542,25 @@
 %    count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
 %    flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
 %    if ( (flags & SettingOptionFlags) != 0 )
-%      WandSettingOptionInfo(wand, argv[i]+1,
+%      CLISettingOptionInfo(cli_wand, argv[i]+1,
 %            (((*argv[i])!='-') ? (char *)NULL
 %                   : (count>0) ? argv[i+1] : "true") );
 %    i += count+1;
 %
 */
-WandExport void WandSettingOptionInfo(MagickWand *wand,const char *option,
+WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,const char *option,
      const char *arg)
 {
-  assert(wand != (MagickWand *) NULL);
-  assert(wand->signature == WandSignature);
-  assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
-  if (wand->debug != MagickFalse)
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
-#define image_info      (wand->image_info)
-#define draw_info       (wand->draw_info)
-#define quantize_info   (wand->quantize_info)
-#define exception       (wand->exception)
+#define image_info      (cli_wand->wand.image_info)
+#define exception       (cli_wand->wand.exception)
+#define draw_info       (cli_wand->draw_info)
+#define quantize_info   (cli_wand->quantize_info)
 #define IfSetOption     (arg!=(char *)NULL)
 #define ArgOption(def)  (IfSetOption?arg:(const char *)(def))
 #define ArgBoolean      (IfSetOption?MagickTrue:MagickFalse)
@@ -527,7 +673,7 @@
       if (LocaleCompare("box",option) == 0)
         {
           /* DEPRECIATED - now "undercolor" */
-          WandSettingOptionInfo(wand,"undercolor",arg);
+          CLISettingOptionInfo(cli_wand,"undercolor",arg);
           break;
         }
       break;
@@ -553,8 +699,9 @@
         }
       if (LocaleCompare("channel",option) == 0)
         {
-          /* This is applied to images in SimpleImageOperator!!!
-             FUTURE: move it to SyncImageSettings() - or alternative
+          /* FUTURE:  -channel mask {vaules}
+             This is applied to images in SimpleImageOperator!!!
+             Move it to SyncImageSettings() - or alternative
           */
           image_info->channel=(ChannelType) (
                IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
@@ -615,7 +762,7 @@
           /* SyncImageSettings() used to set per-image attribute. */
           (void) SetLogEventMask(ArgOption("none"));
           image_info->debug=IsEventLogging(); /* extract logging*/
-          wand->debug=IsEventLogging();
+          cli_wand->wand.debug=IsEventLogging();
           break;
         }
       if (LocaleCompare("define",option) == 0)
@@ -898,97 +1045,6 @@
           (void) SetImageOption(image_info,option,ArgOption(NULL));
           break;
         }
-      if (LocaleCompare("list",option) == 0)
-        {
-          ssize_t
-            list;
-
-          /* FUTURE: This is not really a Setting Option, but a Special
-           * The bulk of this should be turned into a MagickCore function
-           */
-          list=ParseCommandOption(MagickListOptions,MagickFalse,
-               ArgOption("list"));
-          switch (list)
-          {
-            case MagickCoderOptions:
-            {
-              (void) ListCoderInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickColorOptions:
-            {
-              (void) ListColorInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickConfigureOptions:
-            {
-              (void) ListConfigureInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickDelegateOptions:
-            {
-              (void) ListDelegateInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickFontOptions:
-            {
-              (void) ListTypeInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickFormatOptions:
-            {
-              (void) ListMagickInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickLocaleOptions:
-            {
-              (void) ListLocaleInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickLogOptions:
-            {
-              (void) ListLogInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickMagicOptions:
-            {
-              (void) ListMagicInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickMimeOptions:
-            {
-              (void) ListMimeInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickModuleOptions:
-            {
-              (void) ListModuleInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickPolicyOptions:
-            {
-              (void) ListPolicyInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickResourceOptions:
-            {
-              (void) ListMagickResourceInfo((FILE *) NULL,exception);
-              break;
-            }
-            case MagickThresholdOptions:
-            {
-              (void) ListThresholdMaps((FILE *) NULL,exception);
-              break;
-            }
-            default:
-            {
-              (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
-                exception);
-              break;
-            }
-          }
-          break;
-        }
       if (LocaleCompare("log",option) == 0)
         {
           if (IfSetOption)
@@ -1170,6 +1226,11 @@
           draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
           break;
         }
+      if (LocaleCompare("respect-parenthesis",option) == 0)
+        {
+          (void) SetImageOption(image_info,option,ArgOption(NULL));
+          break;
+        }
       break;
     }
     case 's':
@@ -1412,9 +1473,9 @@
       break;
   }
 #undef image_info
+#undef exception
 #undef draw_info
 #undef quantize_info
-#undef exception
 #undef IfSetOption
 #undef ArgOption
 #undef ArgBoolean
@@ -1427,28 +1488,28 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+     W a n d S i m p l e O p e r a t o r I m a g e s                         %
++     C L I S i m p l e O p e r a t o r I m a g e s                           %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  WandSimpleOperatorImages() applys one simple image operation given to all
-%  the images in the current wand,  with the settings that are saved in the
-%  CLI wand.
+%  the images in the CLI wand,  with the settings that was previously saved in
+%  the CLI wand.
 %
 %  It is assumed that any per-image settings are up-to-date with respect to
-%  extra settings that have been saved in the wand.
+%  extra settings that were already saved in the wand.
 %
 %  The format of the WandSimpleOperatorImage method is:
 %
-%    void WandSimpleOperatorImages(MagickWand *wand,
+%    void CLISimpleOperatorImages(MagickCLI *cli_wand,
 %        const MagickBooleanType plus_alt_op, const char *option,
 %        const char *arg1, const char *arg2)
 %
 %  A description of each parameter follows:
 %
-%    o wand: structure holding settings to be applied
+%    o cli_wand: structure holding settings and images to be operated on
 %
 %    o plus_alt_op:  request the 'plus' or alturnative form of the operation
 %
@@ -1460,23 +1521,24 @@
 %
 % Example usage...
 %
-%  WandSimpleOperatorImages(wand, MagickFalse,"crop","100x100+20+30",NULL);
-%  WandSimpleOperatorImages(wand, MagickTrue, "repage",NULL,NULL);
-%  WandSimpleOperatorImages(wand, MagickTrue, "distort","SRT","45");
-%  if ( wand->exception->severity != UndefinedException ) {
+%  CLISimpleOperatorImages(cli_wand, MagickFalse,"crop","100x100+20+30",NULL);
+%  CLISimpleOperatorImages(cli_wand, MagickTrue, "repage",NULL,NULL);
+%  CLISimpleOperatorImages(cli_wand, MagickTrue, "distort","SRT","45");
+%  if ( cli_wand->wand.exception->severity != UndefinedException ) {
 %    CatchException(exception);
 %    exit(1);
 %  }
 %
 % Or for handling command line arguments EG: +/-option ["arg"]
 %
+%    cli_wand
 %    argc,argv
 %    i=index in argv
 %
 %    count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
 %    flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
 %    if ( (flags & SimpleOperatorOptionFlag) != 0 )
-%      WandSimpleOperatorImages(wand,
+%      CLISimpleOperatorImages(cli_wand,
 %          ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
 %          count>=1 ? argv[i+1] : (char *)NULL,
 %          count>=2 ? argv[i+2] : (char *)NULL );
@@ -1486,7 +1548,7 @@
 
 /*
   Internal subrountine to apply one simple image operation to the current
-  image pointed to by the wand.
+  image pointed to by the CLI wand.
 
   The image in the list may be modified in three different ways...
     * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
@@ -1501,7 +1563,7 @@
   also change.  GetFirstImageInList() should be used by caller if they wish
   return the Image pointer to the first image in list.
 */
-static void WandSimpleOperatorImage(MagickWand *wand,
+static void CLISimpleOperatorImage(MagickCLI *cli_wand,
   const MagickBooleanType plus_alt_op, const char *option,
   const char *arg1, const char *arg2)
 {
@@ -1517,21 +1579,19 @@
   MagickStatusType
     flags;
 
-#define image_info      (wand->image_info)
-#define draw_info       (wand->draw_info)
-#define quantize_info   (wand->quantize_info)
-#define image           (wand->images)
-#define exception       (wand->exception)
+#define image_info      (cli_wand->wand.image_info)
+#define image           (cli_wand->wand.images)
+#define exception       (cli_wand->wand.exception)
+#define draw_info       (cli_wand->draw_info)
+#define quantize_info   (cli_wand->quantize_info)
 #define normal_op       (plus_alt_op?MagickFalse:MagickTrue)
 
-  assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
-  assert(draw_info != (DrawInfo *) NULL);      /* ensure it is a CLI wand */
-  assert(image != (Image *) NULL);             /* there is an image */
-  assert(image->signature == MagickSignature); /* and is a valid image */
-
-  if (wand->debug != MagickFalse)
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+  assert(image != (Image *) NULL);             /* an image must be present */
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
   SetGeometryInfo(&geometry_info);
 
@@ -1803,15 +1863,15 @@
           (void) ClampImage(image,exception);
           break;
         }
-      if (LocaleCompare("clip",option) == 0)
+      if (LocaleCompare("cli_wandp",option) == 0)
         {
           if (plus_alt_op == MagickFalse)
             (void) ClipImage(image,exception);
-          else /* "+clip" remove the write mask */
+          else /* "+mask" remove the write mask */
             (void) SetImageMask(image,(Image *) NULL,exception);
           break;
         }
-      if (LocaleCompare("clip-mask",option) == 0)
+      if (LocaleCompare("cli_wandp-mask",option) == 0)
         {
           CacheView
             *mask_view;
@@ -1829,7 +1889,7 @@
             y;
 
           if (plus_alt_op != MagickFalse)
-          { /* "+clip-mask" Remove the write mask */
+          { /* "+cli_wandp-mask" Remove the write mask */
               (void) SetImageMask(image,(Image *) NULL,exception);
               break;
             }
@@ -1839,7 +1899,7 @@
           if (SetImageStorageClass(mask_image,DirectClass,exception)
                == MagickFalse)
             break;
-          /* Create a write mask from clip-mask image */
+          /* Create a write mask from cli_wandp-mask image */
           /* FUTURE: use Alpha operations instead and create a Grey Image */
           mask_view=AcquireCacheView(mask_image);
           for (y=0; y < (ssize_t) mask_image->rows; y++)
@@ -1867,7 +1927,7 @@
           mask_image=DestroyImage(mask_image);
           break;
         }
-      if (LocaleCompare("clip-path",option) == 0)
+      if (LocaleCompare("cli_wandp-path",option) == 0)
         {
           (void) ClipImagePath(image,arg1,
                (MagickBooleanType)(!(int)plus_alt_op),exception);
@@ -2940,6 +3000,7 @@
       if (LocaleCompare("separate",option) == 0)
         {
           /* WARNING: This can generate multiple images! */
+          /* FUTURE - this may be replaced by a "-channel" method */
           new_image=SeparateImages(image,exception);
           break;
         }
@@ -3298,34 +3359,34 @@
 #undef normal_op
 }
 
-WandExport void WandSimpleOperatorImages(MagickWand *wand,
+WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
   const MagickBooleanType plus_alt_op, const char *option,
   const char *arg1, const char *arg2)
 {
   size_t
-    n;
-
-  register ssize_t
+    n,
     i;
 
-  assert(wand->image_info != (const ImageInfo *) NULL);
-  assert(wand->image_info->signature == MagickSignature);
-  assert(wand->draw_info != (DrawInfo *) NULL);   /* ensure it is a CLI wand */
-  assert(wand->images != (Image *) NULL);         /* there is one image */
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+  assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
   i=0;
-  n=GetImageListLength(wand->images);
-  (void) n;
-  wand->images=GetFirstImageInList(wand->images);
-  for ( ; ; )
+  n=GetImageListLength(cli_wand->wand.images);
+  cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
+  while (1)
   {
-    WandSimpleOperatorImage(wand, plus_alt_op, option, arg1, arg2);
-    if ( wand->images->next == (Image *) NULL )
-      break;
-    wand->images=wand->images->next;
     i++;
+    CLISimpleOperatorImage(cli_wand, plus_alt_op, option, arg1, arg2);
+    if ( cli_wand->wand.images->next == (Image *) NULL )
+      break;
+    cli_wand->wand.images=cli_wand->wand.images->next;
   }
-  wand->images=GetFirstImageInList(wand->images);
+  assert( i == n );
+  cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
   return;
 }
 
@@ -3334,25 +3395,25 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+     W a n d L i s t O p e r a t o r I m a g e s                             %
++     C L I L i s t O p e r a t o r I m a g e s                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WandListOperatorImages() applies a single operation that is apply to the
+%  CLIListOperatorImages() applies a single operation that is apply to the
 %  entire image list as a whole. The result is often a complete replacment
 %  of the image list with a completely new list, or just a single image.
 %
 %  The format of the MogrifyImage method is:
 %
-%    void WandListOperatorImages(MagickWand *wand,
+%    void CLIListOperatorImages(MagickCLI *cli_wand,
 %        const MagickBooleanType plus_alt_op,const char *option,
 %        const char *arg1, const char *arg2)
 %
 %  A description of each parameter follows:
 %
-%    o wand: structure holding settings to be applied
+%    o cli_wand: structure holding settings to be applied
 %
 %    o plus_alt_op:  request the 'plus' or alturnative form of the operation
 %
@@ -3364,50 +3425,49 @@
 %
 % Example usage...
 %
-%  WandListOperatorImages(wand,MagickFalse,"duplicate", "3",  NULL);
-%  WandListOperatorImages(wand,MagickTrue, "append",    NULL, NULL);
-%  if ( wand->exception->severity != UndefinedException ) {
+%  CLIListOperatorImages(cli_wand,MagickFalse,"duplicate", "3",  NULL);
+%  CLIListOperatorImages(cli_wand,MagickTrue, "append",    NULL, NULL);
+%  if ( cli_wand->wand.exception->severity != UndefinedException ) {
 %    CatchException(exception);
 %    exit(1);
 %  }
 %
 % Or for handling command line arguments EG: +/-option ["arg"]
 %
+%    cli_wand
 %    argc,argv
 %    i=index in argv
 %
 %    count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
 %    flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
 %    if ( (flags & ListOperatorOptionFlag) != 0 )
-%      WandListOperatorImages(wand,
+%      CLIListOperatorImages(cli_wand,
 %          ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
 %          count>=1 ? argv[i+1] : (char *)NULL,
 %          count>=2 ? argv[i+2] : (char *)NULL );
 %    i += count+1;
 %
 */
-WandExport void WandListOperatorImages(MagickWand *wand,
+WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
      const MagickBooleanType plus_alt_op,const char *option,
      const char *arg1, const char *arg2)
 {
   Image
     *new_images;
 
-#define image_info      (wand->image_info)
-#define draw_info       (wand->draw_info)
-#define quantize_info   (wand->quantize_info)
-#define images          (wand->images)
-#define exception       (wand->exception)
+#define image_info      (cli_wand->wand.image_info)
+#define images          (cli_wand->wand.images)
+#define exception       (cli_wand->wand.exception)
+#define draw_info       (cli_wand->draw_info)
+#define quantize_info   (cli_wand->quantize_info)
 #define normal_op       (plus_alt_op?MagickFalse:MagickTrue)
 
-  assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
-  assert(draw_info != (DrawInfo *) NULL);       /* ensure it is a CLI wand */
-  assert(images != (Image *) NULL);             /* there is an image */
-  assert(images->signature == MagickSignature); /* and is a valid image */
-
-  if (wand->debug != MagickFalse)
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+  assert(images != (Image *) NULL);             /* images must be present */
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
   (void) SyncImagesSettings(image_info,images,exception);
 
@@ -3425,7 +3485,7 @@
       if (LocaleCompare("average",option) == 0)
         {
           /* DEPRECIATED - use -evaluate-sequence Mean */
-          WandListOperatorImages(wand,plus_alt_op,"evaluate-sequence","Mean",
+          CLIListOperatorImages(cli_wand,plus_alt_op,"evaluate-sequence","Mean",
                NULL);
           break;
         }
@@ -3462,6 +3522,7 @@
         }
       if (LocaleCompare("combine",option) == 0)
         {
+          /* FUTURE - this may be replaced by a 'channel' method */
           new_images=CombineImages(images,exception);
           break;
         }
@@ -3535,7 +3596,7 @@
       if (LocaleCompare("deconstruct",option) == 0)
         {
           /* DEPRECIATED - use -layers CompareAny */
-          WandListOperatorImages(wand,plus_alt_op,"layer","CompareAny",NULL);
+          CLIListOperatorImages(cli_wand,plus_alt_op,"layer","CompareAny",NULL);
           break;
         }
       if (LocaleCompare("delete",option) == 0)
@@ -3597,7 +3658,7 @@
       if (LocaleCompare("flatten",option) == 0)
         {
           /* DEPRECIATED use -layers mosaic instead */
-          WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
+          CLIListOperatorImages(cli_wand,plus_alt_op,"layer",option,NULL);
           break;
         }
       if (LocaleCompare("fx",option) == 0)
@@ -3659,22 +3720,22 @@
           insert_image=RemoveLastImageFromList(&images);
           if (plus_alt_op == MagickFalse)
             index=(ssize_t) StringToLong(arg1);
+          index_image=insert_image;
           if (index == 0)
             PrependImageToList(&images,insert_image);
+          else if (index == (ssize_t) GetImageListLength(images))
+            AppendImageToList(&images,insert_image);
           else
-            if (index == (ssize_t) GetImageListLength(images))
-              AppendImageToList(&images,insert_image);
-            else
-              {
-                 index_image=GetImageFromList(images,index-1);
-                 if (index_image == (Image *) NULL)
-                   {
-                     (void) ThrowMagickException(exception,GetMagickModule(),
-                       OptionError,"NoSuchImage","`%s'",arg1);
-                     break;
-                   }
-                InsertImageInList(&index_image,insert_image);
-              }
+            {
+               index_image=GetImageFromList(images,index-1);
+               if (index_image == (Image *) NULL)
+                 {
+                   (void) ThrowMagickException(exception,GetMagickModule(),
+                     OptionError,"NoSuchImage","'%s'",arg1);
+                   break;
+                 }
+              InsertImageInList(&index_image,insert_image);
+            }
           images=GetFirstImageInList(index_image);
           break;
         }
@@ -3866,7 +3927,7 @@
       if (LocaleCompare("mosaic",option) == 0)
         {
           /* DEPRECIATED use -layers mosaic instead */
-          WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
+          CLIListOperatorImages(cli_wand,plus_alt_op,"layer",option,NULL);
           break;
         }
       break;
@@ -4020,7 +4081,7 @@
           if ((p == (Image *) NULL) || (q == (Image *) NULL))
             {
               (void) ThrowMagickException(exception,GetMagickModule(),
-                OptionError,"NoSuchImage","`%s'",images->filename);
+                OptionError,"NoSuchImage","'%s'",images->filename);
               break;
             }
           if (p == q)
@@ -4068,13 +4129,355 @@
 
   if (images != (Image *) NULL)
     images=DestroyImageList(images);
-  images=new_images;
+  images=GetFirstImageInList(new_images);
   return;
 
 #undef image_info
-#undef draw_info
-#undef quantize_info
 #undef images
 #undef exception
+#undef draw_info
+#undef quantize_info
 #undef normal_op
 }
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   C L I S p e c i a l O p e r a t i o n s                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  CLISpecialOption() Applies operations that may involve empty image lists
+%  and or stacks of image lists or image_info settings.
+%
+%  Note: inlike other Operators, these may involve other special 'option'
+%  character prefixes, other than simply '-' or '+' and as such the full
+%  original otpion must be passed.
+%
+%  The format of the CLISpecialOption method is:
+%
+%      void CLISpecialOption(MagickCLI *cli_wand,const char *option,
+%           const char *arg)
+%
+%  A description of each parameter follows:
+%
+%    o cli_wand: the main CLI Wand to use.
+%
+%    o option: The special option (with any switch char) to process
+%
+%    o arg: Argument for option, if required
+%
+*/
+
+#define MaxImageStackDepth  32
+
+WandExport void CLISpecialOperator(MagickCLI *cli_wand,
+  const char *option, const char *arg)
+{
+#define exception       (cli_wand->wand.exception)
+
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+  if (cli_wand->wand.debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+
+  if (LocaleCompare(option,"(") == 0)
+    {
+      /* stack 'push' images */
+      Stack
+        *node;
+
+      size_t
+        size;
+
+      const char*
+        value;
+
+      size=0;
+      node=cli_wand->image_list_stack;
+      for ( ; node != (Stack *)NULL; node=node->next)
+        size++;
+      if ( size >= MaxImageStackDepth )
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"ParenthesisNestedTooDeeply", option);
+          return;
+        }
+      node=(Stack *) AcquireMagickMemory(sizeof(*node));
+      if (node == (Stack *) NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+              ResourceLimitFatalError,"MemoryAllocationFailed", "PushImages");
+          return;
+        }
+      node->data = (void *)cli_wand->wand.images;
+      cli_wand->wand.images = NewImageList();
+      node->next = cli_wand->image_list_stack;
+      cli_wand->image_list_stack = node;
+
+      /* handle respect-parenthesis */
+      value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
+      if (value != (const char *) NULL)
+        option="{";
+      else
+        return;
+    }
+  if (LocaleCompare(option,"{") == 0)
+    {
+      /* stack 'push' of image_info settings */
+      Stack
+        *node;
+
+      size_t
+        size;
+
+      size=0;
+      node=cli_wand->image_info_stack;
+      for ( ; node != (Stack *)NULL; node=node->next)
+        size++;
+      if ( size >= MaxImageStackDepth )
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"ParenthesisNestedTooDeeply", option);
+          return;
+        }
+      node=(Stack *) AcquireMagickMemory(sizeof(*node));
+      if (node == (Stack *) NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+              ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
+          return;
+        }
+
+      node->data = (void *)cli_wand->wand.image_info;
+      cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
+      if (cli_wand->wand.image_info == (ImageInfo *)NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+              ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
+          cli_wand->wand.image_info = (ImageInfo *)node->data;
+          node = (Stack *)RelinquishMagickMemory(node);
+          return;
+        }
+
+      node->next = cli_wand->image_info_stack;
+      cli_wand->image_info_stack = node;
+
+      return;
+    }
+  if (LocaleCompare(option,")") == 0)
+    {
+      /* pop images from stack */
+      Stack
+        *node;
+
+      const char*
+        value;
+
+      node = (void *)cli_wand->image_list_stack;
+      if ( node == (Stack *)NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"UnbalancedParenthesis", option);
+          return;
+        }
+      cli_wand->image_list_stack = node->next;
+
+      AppendImageToList((Image **)&node->data,cli_wand->wand.images);
+      cli_wand->wand.images= (Image *)node->data;
+      node = (Stack *)RelinquishMagickMemory(node);
+
+      /* handle respect-parenthesis - of the previous 'push' settings */
+      node = cli_wand->image_info_stack;
+      if ( node != (Stack *)NULL)
+        {
+          value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
+          if (value != (const char *) NULL)
+            option="}";
+          else
+            return;
+        }
+      else
+        return;
+    }
+  if (LocaleCompare(option,"}") == 0)
+    {
+      /* pop image_info settings from stack */
+      Stack
+        *node;
+
+      node = (void *)cli_wand->image_info_stack;
+      if ( node == (Stack *)NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"UnbalancedParenthesis", option);
+          return;
+        }
+      cli_wand->image_info_stack = node->next;
+
+      (void) DestroyImageInfo(cli_wand->wand.image_info);
+      cli_wand->wand.image_info = (ImageInfo *)node->data;
+      node = (Stack *)RelinquishMagickMemory(node);
+
+      GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
+      cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
+      cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
+
+      return;
+    }
+  if (LocaleCompare(option+1,"clone") == 0)
+    {
+      Image
+        *new_images;
+
+      if (*option == '+')
+        arg="-1";
+      if (IsSceneGeometry(arg,MagickFalse) == MagickFalse)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"InvalidArgument", "'%s': %s", option, arg);
+          return;
+        }
+      if ( cli_wand->image_list_stack == (Stack *)NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"UnableToCloneImage", option);
+          return;
+        }
+      new_images = (Image *)cli_wand->image_list_stack->data;
+      if (new_images == (Image *) NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+               OptionError,"UnableToCloneImage", option);
+          return;
+        }
+      new_images=CloneImages(new_images,arg,exception);
+      if (new_images == (Image *) NULL)
+        {
+          ThrowMagickException(exception,GetMagickModule(),
+                OptionError,"NoSuchImage",option);
+          return;
+        }
+      AppendImageToList(&cli_wand->wand.images,new_images);
+      return;
+    }
+  if ( LocaleCompare("-read",option) == 0 )
+    {
+#if 1
+      Image *
+        new_images;
+
+      CopyMagickString(cli_wand->wand.image_info->filename,arg,MaxTextExtent);
+      if (cli_wand->wand.image_info->ping != MagickFalse)
+        new_images=PingImages(cli_wand->wand.image_info,exception);
+      else
+        new_images=ReadImages(cli_wand->wand.image_info,exception);
+      AppendImageToList(&cli_wand->wand.images, new_images);
+#else
+      /* read images using MagickWand method - no ping */
+      /* This is not working! - it locks up in a CPU loop! */
+      MagickSetLastIterator(&cli_wand->wand);
+      MagickReadImage(&cli_wand->wand,arg);
+      MagickSetFirstIterator(&cli_wand->wand);
+#endif
+      return;
+    }
+  if (LocaleCompare("-noop",option) == 0)
+    return;
+  if (LocaleCompare("-sans",option) == 0)
+    return;
+  if (LocaleCompare("-sans0",option) == 0)
+    return;
+  if (LocaleCompare("-sans2",option) == 0)
+    return;
+  if (LocaleCompare("-list",option) == 0)
+    {
+      /* FUTURE: This should really be built into the MagickCore
+         It does not actually require any wand or images at all!
+       */
+      ssize_t
+        list;
+
+      list=ParseCommandOption(MagickListOptions,MagickFalse, arg);
+      switch (list)
+      {
+        case MagickCoderOptions:
+        {
+          (void) ListCoderInfo((FILE *) NULL,exception);
+          break;
+        }
+        case MagickColorOptions:
+        {
+          (void) ListColorInfo((FILE *) NULL,exception);
+          break;
+        }
+        case MagickConfigureOptions:
+        {
+          (void) ListConfigureInfo((FILE *) NULL,exception);
+          break;
+        }
+        case MagickDelegateOptions:
+        {
+          (void) ListDelegateInfo((FILE *) NULL,exception);
+          break;
+        }
+        case MagickFontOptions:
+        {
+          (void) ListTypeInfo((FILE *) NULL,exception);
+          break;
+        }
+        case MagickFormatOptions:
+          (void) ListMagickInfo((FILE *) NULL,exception);
+          break;
+        case MagickLocaleOptions:
+          (void) ListLocaleInfo((FILE *) NULL,exception);
+          break;
+        case MagickLogOptions:
+          (void) ListLogInfo((FILE *) NULL,exception);
+          break;
+        case MagickMagicOptions:
+          (void) ListMagicInfo((FILE *) NULL,exception);
+          break;
+        case MagickMimeOptions:
+          (void) ListMimeInfo((FILE *) NULL,exception);
+          break;
+        case MagickModuleOptions:
+          (void) ListModuleInfo((FILE *) NULL,exception);
+          break;
+        case MagickPolicyOptions:
+          (void) ListPolicyInfo((FILE *) NULL,exception);
+          break;
+        case MagickResourceOptions:
+          (void) ListMagickResourceInfo((FILE *) NULL,exception);
+          break;
+        case MagickThresholdOptions:
+          (void) ListThresholdMaps((FILE *) NULL,exception);
+          break;
+        default:
+          (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
+            exception);
+          break;
+      }
+      return;
+    }
+
+#if 0
+    // adjust stack handling
+  // Other 'special' options this should handle
+  //    "region" "list" "version"
+  // It does not do "exit" however as due to its side-effect requirements
+#endif
+#if 0
+  if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
+    MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
+#endif
+
+#undef image_info
+#undef images
+#undef exception
+}