This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  08f8b2ab31d4df0b7b80a8d85c8719e07452880b (commit)
       via  f88533cc067ea252254b0851d87f09ef798e2c97 (commit)
       via  13dc7bdb5e3a0eaaf3607b154bba77a01404a788 (commit)
       via  60cbd9b9da2059481e2f29fbb5859a5b0643d3d7 (commit)
      from  c2b4d892103a99b61ceb8ece6911b6c8b8ba3d5a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=08f8b2ab31d4df0b7b80a8d85c8719e07452880b
commit 08f8b2ab31d4df0b7b80a8d85c8719e07452880b
Merge: c2b4d89 f88533c
Author:     Brad King <brad.k...@kitware.com>
AuthorDate: Fri Nov 6 11:20:01 2015 -0500
Commit:     CMake Topic Stage <kwro...@kitware.com>
CommitDate: Fri Nov 6 11:20:01 2015 -0500

    Merge topic 'cpack-dmg-multilanguage-sla' into next
    
    f88533cc CPackDMG: Add support for multilingual SLAs
    13dc7bdb CMake Nightly Date Stamp
    60cbd9b9 CMake Nightly Date Stamp


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f88533cc067ea252254b0851d87f09ef798e2c97
commit f88533cc067ea252254b0851d87f09ef798e2c97
Author:     Simon Levermann <simon-git...@slevermann.de>
AuthorDate: Mon Oct 19 11:13:55 2015 +0200
Commit:     Brad King <brad.k...@kitware.com>
CommitDate: Fri Nov 6 11:14:49 2015 -0500

    CPackDMG: Add support for multilingual SLAs
    
    Multiple languages for SLAs and the SLA UI can be added via the CPack
    variables CPACK_DMG_SLA_DIR and CPACK_DMG_SLA_LANGUAGES.  For each
    language defined in the languages variable, CPack will search for
    <language>.menu.txt and <language>.license.txt in CPACK_DMG_SLA_DIR.
    If the sla directory variable is not defined, the old behaviour using
    CPACK_RESOURCE_FILE_LICENSE is retained.

diff --git a/Help/release/dev/cpack-dmg-multilanguage-sla.rst 
b/Help/release/dev/cpack-dmg-multilanguage-sla.rst
new file mode 100644
index 0000000..9e28fa2
--- /dev/null
+++ b/Help/release/dev/cpack-dmg-multilanguage-sla.rst
@@ -0,0 +1,7 @@
+cpack-dmg-multilanguage-sla
+---------------------------
+
+* The :module:`CPack DragNDrop generator <CPackDMG>` learned to add
+  multi-lingual SLAs to a DMG which is presented to the user when they try to
+  mount the DMG.  See the :variable:`CPACK_DMG_SLA_LANGUAGES` and
+  :variable:`CPACK_DMG_SLA_DIR` variables for details.
diff --git a/Modules/CPackDMG.cmake b/Modules/CPackDMG.cmake
index b7a6ba5..37d7352 100644
--- a/Modules/CPackDMG.cmake
+++ b/Modules/CPackDMG.cmake
@@ -36,6 +36,19 @@
 #  background image is set. The background image is applied after applying the
 #  custom .DS_Store file.
 #
+# .. variable:: CPACK_DMG_SLA_DIR
+#
+#   Directory where license and menu files for different languages are stored.
+#
+# .. variable:: CPACK_DMG_SLA_LANGUAGES
+#
+#   Languages for which a license agreement is provided when mounting the
+#   generated DMG.
+#
+#   For every language in this list, CPack will try to find files
+#   ``<language>.menu.txt`` and ``<language>.license.txt`` in the directory
+#   specified by the :variable:`CPACK_DMG_SLA_DIR` variable.
+#
 # .. variable:: CPACK_COMMAND_HDIUTIL
 #
 #  Path to the hdiutil(1) command used to operate on disk image files on Mac
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index fd71b0e..f23331b 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -726,6 +726,9 @@ endif()
 # Build CPackLib
 add_library(CPackLib ${CPACK_SRCS})
 target_link_libraries(CPackLib CMakeLib)
+if(APPLE)
+  target_link_libraries(CPackLib "-framework Carbon")
+endif()
 
 if(APPLE)
   add_executable(cmakexbuild cmakexbuild.cxx)
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx 
b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 4c400d9..208a64c 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -18,6 +18,24 @@
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/FStream.hxx>
 
+#include <iomanip>
+
+#include <CoreFoundation/CFBase.h>
+#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFLocale.h>
+
+// The carbon framework is deprecated, but the Region codes it supplies are
+// needed for the LPic data structure used for generating multi-lingual SLAs.
+// There does not seem to be a replacement API for these region codes.
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+#include <Carbon/Carbon.h>
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
 static const char* SLAHeader =
 "data 'LPic' (5000) {\n"
 "    $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n"
@@ -103,6 +121,69 @@ int cmCPackDragNDropGenerator::InitializeInternal()
     }
   this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
 
+  if(this->IsSet("CPACK_DMG_SLA_DIR"))
+    {
+    slaDirectory = this->GetOption("CPACK_DMG_SLA_DIR");
+    if(!slaDirectory.empty() && this->IsSet("CPACK_RESOURCE_FILE_LICENSE"))
+      {
+      std::string license_file =
+        this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
+      if(!license_file.empty() &&
+         (license_file.find("CPack.GenericLicense.txt") == std::string::npos))
+        {
+        cmCPackLogger(cmCPackLog::LOG_WARNING,
+          "Both CPACK_DMG_SLA_DIR and CPACK_RESOURCE_FILE_LICENSE specified, "
+          "defaulting to CPACK_DMG_SLA_DIR"
+          << std::endl);
+        }
+      }
+    if(!this->IsSet("CPACK_DMG_LANGUAGES"))
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "CPACK_DMG_SLA_DIR set but no languages defined "
+        "(set CPACK_DMG_LANGUAGES)"
+        << std::endl);
+      return 0;
+      }
+    if(!cmSystemTools::FileExists(slaDirectory, false))
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "CPACK_DMG_SLA_DIR does not exist"
+        << std::endl);
+      return 0;
+      }
+
+    std::vector<std::string> languages;
+    cmSystemTools::ExpandListArgument(this->GetOption("CPACK_DMG_LANGUAGES"),
+                                      languages);
+    if(languages.empty())
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "CPACK_DMG_LANGUAGES set but empty"
+        << std::endl);
+      return 0;
+      }
+    for(size_t i = 0; i < languages.size(); ++i)
+      {
+      std::string license = slaDirectory + "/" + languages[i] + ".license.txt";
+      if (!cmSystemTools::FileExists(license))
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+          "Missing license file " << languages[i] << ".license.txt"
+          << std::endl);
+        return 0;
+        }
+      std::string menu = slaDirectory + "/" + languages[i] + ".menu.txt";
+      if (!cmSystemTools::FileExists(menu))
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+          "Missing menu file " << languages[i] << ".menu.txt"
+          << std::endl);
+        return 0;
+        }
+      }
+    }
+
   return this->Superclass::InitializeInternal();
 }
 
@@ -246,12 +327,23 @@ int cmCPackDragNDropGenerator::CreateDMG(const 
std::string& src_dir,
     this->GetOption("CPACK_DMG_DS_STORE")
     ? this->GetOption("CPACK_DMG_DS_STORE") : "";
 
+  const std::string cpack_dmg_languages =
+    this->GetOption("CPACK_DMG_LANGUAGES")
+      ? this->GetOption("CPACK_DMG_LANGUAGES") : "";
+
   // only put license on dmg if is user provided
   if(!cpack_license_file.empty() &&
       cpack_license_file.find("CPack.GenericLicense.txt") != std::string::npos)
-  {
+    {
     cpack_license_file = "";
-  }
+    }
+
+  // use sla_dir if both sla_dir and license_file are set
+  if(!cpack_license_file.empty() &&
+     !slaDirectory.empty())
+    {
+    cpack_license_file = "";
+    }
 
   // The staging directory contains everything that will end-up inside the
   // final disk image ...
@@ -418,54 +510,122 @@ int cmCPackDragNDropGenerator::CreateDMG(const 
std::string& src_dir,
       }
     }
 
-  if(!cpack_license_file.empty())
-  {
+  if(!cpack_license_file.empty() || !slaDirectory.empty())
+    {
+    // Use old hardcoded style if sla_dir is not set
+    bool oldStyle = slaDirectory.empty();
     std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
     sla_r += "/sla.r";
 
-    cmsys::ifstream ifs;
-    ifs.open(cpack_license_file.c_str());
-    if(ifs.is_open())
-    {
-      cmGeneratedFileStream osf(sla_r.c_str());
-      osf << "#include <CoreServices/CoreServices.r>\n\n";
-      osf << SLAHeader;
-      osf << "\n";
-      osf << "data 'TEXT' (5002, \"English\") {\n";
-      while(ifs.good())
+    std::vector<std::string> languages;
+    if(!oldStyle)
       {
-        std::string line;
-        std::getline(ifs, line);
-        // escape quotes
-        std::string::size_type pos = line.find('\"');
-        while(pos != std::string::npos)
+      cmSystemTools::ExpandListArgument(cpack_dmg_languages, languages);
+      }
+
+    cmGeneratedFileStream ofs(sla_r.c_str());
+    ofs << "#include <CoreServices/CoreServices.r>\n\n";
+    if(oldStyle)
+      {
+      ofs << SLAHeader;
+      ofs << "\n";
+      }
+    else
+      {
+      /*
+       * LPic Layout
+       * (https://github.com/pypt/dmg-add-license/blob/master/main.c)
+       * as far as I can tell (no official documentation seems to exist):
+       * struct LPic {
+       *  uint16_t default_language; // points to a resid, defaulting to 0,
+       *                             // which is the first set language
+       *  uint16_t length;
+       *  struct {
+       *    uint16_t language_code;
+       *    uint16_t resid;
+       *    uint16_t encoding; // Encoding from TextCommon.h,
+       *                       // forcing MacRoman (0) for now. Might need to
+       *                       // allow overwrite per license by user later
+       *  } item[1];
+       * }
+       */
+
+      // Create vector first for readability, then iterate to write to ofs
+      std::vector<uint16_t> header_data;
+      header_data.push_back(0);
+      header_data.push_back(languages.size());
+      for(size_t i = 0; i < languages.size(); ++i)
         {
-          line.replace(pos, 1, "\\\"");
-          pos = line.find('\"', pos+2);
+        CFStringRef language_cfstring = CFStringCreateWithCString(
+          NULL, languages[i].c_str(), kCFStringEncodingUTF8);
+        CFStringRef iso_language =
+          CFLocaleCreateCanonicalLanguageIdentifierFromString(
+            NULL, language_cfstring);
+        if (!iso_language)
+          {
+          cmCPackLogger(cmCPackLog::LOG_ERROR,
+            languages[i] << " is not a recognized language"
+            << std::endl);
+          }
+        char *iso_language_cstr = (char *) malloc(65);
+        CFStringGetCString(iso_language, iso_language_cstr, 64,
+                           kCFStringEncodingMacRoman);
+        LangCode lang = 0;
+        RegionCode region = 0;
+        OSStatus err = LocaleStringToLangAndRegionCodes(iso_language_cstr,
+                                                        &lang, &region);
+        if (err != noErr)
+          {
+          cmCPackLogger(cmCPackLog::LOG_ERROR,
+            "No language/region code available for " << iso_language_cstr
+            << std::endl);
+          free(iso_language_cstr);
+          return 0;
+          }
+        free(iso_language_cstr);
+        header_data.push_back(region);
+        header_data.push_back(i);
+        header_data.push_back(0);
         }
-        // break up long lines to avoid Rez errors
-        std::vector<std::string> lines;
-        const size_t max_line_length = 512;
-        for(size_t i=0; i<line.size(); i+= max_line_length)
+      ofs << "data 'LPic' (5000) {\n";
+      ofs << std::hex << std::uppercase << std::setfill('0');
+
+      for(size_t i = 0; i < header_data.size(); ++i)
+        {
+        if(i % 8 == 0)
           {
-          int line_length = max_line_length;
-          if(i+max_line_length > line.size())
-            line_length = line.size()-i;
-          lines.push_back(line.substr(i, line_length));
+          ofs << "    $\"";
           }
 
-        for(size_t i=0; i<lines.size(); i++)
+        ofs << std::setw(4) << header_data[i];
+
+        if(i % 8 == 7 || i == header_data.size() - 1)
+          {
+          ofs << "\"\n";
+          }
+        else
           {
-          osf << "        \"" << lines[i] << "\"\n";
+          ofs << " ";
           }
-        osf << "        \"\\n\"\n";
+        }
+      ofs << "};\n\n";
+      // Reset ofs options
+      ofs << std::dec << std::nouppercase << std::setfill(' ');
+      }
+
+    if(oldStyle)
+      {
+      WriteLicense(ofs, 0, "", cpack_license_file);
+      }
+    else
+      {
+      for(size_t i = 0; i < languages.size(); ++i)
+        {
+        WriteLicense(ofs, i + 5000, languages[i]);
+        }
       }
-      osf << "};\n";
-      osf << "\n";
-      osf << SLASTREnglish;
-      ifs.close();
-      osf.close();
-    }
+
+    ofs.Close();
 
     // convert to UDCO
     std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
@@ -539,7 +699,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& 
src_dir,
       }
 
     temp_image = temp_udco;
-  }
+    }
 
 
   // Create the final compressed read-only disk image ...
@@ -607,3 +767,126 @@ 
cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
 
   return GetComponentPackageFileName(package_file_name, componentName, false);
 }
+
+void
+cmCPackDragNDropGenerator::WriteLicense(cmGeneratedFileStream& outputStream,
+  int licenseNumber, std::string licenseLanguage, std::string licenseFile)
+{
+  if(!licenseFile.empty())
+    {
+    licenseNumber = 5002;
+    licenseLanguage = "English";
+    }
+
+  // License header
+  outputStream << "data 'TEXT' (" << licenseNumber << ", \""
+    << licenseLanguage << "\") {\n";
+  // License body
+  std::string actual_license = !licenseFile.empty() ? licenseFile :
+    (slaDirectory + "/" + licenseLanguage + ".license.txt");
+  cmsys::ifstream license_ifs;
+  license_ifs.open(actual_license.c_str());
+  if(license_ifs.is_open())
+    {
+    while(license_ifs.good())
+      {
+      std::string line;
+      std::getline(license_ifs, line);
+      if(!line.empty())
+        {
+        EscapeQuotes(line);
+        std::vector<std::string> lines;
+        BreakLongLine(line, lines);
+        for(size_t i = 0; i < lines.size(); ++i)
+          {
+          outputStream << "        \"" << lines[i] << "\"\n";
+          }
+        }
+      outputStream << "        \"\\n\"\n";
+      }
+    license_ifs.close();
+    }
+
+  // End of License
+  outputStream << "};\n\n";
+  if(!licenseFile.empty())
+    {
+    outputStream << SLASTREnglish;
+    }
+  else
+    {
+    // Menu header
+    outputStream << "resource 'STR#' (" << licenseNumber << ", \""
+      << licenseLanguage << "\") {\n";
+    outputStream << "    {\n";
+
+    // Menu body
+    cmsys::ifstream menu_ifs;
+    menu_ifs.open((slaDirectory+"/"+licenseLanguage+".menu.txt").c_str());
+    if(menu_ifs.is_open())
+      {
+      size_t lines_written = 0;
+      while(menu_ifs.good())
+        {
+        // Lines written from original file, not from broken up lines
+        std::string line;
+        std::getline(menu_ifs, line);
+        if(!line.empty())
+          {
+          EscapeQuotes(line);
+          std::vector<std::string> lines;
+          BreakLongLine(line, lines);
+          for(size_t i = 0; i < lines.size(); ++i)
+            {
+            std::string comma;
+            // We need a comma after every complete string,
+            // but not on the very last line
+            if(lines_written != 8 && i == lines.size() - 1)
+              {
+              comma = ",";
+              }
+            else
+              {
+              comma = "";
+              }
+            outputStream << "        \"" << lines[i] << "\"" << comma << "\n";
+            }
+          ++lines_written;
+          }
+        }
+      menu_ifs.close();
+      }
+
+    //End of menu
+    outputStream << "    }\n";
+    outputStream << "};\n";
+    outputStream << "\n";
+    }
+}
+
+void
+cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
+  std::vector<std::string>& lines)
+{
+  const size_t max_line_length = 512;
+  for(size_t i = 0; i < line.size(); i += max_line_length)
+    {
+    int line_length = max_line_length;
+    if(i + max_line_length > line.size())
+      {
+      line_length = line.size() - i;
+      }
+    lines.push_back(line.substr(i, line_length));
+    }
+}
+
+void
+cmCPackDragNDropGenerator::EscapeQuotes(std::string& line)
+{
+  std::string::size_type pos = line.find('\"');
+  while(pos != std::string::npos)
+    {
+    line.replace(pos, 1, "\\\"");
+    pos = line.find('\"', pos + 2);
+    }
+}
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h 
b/Source/CPack/cmCPackDragNDropGenerator.h
index 1c84d49..12db469 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -15,6 +15,8 @@
 
 #include "cmCPackGenerator.h"
 
+class cmGeneratedFileStream;
+
 /** \class cmCPackDragNDropGenerator
  * \brief A generator for OSX drag-n-drop installs
  */
@@ -42,6 +44,15 @@ protected:
   int CreateDMG(const std::string& src_dir, const std::string& output_file);
 
   std::string InstallPrefix;
+
+private:
+  std::string slaDirectory;
+
+  void WriteLicense(cmGeneratedFileStream& outputStream, int licenseNumber,
+    std::string licenseLanguage, std::string licenseFile = "");
+  void BreakLongLine(const std::string& line,
+    std::vector<std::string>& lines);
+  void EscapeQuotes(std::string& line);
 };
 
 #endif

-----------------------------------------------------------------------

Summary of changes:
 Help/release/dev/cpack-dmg-multilanguage-sla.rst |    7 +
 Modules/CPackDMG.cmake                           |   13 +
 Source/CMakeLists.txt                            |    3 +
 Source/CMakeVersion.cmake                        |    2 +-
 Source/CPack/cmCPackDragNDropGenerator.cxx       |  361 +++++++++++++++++++---
 Source/CPack/cmCPackDragNDropGenerator.h         |   11 +
 6 files changed, 357 insertions(+), 40 deletions(-)
 create mode 100644 Help/release/dev/cpack-dmg-multilanguage-sla.rst


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
http://public.kitware.com/mailman/listinfo/cmake-commits

Reply via email to