Commits

Dmitri Nesteruk committed b61b7a6

stored entries now keep their conversion options

Comments (0)

Files changed (19)

 <Application x:Class="DmitriNesteruk.TypograFix.App"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-     Startup="ApplicationStartup" Exit="ApplicationExit" StartupUri="MainWindow.xaml">
+     Startup="ApplicationStartup" Exit="ApplicationExit">
   <Application.Resources>
   </Application.Resources>
 </Application>
 using System.Windows.Threading;
 using DmitriNesteruk.TypograFix.Common;
 using DmitriNesteruk.TypograFix.Properties;
+using Microsoft.Practices.Unity;
 using Microsoft.SqlServer.MessageBox;
 using ServiceStack.Text;
 using Application=System.Windows.Application;
     internal static string EntryText = string.Empty;
     internal static ConversionOptions ConversionOptions { get; set; }
     internal static Dictionary<string, ConversionOptions> OptionPresets { get; set; }
-    [Obsolete]
-    internal static StringCollection StoredEntries { get; set; }
     /// <summary>
     /// The entries that got saved. No, not 'Jesus saved', just saved.
     /// </summary>
-    internal static List<StoredEntry> StoredEntries2 { get; set; }
+    internal static StoredEntries StoredEntries2 { get; set; }
     internal static PrintOptions PrintOptions { get; set; }
+    private readonly IUnityContainer container;
+
+    public App()
+    {
+      container = new UnityContainer();
+    }
 
     private static void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
     {
 #endif
 
       ConversionOptions = new ConversionOptions();
-      StoredEntries = new StringCollection();
+      StoredEntries2 = new StoredEntries();
       OptionPresets = new Dictionary<string, ConversionOptions>();
 
       if (Settings.Default != null)
           if (co != null)
             ConversionOptions = co;
         }
-        if (Settings.Default["StoredEntries"] != null)
+
+        if (Settings.Default["StoredEntries2"] != null)
         {
-          var se = Settings.Default["StoredEntries"] as StringCollection;
-          if (se != null)
-            StoredEntries = se;
+          var se = Settings.Default["StoredEntries2"] as string;
+          if (!string.IsNullOrEmpty(se))
+          {
+            try
+            {
+              StoredEntries2 = (StoredEntries) JsonSerializer.DeserializeFromString(se, typeof (StoredEntries));
+            } 
+            catch (Exception ex)
+            {
+              // we need to know about this
+              throw new Exception("Could not deserialize options presets from string '{0}'".ƒ(se), ex);
+            }
+          }
         }
+
         if (Settings.Default["PrintOptions"] != null)
         {
           var po = Settings.Default["PrintOptions"] as PrintOptions;
           if (po != null)
             PrintOptions = po;
         }
+
         if (Settings.Default["OptionPresets"] != null)
         {
           var op = Settings.Default["OptionPresets"] as string;
             } 
             catch (Exception ex)
             {
-#if DEBUG
+              // we need to know about this
               throw new Exception("Could not deserialize options presets from string '{0}'".ƒ(op), ex);
-#endif
             }
           }
         }
       }
+
+      // we more or less insist on starting things this way:
+      var mainWindow = container.Resolve<MainWindow>();
+      mainWindow.ShowDialog();
     }
 
     /// <summary>
     /// </summary>
     public static void SaveSettings()
     {
-      Settings.Default["EntryText"] = EntryText;
-      Settings.Default["ConversionOptions"] = ConversionOptions;
-      Settings.Default["StoredEntries"] = StoredEntries;
-      Settings.Default["PrintOptions"] = PrintOptions;
-      
-      // OptionsPresets gets saved as a JSON string
-      Settings.Default["OptionPresets"] = JsonSerializer.SerializeToString(OptionPresets, typeof (Dictionary<string, ConversionOptions>));
+      try
+      {
+        Settings.Default["EntryText"] = EntryText;
+        Settings.Default["ConversionOptions"] = ConversionOptions;
+        Settings.Default["StoredEntries2"] = JsonSerializer.SerializeToString(StoredEntries2, typeof (StoredEntries));
+        Settings.Default["PrintOptions"] = PrintOptions;
 
-      Settings.Default.Save();
+        // OptionsPresets gets saved as a JSON string
+        Settings.Default["OptionPresets"] = JsonSerializer.SerializeToString(OptionPresets, typeof (Dictionary<string, ConversionOptions>));
+
+        Settings.Default.Save();
+      } 
+      catch (Exception ex)
+      {
+        var emb = new ExceptionMessageBox(ex);
+        emb.Text = "Tried to save settings but couldn't because, apparently...";
+        emb.Show(null);
+      }
     }
 
     static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)

Converters/BoolToInvisibilityConverter.cs

+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace DmitriNesteruk.TypograFix.Converters
+{
+  /// <summary>
+  /// Boolean to invisibility converter.
+  /// </summary>
+  [ValueConversion(typeof(bool), typeof(Visibility))]
+  public sealed class BoolToInvisibilityConverter : IValueConverter
+  {
+    public object Convert(object value, Type targetType,
+                          object parameter, CultureInfo culture)
+    {
+      return (bool)value ? Visibility.Collapsed : Visibility.Visible;
+    }
+
+    public object ConvertBack(object value, Type targetType,
+                              object parameter, CultureInfo culture)
+    {
+      return ((Visibility)value) != Visibility.Visible;
+    }
+  }
+}

Converters/BoolToVisibilityConverter.cs

+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace DmitriNesteruk.TypograFix.Converters
+{
+  /// <summary>
+  /// Boolean to visibility value converter.
+  /// </summary>
+  [ValueConversion(typeof(bool), typeof(Visibility))]
+  public sealed class BoolToVisibilityConverter : IValueConverter
+  {
+    #region IValueConverter Members
+
+    public object Convert(object value, Type targetType,
+                          object parameter, CultureInfo culture)
+    {
+      return (bool)value ? Visibility.Visible : Visibility.Collapsed;
+    }
+    public object ConvertBack(object value, Type targetType,
+                              object parameter, CultureInfo culture)
+    {
+      return ((Visibility) value) == Visibility.Visible;
+    }
+
+    #endregion
+  }
+}

Converters/ConversionStatusToBrushConverter.cs

+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+using DmitriNesteruk.TypograFix.Common;
+
+namespace DmitriNesteruk.TypograFix.Converters
+{
+  /// <summary>
+  /// ConversionStatusToBrushConverter.
+  /// </summary>
+  [ValueConversion(typeof(ConversionStatus), typeof(Brush))]
+  internal sealed class ConversionStatusToBrushConverter : IValueConverter
+  {
+    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+      switch ((ConversionStatus) value)
+      {
+        case ConversionStatus.Success:
+          return Brushes.Green;
+        case ConversionStatus.Malformed:
+          return Brushes.Yellow;
+        case ConversionStatus.Failure:
+          return Brushes.Red;
+      }
+      Debug.Assert(false, "Should not be here");
+      return Brushes.Gray;
+    }
+
+    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+      return ConversionStatus.Success;
+    }
+  }
+}

Converters/EnumToFriendlyNameConverter.cs

+using System;
+using System.ComponentModel;
+using System.Globalization;
+using System.Reflection;
+using System.Windows.Data;
+
+namespace DmitriNesteruk.TypograFix.Converters
+{
+  /// <summary>
+  /// This class simply takes an enum and uses some reflection to obtain
+  /// the friendly name for the enum. Where the friendlier name is
+  /// obtained using the LocalizableDescriptionAttribute, which holds the localized
+  /// value read from the resource file for the enum
+  /// </summary>
+  [ValueConversion(typeof (object), typeof (String))]
+  public class EnumToFriendlyNameConverter : IValueConverter
+  {
+    #region IValueConverter implementation
+
+    /// <summary>
+    /// Convert value for binding from source object
+    /// </summary>
+    public object Convert(object value, Type targetType,
+      object parameter, CultureInfo culture)
+    {
+      // To get around the stupid WPF designer bug
+      if (value != null)
+      {
+        FieldInfo fi = value.GetType().GetField(value.ToString());
+
+        // To get around the stupid WPF designer bug
+        if (fi != null)
+        {
+          var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
+          return ((attributes.Length > 0) &&
+                  (!String.IsNullOrEmpty(attributes[0].Description)))
+                   ? attributes[0].Description
+                   : value.ToString();
+        }
+      }
+
+      return string.Empty;
+    }
+
+    /// <summary>
+    /// ConvertBack value from binding back to source object
+    /// </summary>
+    public object ConvertBack(object value, Type targetType,
+      object parameter, CultureInfo culture)
+    {
+      throw new Exception("Cant convert back");
+    }
+
+    #endregion
+  }
+}
     xmlns:dv="http://schemas.denisvuyka.wordpress.com/wpfpropertygrid"
     xmlns:TypograFix="clr-namespace:DmitriNesteruk.TypograFix"
     xmlns:Pages="clr-namespace:DmitriNesteruk.TypograFix.Pages"
-    Title="TypograFix" Height="400" Width="800" Loaded="OnLoad" Name="myWindow" 
+        xmlns:Converters="clr-namespace:DmitriNesteruk.TypograFix.Converters" Title="TypograFix" Height="400" Width="800" Loaded="OnLoad" Name="myWindow" 
     TypograFix:WindowSettings.Save="True"
     FontFamily="Segoe UI">
   <!-- popups are presented towards the end of the document, but inside the grid -->
       <TabItem Header="Linear">
         <Grid Background="Black">
           <Grid.Resources>
-            <TypograFix:BoolToVisibilityConverter x:Key="btvc"/>
-            <TypograFix:ConversionStatusToBrushConverter x:Key="cstbc"/>
+            <Converters:BoolToVisibilityConverter x:Key="btvc"/>
+            <Converters:ConversionStatusToBrushConverter x:Key="cstbc"/>
           </Grid.Resources>
           <Grid.RowDefinitions>
             <RowDefinition Height="Auto" MinHeight="38"/>

MainWindow.xaml.cs

 
     private void AddSlotButton(int entryIndex)
     {
-      string entry = App.StoredEntries[entryIndex];
-
+      var entry = App.StoredEntries2[entryIndex];
       var btn = new Button
-                  {
-                    ToolTip = entry.Substring(0, Math.Min(100, entry.Length)) + "...",
-                    Content = (entryIndex + 1).ToString(),
-                    Margin = new Thickness(0, 3, 3, 3)
-                  };
+        {
+          ToolTip = entry.Text.Substring(0, Math.Min(100, entry.Text.Length)) + "...",
+          Content = (entryIndex + 1).ToString(),
+          Margin = new Thickness(0, 3, 3, 3)
+        };
       btn.MinWidth = btn.MinHeight = 23;
       btn.Tag = entryIndex;
-      btn.Click += (s, a) => { tbIn.Text = App.StoredEntries[(int) ((Button) s).Tag]; };
+      btn.Click += (s, a) =>
+        {
+          var theEntry = App.StoredEntries2[(int) ((Button) s).Tag];
+          tbIn.Text = theEntry.Text;
+          UpdateOptions(theEntry.ConversionOptions);
+        };
       btn.MouseDoubleClick += OnRemoveSaveSlot;
       btn.MouseRightButtonDown += OnSaveIntoSaveSlot;
       SavePanel.Children.Add(btn);
         string msg = "An exception has occurred";
         try
         {
-          results.Element1 = gp.Generate(text, App.ConversionOptions, 5000, true, out cs, out msg);
+          results.First = gp.Generate(text, App.ConversionOptions, 5000, true, out cs, out msg);
         }
         catch (Exception ex)
         {
             sb.AppendLine(e.Message);
           sb.AppendLine(ex.StackTrace);
           sb.AppendLine("</pre>");
-          results.Element1 = sb.ToString();
+          results.First = sb.ToString();
         }
-        results.Element2 = msg;
-        results.Element3 = cs;
+        results.Second = msg;
+        results.Third = cs;
         return results;
       };
 
       var gen = iocContainer.Resolve<Generator>();
       Triple<string, string, ConversionStatus> result = process(gen, inputText);
-      SetGeneratedData(result.Element3, result.Element2, result.Element1);
+      SetGeneratedData(result.Third, result.Second, result.First);
     }
 
     private void OneTimeViewerInitialization()
 
     private void OnAddSaveSlot(object sender, RoutedEventArgs e)
     {
-      App.StoredEntries.Add(tbIn.Text);
-      AddSlotButton(App.StoredEntries.Count - 1);
+      App.StoredEntries2.Add(new StoredEntry(tbIn.Text, App.ConversionOptions));
+      AddSlotButton(App.StoredEntries2.Count - 1);
     }
 
     private void OnCharMap(object sender, RoutedEventArgs e)
       }
     }
 
+    /// <summary>
+    /// Rewires eventing from App.ConversionOptions
+    /// </summary>
+    private void UpdateOptions(ConversionOptions options)
+    {
+      var npc = (INotifyPropertyChanged) App.ConversionOptions;
+      npc.PropertyChanged -= OnConversionOptionsChanged;
+      App.ConversionOptions = options;
+
+      npc = (INotifyPropertyChanged)App.ConversionOptions;
+      npc.PropertyChanged += OnConversionOptionsChanged;
+      propGrid.SelectedObject = App.ConversionOptions;
+    }
+
     private void OnInputTextChanged(object sender, TextChangedEventArgs e)
     {
       DoUpdate();
                                            "TypograFix", MessageBoxButton.YesNo, MessageBoxImage.Question);
       if (r == MessageBoxResult.Yes)
       {
-        App.StoredEntries.RemoveAt(n);
+        App.StoredEntries2.RemoveAt(n);
 
         foreach (Button btn in SavePanel.Children.OfType<Button>().Where(b => b.Tag != null && (int) b.Tag > n))
         {
                                            "TypograFix", MessageBoxButton.OKCancel, MessageBoxImage.Question);
       if (r == MessageBoxResult.OK)
       {
-        App.StoredEntries[n] = tbIn.Text;
+        App.StoredEntries2[n] = new StoredEntry(tbIn.Text, App.ConversionOptions);
       }
     }
 
 
     private void UpdateSlots()
     {
-      for (int i = 0; i < App.StoredEntries.Count; ++i)
+      for (int i = 0; i < App.StoredEntries2.Count; ++i)
         AddSlotButton(i);
     }
 

Pages/CodeAnnotationEditor.xaml

     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dv="http://schemas.denisvuyka.wordpress.com/wpfpropertygrid" x:Name="myEditor"
              xmlns:local="clr-namespace:DmitriNesteruk.TypograFix"
              xmlns:common="clr-namespace:DmitriNesteruk.TypograFix.Common;assembly=TypograFix.Common"
-             UseLayoutRounding="True">
+             xmlns:Converters="clr-namespace:DmitriNesteruk.TypograFix.Converters" UseLayoutRounding="True">
   <Grid DataContext="{Binding ElementName=myEditor, Path=.}">
     <Grid.Resources>
-      <local:EnumToFriendlyNameConverter x:Key="eic"/>
+      <Converters:EnumToFriendlyNameConverter x:Key="eic"/>
     </Grid.Resources>
     <Grid.RowDefinitions>
       <RowDefinition Height="Auto"/>

Properties/Settings.Designer.cs

 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:4.0.30319.269
+//     Runtime Version:4.0.30319.17929
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
     
     
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
     internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
         
         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
         
         [global::System.Configuration.UserScopedSettingAttribute()]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-        public global::System.Collections.Specialized.StringCollection StoredEntries {
+        [global::System.Configuration.DefaultSettingValueAttribute("")]
+        public string StoredEntries2 {
             get {
-                return ((global::System.Collections.Specialized.StringCollection)(this["StoredEntries"]));
-            }
-            set {
-                this["StoredEntries"] = value;
-            }
-        }
-        
-        [global::System.Configuration.UserScopedSettingAttribute()]
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-        public global::DmitriNesteruk.TypograFix.StoredEntries StoredEntries2 {
-            get {
-                return ((global::DmitriNesteruk.TypograFix.StoredEntries)(this["StoredEntries2"]));
+                return ((string)(this["StoredEntries2"]));
             }
             set {
                 this["StoredEntries2"] = value;
                 this["OptionPresets"] = value;
             }
         }
-        
-        [global::System.Configuration.UserScopedSettingAttribute()]
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-        [global::System.Configuration.DefaultSettingValueAttribute("")]
-        public string StoredEntries21 {
-            get {
-                return ((string)(this["StoredEntries21"]));
-            }
-            set {
-                this["StoredEntries21"] = value;
-            }
-        }
     }
 }

Properties/Settings.settings

     <Setting Name="ConversionOptions" Type="DmitriNesteruk.TypograFix.Common.ConversionOptions" Scope="User">
       <Value Profile="(Default)" />
     </Setting>
-    <Setting Name="StoredEntries" Type="System.Collections.Specialized.StringCollection" Scope="User">
-      <Value Profile="(Default)" />
-    </Setting>
-    <Setting Name="StoredEntries2" Type="DmitriNesteruk.TypograFix.StoredEntries" Scope="User">
+    <Setting Name="StoredEntries2" Type="System.String" Scope="User">
       <Value Profile="(Default)" />
     </Setting>
     <Setting Name="PrintOptions" Type="DmitriNesteruk.TypograFix.Common.PrintOptions" Scope="User">
     <Setting Name="OptionPresets" Type="System.String" Scope="User">
       <Value Profile="(Default)" />
     </Setting>
-    <Setting Name="StoredEntries2" Type="System.String" Scope="User">
-      <Value Profile="(Default)" />
-    </Setting>
   </Settings>
 </SettingsFile>

Tests/TypograFix.Tests.csproj

   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
     <DebugSymbols>true</DebugSymbols>
-    <OutputPath>bin\x64\Debug\</OutputPath>
+    <OutputPath>..\bin\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <DebugType>full</DebugType>
     <PlatformTarget>x64</PlatformTarget>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
-    <OutputPath>bin\x64\Release\</OutputPath>
+    <OutputPath>..\bin\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <Optimize>true</Optimize>
     <DebugType>pdbonly</DebugType>

TypograFix.Common/ConversionOptions.cs

       CodeBlockLabel = "({0})";
     }
 
+    // todo: temporary, replace by prop assignment
+    public void CopyFrom(ConversionOptions other)
+    {
+      codeblockannotations = other.codeblockannotations;
+      codeblocknumbering = other.codeblocknumbering;
+      codeblocklabel = other.codeblocklabel;
+      codeblockfontfamily = other.codeblockfontfamily;
+      codeblockmajorfontsize = other.codeblockmajorfontsize;
+      codeblockminorfontsize = other.codeblockminorfontsize;
+      f1keybinding = other.f1keybinding;
+      f2keybinding = other.f2keybinding;
+      f3keybinding = other.f3keybinding;
+      f4keybinding = other.f4keybinding;
+      f5keybinding = other.f5keybinding;
+      f6keybinding = other.f6keybinding;
+      f7keybinding = other.f7keybinding;
+      f8keybinding = other.f8keybinding;
+      f9keybinding = other.f9keybinding;
+      f10keybinding = other.f10keybinding;
+      f11keybinding = other.f11keybinding;
+      f12keybinding = other.f12keybinding;
+      externalimagebaseline = other.externalimagebaseline;
+      tocaftertoken = other.tocaftertoken;
+      freeformlinespacing = other.freeformlinespacing;
+      freeformbaseline = other.freeformbaseline;
+      freeformprefix = other.freeformprefix;
+      freeformfontfamily = other.freeformfontfamily;
+      freeformfontsize = other.freeformfontsize;
+      freeformmaxwidth = other.freeformmaxwidth;
+      freeformmaxheight = other.freeformmaxheight;
+      freeformsmallcaps = other.freeformsmallcaps;
+      freeformitalic = other.freeformitalic;
+      freeformcontextualligatures = other.freeformcontextualligatures;
+      freeformstandardligatures = other.freeformstandardligatures;
+      freeformswash = other.freeformswash;
+      freeformstylisticset = other.freeformstylisticset;
+      useimagecomments = other.useimagecomments;
+      imagecommentsprefix = other.imagecommentsprefix;
+      imagecommentfont = other.imagecommentfont;
+      imagecommentfontsize = other.imagecommentfontsize;
+      imagecommentsbackgroundcolor = other.imagecommentsbackgroundcolor;
+      imagecommentsforegroundcolor = other.imagecommentsforegroundcolor;
+      imagecommentsmargin = other.imagecommentsmargin;
+      imagecommentspadding = other.imagecommentspadding;
+      imagecommentsrendering = other.imagecommentsrendering;
+      imagesubstitutionoption = other.imagesubstitutionoption;
+      imageheadingprefix = other.imageheadingprefix;
+      imageheadingfontfamily = other.imageheadingfontfamily;
+      imageheadingfontsizeprimary = other.imageheadingfontsizeprimary;
+      imageheadingfontsizesecondary = other.imageheadingfontsizesecondary;
+      imageheadingfontsizetertiary = other.imageheadingfontsizetertiary;
+      imageheadingforegroundcolor = other.imageheadingforegroundcolor;
+      imageheadingitalic = other.imageheadingitalic;
+      blanklinebeforeheadings = other.blanklinebeforeheadings;
+      codetrim = other.codetrim;
+      italicizecomments = other.italicizecomments;
+      fontsize = other.fontsize;
+      syntaxhighlightingoptions = other.syntaxhighlightingoptions;
+      prettyampersand = other.prettyampersand;
+      alternate = other.alternate;
+      nobreaksaftercomments = other.nobreaksaftercomments;
+      keywordcolor = other.keywordcolor;
+      rasterizecode = other.rasterizecode;
+      preproccolor = other.preproccolor;
+      stringcolor = other.stringcolor;
+      commentcolor = other.commentcolor;
+      linenumbers = other.linenumbers;
+      backreferencetext = other.backreferencetext;
+      referencelocation = other.referencelocation;
+      backreferencelocation = other.backreferencelocation;
+      convertapprox = other.convertapprox;
+      doublecurlyoptions = other.doublecurlyoptions;
+      convertpm = other.convertpm;
+      wikiheadings = other.wikiheadings;
+      blanklineafterclosingparagraph = other.blanklineafterclosingparagraph;
+      doubleatincode = other.doubleatincode;
+      convertsuper = other.convertsuper;
+      convertfiandfl = other.convertfiandfl;
+      escapelessgreaterincode = other.escapelessgreaterincode;
+      obfuscateat = other.obfuscateat;
+      backquotetocode = other.backquotetocode;
+      generatetoc = other.generatetoc;
+      toclabel = other.toclabel;
+      reflabel = other.reflabel;
+      autoparagraphs = other.autoparagraphs;
+      forcepinsideli = other.forcepinsideli;
+      diactricsoptions = other.diactricsoptions;
+      angleddoublequotes = other.angleddoublequotes;
+      verticalellipsis = other.verticalellipsis;
+      orderedliststyletype = other.orderedliststyletype;
+      preindent = other.preindent;
+      unorderedliststyletype = other.unorderedliststyletype;
+      referencestyle = other.referencestyle;
+      spacespertab = other.spacespertab;
+      qtableoptions = other.qtableoptions;
+      imageUploadApiKey = other.imageUploadApiKey;
+      autoTwitter = other.autoTwitter;
+      forceUtf8 = other.forceUtf8;
+      rasterizationFont = other.rasterizationFont;
+      emphasisFontOverride = other.emphasisFontOverride;
+      postprocessingOptions = other.postprocessingOptions;
+      obfuscateText = other.obfuscateText;
+      emitAmpersandClass = other.emitAmpersandClass;
+      tocRightAlign = other.tocRightAlign;
+      headingNumberingOptions = other.headingNumberingOptions;
+      colorHeadings = other.colorHeadings;
+    }
+
     [Category("Headings")]
     [DisplayName("Color headings")]
     [Description("When set, takes rasterization FG color and applies it to headings. YMMV.")]

TypograFix.Common/StoredEntry.cs

-namespace DmitriNesteruk.TypograFix
+using System;
+using System.Runtime.Serialization;
+
+namespace DmitriNesteruk.TypograFix
 {
   using System.Collections.ObjectModel;
   using Common;
 
+  [Serializable]
   public class StoredEntries : Collection<StoredEntry>
   {
   }
 
+  [Serializable]
   public class StoredEntry
   {
     public StoredEntry(string text, ConversionOptions conversionOptions)

TypograFix.Common/Triple.cs

   /// <summary>
   /// A tuple of size 3.
   /// </summary>
-  /// <typeparam name="T1">The type of the 1st element of the tuple.</typeparam>
-  /// <typeparam name="T2">The type of the 2nd element of the tuple.</typeparam>
-  /// <typeparam name="T3">The type of the 3rd element of the tuple.</typeparam>
+  /// <typeparam name="T">The type of the 1st element of the tuple.</typeparam>
+  /// <typeparam name="U">The type of the 2nd element of the tuple.</typeparam>
+  /// <typeparam name="V">The type of the 3rd element of the tuple.</typeparam>
   /// <remarks>Bring on .Net 4 so I don't have to bake my own tuples.</remarks>
-  public class Triple<T1, T2, T3> : IEquatable<Triple<T1, T2, T3>>
+  public class Triple<T, U, V> : IEquatable<Triple<T, U, V>>
   {
-    #region Fields
-    private T1 element1;
-    private T2 element2;
-    private T3 element3;
-    #endregion
-    #region Properties
     /// <summary>
     /// Gets or sets the 1st element.
     /// </summary>
     /// <value>The 1st element.</value>
-    public T1 Element1
-    {
-      get { return element1; }
-      set { element1 = value; }
-    }
+    public T First { get; set; }
+
     /// <summary>
     /// Gets or sets the 2nd element.
     /// </summary>
     /// <value>The 2nd element.</value>
-    public T2 Element2
-    {
-      get { return element2; }
-      set { element2 = value; }
-    }
+    public U Second { get; set; }
+
     /// <summary>
     /// Gets or sets the 3rd element.
     /// </summary>
     /// <value>The 3rd element.</value>
-    public T3 Element3
-    {
-      get { return element3; }
-      set { element3 = value; }
-    }
-    #endregion
-    #region Constructors
+    public V Third { get; set; }
+
     /// <summary>
     /// Initializes a new instance of the <see cref="Triple&lt;T1, T2, T3&gt;"/> class.
     /// </summary>
     /// <summary>
     /// Initializes a new instance of the <see cref="Triple&lt;T1, T2, T3&gt;"/> class.
     /// </summary>
-    /// <param name="element1">The 1st element.</param>
-    /// <param name="element2">The 2nd element.</param>
-    /// <param name="element3">The 3rd element.</param>
-    public Triple(T1 element1, T2 element2, T3 element3)
+    /// <param name="first">The 1st element.</param>
+    /// <param name="second">The 2nd element.</param>
+    /// <param name="third">The 3rd element.</param>
+    public Triple(T first, U second, V third)
     {
-      this.element1 = element1;
-      this.element2 = element2;
-      this.element3 = element3;
+      this.First = first;
+      this.Second = second;
+      this.Third = third;
     }
-    #endregion
-    #region Methods
+
     /// <summary>
     /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
     /// </summary>
     /// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
     public override bool Equals(object obj)
     {
-      Triple<T1, T2, T3> other = obj as Triple<T1, T2, T3>;
+      Triple<T, U, V> other = obj as Triple<T, U, V>;
       if (other != null)
         return Equals(other);
       return false;
     /// <returns>
     /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
     /// </returns>
-    public bool Equals(Triple<T1, T2, T3> other)
+    public bool Equals(Triple<T, U, V> other)
     {
       return
-        Element1.Equals(other.Element1) &&
-        Element2.Equals(other.Element2) &&
-        Element3.Equals(other.Element3);
+        First.Equals(other.First) &&
+        Second.Equals(other.Second) &&
+        Third.Equals(other.Third);
     }
     /// <summary>
     /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
     public override string ToString()
     {
       StringBuilder sb = new StringBuilder();
-      sb.Append("Element1 = " + Element1 + ";");
-      sb.Append("Element2 = " + Element2 + ";");
-      sb.Append("Element3 = " + Element3);
+      sb.Append("First = " + First + ";");
+      sb.Append("Second = " + Second + ";");
+      sb.Append("Third = " + Third);
       return sb.ToString();
     }
-    #endregion
   }
 
 }

TypograFix.csproj

       <SubType>Code</SubType>
     </Compile>
     <Compile Include="BrowserSilencer.cs" />
-    <Compile Include="EnumToFriendlyNameConverter.cs" />
+    <Compile Include="Converters\BoolToInvisibilityConverter.cs" />
+    <Compile Include="Converters\BoolToVisibilityConverter.cs" />
+    <Compile Include="Converters\ConversionStatusToBrushConverter.cs" />
+    <Compile Include="Converters\EnumToFriendlyNameConverter.cs" />
     <Compile Include="EnumValuesExtension.cs" />
     <Compile Include="Pages\CodeAnnotationEditor.xaml.cs">
       <DependentUpon>CodeAnnotationEditor.xaml</DependentUpon>
     </Compile>
     <Compile Include="Pages\RenderMode.cs" />
     <Compile Include="Properties\AssemblyGlobalInfo.cs" />
-    <Compile Include="BoolToVisibilityConverter.cs" />
-    <Compile Include="ConversionStatusToBrushConverter.cs" />
     <Compile Include="GlobalSuppressions.cs" />
     <Compile Include="Properties\AssemblyInfo.cs">
       <SubType>Code</SubType>

TypograFixImpl/Generator.cs

 namespace DmitriNesteruk.TypograFixImpl
 {
+  using CodeFormatting;
+  using Generators;
+  using Microsoft.Practices.Unity;
+  using Obfuscation;
   using System;
   using System.Collections.Generic;
   using System.Diagnostics;
   using System.Drawing.Imaging;
   using System.IO;
   using System.Linq;
+  using System.Net;
   using System.Runtime.CompilerServices;
   using System.Text;
   using System.Text.RegularExpressions;
   using System.Windows.Documents;
   using System.Xml.Linq;
-  using CodeFormatting;
+  using TypograFix;
   using TypograFix.Common;
-  using Microsoft.Practices.Unity;
-  using System.Net;
-  using TypograFix;
-  using Generators;
-  using DmitriNesteruk.TypograFixImpl.Obfuscation;
 
   /// <summary>
   /// Beautifies HTML, adding all sorts of typographic embellishments.
 
                 languageMarker = ' ';
                 i = j + 2;
-                continue;
               }
               break;
             }
       string filename = Path.Combine(Path.GetTempPath(), options.FreeformPrefix + index + ".png");
 
       // if there is already a freeform image at this index
-      var found = freeformImages.Where(fi => fi.Element3 == index);
+      var found = freeformImages.Where(fi => fi.Third == index);
       if (found.Any())
       {
         // if it has identical params and it exists, do not regenerate it
         var fi = found.First();
-        if (fi.Element1.Equals(options) && fi.Element2.Equals(markup) && File.Exists(filename))
+        if (fi.First.Equals(options) && fi.Second.Equals(markup) && File.Exists(filename))
           return filename;
         // make sure the old image is removed
         freeformImages.Remove(fi);

Typografix.Bitmap/Typografix.Bitmap.cpp

   {
     // iteratively apply typography settings to range
     int passedChars = 0;
-    for (vme::const_iterator it = elements.begin(); it != elements.end(); it++)
+    for (auto it = elements.begin(); it != elements.end(); it++)
     {
       IDWriteTypography* t;
       pDWriteFactory->CreateTypography(&t);
 adapted to another application (e.g., BlogEngine.net). This is a demonstration
 of some of TypograFix's capabilities.&lt;/p&gt;</value>
    </setting>
-   <setting name="OptionPresets" serializeAs="String">
+   <setting name="StoredEntries2" serializeAs="String">
     <value />
    </setting>
-   <setting name="StoredEntries2" serializeAs="String">
+   <setting name="OptionPresets" serializeAs="String">
     <value />
    </setting>
   </DmitriNesteruk.TypograFix.Properties.Settings>