]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - ppdc/ppdc-catalog.cxx
Update all references to OS X to macOS.
[thirdparty/cups.git] / ppdc / ppdc-catalog.cxx
index 29de91f673968b1b5139b30393e640fd353e65cb..1ec051d73a68d2dd4a6e0209de39868de0cf84a2 100644 (file)
@@ -1,33 +1,21 @@
 //
-// "$Id$"
+// Shared message catalog class for the CUPS PPD Compiler.
 //
-//   Shared message catalog class for the CUPS PPD Compiler.
+// Copyright 2007-2016 by Apple Inc.
+// Copyright 2002-2006 by Easy Software Products.
 //
-//   Copyright 2007-2008 by Apple Inc.
-//   Copyright 2002-2006 by Easy Software Products.
-//
-//   These coded instructions, statements, and computer programs are the
-//   property of Apple Inc. and are protected by Federal copyright
-//   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
-//   which should have been included with this file.  If this file is
-//   file is missing or damaged, see the license at "http://www.cups.org/".
-//
-// Contents:
-//
-//   ppdcCatalog::ppdcCatalog()   - Create a shared message catalog.
-//   ppdcCatalog::~ppdcCatalog()  - Destroy a shared message catalog.
-//   ppdcCatalog::add_message()   - Add a new message.
-//   ppdcCatalog::find_message()  - Find a message in a catalog...
-//   ppdcCatalog::load_messages() - Load messages from a .po file.
-//   ppdcCatalog::save_messages() - Save the messages to a .po file.
+// These coded instructions, statements, and computer programs are the
+// property of Apple Inc. and are protected by Federal copyright
+// law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+// which should have been included with this file.  If this file is
+// file is missing or damaged, see the license at "http://www.cups.org/".
 //
 
 //
 // Include necessary headers...
 //
 
-#include "ppdc.h"
-#include <cups/globals.h>
+#include "ppdc-private.h"
 
 
 //
@@ -47,6 +35,9 @@ typedef enum
 // Local functions...
 //
 
+#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
+static void    apple_add_message(CFStringRef key, CFStringRef val, ppdcCatalog *c);
+#endif /* __APPLE__ && CUPS_BUNDLEDIR */
 static int     get_utf8(char *&ptr);
 static int     get_utf16(cups_file_t *fp, ppdc_cs_t &cs);
 static int     put_utf8(int ch, char *&ptr, char *end);
@@ -61,9 +52,7 @@ ppdcCatalog::ppdcCatalog(const char *l,       // I - Locale
                          const char *f)        // I - Message catalog file
   : ppdcShared()
 {
-  _cups_globals_t      *cg = _cupsGlobals();
-                                       // Global information
-
+  PPDC_NEW;
 
   locale   = new ppdcString(l);
   filename = new ppdcString(f);
@@ -75,7 +64,70 @@ ppdcCatalog::ppdcCatalog(const char *l,      // I - Locale
     char       pofile[1024];           // Message catalog file
 
 
-    snprintf(pofile, sizeof(pofile), "%s/%s/ppdc_%s.po", cg->localedir, l, l);
+#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
+    char               applelang[256]; // Apple language ID
+    CFURLRef           url;            // URL to cups.strings file
+    CFReadStreamRef    stream = NULL;  // File stream
+    CFPropertyListRef  plist = NULL;   // Localization file
+
+    snprintf(pofile, sizeof(pofile), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", _cupsAppleLanguage(l, applelang, sizeof(applelang)));
+    if (access(pofile, 0))
+    {
+      // Try alternate lproj directory names...
+      const char *tl = l;              // Temporary locale string
+
+      if (!strncmp(l, "en", 2))
+       tl = "English";
+      else if (!strncmp(l, "nb", 2))
+        tl = "no";
+      else if (!strncmp(l, "nl", 2))
+       tl = "Dutch";
+      else if (!strncmp(l, "fr", 2))
+       tl = "French";
+      else if (!strncmp(l, "de", 2))
+       tl = "German";
+      else if (!strncmp(l, "it", 2))
+       tl = "Italian";
+      else if (!strncmp(l, "ja", 2))
+       tl = "Japanese";
+      else if (!strncmp(l, "es", 2))
+       tl = "Spanish";
+
+      snprintf(pofile, sizeof(pofile), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", tl);
+    }
+
+    url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)pofile, (CFIndex)strlen(pofile), false);
+    if (url)
+    {
+      stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
+
+      if (stream)
+      {
+       /*
+       * Read the property list containing the localization data.
+       */
+
+       CFReadStreamOpen(stream);
+
+       plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, stream, 0, kCFPropertyListImmutable, NULL, NULL);
+
+       if (plist && CFGetTypeID(plist) == CFDictionaryGetTypeID())
+         CFDictionaryApplyFunction((CFDictionaryRef)plist, (CFDictionaryApplierFunction)apple_add_message, this);
+
+       if (plist)
+         CFRelease(plist);
+
+       CFRelease(stream);
+      }
+
+      CFRelease(url);
+    }
+
+#else
+    _cups_globals_t    *cg = _cupsGlobals();
+                                       // Global information
+
+    snprintf(pofile, sizeof(pofile), "%s/%s/cups_%s.po", cg->localedir, l, l);
 
     if (load_messages(pofile) && strchr(l, '_'))
     {
@@ -84,14 +136,15 @@ ppdcCatalog::ppdcCatalog(const char *l,    // I - Locale
 
 
       strlcpy(baseloc, l, sizeof(baseloc));
-      snprintf(pofile, sizeof(pofile), "%s/%s/ppdc_%s.po", cg->localedir,
+      snprintf(pofile, sizeof(pofile), "%s/%s/cups_%s.po", cg->localedir,
                baseloc, baseloc);
 
       load_messages(pofile);
     }
+#endif /* __APPLE__ && CUPS_BUNDLEDIR */
   }
 
-  if (f)
+  if (f && *f)
     load_messages(f);
 }
 
@@ -102,9 +155,11 @@ ppdcCatalog::ppdcCatalog(const char *l,    // I - Locale
 
 ppdcCatalog::~ppdcCatalog()
 {
-  delete locale;
-  delete filename;
-  delete messages;
+  PPDC_DELETE;
+
+  locale->release();
+  filename->release();
+  messages->release();
 }
 
 
@@ -113,14 +168,16 @@ ppdcCatalog::~ppdcCatalog()
 //
 
 void
-ppdcCatalog::add_message(const char *id)// I - Message ID to add
+ppdcCatalog::add_message(
+    const char *id,                    // I - Message ID to add
+    const char *string)                        // I - Translation string
 {
   ppdcMessage  *m;                     // Current message
   char         text[1024];             // Text to translate
 
 
   // Range check input...
-  if (!id || !*id)
+  if (!id)
     return;
 
   // Verify that we don't already have the message ID...
@@ -128,11 +185,23 @@ ppdcCatalog::add_message(const char *id)// I - Message ID to add
        m;
        m = (ppdcMessage *)messages->next())
     if (!strcmp(m->id->value, id))
+    {
+      if (string)
+      {
+        m->string->release();
+       m->string = new ppdcString(string);
+      }
       return;
+    }
 
   // Add the message...
-  snprintf(text, sizeof(text), "TRANSLATE %s", id);
-  messages->add(new ppdcMessage(id, text));
+  if (!string)
+  {
+    snprintf(text, sizeof(text), "TRANSLATE %s", id);
+    string = text;
+  }
+
+  messages->add(new ppdcMessage(id, string));
 }
 
 
@@ -147,6 +216,9 @@ ppdcCatalog::find_message(
   ppdcMessage  *m;                     // Current message
 
 
+  if (!*id)
+    return (id);
+
   for (m = (ppdcMessage *)messages->first();
        m;
        m = (ppdcMessage *)messages->next())
@@ -166,7 +238,6 @@ ppdcCatalog::load_messages(
     const char *f)                     // I - Message catalog file
 {
   cups_file_t  *fp;                    // Message file
-  ppdcMessage  *temp;                  // Current message
   char         line[4096],             // Line buffer
                *ptr,                   // Pointer into buffer
                id[4096],               // Translation ID
@@ -178,13 +249,13 @@ ppdcCatalog::load_messages(
   if ((fp = cupsFileOpen(f, "r")) == NULL)
     return (-1);
 
-  if ((ptr = strrchr(f, '.')) == NULL)
+  if ((ptr = (char *)strrchr(f, '.')) == NULL)
     goto unknown_load_format;
   else if (!strcmp(ptr, ".strings"))
   {
    /*
-    * Read messages in Mac OS X ".strings" format, which are UTF-16 text
-    * files of the format:
+    * Read messages in macOS ".strings" format, which are either UTF-8/UTF-16
+    * text files of the format:
     *
     *     "id" = "str";
     *
@@ -210,13 +281,19 @@ ppdcCatalog::load_messages(
          if ((ch = get_utf16(fp, cs)) == 0)
            break;
 
-          if (ch == 'n')
+         if (ch == 'n')
            ch = '\n';
          else if (ch == 't')
            ch = '\t';
         }
+       else if (ch == '\"')
+       {
+         *ptr = '\0';
+         ptr  = NULL;
+       }
 
-        put_utf8(ch, ptr, end);
+        if (ptr)
+         put_utf8(ch, ptr, end);
       }
       else if (ch == '/')
       {
@@ -247,13 +324,8 @@ ppdcCatalog::load_messages(
       }
       else if (ch == '\"')
       {
-        // Start or finish quoted string...
-       if (ptr)
-       {
-         *ptr = '\0';
-         ptr  = NULL;
-       }
-       else if (id[0])
+        // Start quoted string...
+       if (id[0])
        {
          ptr = str;
          end = str + sizeof(str) - 1;
@@ -267,9 +339,8 @@ ppdcCatalog::load_messages(
       else if (ch == ';')
       {
         // Add string...
-       temp = new ppdcMessage(id, str);
-
-       messages->add(temp);
+       add_message(id, str);
+       id[0] = '\0';
       }
     }
   }
@@ -292,9 +363,16 @@ ppdcCatalog::load_messages(
     *     "multiple lines"
     */
 
+    int        which,                          // In msgid?
+       haveid,                         // Did we get a msgid string?
+       havestr;                        // Did we get a msgstr string?
+
     linenum = 0;
     id[0]   = '\0';
     str[0]  = '\0';
+    haveid  = 0;
+    havestr = 0;
+    which   = 0;
 
     while (cupsFileGets(fp, line, sizeof(line)))
     {
@@ -305,10 +383,11 @@ ppdcCatalog::load_messages(
        continue;
 
       // Strip the trailing quote...
-      if ((ptr = strrchr(line, '\"')) == NULL)
+      if ((ptr = (char *)strrchr(line, '\"')) == NULL)
       {
-       fprintf(stderr, "ERROR: Expected quoted string on line %d of %s!\n",
-               linenum, f);
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Expected quoted string on line %d of %s."),
+                       linenum, f);
        cupsFileClose(fp);
        return (-1);
       }
@@ -318,8 +397,9 @@ ppdcCatalog::load_messages(
       // Find start of value...
       if ((ptr = strchr(line, '\"')) == NULL)
       {
-       fprintf(stderr, "ERROR: Expected quoted string on line %d of %s!\n",
-               linenum, f);
+       _cupsLangPrintf(stderr,
+                       _("ppdc: Expected quoted string on line %d of %s."),
+                       linenum, f);
        cupsFileClose(fp);
        return (-1);
       }
@@ -369,48 +449,46 @@ ppdcCatalog::load_messages(
       // Create or add to a message...
       if (!strncmp(line, "msgid", 5))
       {
-       if (id[0] && str[0])
-       {
-         temp = new ppdcMessage(id, str);
-
-         messages->add(temp);
-       }
+       if (haveid && havestr)
+         add_message(id, str);
 
        strlcpy(id, ptr, sizeof(id));
        str[0] = '\0';
+       haveid  = 1;
+       havestr = 0;
+       which   = 1;
       }
       else if (!strncmp(line, "msgstr", 6))
       {
-       if (!id[0])
+       if (!haveid)
        {
-         fprintf(stderr, "ERROR: Need a msgid line before any "
-                         "translation strings on line %d of %s!\n",
-                 linenum, f);
+         _cupsLangPrintf(stderr,
+                         _("ppdc: Need a msgid line before any "
+                           "translation strings on line %d of %s."),
+                         linenum, f);
          cupsFileClose(fp);
          return (-1);
        }
 
        strlcpy(str, ptr, sizeof(str));
+       havestr = 1;
+       which   = 2;
       }
-      else if (line[0] == '\"' && str[0])
+      else if (line[0] == '\"' && which == 2)
        strlcat(str, ptr, sizeof(str));
-      else if (line[0] == '\"' && id[0])
+      else if (line[0] == '\"' && which == 1)
        strlcat(id, ptr, sizeof(id));
       else
       {
-       fprintf(stderr, "ERROR: Unexpected text on line %d of %s!\n",
-               linenum, f);
+       _cupsLangPrintf(stderr, _("ppdc: Unexpected text on line %d of %s."),
+                       linenum, f);
        cupsFileClose(fp);
        return (-1);
       }
     }
 
-    if (id[0] && str[0])
-    {
-      temp = new ppdcMessage(id, str);
-
-      messages->add(temp);
-    }
+    if (haveid && havestr)
+      add_message(id, str);
   }
   else
     goto unknown_load_format;
@@ -429,7 +507,8 @@ ppdcCatalog::load_messages(
 
   unknown_load_format:
 
-  fprintf(stderr, "ERROR: Unknown message catalog format for \"%s\"!\n", f);
+  _cupsLangPrintf(stderr,
+                  _("ppdc: Unknown message catalog format for \"%s\"."), f);
   cupsFileClose(fp);
   return (-1);
 }
@@ -451,7 +530,7 @@ ppdcCatalog::save_messages(
 
 
   // Open the file...
-  if ((ptr = strrchr(f, '.')) == NULL)
+  if ((ptr = (char *)strrchr(f, '.')) == NULL)
     return (-1);
 
   if (!strcmp(ptr, ".gz"))
@@ -579,6 +658,27 @@ ppdcCatalog::save_messages(
 }
 
 
+#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
+//
+// 'apple_add_message()' - Add a message from a localization dictionary.
+//
+
+static void
+apple_add_message(CFStringRef key,     // I - Localization key
+                  CFStringRef val,     // I - Localized value
+                  ppdcCatalog *c)      // I - Message catalog
+{
+  char id[1024],                       // Message id
+       str[1024];                      // Localized message
+
+
+  if (CFStringGetCString(key, id, sizeof(id), kCFStringEncodingUTF8) &&
+      CFStringGetCString(val, str, sizeof(str), kCFStringEncodingUTF8))
+    c->add_message(id, str);
+}
+#endif /* __APPLE__ && CUPS_BUNDLEDIR */
+
+
 //
 // 'get_utf8()' - Get a UTF-8 character.
 //
@@ -697,7 +797,8 @@ get_utf16(cups_file_t *fp,          // I  - File to read from
   if (cs == PPDC_CS_UTF8)
   {
     // UTF-8 character...
-    ch = cupsFileGetChar(fp);
+    if ((ch = cupsFileGetChar(fp)) < 0)
+      return (0);
 
     if ((ch & 0xe0) == 0xc0)
     {
@@ -785,7 +886,7 @@ put_utf8(int  ch,                   // I  - Unicode character
     if (ptr >= end)
       return (-1);
 
-    *ptr++ = ch;
+    *ptr++ = (char)ch;
   }
   else if (ch < 0x800)
   {
@@ -793,8 +894,8 @@ put_utf8(int  ch,                   // I  - Unicode character
     if ((ptr + 1) >= end)
       return (-1);
 
-    *ptr++ = 0xc0 | (ch >> 6);
-    *ptr++ = 0x80 | (ch & 0x3f);
+    *ptr++ = (char)(0xc0 | (ch >> 6));
+    *ptr++ = (char)(0x80 | (ch & 0x3f));
   }
   else if (ch < 0x10000)
   {
@@ -802,9 +903,9 @@ put_utf8(int  ch,                   // I  - Unicode character
     if ((ptr + 2) >= end)
       return (-1);
 
-    *ptr++ = 0xe0 | (ch >> 12);
-    *ptr++ = 0x80 | ((ch >> 6) & 0x3f);
-    *ptr++ = 0x80 | (ch & 0x3f);
+    *ptr++ = (char)(0xe0 | (ch >> 12));
+    *ptr++ = (char)(0x80 | ((ch >> 6) & 0x3f));
+    *ptr++ = (char)(0x80 | (ch & 0x3f));
   }
   else
   {
@@ -812,10 +913,10 @@ put_utf8(int  ch,                 // I  - Unicode character
     if ((ptr + 3) >= end)
       return (-1);
 
-    *ptr++ = 0xf0 | (ch >> 18);
-    *ptr++ = 0x80 | ((ch >> 12) & 0x3f);
-    *ptr++ = 0x80 | ((ch >> 6) & 0x3f);
-    *ptr++ = 0x80 | (ch & 0x3f);
+    *ptr++ = (char)(0xf0 | (ch >> 18));
+    *ptr++ = (char)(0x80 | ((ch >> 12) & 0x3f));
+    *ptr++ = (char)(0x80 | ((ch >> 6) & 0x3f));
+    *ptr++ = (char)(0x80 | (ch & 0x3f));
   }
 
   return (0);
@@ -836,8 +937,8 @@ put_utf16(cups_file_t *fp,          // I - File to write to
   if (ch < 0x10000)
   {
     // One-word UTF-16 big-endian...
-    buffer[0] = ch >> 8;
-    buffer[1] = ch;
+    buffer[0] = (unsigned char)(ch >> 8);
+    buffer[1] = (unsigned char)ch;
 
     if (cupsFileWrite(fp, (char *)buffer, 2) == 2)
       return (0);
@@ -847,10 +948,10 @@ put_utf16(cups_file_t *fp,                // I - File to write to
     // Two-word UTF-16 big-endian...
     ch -= 0x10000;
 
-    buffer[0] = 0xd8 | (ch >> 18);
-    buffer[1] = ch >> 10;
-    buffer[2] = 0xdc | ((ch >> 8) & 0x03);
-    buffer[3] = ch;
+    buffer[0] = (unsigned char)(0xd8 | (ch >> 18));
+    buffer[1] = (unsigned char)(ch >> 10);
+    buffer[2] = (unsigned char)(0xdc | ((ch >> 8) & 0x03));
+    buffer[3] = (unsigned char)ch;
 
     if (cupsFileWrite(fp, (char *)buffer, 4) == 4)
       return (0);
@@ -858,8 +959,3 @@ put_utf16(cups_file_t *fp,          // I - File to write to
 
   return (-1);
 }
-
-
-//
-// End of "$Id$".
-//