13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                  L       OOO    CCCC   AAA   L      EEEEE                   %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                  L      O   O  C      A   A  L      E                       %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                  L      O   O  C      AAAAA  L      EEE                     %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                  L      O   O  C      A   A  L      E                       %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                  LLLLL   OOO    CCCC  A   A  LLLLL  EEEEE                   %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                      MagickCore Image Locale Methods                        %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 2003                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/configure.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
48007e925e29fea767305ade6e1d635e5e517a13b3dirk#include "MagickCore/image-private.h"
49abed7e293f2e8a83e8036df7f2a3e1d9859e5fb2dirk#include "MagickCore/linked-list.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/locale_.h"
515ff4eaf57b3cd47d0371f204f865cbba614674a0cristy#include "MagickCore/locale-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
54d2d11ec3ae6f94d5b49cbaf90e7f9ca18c252d29cristy#include "MagickCore/nt-base-private.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/semaphore.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/splay-tree.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
587832dc2d904c471770087cce18a9a2d76c2216a3cristy#include "MagickCore/string-private.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/token.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
61d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristy#include "MagickCore/utility-private.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/xml-tree.h"
633291f51a77fdd817efb58d652c78c407cbfdf7d1cristy#include "MagickCore/xml-tree-private.h"
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Define declarations.
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
68c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_HAVE_NEWLOCALE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
69c6a82901209d11a186620b6372d8a6b18a552b50cristy#  define MAGICKCORE_LOCALE_SUPPORT
70c6a82901209d11a186620b6372d8a6b18a552b50cristy#endif
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define LocaleFilename  "locale.xml"
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxRecursionDepth  200
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Static declarations.
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic const char
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *LocaleMap =
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "<?xml version=\"1.0\"?>"
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "<localemap>"
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  <locale name=\"C\">"
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "    <Exception>"
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "     <Message name=\"\">"
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "     </Message>"
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "    </Exception>"
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  </locale>"
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "</localemap>";
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic SemaphoreInfo
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *locale_semaphore = (SemaphoreInfo *) NULL;
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic SplayTreeInfo
9386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  *locale_cache = (SplayTreeInfo *) NULL;
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
95c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT)
96a20c904a6f3e3a11939d5260485be72d5c849c63cristystatic volatile locale_t
97b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  c_locale = (locale_t) NULL;
98c6a82901209d11a186620b6372d8a6b18a552b50cristy#endif
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
104904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy  IsLocaleTreeInstantiated(ExceptionInfo *),
105cd2cd1803dda951bcfff101c44032ae17e52655fcristy  LoadLocaleCache(SplayTreeInfo *,const char *,const char *,const char *,
106cd2cd1803dda951bcfff101c44032ae17e52655fcristy    const size_t,ExceptionInfo *);
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
108c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT)
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
114b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy+   A c q u i r e C L o c a l e                                               %
115a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
116a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
117a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
118a20c904a6f3e3a11939d5260485be72d5c849c63cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
120b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  AcquireCLocale() allocates the C locale object, or (locale_t) 0 with
121a20c904a6f3e3a11939d5260485be72d5c849c63cristy%  errno set if it cannot be acquired.
122a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
123b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  The format of the AcquireCLocale method is:
124a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
125b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%      locale_t AcquireCLocale(void)
126a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
127a20c904a6f3e3a11939d5260485be72d5c849c63cristy*/
128b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristystatic locale_t AcquireCLocale(void)
129a20c904a6f3e3a11939d5260485be72d5c849c63cristy{
130a20c904a6f3e3a11939d5260485be72d5c849c63cristy#if defined(MAGICKCORE_HAVE_NEWLOCALE)
131b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (c_locale == (locale_t) NULL)
132b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    c_locale=newlocale(LC_ALL_MASK,"C",(locale_t) 0);
133360889c1650bd82cff29db568cee55949314d543Jeroen Ooms#elif defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
134b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (c_locale == (locale_t) NULL)
135b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    c_locale=_create_locale(LC_ALL,"C");
136a20c904a6f3e3a11939d5260485be72d5c849c63cristy#endif
137b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return(c_locale);
138b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
139a723b6a0656cce17bf5495a3e6bc2780f0b7aed5cristy#endif
140b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
14186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy/*
14286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%                                                                             %
14486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%                                                                             %
14586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%                                                                             %
14686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  A c q u i r e L o c a l e S p l a y T r e e                                %
14786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%                                                                             %
14886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%                                                                             %
14986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%                                                                             %
15086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
15286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  AcquireLocaleSplayTree() caches one or more locale configurations which
15386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  provides a mapping between locale attributes and a locale tag.
15486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
15586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  The format of the AcquireLocaleSplayTree method is:
15686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
15786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%      SplayTreeInfo *AcquireLocaleSplayTree(const char *filename,
15886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%        ExceptionInfo *exception)
15986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
16086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  A description of each parameter follows:
16186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
16286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%    o filename: the font file tag.
16386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
16486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%    o locale: the actual locale.
16586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
16686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%    o exception: return any errors or warnings in this structure.
16786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%
16886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy*/
16986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy
17086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristystatic void *DestroyLocaleNode(void *locale_info)
17186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy{
17286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  register LocaleInfo
17386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    *p;
17486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy
17586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  p=(LocaleInfo *) locale_info;
17686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  if (p->path != (char *) NULL)
17786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    p->path=DestroyString(p->path);
17886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  if (p->tag != (char *) NULL)
17986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    p->tag=DestroyString(p->tag);
18086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  if (p->message != (char *) NULL)
18186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    p->message=DestroyString(p->message);
18286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  return(RelinquishMagickMemory(p));
18386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy}
18486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy
18586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristystatic SplayTreeInfo *AcquireLocaleSplayTree(const char *filename,
18686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  const char *locale,ExceptionInfo *exception)
18786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy{
18886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  MagickStatusType
18986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    status;
19086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy
19186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  SplayTreeInfo
192c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk    *cache;
19386e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy
194c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk  cache=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
19586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    DestroyLocaleNode);
196004a3a810bab060902caeba76ec780d13d9e64ecdirk  if (cache == (SplayTreeInfo *) NULL)
19786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
19886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  status=MagickTrue;
199191ba5c4efb33f9f70da0216a31343d658156ba7cristy#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
20086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  {
20166f8c5f040cd0dc76d76e8e041764e2f799fae76cristy    const StringInfo
20266f8c5f040cd0dc76d76e8e041764e2f799fae76cristy      *option;
20366f8c5f040cd0dc76d76e8e041764e2f799fae76cristy
20466f8c5f040cd0dc76d76e8e041764e2f799fae76cristy    LinkedListInfo
20566f8c5f040cd0dc76d76e8e041764e2f799fae76cristy      *options;
20666f8c5f040cd0dc76d76e8e041764e2f799fae76cristy
20766f8c5f040cd0dc76d76e8e041764e2f799fae76cristy    options=GetLocaleOptions(filename,exception);
20886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    option=(const StringInfo *) GetNextValueInLinkedList(options);
20966f8c5f040cd0dc76d76e8e041764e2f799fae76cristy    while (option != (const StringInfo *) NULL)
21086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    {
211c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk      status&=LoadLocaleCache(cache,(const char *)
212cd2cd1803dda951bcfff101c44032ae17e52655fcristy        GetStringInfoDatum(option),GetStringInfoPath(option),locale,0,
213cd2cd1803dda951bcfff101c44032ae17e52655fcristy        exception);
21486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy      option=(const StringInfo *) GetNextValueInLinkedList(options);
21566f8c5f040cd0dc76d76e8e041764e2f799fae76cristy    }
21666f8c5f040cd0dc76d76e8e041764e2f799fae76cristy    options=DestroyLocaleOptions(options);
217c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk    if (GetNumberOfNodesInSplayTree(cache) == 0)
21886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy      {
21966f8c5f040cd0dc76d76e8e041764e2f799fae76cristy        options=GetLocaleOptions("english.xml",exception);
22086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy        option=(const StringInfo *) GetNextValueInLinkedList(options);
22166f8c5f040cd0dc76d76e8e041764e2f799fae76cristy        while (option != (const StringInfo *) NULL)
22266f8c5f040cd0dc76d76e8e041764e2f799fae76cristy        {
223c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk          status&=LoadLocaleCache(cache,(const char *)
224cd2cd1803dda951bcfff101c44032ae17e52655fcristy            GetStringInfoDatum(option),GetStringInfoPath(option),locale,0,
225cd2cd1803dda951bcfff101c44032ae17e52655fcristy            exception);
22666f8c5f040cd0dc76d76e8e041764e2f799fae76cristy          option=(const StringInfo *) GetNextValueInLinkedList(options);
22766f8c5f040cd0dc76d76e8e041764e2f799fae76cristy        }
22866f8c5f040cd0dc76d76e8e041764e2f799fae76cristy        options=DestroyLocaleOptions(options);
22986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy      }
23066f8c5f040cd0dc76d76e8e041764e2f799fae76cristy  }
231191ba5c4efb33f9f70da0216a31343d658156ba7cristy#endif
232c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk  if (GetNumberOfNodesInSplayTree(cache) == 0)
233c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk    status&=LoadLocaleCache(cache,LocaleMap,"built-in",locale,0,
234cd2cd1803dda951bcfff101c44032ae17e52655fcristy      exception);
235c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk  return(cache);
23686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy}
23786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy
238c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT)
239b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy/*
240b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
242b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
243b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
244b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy+   D e s t r o y C L o c a l e                                               %
245b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
246b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
247b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
248b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
250b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  DestroyCLocale() releases the resources allocated for a locale object
251b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  returned by a call to the AcquireCLocale() method.
252b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
253b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  The format of the DestroyCLocale method is:
254b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
255b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%      void DestroyCLocale(void)
256b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
257b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy*/
258b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristystatic void DestroyCLocale(void)
259b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
260b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#if defined(MAGICKCORE_HAVE_NEWLOCALE)
261b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (c_locale != (locale_t) NULL)
262b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    freelocale(c_locale);
263360889c1650bd82cff29db568cee55949314d543Jeroen Ooms#elif defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
264b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (c_locale != (locale_t) NULL)
265b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    _free_locale(c_locale);
266b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#endif
267b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  c_locale=(locale_t) NULL;
268a20c904a6f3e3a11939d5260485be72d5c849c63cristy}
269a723b6a0656cce17bf5495a3e6bc2780f0b7aed5cristy#endif
270a20c904a6f3e3a11939d5260485be72d5c849c63cristy
271a20c904a6f3e3a11939d5260485be72d5c849c63cristy/*
272a20c904a6f3e3a11939d5260485be72d5c849c63cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
274a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
275a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   D e s t r o y L o c a l e O p t i o n s                                   %
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  DestroyLocaleOptions() releases memory associated with an locale
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  messages.
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the DestroyProfiles method is:
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      LinkedListInfo *DestroyLocaleOptions(Image *image)
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void *DestroyOptions(void *message)
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(DestroyStringInfo((StringInfo *) message));
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport LinkedListInfo *DestroyLocaleOptions(LinkedListInfo *messages)
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(messages != (LinkedListInfo *) NULL);
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(DestroyLinkedList(messages,DestroyOptions));
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
312b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy+  F o r m a t L o c a l e F i l e                                            %
313a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
314a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
315a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
316a20c904a6f3e3a11939d5260485be72d5c849c63cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
318b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  FormatLocaleFile() prints formatted output of a variable argument list to a
319b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  file in the "C" locale.
320b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
321b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  The format of the FormatLocaleFile method is:
322a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
323b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%      ssize_t FormatLocaleFile(FILE *file,const char *format,...)
324a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
325b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  A description of each parameter follows.
326b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
327b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%   o file:  the file.
328b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
329b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%   o format:  A file describing the format to use to write the remaining
330b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%     arguments.
331a20c904a6f3e3a11939d5260485be72d5c849c63cristy%
332a20c904a6f3e3a11939d5260485be72d5c849c63cristy*/
333b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
3347832dc2d904c471770087cce18a9a2d76c2216a3cristyMagickPrivate ssize_t FormatLocaleFileList(FILE *file,
33505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk  const char *magick_restrict format,va_list operands)
336a20c904a6f3e3a11939d5260485be72d5c849c63cristy{
33720ec75933833a479a457aeb76c7f9338e1e1c093cristy  ssize_t
338b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    n;
339b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
340c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_VFPRINTF_L)
341b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  {
342b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    locale_t
343b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      locale;
344b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
345b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    locale=AcquireCLocale();
346b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (locale == (locale_t) NULL)
34720ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vfprintf(file,format,operands);
348b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    else
34926d782050ee830ab4503bf14708ec69f4396233acristy#if defined(MAGICKCORE_WINDOWS_SUPPORT)
35020ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vfprintf_l(file,format,locale,operands);
35126d782050ee830ab4503bf14708ec69f4396233acristy#else
35220ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vfprintf_l(file,locale,format,operands);
353405905f9a85da5d3b531e495986818fdd9f765cccristy#endif
354b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
355b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#else
356c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_USELOCALE)
357b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  {
358b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    locale_t
359b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      locale,
360b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      previous_locale;
361b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
362b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    locale=AcquireCLocale();
363b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (locale == (locale_t) NULL)
36420ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vfprintf(file,format,operands);
365b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    else
366b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      {
367b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        previous_locale=uselocale(locale);
36820ec75933833a479a457aeb76c7f9338e1e1c093cristy        n=(ssize_t) vfprintf(file,format,operands);
369b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        uselocale(previous_locale);
370b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      }
371b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
372b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#else
37320ec75933833a479a457aeb76c7f9338e1e1c093cristy  n=(ssize_t) vfprintf(file,format,operands);
374b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#endif
375a20c904a6f3e3a11939d5260485be72d5c849c63cristy#endif
3763da0b407cca2ae0112df448b5eb15047a552b3aacristy  return(n);
377b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
378b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
37905d2ff7ebf21f659f5b11e45afb294e152f4330cdirkMagickExport ssize_t FormatLocaleFile(FILE *file,
38005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk  const char *magick_restrict format,...)
381b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
382b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  ssize_t
383b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    n;
384b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
385b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  va_list
386b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    operands;
387b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
388b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  va_start(operands,format);
38920ec75933833a479a457aeb76c7f9338e1e1c093cristy  n=FormatLocaleFileList(file,format,operands);
390b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  va_end(operands);
391b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return(n);
392b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
393b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
394b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy/*
395b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
397b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
398b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
399b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy+  F o r m a t L o c a l e S t r i n g                                        %
400b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
401b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
402b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%                                                                             %
403b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
405b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  FormatLocaleString() prints formatted output of a variable argument list to
406b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  a string buffer in the "C" locale.
407b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
408b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  The format of the FormatLocaleString method is:
409b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
410b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%      ssize_t FormatLocaleString(char *string,const size_t length,
411b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%        const char *format,...)
412b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
413b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%  A description of each parameter follows.
414b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
415b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%   o string:  FormatLocaleString() returns the formatted string in this
416b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%     character buffer.
417b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
418b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%   o length: the maximum length of the string.
419b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
420b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%   o format:  A string describing the format to use to write the remaining
421b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%     arguments.
422b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy%
423b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy*/
424b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
42505d2ff7ebf21f659f5b11e45afb294e152f4330cdirkMagickPrivate ssize_t FormatLocaleStringList(char *magick_restrict string,
42605d2ff7ebf21f659f5b11e45afb294e152f4330cdirk  const size_t length,const char *magick_restrict format,va_list operands)
427b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
42820ec75933833a479a457aeb76c7f9338e1e1c093cristy  ssize_t
429b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    n;
430b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
431c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_VSNPRINTF_L)
432405905f9a85da5d3b531e495986818fdd9f765cccristy  {
433405905f9a85da5d3b531e495986818fdd9f765cccristy    locale_t
434405905f9a85da5d3b531e495986818fdd9f765cccristy      locale;
435405905f9a85da5d3b531e495986818fdd9f765cccristy
436405905f9a85da5d3b531e495986818fdd9f765cccristy    locale=AcquireCLocale();
437405905f9a85da5d3b531e495986818fdd9f765cccristy    if (locale == (locale_t) NULL)
43820ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vsnprintf(string,length,format,operands);
439405905f9a85da5d3b531e495986818fdd9f765cccristy    else
44026d782050ee830ab4503bf14708ec69f4396233acristy#if defined(MAGICKCORE_WINDOWS_SUPPORT)
44120ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vsnprintf_l(string,length,format,locale,operands);
44226d782050ee830ab4503bf14708ec69f4396233acristy#else
44320ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vsnprintf_l(string,length,locale,format,operands);
444405905f9a85da5d3b531e495986818fdd9f765cccristy#endif
445405905f9a85da5d3b531e495986818fdd9f765cccristy  }
446b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#elif defined(MAGICKCORE_HAVE_VSNPRINTF)
447c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_USELOCALE)
448b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  {
449b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    locale_t
450b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      locale,
451b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      previous_locale;
452b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
453b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    locale=AcquireCLocale();
454b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (locale == (locale_t) NULL)
45520ec75933833a479a457aeb76c7f9338e1e1c093cristy      n=(ssize_t) vsnprintf(string,length,format,operands);
456b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    else
457b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      {
458b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        previous_locale=uselocale(locale);
45920ec75933833a479a457aeb76c7f9338e1e1c093cristy        n=(ssize_t) vsnprintf(string,length,format,operands);
460b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        uselocale(previous_locale);
461b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      }
462b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
463b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#else
46420ec75933833a479a457aeb76c7f9338e1e1c093cristy  n=(ssize_t) vsnprintf(string,length,format,operands);
465b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#endif
466b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#else
46720ec75933833a479a457aeb76c7f9338e1e1c093cristy  n=(ssize_t) vsprintf(string,format,operands);
468b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy#endif
469b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (n < 0)
470b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    string[length-1]='\0';
47120ec75933833a479a457aeb76c7f9338e1e1c093cristy  return(n);
472b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
473b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
47405d2ff7ebf21f659f5b11e45afb294e152f4330cdirkMagickExport ssize_t FormatLocaleString(char *magick_restrict string,
47505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk  const size_t length,const char *magick_restrict format,...)
476b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
477b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  ssize_t
478b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    n;
479b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
480b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  va_list
481b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    operands;
482b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
483b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  va_start(operands,format);
48420ec75933833a479a457aeb76c7f9338e1e1c093cristy  n=FormatLocaleStringList(string,length,format,operands);
485b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  va_end(operands);
486b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return(n);
487a20c904a6f3e3a11939d5260485be72d5c849c63cristy}
488a20c904a6f3e3a11939d5260485be72d5c849c63cristy
489a20c904a6f3e3a11939d5260485be72d5c849c63cristy/*
490a20c904a6f3e3a11939d5260485be72d5c849c63cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
492a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
493a20c904a6f3e3a11939d5260485be72d5c849c63cristy%                                                                             %
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy+   G e t L o c a l e I n f o _                                               %
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetLocaleInfo_() searches the locale list for the specified tag and if
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  found returns attributes for that element.
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetLocaleInfo method is:
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      const LocaleInfo *GetLocaleInfo_(const char *tag,
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ExceptionInfo *exception)
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o tag: the locale tag.
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport const LocaleInfo *GetLocaleInfo_(const char *tag,
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
51849d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy  const LocaleInfo
51949d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy    *locale_info;
52049d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
522904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy  if (IsLocaleTreeInstantiated(exception) == MagickFalse)
523904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy    return((const LocaleInfo *) NULL);
52449d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy  LockSemaphoreInfo(locale_semaphore);
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
52786e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy      ResetSplayTreeIterator(locale_cache);
52886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy      locale_info=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache);
52949d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy      UnlockSemaphoreInfo(locale_semaphore);
53049d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy      return(locale_info);
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
53286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  locale_info=(const LocaleInfo *) GetValueFromSplayTree(locale_cache,tag);
53349d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy  UnlockSemaphoreInfo(locale_semaphore);
53449d4d2247a71eab1c5c56bae91a5f9d0fcc4475ccristy  return(locale_info);
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t L o c a l e I n f o L i s t                                         %
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetLocaleInfoList() returns any locale messages that match the
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  specified pattern.
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetLocaleInfoList function is:
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      const LocaleInfo **GetLocaleInfoList(const char *pattern,
554bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%        size_t *number_messages,ExceptionInfo *exception)
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o pattern: Specifies a pointer to a text string containing a pattern.
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o number_messages:  This integer returns the number of locale messages in
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    the list.
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristyextern "C" {
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int LocaleInfoCompare(const void *x,const void *y)
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const LocaleInfo
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **p,
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **q;
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(const LocaleInfo **) x,
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(const LocaleInfo **) y;
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare((*p)->path,(*q)->path) == 0)
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(LocaleCompare((*p)->tag,(*q)->tag));
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(LocaleCompare((*p)->path,(*q)->path));
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport const LocaleInfo **GetLocaleInfoList(const char *pattern,
589bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t *number_messages,ExceptionInfo *exception)
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const LocaleInfo
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **messages;
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const LocaleInfo
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
597bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate locale list.
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pattern != (char *) NULL);
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
605bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  assert(number_messages != (size_t *) NULL);
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *number_messages=0;
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=GetLocaleInfo_("*",exception);
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (p == (const LocaleInfo *) NULL)
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((const LocaleInfo **) NULL);
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  messages=(const LocaleInfo **) AcquireQuantumMemory((size_t)
61186e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    GetNumberOfNodesInSplayTree(locale_cache)+1UL,sizeof(*messages));
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (messages == (const LocaleInfo **) NULL)
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((const LocaleInfo **) NULL);
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Generate locale list.
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
617f84a193d5f435588cd78d521fff3f1f852e227f8cristy  LockSemaphoreInfo(locale_semaphore);
61886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  ResetSplayTreeIterator(locale_cache);
61986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache);
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; p != (const LocaleInfo *) NULL; )
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((p->stealth == MagickFalse) &&
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (GlobExpression(p->tag,pattern,MagickTrue) != MagickFalse))
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      messages[i++]=p;
62586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache);
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
627f84a193d5f435588cd78d521fff3f1f852e227f8cristy  UnlockSemaphoreInfo(locale_semaphore);
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  qsort((void *) messages,(size_t) i,sizeof(*messages),LocaleInfoCompare);
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  messages[i]=(LocaleInfo *) NULL;
630bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  *number_messages=(size_t) i;
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(messages);
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t L o c a l e L i s t                                                 %
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetLocaleList() returns any locale messages that match the specified
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pattern.
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetLocaleList function is:
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
650bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      char **GetLocaleList(const char *pattern,size_t *number_messages,
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        Exceptioninfo *exception)
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o pattern: Specifies a pointer to a text string containing a pattern.
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o number_messages:  This integer returns the number of messages in the
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      list.
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristyextern "C" {
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int LocaleTagCompare(const void *x,const void *y)
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **p,
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **q;
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(char **) x;
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(char **) y;
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(LocaleCompare(*p,*q));
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6835cd9a679bfdcfab16665175604c2e3ed9542da88cristyMagickExport char **GetLocaleList(const char *pattern,size_t *number_messages,
6845cd9a679bfdcfab16665175604c2e3ed9542da88cristy  ExceptionInfo *exception)
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **messages;
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const LocaleInfo
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
692bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate locale list.
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pattern != (char *) NULL);
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
700bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  assert(number_messages != (size_t *) NULL);
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *number_messages=0;
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=GetLocaleInfo_("*",exception);
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (p == (const LocaleInfo *) NULL)
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((char **) NULL);
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  messages=(char **) AcquireQuantumMemory((size_t)
70686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    GetNumberOfNodesInSplayTree(locale_cache)+1UL,sizeof(*messages));
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (messages == (char **) NULL)
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((char **) NULL);
709f84a193d5f435588cd78d521fff3f1f852e227f8cristy  LockSemaphoreInfo(locale_semaphore);
71086e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache);
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; p != (const LocaleInfo *) NULL; )
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((p->stealth == MagickFalse) &&
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (GlobExpression(p->tag,pattern,MagickTrue) != MagickFalse))
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      messages[i++]=ConstantString(p->tag);
71686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache);
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
718f84a193d5f435588cd78d521fff3f1f852e227f8cristy  UnlockSemaphoreInfo(locale_semaphore);
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  qsort((void *) messages,(size_t) i,sizeof(*messages),LocaleTagCompare);
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  messages[i]=(char *) NULL;
721bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  *number_messages=(size_t) i;
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(messages);
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t L o c a l e M e s s a g e                                           %
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetLocaleMessage() returns a message in the current locale that matches the
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supplied tag.
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetLocaleMessage method is:
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      const char *GetLocaleMessage(const char *tag)
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o tag: Return a message that matches this tag in the current locale.
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport const char *GetLocaleMessage(const char *tag)
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
75121967fb1fb285c755c58b183e45b7b70c4d1978acristy    name[MagickLocaleExtent];
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const LocaleInfo
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *locale_info;
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *exception;
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tag == (const char *) NULL) || (*tag == '\0'))
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(tag);
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  exception=AcquireExceptionInfo();
76221967fb1fb285c755c58b183e45b7b70c4d1978acristy  (void) FormatLocaleString(name,MagickLocaleExtent,"%s/",tag);
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  locale_info=GetLocaleInfo_(name,exception);
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  exception=DestroyExceptionInfo(exception);
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (locale_info != (const LocaleInfo *) NULL)
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(locale_info->message);
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(tag);
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  G e t L o c a l e O p t i o n s                                            %
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetLocaleOptions() returns any Magick configuration messages associated
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  with the specified filename.
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetLocaleOptions method is:
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      LinkedListInfo *GetLocaleOptions(const char *filename,
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ExceptionInfo *exception)
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o filename: the locale file tag.
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport LinkedListInfo *GetLocaleOptions(const char *filename,
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
800151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    path[MagickPathExtent];
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *element;
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  LinkedListInfo
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *messages,
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *paths;
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  StringInfo
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xml;
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(filename != (const char *) NULL);
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
815151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  (void) CopyMagickString(path,filename,MagickPathExtent);
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Load XML from configuration files to linked-list.
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  messages=NewLinkedList(0);
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  paths=GetConfigurePaths(filename,exception);
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (paths != (LinkedListInfo *) NULL)
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ResetLinkedListIterator(paths);
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      element=(const char *) GetNextValueInLinkedList(paths);
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      while (element != (const char *) NULL)
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
82721967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) FormatLocaleString(path,MagickPathExtent,"%s%s",element,
82821967fb1fb285c755c58b183e45b7b70c4d1978acristy          filename);
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(LocaleEvent,GetMagickModule(),
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "Searching for locale file: \"%s\"",path);
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        xml=ConfigureFileToStringInfo(path);
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (xml != (StringInfo *) NULL)
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) AppendValueToLinkedList(messages,xml);
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        element=(const char *) GetNextValueInLinkedList(paths);
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      paths=DestroyLinkedList(paths,RelinquishMagickMemory);
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8380157aeadef2fce908277168097a160a8f15a6952cristy#if defined(MAGICKCORE_WINDOWS_SUPPORT)
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    char
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *blob;
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    blob=(char *) NTResourceToBlob(filename);
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (blob != (char *) NULL)
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
84685d6de50bbee8b1c2a772bc9dcf38e0e7155d041cristy        xml=AcquireStringInfo(0);
84785d6de50bbee8b1c2a772bc9dcf38e0e7155d041cristy        SetStringInfoLength(xml,strlen(blob)+1);
848d61c7adb5d6f81182c79dca8ff608c1701aac8f8dirk        SetStringInfoDatum(xml,(const unsigned char *) blob);
849732d7849f114281314c3a287a1ed131add137764cristy        blob=(char *) RelinquishMagickMemory(blob);
85085d6de50bbee8b1c2a772bc9dcf38e0e7155d041cristy        SetStringInfoPath(xml,filename);
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) AppendValueToLinkedList(messages,xml);
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResetLinkedListIterator(messages);
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(messages);
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t L o c a l e V a l u e                                               %
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetLocaleValue() returns the message associated with the locale info.
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetLocaleValue method is:
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      const char *GetLocaleValue(const LocaleInfo *locale_info)
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o locale_info:  The locale info.
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport const char *GetLocaleValue(const LocaleInfo *locale_info)
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(locale_info != (LocaleInfo *) NULL);
885e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(locale_info->signature == MagickCoreSignature);
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(locale_info->message);
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
894904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy+   I s L o c a l e T r e e I n s t a n t i a t e d                           %
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
900904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy%  IsLocaleTreeInstantiated() determines if the locale tree is instantiated.
901904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy%  If not, it instantiates the tree and returns it.
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
903904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy%  The format of the IsLocaleInstantiated method is:
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
905904e591bcf6bce4c0086cc200d0efe7fdd3834aecristy%      MagickBooleanType IsLocaleTreeInstantiated(ExceptionInfo *exception)
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
912904e591bcf6bce4c0086cc200d0efe7fdd3834aecristystatic MagickBooleanType IsLocaleTreeInstantiated(ExceptionInfo *exception)
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
91486e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  if (locale_cache == (SplayTreeInfo *) NULL)
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
916cd2cd1803dda951bcfff101c44032ae17e52655fcristy      if (locale_semaphore == (SemaphoreInfo *) NULL)
917cd2cd1803dda951bcfff101c44032ae17e52655fcristy        ActivateSemaphoreInfo(&locale_semaphore);
918cd2cd1803dda951bcfff101c44032ae17e52655fcristy      LockSemaphoreInfo(locale_semaphore);
919cd2cd1803dda951bcfff101c44032ae17e52655fcristy      if (locale_cache == (SplayTreeInfo *) NULL)
920cd2cd1803dda951bcfff101c44032ae17e52655fcristy        {
921cd2cd1803dda951bcfff101c44032ae17e52655fcristy          char
922cd2cd1803dda951bcfff101c44032ae17e52655fcristy            *locale;
923cd2cd1803dda951bcfff101c44032ae17e52655fcristy
924cd2cd1803dda951bcfff101c44032ae17e52655fcristy          register const char
925cd2cd1803dda951bcfff101c44032ae17e52655fcristy            *p;
926cd2cd1803dda951bcfff101c44032ae17e52655fcristy
927cd2cd1803dda951bcfff101c44032ae17e52655fcristy          locale=(char *) NULL;
928cd2cd1803dda951bcfff101c44032ae17e52655fcristy          p=setlocale(LC_CTYPE,(const char *) NULL);
929cd2cd1803dda951bcfff101c44032ae17e52655fcristy          if (p != (const char *) NULL)
930cd2cd1803dda951bcfff101c44032ae17e52655fcristy            locale=ConstantString(p);
931cd2cd1803dda951bcfff101c44032ae17e52655fcristy          if (locale == (char *) NULL)
932cd2cd1803dda951bcfff101c44032ae17e52655fcristy            locale=GetEnvironmentValue("LC_ALL");
933cd2cd1803dda951bcfff101c44032ae17e52655fcristy          if (locale == (char *) NULL)
934cd2cd1803dda951bcfff101c44032ae17e52655fcristy            locale=GetEnvironmentValue("LC_MESSAGES");
935cd2cd1803dda951bcfff101c44032ae17e52655fcristy          if (locale == (char *) NULL)
936cd2cd1803dda951bcfff101c44032ae17e52655fcristy            locale=GetEnvironmentValue("LC_CTYPE");
937cd2cd1803dda951bcfff101c44032ae17e52655fcristy          if (locale == (char *) NULL)
938cd2cd1803dda951bcfff101c44032ae17e52655fcristy            locale=GetEnvironmentValue("LANG");
939cd2cd1803dda951bcfff101c44032ae17e52655fcristy          if (locale == (char *) NULL)
940cd2cd1803dda951bcfff101c44032ae17e52655fcristy            locale=ConstantString("C");
941cd2cd1803dda951bcfff101c44032ae17e52655fcristy          locale_cache=AcquireLocaleSplayTree(LocaleFilename,locale,exception);
942cd2cd1803dda951bcfff101c44032ae17e52655fcristy          locale=DestroyString(locale);
943cd2cd1803dda951bcfff101c44032ae17e52655fcristy        }
944cd2cd1803dda951bcfff101c44032ae17e52655fcristy      UnlockSemaphoreInfo(locale_semaphore);
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
94686e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  return(locale_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95141c3c77d6f4e3131bf2be0b35277c086b69ce492cristy%                                                                             %
95241c3c77d6f4e3131bf2be0b35277c086b69ce492cristy%                                                                             %
95341c3c77d6f4e3131bf2be0b35277c086b69ce492cristy%                                                                             %
954c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy+   I n t e r p r e t L o c a l e V a l u e                                   %
955c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%                                                                             %
956c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%                                                                             %
957c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%                                                                             %
958c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
960c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%  InterpretLocaleValue() interprets the string as a floating point number in
961c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%  the "C" locale and returns its value as a double. If sentinal is not a null
962c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%  pointer, the method also sets the value pointed by sentinal to point to the
963c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%  first character after the number.
964c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
965c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%  The format of the InterpretLocaleValue method is:
966c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
967c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%      double InterpretLocaleValue(const char *value,char **sentinal)
968c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
969c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%  A description of each parameter follows:
970c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
971c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%    o value: the string value.
972c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
973c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%    o sentinal:  if sentinal is not NULL, a pointer to the character after the
974c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%      last character used in the conversion is stored in the location
975c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%      referenced by sentinal.
976c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%
977c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy*/
97805d2ff7ebf21f659f5b11e45afb294e152f4330cdirkMagickExport double InterpretLocaleValue(const char *magick_restrict string,
97905d2ff7ebf21f659f5b11e45afb294e152f4330cdirk  char **magick_restrict sentinal)
980c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy{
981670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy  char
982670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy    *q;
983670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy
984c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy  double
985c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy    value;
986c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy
987670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy  if ((*string == '0') && ((string[1] | 0x20)=='x'))
988670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy    value=(double) strtoul(string,&q,16);
989670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy  else
990670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy    {
991c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_STRTOD_L)
992670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy      locale_t
993670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy        locale;
994670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy
995670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy      locale=AcquireCLocale();
996670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy      if (locale == (locale_t) NULL)
997670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy        value=strtod(string,&q);
998670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy      else
999670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy        value=strtod_l(string,&q,locale);
1000c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy#else
1001670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy      value=strtod(string,&q);
1002c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy#endif
1003670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy    }
1004670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy  if (sentinal != (char **) NULL)
1005670aa3c328eb7d97a3edd44ef7b4244d2effa935cristy    *sentinal=q;
1006c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy  return(value);
1007c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy}
1008c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy
1009c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy/*
1010c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%                                                                             %
1012c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%                                                                             %
1013c1acd8495db5b00e9ced313e86dfdbe8c60c111dcristy%                                                                             %
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  L i s t L o c a l e I n f o                                                %
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ListLocaleInfo() lists the locale info to a file.
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ListLocaleInfo method is:
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType ListLocaleInfo(FILE *file,ExceptionInfo *exception)
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o file:  An pointer to a FILE.
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType ListLocaleInfo(FILE *file,
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *path;
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const LocaleInfo
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **locale_info;
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1042bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1045bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_messages;
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (file == (const FILE *) NULL)
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    file=stdout;
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_messages=0;
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  locale_info=GetLocaleInfoList("*",&number_messages,exception);
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (locale_info == (const LocaleInfo **) NULL)
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  path=(const char *) NULL;
1055bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) number_messages; i++)
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (locale_info[i]->stealth != MagickFalse)
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((path == (const char *) NULL) ||
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (LocaleCompare(path,locale_info[i]->path) != 0))
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (locale_info[i]->path != (char *) NULL)
1063b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy          (void) FormatLocaleFile(file,"\nPath: %s\n\n",locale_info[i]->path);
1064b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleFile(file,"Tag/Message\n");
10651e604812fad85bb96f757a2393015ae3d061c39acristy        (void) FormatLocaleFile(file,
10661e604812fad85bb96f757a2393015ae3d061c39acristy          "-------------------------------------------------"
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "------------------------------\n");
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    path=locale_info[i]->path;
1070b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleFile(file,"%s\n",locale_info[i]->tag);
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (locale_info[i]->message != (char *) NULL)
1072b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      (void) FormatLocaleFile(file,"  %s",locale_info[i]->message);
1073b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleFile(file,"\n");
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) fflush(file);
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  locale_info=(const LocaleInfo **)
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    RelinquishMagickMemory((void *) locale_info);
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1086fc0f1249300d84ccb63b81a9dd87245d6ed34806dirk+   L o a d L o c a l e C a c h e                                             %
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
109286e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  LoadLocaleCache() loads the locale configurations which provides a mapping
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  between locale attributes and a locale name.
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
109586e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy%  The format of the LoadLocaleCache method is:
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1097c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk%      MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
1098c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk%        const char *filename,const size_t depth,ExceptionInfo *exception)
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o xml:  The locale list in XML format.
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o filename:  The locale list filename.
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o depth: depth of <include /> statements.
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1112bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic void ChopLocaleComponents(char *path,const size_t components)
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11179d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
11189d314ff2c17a77996c05413c2013880387e50f0ecristy    count;
11199d314ff2c17a77996c05413c2013880387e50f0ecristy
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*path == '\0')
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=path+strlen(path)-1;
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*p == '/')
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p='\0';
1125bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (count=0; (count < (ssize_t) components) && (p > path); p--)
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p == '/')
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p='\0';
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        count++;
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
1131bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  if (count < (ssize_t) components)
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *path='\0';
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11352359e74755f994c60e7a3bd7d2828b45d7680675cristystatic void LocaleFatalErrorHandler(
11362359e74755f994c60e7a3bd7d2828b45d7680675cristy  const ExceptionType magick_unused(severity),
11372359e74755f994c60e7a3bd7d2828b45d7680675cristy  const char *reason,const char *description)
11382359e74755f994c60e7a3bd7d2828b45d7680675cristy{
1139348c837caadc66adf93e30b08aa1588c7036449fdirk  magick_unreferenced(severity);
1140d2a7a2d4a46c82a8679688ae763ef9d7bb53ccd7dirk
11412359e74755f994c60e7a3bd7d2828b45d7680675cristy  if (reason == (char *) NULL)
11422359e74755f994c60e7a3bd7d2828b45d7680675cristy    return;
1143b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
11442359e74755f994c60e7a3bd7d2828b45d7680675cristy  if (description != (char *) NULL)
1145b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleFile(stderr," (%s)",description);
1146b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(stderr,".\n");
11472359e74755f994c60e7a3bd7d2828b45d7680675cristy  (void) fflush(stderr);
11482359e74755f994c60e7a3bd7d2828b45d7680675cristy  exit(1);
11492359e74755f994c60e7a3bd7d2828b45d7680675cristy}
11502359e74755f994c60e7a3bd7d2828b45d7680675cristy
1151c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirkstatic MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
1152c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk  const char *filename,const char *locale,const size_t depth,ExceptionInfo *exception)
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
115521967fb1fb285c755c58b183e45b7b70c4d1978acristy    keyword[MagickLocaleExtent],
115621967fb1fb285c755c58b183e45b7b70c4d1978acristy    message[MagickLocaleExtent],
115721967fb1fb285c755c58b183e45b7b70c4d1978acristy    tag[MagickLocaleExtent],
11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *token;
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1163909b647caa79e7dd752f7daae08177ec74fb841acristy  FatalErrorHandler
1164909b647caa79e7dd752f7daae08177ec74fb841acristy    fatal_handler;
1165909b647caa79e7dd752f7daae08177ec74fb841acristy
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  LocaleInfo
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *locale_info;
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1169759ba919e9fe454989454f481f4055fd38b32307cristy  MagickStatusType
11703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1175fc0f1249300d84ccb63b81a9dd87245d6ed34806dirk  size_t
1176fc0f1249300d84ccb63b81a9dd87245d6ed34806dirk    extent;
1177fc0f1249300d84ccb63b81a9dd87245d6ed34806dirk
11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read the locale configure file.
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "Loading locale configure file \"%s\" ...",filename);
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (xml == (const char *) NULL)
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=MagickTrue;
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  locale_info=(LocaleInfo *) NULL;
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *tag='\0';
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *message='\0';
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *keyword='\0';
11902359e74755f994c60e7a3bd7d2828b45d7680675cristy  fatal_handler=SetFatalErrorHandler(LocaleFatalErrorHandler);
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  token=AcquireString(xml);
1192fc0f1249300d84ccb63b81a9dd87245d6ed34806dirk  extent=strlen(token)+MagickPathExtent;
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (q=(char *) xml; *q != '\0'; )
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Interpret XML.
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
11988bedb4edca01599dfd0612cb0daa35b09c67d736Cristy    GetNextToken(q,&q,extent,token);
11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*token == '\0')
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
120121967fb1fb285c755c58b183e45b7b70c4d1978acristy    (void) CopyMagickString(keyword,token,MagickLocaleExtent);
12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Doctype element.
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
12098bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          while (isspace((int) ((unsigned char) *q)) != 0)
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q++;
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
12153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleNCompare(keyword,"<!--",4) == 0)
12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Comment element.
12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
12228bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
12233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          while (isspace((int) ((unsigned char) *q)) != 0)
12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q++;
12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
12283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"<include") == 0)
12293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
12313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Include element.
12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
123521967fb1fb285c755c58b183e45b7b70c4d1978acristy          (void) CopyMagickString(keyword,token,MagickLocaleExtent);
12368bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
12373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (*token != '=')
12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
12398bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (LocaleCompare(keyword,"locale") == 0)
12413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (LocaleCompare(locale,token) != 0)
12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              continue;
12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (LocaleCompare(keyword,"file") == 0)
12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (depth > 200)
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) ThrowMagickException(exception,GetMagickModule(),
1250efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy                  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  char
1254151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy                    path[MagickPathExtent],
1255b81f0abf7970b3c3e43ba0c95266a1c252806425dirk                    *file_xml;
12563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *path='\0';
12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  GetPathComponent(filename,HeadPath,path);
12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (*path != '\0')
12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) ConcatenateMagickString(path,DirectorySeparator,
1261151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy                      MagickPathExtent);
12623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (*token == *DirectorySeparator)
1263151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy                    (void) CopyMagickString(path,token,MagickPathExtent);
12643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else
1265151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy                    (void) ConcatenateMagickString(path,token,MagickPathExtent);
1266b81f0abf7970b3c3e43ba0c95266a1c252806425dirk                  file_xml=FileToXML(path,~0UL);
1267b81f0abf7970b3c3e43ba0c95266a1c252806425dirk                  if (file_xml != (char *) NULL)
12683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
1269c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk                      status&=LoadLocaleCache(cache,file_xml,path,locale,
1270cd2cd1803dda951bcfff101c44032ae17e52655fcristy                        depth+1,exception);
1271b81f0abf7970b3c3e43ba0c95266a1c252806425dirk                      file_xml=DestroyString(file_xml);
12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
12733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
12743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
12783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"<locale") == 0)
12793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
12803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
12813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Locale element.
12823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
12833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((*token != '>') && (*q != '\0'))
12843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
128521967fb1fb285c755c58b183e45b7b70c4d1978acristy          (void) CopyMagickString(keyword,token,MagickLocaleExtent);
12868bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
12873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (*token != '=')
12883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
12898bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
12903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
12923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
12933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"</locale>") == 0)
12943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
12953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ChopLocaleComponents(tag,1);
129621967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent);
12973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
12983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
12993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"<localemap>") == 0)
13003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
13013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"</localemap>") == 0)
13023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
13033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"<message") == 0)
13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
13063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Message element.
13073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
13083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((*token != '>') && (*q != '\0'))
13093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
131021967fb1fb285c755c58b183e45b7b70c4d1978acristy          (void) CopyMagickString(keyword,token,MagickLocaleExtent);
13118bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
13123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (*token != '=')
13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
13148bedb4edca01599dfd0612cb0daa35b09c67d736Cristy          GetNextToken(q,&q,extent,token);
13153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (LocaleCompare(keyword,"name") == 0)
13163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
131721967fb1fb285c755c58b183e45b7b70c4d1978acristy              (void) ConcatenateMagickString(tag,token,MagickLocaleExtent);
131821967fb1fb285c755c58b183e45b7b70c4d1978acristy              (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent);
13193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
13203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
13213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (p=(char *) q; (*q != '<') && (*q != '\0'); q++) ;
13223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while (isspace((int) ((unsigned char) *p)) != 0)
13233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p++;
13243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q--;
13253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((isspace((int) ((unsigned char) *q)) != 0) && (q > p))
13263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q--;
1327fb34f5cabef5c07f924c3c8266cbbefc64fda5d3cristy        (void) CopyMagickString(message,p,MagickMin((size_t) (q-p+2),
132821967fb1fb285c755c58b183e45b7b70c4d1978acristy          MagickLocaleExtent));
132973bd4a51b419e914565bdf204bf1540dc4c8ee26cristy        locale_info=(LocaleInfo *) AcquireMagickMemory(sizeof(*locale_info));
13303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (locale_info == (LocaleInfo *) NULL)
13313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
13323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ResetMagickMemory(locale_info,0,sizeof(*locale_info));
13333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        locale_info->path=ConstantString(filename);
13343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        locale_info->tag=ConstantString(tag);
13353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        locale_info->message=ConstantString(message);
1336e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy        locale_info->signature=MagickCoreSignature;
1337c9f5cc8270d23f1ccfd25806c16be69fbcb6863cdirk        status=AddValueToSplayTree(cache,locale_info->tag,locale_info);
13383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
13393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ThrowMagickException(exception,GetMagickModule(),
1340efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy            ResourceLimitError,"MemoryAllocationFailed","`%s'",
13413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            locale_info->tag);
134221967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) ConcatenateMagickString(tag,message,MagickLocaleExtent);
134321967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) ConcatenateMagickString(tag,"\n",MagickLocaleExtent);
13443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q++;
13453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
13463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
13473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(keyword,"</message>") == 0)
13483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
13493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ChopLocaleComponents(tag,2);
135021967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent);
13513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
13523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
13533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*keyword == '<')
13543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
13553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
13563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Subpath element.
13573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
13583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (*(keyword+1) == '?')
13593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          continue;
13603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (*(keyword+1) == '/')
13613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
13623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ChopLocaleComponents(tag,1);
13633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (*tag != '\0')
136421967fb1fb285c755c58b183e45b7b70c4d1978acristy              (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent);
13653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
13663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
13673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        token[strlen(token)-1]='\0';
136821967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) CopyMagickString(token,token+1,MagickLocaleExtent);
136921967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) ConcatenateMagickString(tag,token,MagickLocaleExtent);
137021967fb1fb285c755c58b183e45b7b70c4d1978acristy        (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent);
13713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
13723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
13738bedb4edca01599dfd0612cb0daa35b09c67d736Cristy    GetNextToken(q,(const char **) NULL,extent,token);
13743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*token != '=')
13753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
13763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
13773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  token=(char *) RelinquishMagickMemory(token);
1378909b647caa79e7dd752f7daae08177ec74fb841acristy  (void) SetFatalErrorHandler(fatal_handler);
1379759ba919e9fe454989454f481f4055fd38b32307cristy  return(status != 0 ? MagickTrue : MagickFalse);
13803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
13833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13878ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%   L o c a l e C o m p a r e                                                 %
13888ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
13898ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
13908ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
13918ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13928ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
13938ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  LocaleCompare() performs a case-insensitive comparison of two strings
13948ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  byte-by-byte, according to the ordering of the current locale encoding.
13958ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  LocaleCompare returns an integer greater than, equal to, or less than 0,
13968ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  if the string pointed to by p is greater than, equal to, or less than the
13978ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  string pointed to by q respectively.  The sign of a non-zero return value
13988ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  is determined by the sign of the difference between the values of the first
13998ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  pair of bytes that differ in the strings being compared.
14008ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14018ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  The format of the LocaleCompare method is:
14028ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14038ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%      int LocaleCompare(const char *p,const char *q)
14048ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14058ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  A description of each parameter follows:
14068ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14078ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o p: A pointer to a character string.
14088ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14098ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o q: A pointer to a character string to compare to p.
14108ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14118ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy*/
14128ba074d50ed39dc2a5996238a0d60da6b75bc62bCristyMagickExport int LocaleCompare(const char *p,const char *q)
14138ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy{
14148ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  if ((p == (char *) NULL) && (q == (char *) NULL))
14158ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(0);
14168ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  if (p == (char *) NULL)
14178ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(-1);
14188ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  if (q == (char *) NULL)
14198ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(1);
14208ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy#if defined(MAGICKCORE_HAVE_STRCASECMP)
14218ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  return(strcasecmp(p,q));
14228ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy#else
14238ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  {
14248ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    register int
14258ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      c,
14268ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      d;
14278ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
14288ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    for ( ; ; )
14298ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    {
14308ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      c=(int) *((unsigned char *) p);
14318ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      d=(int) *((unsigned char *) q);
14328ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      if ((c == 0) || (AsciiMap[c] != AsciiMap[d]))
14338ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy        break;
14348ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      p++;
14358ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      q++;
14368ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    }
14378ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(AsciiMap[c]-(int) AsciiMap[d]);
14388ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  }
14398ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy#endif
14408ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy}
14418ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
14428ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy/*
14438ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14448ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14458ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14468ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14478ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%   L o c a l e L o w e r                                                     %
14488ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14498ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14508ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14518ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14528ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14538ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  LocaleLower() transforms all of the characters in the supplied
14548ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  null-terminated string, changing all uppercase letters to lowercase.
14558ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14568ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  The format of the LocaleLower method is:
14578ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14588ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%      void LocaleLower(char *string)
14598ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14608ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  A description of each parameter follows:
14618ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14628ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o string: A pointer to the string to convert to lower-case Locale.
14638ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14648ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy*/
14658ba074d50ed39dc2a5996238a0d60da6b75bc62bCristyMagickExport void LocaleLower(char *string)
14668ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy{
14678ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  register char
14688ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    *q;
14698ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
14708ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  assert(string != (char *) NULL);
14718ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  for (q=string; *q != '\0'; q++)
14728ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    *q=(char) tolower((int) *q);
14738ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy}
14748ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
14758ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy/*
14768ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14778ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14788ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14798ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14808ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%   L o c a l e N C o m p a r e                                               %
14818ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14828ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14838ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
14848ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14858ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14868ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  LocaleNCompare() performs a case-insensitive comparison of two strings
14878ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  byte-by-byte, according to the ordering of the current locale encoding.
14888ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14898ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  LocaleNCompare returns an integer greater than, equal to, or less than 0,
14908ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  if the string pointed to by p is greater than, equal to, or less than the
14918ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  string pointed to by q respectively.  The sign of a non-zero return value
14928ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  is determined by the sign of the difference between the values of the first
14938ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  pair of bytes that differ in the strings being compared.
14948ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14958ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  The LocaleNCompare method makes the same comparison as LocaleCompare but
14968ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  looks at a maximum of n bytes.  Bytes following a null byte are not
14978ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  compared.
14988ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
14998ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  The format of the LocaleNCompare method is:
15008ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15018ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%      int LocaleNCompare(const char *p,const char *q,const size_t n)
15028ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15038ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  A description of each parameter follows:
15048ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15058ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o p: A pointer to a character string.
15068ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15078ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o q: A pointer to a character string to compare to p.
15088ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15098ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o length: the number of characters to compare in strings p and q.
15108ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15118ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy*/
15128ba074d50ed39dc2a5996238a0d60da6b75bc62bCristyMagickExport int LocaleNCompare(const char *p,const char *q,const size_t length)
15138ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy{
15148ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  if ((p == (char *) NULL) && (q == (char *) NULL))
15158ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(0);
15168ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  if (p == (char *) NULL)
15178ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(-1);
15188ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  if (q == (char *) NULL)
15198ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(1);
15208ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy#if defined(MAGICKCORE_HAVE_STRNCASECMP)
15218ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  return(strncasecmp(p,q,length));
15228ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy#else
15238ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  {
15248ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    register int
15258ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      c,
15268ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      d;
15278ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
15288ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    register size_t
15298ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      i;
15308ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
15318ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    for (i=length; i != 0; i--)
15328ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    {
15338ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      c=(int) *((unsigned char *) p);
15348ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      d=(int) *((unsigned char *) q);
15358ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      if (AsciiMap[c] != AsciiMap[d])
15368ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy        return(AsciiMap[c]-(int) AsciiMap[d]);
15378ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      if (c == 0)
15388ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy        return(0);
15398ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      p++;
15408ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy      q++;
15418ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    }
15428ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    return(0);
15438ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  }
15448ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy#endif
15458ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy}
15468ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
15478ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy/*
15488ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15498ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15508ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15518ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15528ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%   L o c a l e U p p e r                                                     %
15538ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15548ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15558ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15568ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15578ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15588ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  LocaleUpper() transforms all of the characters in the supplied
15598ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  null-terminated string, changing all lowercase letters to uppercase.
15608ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15618ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  The format of the LocaleUpper method is:
15628ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15638ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%      void LocaleUpper(char *string)
15648ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15658ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%  A description of each parameter follows:
15668ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15678ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%    o string: A pointer to the string to convert to upper-case Locale.
15688ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%
15698ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy*/
15708ba074d50ed39dc2a5996238a0d60da6b75bc62bCristyMagickExport void LocaleUpper(char *string)
15718ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy{
15728ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  register char
15738ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    *q;
15748ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
15758ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  assert(string != (char *) NULL);
15768ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy  for (q=string; *q != '\0'; q++)
15778ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy    *q=(char) toupper((int) *q);
15788ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy}
15798ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy
15808ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy/*
15818ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15828ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15838ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
15848ba074d50ed39dc2a5996238a0d60da6b75bc62bCristy%                                                                             %
1585f34a145c545cb86152ad42a787f6d5fffea6b77ccristy+   L o c a l e C o m p o n e n t G e n e s i s                               %
1586f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1587f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1588f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1589f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1591f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%  LocaleComponentGenesis() instantiates the locale component.
1592f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1593f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%  The format of the LocaleComponentGenesis method is:
1594f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1595f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%      MagickBooleanType LocaleComponentGenesis(void)
1596f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1597f34a145c545cb86152ad42a787f6d5fffea6b77ccristy*/
15985ff4eaf57b3cd47d0371f204f865cbba614674a0cristyMagickPrivate MagickBooleanType LocaleComponentGenesis(void)
1599f34a145c545cb86152ad42a787f6d5fffea6b77ccristy{
16007c9770650f31145e0fe8811d10b2e0ecd47697c8cristy  if (locale_semaphore == (SemaphoreInfo *) NULL)
16017c9770650f31145e0fe8811d10b2e0ecd47697c8cristy    locale_semaphore=AcquireSemaphoreInfo();
1602f34a145c545cb86152ad42a787f6d5fffea6b77ccristy  return(MagickTrue);
1603f34a145c545cb86152ad42a787f6d5fffea6b77ccristy}
1604f34a145c545cb86152ad42a787f6d5fffea6b77ccristy
1605f34a145c545cb86152ad42a787f6d5fffea6b77ccristy/*
1606f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1607f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1608f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1609f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1610f34a145c545cb86152ad42a787f6d5fffea6b77ccristy+   L o c a l e C o m p o n e n t T e r m i n u s                             %
1611f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1612f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1613f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%                                                                             %
1614f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1615f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1616f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%  LocaleComponentTerminus() destroys the locale component.
1617f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1618f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%  The format of the LocaleComponentTerminus method is:
1619f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1620f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%      LocaleComponentTerminus(void)
1621f34a145c545cb86152ad42a787f6d5fffea6b77ccristy%
1622f34a145c545cb86152ad42a787f6d5fffea6b77ccristy*/
16235ff4eaf57b3cd47d0371f204f865cbba614674a0cristyMagickPrivate void LocaleComponentTerminus(void)
1624f34a145c545cb86152ad42a787f6d5fffea6b77ccristy{
162518b17443128598500357da7bff2f01683cf32890cristy  if (locale_semaphore == (SemaphoreInfo *) NULL)
162604b11db5504ecdf205114ae7e9e68774a1ff0b9bcristy    ActivateSemaphoreInfo(&locale_semaphore);
1627f84a193d5f435588cd78d521fff3f1f852e227f8cristy  LockSemaphoreInfo(locale_semaphore);
162886e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy  if (locale_cache != (SplayTreeInfo *) NULL)
162986e5ac9bd8a1d10f4fc55dae95585db303b6a1e7cristy    locale_cache=DestroySplayTree(locale_cache);
1630c6a82901209d11a186620b6372d8a6b18a552b50cristy#if defined(MAGICKCORE_LOCALE_SUPPORT)
1631b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  DestroyCLocale();
1632a723b6a0656cce17bf5495a3e6bc2780f0b7aed5cristy#endif
1633f84a193d5f435588cd78d521fff3f1f852e227f8cristy  UnlockSemaphoreInfo(locale_semaphore);
16343d162a93f537cb7cbb6d9fa3b8e73e8f992a527acristy  RelinquishSemaphoreInfo(&locale_semaphore);
1635f34a145c545cb86152ad42a787f6d5fffea6b77ccristy}
1636