summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/DBCSFix
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/DBCSFix')
-rw-r--r--tools/Sandcastle/Source/DBCSFix/DBCSFix.csproj83
-rw-r--r--tools/Sandcastle/Source/DBCSFix/GlobalSuppressions.cs16
-rw-r--r--tools/Sandcastle/Source/DBCSFix/Program.cs210
-rw-r--r--tools/Sandcastle/Source/DBCSFix/Properties/AssemblyInfo.cs37
-rw-r--r--tools/Sandcastle/Source/DBCSFix/Properties/Settings.Designer.cs26
-rw-r--r--tools/Sandcastle/Source/DBCSFix/Properties/Settings.settings5
-rw-r--r--tools/Sandcastle/Source/DBCSFix/Settings.cs34
-rw-r--r--tools/Sandcastle/Source/DBCSFix/app.config15
-rw-r--r--tools/Sandcastle/Source/DBCSFix/readme.txt42
9 files changed, 468 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/DBCSFix/DBCSFix.csproj b/tools/Sandcastle/Source/DBCSFix/DBCSFix.csproj
new file mode 100644
index 0000000..26b7d78
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/DBCSFix.csproj
@@ -0,0 +1,83 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{80407AE8-7A1F-4C28-8627-6C871E1D717A}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>DBCSFix</RootNamespace>
+ <AssemblyName>DBCSFix</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ <DependentUpon>Settings.settings</DependentUpon>
+ </Compile>
+ <Compile Include="Settings.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="readme.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CommandLine\CommandLine.csproj">
+ <Project>{6CF7CA42-3706-4F6B-A2B4-10EF3F511888}</Project>
+ <Name>CommandLine</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- Copy the output assemblies to a common binaries directory (ProductionTools). -->
+ <Target Name="AfterBuild">
+ <CreateItem Include="$(OutputPath)\$(AssemblyName).*">
+ <Output TaskParameter="Include" ItemName="ProductionFiles" />
+ </CreateItem>
+ <Copy SourceFiles="@(ProductionFiles)" DestinationFolder="..\..\ProductionTools" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/tools/Sandcastle/Source/DBCSFix/GlobalSuppressions.cs b/tools/Sandcastle/Source/DBCSFix/GlobalSuppressions.cs
new file mode 100644
index 0000000..951acfd
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/GlobalSuppressions.cs
@@ -0,0 +1,16 @@
+// Copyright © Microsoft Corporation.
+// This source file is subject to the Microsoft Permissive License.
+// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
+// All other rights reserved.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
diff --git a/tools/Sandcastle/Source/DBCSFix/Program.cs b/tools/Sandcastle/Source/DBCSFix/Program.cs
new file mode 100644
index 0000000..515da50
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/Program.cs
@@ -0,0 +1,210 @@
+// Copyright © Microsoft Corporation.
+// This source file is subject to the Microsoft Permissive License.
+// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
+// All other rights reserved.
+
+using Microsoft.Ddue.Tools.CommandLine;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace DBCSFix
+{
+ internal class Program
+ {
+ public static void Main(string[] args)
+ {
+ ConsoleApplication.WriteBanner();
+
+ // get and validate args
+ OptionCollection programOptions = new OptionCollection();
+ programOptions.Add(new SwitchOption("?", "Show this help page."));
+ programOptions.Add(new StringOption("d", @"The directory containing CHM input files (e.g., HHP file). For example, 'C:\DocProject\Output\Chm'. Default is the current directory."));
+ programOptions.Add(new StringOption("l", @"The language code ID in decimal. For example, '1033'. Default is '1033' (for EN-US)."));
+ ParseArgumentsResult options = programOptions.ParseArguments(args);
+ if (options.Options["?"].IsPresent)
+ programOptions.WriteOptionSummary(Console.Error);
+
+ // determine the working dir
+ string chmDirectory;
+ if (options.Options["d"].IsPresent)
+ chmDirectory = options.Options["d"].Value.ToString();
+ else
+ chmDirectory = Environment.CurrentDirectory;
+
+ // determine the desired language
+ string lcid;
+ if (options.Options["l"].IsPresent)
+ lcid = options.Options["l"].Value.ToString();
+ else
+ lcid = "1033";
+
+ // ensure working dir exists
+ if (!Directory.Exists(chmDirectory))
+ {
+ Console.WriteLine("The specified directory '{0}' doesn't exist. Quitting.", chmDirectory);
+ return;
+ }
+
+ // convert unsupported high-order chars to ascii equivalents
+ substituteAsciiEquivalents(chmDirectory, lcid);
+
+ // no further work required for 1033
+ if (String.Equals(lcid, "1033"))
+ return;
+
+ // convert unsupported chars to named entities
+ substituteNamedEntities(chmDirectory);
+
+ // convert charset declarations from utf8 to proper ansi codepage value
+ substituteCodepages(chmDirectory, lcid);
+
+ // convert char encodings from utf8 to ansi
+ convertUtf8ToAnsi(chmDirectory, lcid);
+ }
+
+ private static void convertUtf8ToAnsi(string chmDirectory, string lcid)
+ {
+ Console.WriteLine("Converting character encodings from utf8 to ansi.");
+ Encoding ansi = Encoding.GetEncoding(encodingNameForLcid(lcid));
+
+ List < string > files = new List < string >();
+ files.AddRange(Directory.GetFiles(chmDirectory, "*.htm", SearchOption.AllDirectories));
+
+ foreach (string file in files)
+ {
+ using (StreamWriter sw = new StreamWriter(file + ".tmp", false, ansi))
+ {
+ using (StreamReader input = new StreamReader(file))
+ {
+ Encoding sourceEncoding = input.CurrentEncoding;
+ string line;
+ while ((line = input.ReadLine()) != null)
+ {
+ byte[] sourceBytes = sourceEncoding.GetBytes(line);
+ byte[] ansiBytes = Encoding.Convert(sourceEncoding, ansi, sourceBytes);
+ sw.WriteLine(ansi.GetString(ansiBytes));
+ }
+ }
+ }
+
+ File.Delete(file);
+ File.Move(file + ".tmp", file);
+ }
+ }
+
+ private static string encodingNameForLcid(string lcid)
+ {
+ string charset = System.Configuration.ConfigurationSettings.AppSettings[lcid];
+ if (String.IsNullOrEmpty(charset))
+ return "Windows-1252";
+ else
+ return charset;
+ }
+
+ private static void substituteAsciiEquivalents(string chmDirectory, string lcid)
+ {
+ Console.WriteLine("Converting unsupported high-order characters to 7-bit ASCII equivalents.");
+
+ /* substitution table:
+ * Char name utf8 (hex) ascii
+ * Non-breaking space \xC2\xA0 "&nbsp;" (for all languages except Japanese)
+ * Non-breaking hyphen \xE2\x80\x91 "-"
+ * En dash \xE2\x80\x93 "-"
+ * Left curly single quote \xE2\x80\x98 "'"
+ * Right curly single quote \xE2\x80\x99 "'"
+ * Left curly double quote \xE2\x80\x9C "\""
+ * Right curly double quote \xE2\x80\x9D "\""
+ * Horizontal ellipsis U+2026 "..."
+ */
+
+ Dictionary < Regex, string > substitutionPatterns = new Dictionary < Regex, string >();
+ substitutionPatterns.Add(new Regex(@"\u2018|\u2019", RegexOptions.Compiled), "'");
+ substitutionPatterns.Add(new Regex(@"\u201C|\u201D", RegexOptions.Compiled), "\"");
+ substitutionPatterns.Add(new Regex(@"\u2026", RegexOptions.Compiled), "...");
+ if (chmDirectory != "1041")
+ substitutionPatterns.Add(new Regex(@"\u00A0", RegexOptions.Compiled), "&nbsp;");
+ else
+ substitutionPatterns.Add(new Regex(@"\u00A0", RegexOptions.Compiled), " ");
+
+ string ansi = Encoding.GetEncoding(encodingNameForLcid(lcid)).HeaderName;
+ Console.WriteLine("EncodingName: " + ansi);
+ if (!string.Equals(ansi, "Windows-1252"))
+ {
+ substitutionPatterns.Add(new Regex(@"\u2011|\u2013", RegexOptions.Compiled), "-");
+ substituteInFiles(chmDirectory, "*.htm", substitutionPatterns);
+ }
+ else
+ {
+ // replace em-dashes with hyphens, if not windows-1252 (e.g., 1033)
+ substitutionPatterns.Add(new Regex(@"\u2011|\u2013|\u2014", RegexOptions.Compiled), "-");
+ }
+ }
+
+ private static void substituteCodepages(string chmDirectory, string lcid)
+ {
+ Console.WriteLine("Inserting charset declarations.");
+
+ Dictionary < Regex, string > substitutionPatterns = new Dictionary < Regex, string >();
+ substitutionPatterns.Add(new Regex(@"CHARSET=UTF-8", RegexOptions.Compiled | RegexOptions.IgnoreCase), "CHARSET=" + encodingNameForLcid(lcid));
+
+ substituteInFiles(chmDirectory, "*.htm", substitutionPatterns);
+ }
+
+ private static void substituteInFiles(string directory, string fileSpec, ICollection < KeyValuePair < Regex, string > > substitutionPatterns)
+ {
+ Debug.Assert(Directory.Exists(directory), "Specified directory doesn't exist.");
+ Debug.Assert(!String.IsNullOrEmpty(fileSpec), "FileSpec is empty");
+ Debug.Assert(substitutionPatterns.Count > 0, "No substitution patterns.");
+
+ string[] files = Directory.GetFiles(directory, fileSpec, SearchOption.AllDirectories);
+ foreach (string file in files)
+ {
+ using (StreamWriter output = new StreamWriter(file + ".tmp", true, Encoding.UTF8))
+ {
+ using (StreamReader input = new StreamReader(file))
+ {
+ string line;
+ while ((line = input.ReadLine()) != null)
+ {
+ foreach (KeyValuePair < Regex, string > pattern in substitutionPatterns)
+ {
+ line = pattern.Key.Replace(line, pattern.Value);
+ }
+ output.WriteLine(line);
+ }
+ }
+ }
+
+ File.Delete(file);
+ File.Move(file + ".tmp", file);
+ }
+ }
+
+ private static void substituteNamedEntities(string chmDirectory)
+ {
+ Console.WriteLine("Converting other unsupported high-order characters to named entities.");
+
+ /* substitution table:
+ * Char name utf8 (hex) named entity
+ * Copyright \xC2\xA0 &copy
+ * Registered trademark \xC2\xAE &reg
+ * Em dash \xE2\x80\x94 &mdash;
+ * Trademark \xE2\x84\xA2 &trade;
+ */
+
+ Dictionary < Regex, string > substitutionPatterns = new Dictionary < Regex, string >();
+ substitutionPatterns.Add(new Regex(@"\u00A9", RegexOptions.Compiled), "&copy;");
+ substitutionPatterns.Add(new Regex(@"\u00AE", RegexOptions.Compiled), "&reg;");
+ substitutionPatterns.Add(new Regex(@"\u2014", RegexOptions.Compiled), "&mdash;");
+ substitutionPatterns.Add(new Regex(@"\u2122", RegexOptions.Compiled), "&trade;");
+
+ substituteInFiles(chmDirectory, "*.htm", substitutionPatterns);
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/DBCSFix/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/DBCSFix/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ae06688
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+// Copyright © Microsoft Corporation.
+// This source file is subject to the Microsoft Permissive License.
+// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
+// All other rights reserved.
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DBCSFix")]
+[assembly: AssemblyDescription("Works around codepage limitations in the CHM compiler.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DBCSFix")]
+[assembly: AssemblyCopyright("Copyright © 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6b2709f4-d535-4a7a-bacf-f6564c42a653")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("2.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/DBCSFix/Properties/Settings.Designer.cs b/tools/Sandcastle/Source/DBCSFix/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..2a727ca
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace DBCSFix.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/DBCSFix/Properties/Settings.settings b/tools/Sandcastle/Source/DBCSFix/Properties/Settings.settings
new file mode 100644
index 0000000..8e615f2
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/Properties/Settings.settings
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles />
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/tools/Sandcastle/Source/DBCSFix/Settings.cs b/tools/Sandcastle/Source/DBCSFix/Settings.cs
new file mode 100644
index 0000000..f2ad7ea
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/Settings.cs
@@ -0,0 +1,34 @@
+// Copyright © Microsoft Corporation.
+// This source file is subject to the Microsoft Permissive License.
+// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
+// All other rights reserved.
+
+namespace DBCSFix.Properties
+{
+
+
+ // This class allows you to handle specific events on the settings class:
+ // The SettingChanging event is raised before a setting's value is changed.
+ // The PropertyChanged event is raised after a setting's value is changed.
+ // The SettingsLoaded event is raised after the setting values are loaded.
+ // The SettingsSaving event is raised before the setting values are saved.
+ internal sealed partial class Settings {
+
+ public Settings() {
+ // // To add event handlers for saving and changing settings, uncomment the lines below:
+ //
+ // this.SettingChanging += this.SettingChangingEventHandler;
+ //
+ // this.SettingsSaving += this.SettingsSavingEventHandler;
+ //
+ }
+
+ private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
+ // Add code to handle the SettingChangingEvent event here.
+ }
+
+ private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
+ // Add code to handle the SettingsSaving event here.
+ }
+ }
+}
diff --git a/tools/Sandcastle/Source/DBCSFix/app.config b/tools/Sandcastle/Source/DBCSFix/app.config
new file mode 100644
index 0000000..17fa07c
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/app.config
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <appSettings>
+ <add key="1028" value="big5"/>
+ <add key="3076" value="big5"/>
+ <add key="1029" value="Windows-1250"/>
+ <add key="1038" value="Windows-1250"/>
+ <add key="1045" value="Windows-1250"/>
+ <add key="1049" value="Windows-1251"/>
+ <add key="1055" value="Windows-1254"/>
+ <add key="1041" value="shift-jis"/>
+ <add key="1042" value="ks_c_5601-1987"/>
+ <add key="2052" value="gb2312"/>
+ </appSettings>
+</configuration> \ No newline at end of file
diff --git a/tools/Sandcastle/Source/DBCSFix/readme.txt b/tools/Sandcastle/Source/DBCSFix/readme.txt
new file mode 100644
index 0000000..dfe8694
--- /dev/null
+++ b/tools/Sandcastle/Source/DBCSFix/readme.txt
@@ -0,0 +1,42 @@
+dbcsFix.exe
+(C) Microsoft 2007
+
+FUNCTION:
+dbcsFix.exe attempts to work around limitations in the CHM compiler regarding character encodings and representations. Specifically:
+1. Replaces some characters with ASCII equivelents, as follows:
+ /* substitution table:
+ * Char name utf8 (hex) ascii
+ * Non-breaking space \xC2\xA0 "&nbsp;" (for all languages except Japanese)
+ * Non-breaking hyphen \xE2\x80\x91 "-"
+ * En dash \xE2\x80\x93 "-"
+ * Left curly single quote \xE2\x80\x98 "'"
+ * Right curly single quote \xE2\x80\x99 "'"
+ * Left curly double quote \xE2\x80\x9C "\""
+ * Right curly double quote \xE2\x80\x9D "\""
+ * Horizontal ellipsis U+2026 "..."
+ */
+After this step, no further work is done when LCID == 1033.
+
+2. Replaces some characters with named entitites, as follows:
+ /* substitution table:
+ * Char name utf8 (hex) named entity
+ * Copyright \xC2\xA0 &copy
+ * Registered trademark \xC2\xAE &reg
+ * Em dash \xE2\x80\x94 &mdash;
+ * Trademark \xE2\x84\xA2 &trade;
+ */
+
+3. Replaces the default "CHARSET=UTF-8" setting in the HTML generated by ChmBuilder with "CHARSET=" + the proper value for the specified LCID, as determined by the application's .config file
+
+4. Re-encodes all input HTML from their current encoding (UTF-8, as output by ChmBuilder) to the correct encoding for the specified LCID.
+
+USAGE:
+dbcsFix.exe [-d=Directory] [-l=LCID]
+-d is the directory containing CHM input files (e.g., HHP file). For example, 'C:\DocProject\Output\Chm'. Default is the current directory.
+-l is the language code ID in decimal. For example, '1033'. Default is '1033' (for EN-US).
+
+Usage is also available with -?
+
+After processing the inputs with dbcsFix.exe, the call to the CHM compiler must be made when the system locale is the same as the value set when calling this tool. This can be done either by changing your system settings via the control panel, or by using the 3rd party utility SbAppLocale (http://www.steelbytes.com/?mid=45). In the latter case, the call should be similar to:
+SbAppLocale.exe $(LCID) "%PROGRAMFILES%\HTML Help Workshop\hhc.exe" Path\Project.Hhp
+