+When seeing the article
+Line
+Counter - Writing a Visual Studio 2005 Add-In
+[^],
+I wanted to show you how to write that AddIn for SharpDevelop.
+In this article I will show you how to create an AddIn, but I will not discuss
+the concepts of the SharpDevelop's AddIn architecture here - you can read more
+about that in my article
+Building
+Applications with the SharpDevelop Core
+[^].
+The line counter code is taken from the VS 2005 AddIn written by Jon Rista; the
+counting algorithm itself is from Oz Solomon.
+
+
+ Creating a new AddIn
+
+Our AddIn will be a menu entry in the "Tools" menu that opens a document window
+displaying the line counter UI. SharpDevelop already comes with a project
+template for an AddIn extending the "Tools" menu: "Tools menu entry"
+
+
+We create a SharpDevelop Macro with the name "LineCounter". The "SharpDevelop
+AddIn" template could also be used, but it starts with an AddIn defining a pad
+(a docked tool window like "Projects", "Properties"); the "Tool menu entry"
+AddIn starts with a menu command.
+Now let's look at what SharpDevelop has generated for us:
+We have a project with a few files:
+
+First look at the .addin file:
+The template already defines a menu item in the tools menu, we'll just modify
+the label. And we'll add a new section to the .addin file: the <Manifest>
+section. Our AddIn needs a unique identity - use something like a namespace
+name. Because we don't want lots of AddIns with the identity "AddIn1" around,
+the template does not contain the manifest section by default. The identity is
+not strictly required, but it allows us to use SharpDevelop's AddIn manager for
+our AddIn - and it is also required when other AddIns want to reference your
+AddIn. Because the API between SharpDevelop 2.0.x.y and SharpDevelop 2.1.a.b
+will change a bit, we use the dependency to ensure that our AddIn can only be
+installed into SharpDevelop 2.0.*.*.
+Since our LineCounter will only work when a solution is opened, we put the menu
+item inside a <Condition name="SolutionOpen" action="disable">
+Here is how the content of LineCounter.addin should look like after these steps:
+
<AddIn name = "LineCounter"
+ author = "Daniel Grunwald"
+ url = "http://www.codeproject.com/useritems/LineCounterSharpDevelopAddIn.asp"
+ description = "Advanced line counter AddIn">
+
+ <Manifest>
+ <Identity>Grunwald.LineCounter</Identity>
+ <Dependency addin="SharpDevelop" version="2.0"/>
+ </Manifest>
+
+ <Runtime>
+ <Import assembly = "LineCounter.dll"/>
+ </Runtime>
+
+ <Path name = "/Workspace/Tools">
+ <!-- disable our menu item if condition "SolutionOpen" is not met -->
+ <Condition name="SolutionOpen" action = "disable">
+ <MenuItem id = "LineCounterCommand1"
+ label = "Show Line Counter"
+ class = "Grunwald.LineCounter.ToolCommand1"/>
+ </Condition>
+ </Path>
+</AddIn>
+
Our menu item uses the "class" attribute. When the menu item is
+clicked, SharpDevelop will create an instance of this class and call its Run()
+method. This class is defined the file Command.cs. The example code from the
+template accesses the currently opened text editor and reverses the letters in
+the currently selected text. We are not interested in accessing the text editor,
+so we can delete the content of the Run() method and start writing our own.
+
+ Testing
+
+However, first we want to get our AddIn running. For testing, we'll display a
+MessageBox inside Run(). If you now try to compile the AddIn, you'll get errors
+about missing references. This is because the template is missing the assembly
+references to the SharpDevelop libraries - these have to hard-coded paths in
+most cases, so you should add them manually. Add references to
+ICSharpCode.Core.dll and ICSharpCode.SharpDevelop.dll from the bin directory of
+your SharpDevelop installation. ICSharpCode.Core contains the AddIn system, we
+need the base class of our menu command from it. ICSharpCode.SharpDevelop is the
+largest part of SharpDevelop, we'll use the project system from it.
+Make sure you set "Local copy" for the references to
+False.
+
+
+You should now be able to successfully compile the project. If you look into the
+bin/Debug directory, you will see a copy of LineCounter.addin, the compiled
+LineCounter.dll and the debug symbols.
+If you want to test your AddIn, you need to register it with SharpDevelop. The
+best way for testing is to copy these files to the AddIns directory of your
+SharpDevelop installation. Restart SharpDevelop to let it load the AddIn. You
+should see the "Line Counter" command in the Tools menu, disabled until you open
+a solution. If you click the menu item, the message box should show up.
+If you want to update your AddIn, you'll need to shutdown SharpDevelop, copy the
+files and restart it. If you do this a few times, you'll probably want to use a
+separate installation of SharpDevelop to develop your AddIn, so you can leave
+your development environment opened. Alternatively, you could use
+Visual Studio to write your AddIn...
+
+ Creating the line counter
+
+Now to the real work: Implementing the line counter. We want to display the line
+counter user interface as a document, like the start page. Document views in
+SharpDevelop are called ViewContents.
+There are two types of view contents: primary and secondary. A primary view
+content is capable of displaying something on its own; a secondary view content
+extends another view content by displaying multiple tabs in the document -
+SharpDevelop's Windows.Forms designer is a secondary view content. We want to
+display a simple document view, so we'll use a normal (primary) view
+content.
+
+Showing such a view content is easy:
+
public override void Run()
+{
+ WorkbenchSingleton.Workbench.ShowView(new LineCounterViewContent());
+}
+
+Now create the new class named LineCounterViewContent. Let it derive from
+ICSharpCode.SharpDevelop.Gui.AbstractViewContent to get default implementations
+for most of the IViewContent members.
+We will need to implement the abstract property Control - here we have to return
+the control to display.
+
+public class LineCounterViewContent : AbstractViewContent
+{
+ LineCounterBrowser browser = new LineCounterBrowser();
+ public override Control Control {
+ get { return browser; }
+ }
+ public LineCounterViewContent() {
+ this.TitleName = "Line Counter";
+ }
+}
+
+This control is a UserControl copied from the
+Visual
+Studio Line Counter article
+[^] —
+copy LineCounterBrowser.* into the "Src" directory and use "Add existing file"
+to add LineCounterBrowser.cs to the project. SharpDevelop should add
+LineCounterBrowser.Designer.cs and LineCounterBrowser.resx automatically.
+Now we still have to change the parts where the line counter references Visual
+Studio's EnvDTE class and replace them with the appropriate calls to the
+SharpDevelop API.
+
+ Accessing the project in SharpDevelop
+
+First fix the using-Statements: remove those importing Visual Studio namespaces.
+Instead we will use:
+
using ICSharpCode.SharpDevelop.Project;
+Then remove the variable and property referencing the EnvDTE
+object.
+Now move on to the methods. The first method requiring a rewrite is
+"ScanSolution". We can simply get the solution instance from a static class:
+ProjectService.
+
Solution solution = ProjectService.OpenSolution;
+ if (solution != null) // OpenSolution is null when no solution is opened
+ {
+ FileInfo fiSolution = new FileInfo(solution.FileName);
+
+SharpDevelop doesn't need "plural" classes like "Projects", but
+uses the standard .NET collection classes. Unlike Visual Studio,
+solution.Projects returns all projects; including those in solution folders.
+It's implemented as iterator (with yield return), that's why you don't have
+something simple as solution.Projects.Count. As I cannot really imagine
+solutions with thousands of projects, we can just copy the values returned by
+the iterator into a list to have a normal collection to work with.
+
+As you might guess, IProject is the interface all projects
+implement. The actual object type depends on the project type - every language
+binding comes with its own project class (but SharpDevelop contains the classes
+AbstractProject and MSBuildProject they can inherit most functionality from).
+The loop body can be simplified quite a bit: SharpDevelop will display its usual
+error handling dialog box for unhandled exceptions, so we don't need to use
+try-catch to redirect them to the debug view (where nobody really reads
+them...). The language ID is a straightforward property of the IProject
+interface, no need to query the CodeModel.
+
foreach (IProject fiProject in projects) {
+ tsprgTotal.PerformStep();
+ string projName, lang;
+ if (fiProject.FileName.IndexOf("://") != -1)
+ {
+ projName = fiProject.FileName; // this is a web project
+ lang = "{00000001-0000-0000-0000-000000000000}";
+ } else {
+ projName = fiProject.Name;
+ lang = fiProject.TypeGuid;
+ }
+
+ int iconIndex;
+ m_projIconMappings.TryGetValue(lang, out iconIndex); // default icon 0
+ summary = new LineCountSummary(projName, iconIndex);
+ m_summaryList.Add(summary);
+
+ tsprgTask.Maximum = 0;
+ tsprgTotal.Value = 0;
+ ScanProjectItems(fiProject.Items, summary);
+ }
+
+ScanProjectItems is the next method we'll look at. ProjectItems becomes
+List<ProjectItem>. You'll also need to change the summary since
+SharpDevelop stores all project items in this collection - no need to use
+recursion to get Designer.cs files. In the SharpDevelop model, every project
+item is exactly one file. This simplifies the method greatly:
+
private void ScanProjectItems(List<ProjectItem> projectItems, LineCountSummary summary)
+{
+ tsprgTask.Maximum += projectItems.Count;
+ foreach (ProjectItem projectItem in projectItems)
+ {
+ tsprgTask.PerformStep();
+ if (!(projectItem is FileProjectItem)) {
+ // Skip references and other special MSBuild things
+ continue;
+ }
+ string projectFile = projectItem.FileName;
+ if (!Directory.Exists(projectFile))
+ {
+ int iconIndex = 0;
+ m_fileIconMappings.TryGetValue(Path.GetExtension(projectFile), out iconIndex);
+ summary.FileLineCountInfo.Add(new LineCountInfo(projectFile, iconIndex, summary));
+ }
+ }
+}
+Now try to compile again. The only thing missing is
+"CodeModelLanguageConstants", a class containing the GUIDs for C#, VB and
+(M)C++. SharpDevelop supports C#, VB, Boo and MSIL projects; this is not
+matching the icons we imported from the Visual Studio AddIn. We'll look for a
+way to get icons directly from SharpDevelop soon; for now just hard-code the
+values for C# and VB:
+
// Map project types to icons for use in the projects list
+m_projIconMappings = new Dictionary<string, int>();
+m_projIconMappings.Add("{00000000-0000-0000-0000-000000000000}", 0);
+m_projIconMappings.Add("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", 1); // C#
+m_projIconMappings.Add("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}", 2); // VB
+m_projIconMappings.Add("{00000001-0000-0000-0000-000000000000}", 5);
+
+
+ This fixes all compile errors. And if you test it, you'll find that it even
+ runs correctly! :-)
+
+
+ Although the extension process is very different in SharpDevelop and Visual
+ Studio; the API is quite similar - after all, both are modelling MSBuild
+ solutions and after a similar feature set. I hope this shows you that porting
+ AddIns from Visual Studio to SharpDevelop isn't very hard and we would like to
+ see more SharpDevelop AddIns in the future.
+
+
+ Here an image showing the AddIn counting itself:
+
+
+
+
+
+ Possible improvements
+
+While this is a basic port of the AddIn to SharpDevelop, there are lots of
+possibilities for improvement.
+
+ Getting Icons from SharpDevelop
+
+First, we to replace some bad code in AddFileListItem: Remove the code from the
+"TODO: Add image index setting" command to the "lvi.ImageIndex = iconIndex;"
+line and replace it with "lvi.ImageIndex = info.IconIndex;". Now only one
+read-access on the m_fileIconMappings hashtable is left - the one in
+ScanProjectItems.
+Before we can continue, we need to be aware how SharpDevelop deals with icons:
+Menu items are defined in XML and can be shown before the AddIn library is
+loaded. Because of that, resource files can be registered in XML which makes the
+icons inside it available to the ICSharpCode.Core.ResourceService. AddIns like
+language bindings can register such file extensions and project types with such
+icons. SharpDevelop's class IconService provides convenience methods for
+accessing these icons: GetImageForFile or GetImageForProjectType get the icon's
+name by looking up the project type or file extension. If you have an icon name,
+you can use GetBitmap or GetIcon to access it. The ResourceService converts
+between Bitmap and Icon on demand, but it is suggested to use .png bitmaps in
+the resource files and the GetBitmap method to load them.
+This means with these simple IconService methods we can load the bitmap for the
+correct project/file type, just like SharpDevelop's project browser does.
+The line counter code uses image lists with a few predefined images. Because I
+do not want to change it, I will just introduce a new class ImageListHelper that
+can add SharpDevelop icons to an existing image list.
+
public class ImageListHelper
+{
+ ImageList imageList;
+ Dictionary<string, int> dict = new Dictionary<string, int>();
+
+ public ImageListHelper(ImageList imageList)
+ {
+ if (imageList == null)
+ throw new ArgumentNullException("imageList");
+ this.imageList = imageList;
+ }
+
+ public int GetIndex(string imageName)
+ {
+ int index;
+ if (!dict.TryGetValue(imageName, out index)) {
+ index = imageList.Images.Count;
+ imageList.Images.Add(IconService.GetBitmap(imageName));
+ dict[imageName] = index;
+ }
+ return index;
+ }
+}
+
+We
+will use two instances of this class to control the two image lists
+imgProjectTypes and imgFileTypes.
+ScanSolution() is getting the icon index from m_projIconMappings - we will
+change this line to use our ImageListHelper instead.
+Replace "m_projIconMappings.TryGetValue(lang, out iconIndex);" with
+
+ Now the AddIn is using the icons shipping with SharpDevelop and will
+ automatically use the icons of other languages added to SharpDevelop.
+
+
+ Adding new counting algorithms
+
+The great thing about the SharpDevelop AddIn infrastructure is that it allows
+one AddIn to extend another. We will modify the Line Counter in such a way that
+it is possible for other AddIns to introduce new counting algorithms. We want to
+lazy-load our counting algorithms only when a file of the specified type is
+encountered.
+This leads to the doozer-descriptor-implementation pattern you will often see
+for extendable SharpDevelop features.
+
+In the AddInTree, one can register classes - we already did this with the
+command for our menu item. We will add a new path to the AddInTree containing
+counting algorithm implementations. We will have to use classes instead of
+methods to be able to register them in the AddInTree, so let's create an
+interface and the classes:
+
public interface ICountingAlgorithm
+{
+ void CountLines(LineCountInfo info);
+}
+
+public class CountingAlgorithmGeneric : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesGeneric(info);
+ }
+}
+public class CountingAlgorithmCStyle : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesCStyle(info);
+ }
+}
+public class CountingAlgorithmVBStyle : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesVBStyle(info);
+ }
+}
+public class CountingAlgorithmXmlStyle : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesXMLStyle(info);
+ }
+}
+
The Count* methods in LineCounterBrowser have been changed from
+"private" to "internal static".
+We still need a way to associate the algorithms with file extensions. This is
+done directly in the XML code defining the AddInTree:
+
<Path name = "/AddIns/LineCounter/CountingAlgorithms">
+ <LineCountingAlgorithm
+ id = "Generic"
+ extensions = ".txt;.res;.sql;.cd"
+ class = "LineCounterAddin.CountingAlgorithmGeneric" />
+ <LineCountingAlgorithm
+ id = "CStyle"
+ extensions = ".cs;.vj;.js;.cpp;.cc;.cxx;.c;.hpp;.hh;.hxx;.h;.idl;.odl;.css"
+ class = "LineCounterAddin.CountingAlgorithmCStyle" />
+ <LineCountingAlgorithm
+ id = "VBStyle"
+ extensions = ".vb;.vbs"
+ class = "LineCounterAddin.CountingAlgorithmVBStyle" />
+ <LineCountingAlgorithm
+ id = "XmlStyle"
+ extensions = ".xml;.xsl;.xslt;.xsd;.config;.resx;.aspx;.ascx;.ashx;.asmx;.asax;.html;.html"
+ class = "LineCounterAddin.CountingAlgorithmXmlStyle" />
+</Path>
+
Because we are using custom attributes, we are using a new codon
+name "LineCountingAlgorithm". Don't be irritated that it's not defined in the
+XML schema for .addin files - we are creating a new possible codon name here;
+the XML schema is just for code completion when editing the .addin file.
+Now how can we define this codon type? Constructing objects from the AddInTree
+is done by the doozers (the name comes
+from
+these
+guys
+[^]).
+This means you have to register a new doozer for line counting algorithms.
+This is done by editing the <Runtime> section of your .addin file:
+
Initialising this list in the constructor is easy:
+
+countingAlgorithms = AddInTree.BuildItems<CountingAlgorithmDescriptor>
+ ("/AddIns/LineCounter/CountingAlgorithms", this);
+// Iterate through algorithms to fill list of known countable types
+foreach (CountingAlgorithmDescriptor desc in countingAlgorithms) {
+ m_countableTypes.AddRange(desc.extensions);
+}
+
+
+ And finally, replace the usage of m_countAlgorithms in the inner try-catch
+ block in SumSolution() with this code:
+
+
+ foreach (CountingAlgorithmDescriptor desc in countingAlgorithms) {
+ if (desc.CanCountLines(info)) {
+ desc.GetAlgorithm().CountLines(info);
+ break;
+ }
+ }
+
+
+
+
+
+ So, let's reiterate how this extension model works:
+
+
+ When SharpDevelop starts, SharpDevelop only loads your .addin file, but this
+ bit of XML parsing is quite fast. Your .dll is not loaded, but SharpDevelop
+ remembers where it has to look when the CountingAlgorithmDoozer is needed. Now
+ the user opens a solution and clicks on "Tools > Show Line Counter".
+ Launching the menu command will load you AddIn assembly and create an instance
+ of the ToolCommand1 class and call Run() on it. The LineCounterBrowser
+ constructor now calls AddInTree.BuildItems for
+ /AddIns/LineCounter/CountingAlgorithms. To build the items in that path, the
+ doozer is required, so SharpDevelop creates the doozer instance here and uses
+ it to build all items. The doozer does not create instances of the algorithm
+ classes; it only creates a descriptor instance.
+
+
+ Only when counting the lines in a file of any matching extension, the
+ descriptor creates an instance of the class. The "AddIn" stored is the context
+ in which the class name occured - it knows which runtime assemblies were
+ specified in that XML file.
+
+
+ If there were additional algorithms in other assemblies (for example a Boo
+ line counter), those assemblies would be loaded only if you count files in
+ those languages.
+
+
+ This means unused SharpDevelop AddIns use very little memory and startup time
+ (if their extension points are coded properly) - it only takes parsing the
+ XML, storing the resulting codons in a compact object tree where they are
+ mixed with the other AddIns' codons.
+
+
+ Creating an AddIn installation package
+
+Now to move to a completely different and much easier topic at the end: we want
+to have an easy way for users to install, update and uninstall our AddIn.
+
+Creating a SharpDevelop AddIn installation package (.sdaddin file) is easy. Just
+create a zip file containing LineCounter.addin and LineCounter.dll and rename
+the zip file to "LineCounter.sdaddin". That really was everything you had to do
+- double-clicking this .sdaddin file will open SharpDevelop's AddIn manager
+where you can install the AddIn with just one click. AddIns installed this way
+will be extracted to %Application Data%\.ICSharpCode\SharpDevelop2\AddIns.
+
+
+
+ SharpDevelop 2.0 is released under the terms of the GNU Lesser General Public
+ License. In plain English, that means you can use any license you want for
+ your own AddIns and do not have to open-source them. You only have to release
+ modifications to the SharpDevelop libraries.
+
+
+ Summary
+
+
+ This article shows you how to start writing SharpDevelop AddIns. It is a
+ complete walkthrough from creating a new project to creating the installation
+ package.
+
+
+ History
+
+
+
+ 18th July, 2006: Article published (based on SharpDevelop
+ 2.0.0.1591).
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/addinmanager.png b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/addinmanager.png
new file mode 100644
index 0000000000..390fff1ad3
Binary files /dev/null and b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/addinmanager.png differ
diff --git a/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/projectbrowser.png b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/projectbrowser.png
new file mode 100644
index 0000000000..2ed27ef6b3
Binary files /dev/null and b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/projectbrowser.png differ
diff --git a/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/properties.png b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/properties.png
new file mode 100644
index 0000000000..0b226ff166
Binary files /dev/null and b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/properties.png differ
diff --git a/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/screenshot.png b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/screenshot.png
new file mode 100644
index 0000000000..87add37854
Binary files /dev/null and b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/screenshot.png differ
diff --git a/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/screenshot2.png b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/screenshot2.png
new file mode 100644
index 0000000000..732d8d0cf8
Binary files /dev/null and b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/screenshot2.png differ
diff --git a/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/templatetype.png b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/templatetype.png
new file mode 100644
index 0000000000..861f2b993a
Binary files /dev/null and b/samples/LineCounter/Article/LineCounterSharpDevelopAddIn/templatetype.png differ
diff --git a/samples/LineCounter/Configuration/AssemblyInfo.cs b/samples/LineCounter/Configuration/AssemblyInfo.cs
new file mode 100644
index 0000000000..82045e9df2
--- /dev/null
+++ b/samples/LineCounter/Configuration/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+/*
+ * Created by SharpDevelop.
+ * User: Daniel Grunwald
+ * Date: 09.05.2006
+ * Time: 17:22
+ */
+
+using System.Reflection;
+
+[assembly: AssemblyTitle("LineCounter")]
+[assembly: AssemblyDescription("Macro AddIn for SharpDevelop 2.0")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SharpDevelop")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has following format :
+//
+// Major.Minor.Build.Revision
+//
+// You can specify all values by your own or you can build default build and revision
+// numbers with the '*' character (the default):
+
+[assembly: AssemblyVersion("1.0.*")]
+
diff --git a/samples/LineCounter/LineCounter.addin b/samples/LineCounter/LineCounter.addin
new file mode 100644
index 0000000000..d2091518fd
--- /dev/null
+++ b/samples/LineCounter/LineCounter.addin
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/LineCounter/LineCounter.csproj b/samples/LineCounter/LineCounter.csproj
new file mode 100644
index 0000000000..3cd9bb19b5
--- /dev/null
+++ b/samples/LineCounter/LineCounter.csproj
@@ -0,0 +1,73 @@
+
+
+ Library
+ LineCounterAddin
+ LineCounter
+ Debug
+ AnyCPU
+ {880A7EAF-D0B4-46AC-A9B6-B6156512037A}
+ ..\..\AddIns\
+ False
+ False
+ False
+ Auto
+ 4194304
+ AnyCPU
+ 4096
+ 4
+ false
+
+
+ obj\
+ obj\Debug\
+ False
+ DEBUG,TRACE,IMPR1,IMPR2,IMPR3
+ true
+ Full
+ True
+
+
+ obj\
+ obj\Release\
+ True
+ TRACE,IMPR1,IMPR2,IMPR3
+ false
+ None
+ False
+
+
+
+
+
+
+
+
+ ..\..\bin\ICSharpCode.SharpDevelop.dll
+ False
+ False
+
+
+ ..\..\bin\ICSharpCode.Core.dll
+ False
+ False
+
+
+
+
+ Always
+
+
+
+
+
+
+ LineCounterBrowser.cs
+
+
+ LineCounterBrowser.cs
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/LineCounter/LineCounter.sln b/samples/LineCounter/LineCounter.sln
new file mode 100644
index 0000000000..1b940f8e29
--- /dev/null
+++ b/samples/LineCounter/LineCounter.sln
@@ -0,0 +1,16 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# SharpDevelop 2.1.0.1394
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LineCounter", "LineCounter.csproj", "{880A7EAF-D0B4-46AC-A9B6-B6156512037A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {880A7EAF-D0B4-46AC-A9B6-B6156512037A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {880A7EAF-D0B4-46AC-A9B6-B6156512037A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {880A7EAF-D0B4-46AC-A9B6-B6156512037A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {880A7EAF-D0B4-46AC-A9B6-B6156512037A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/samples/LineCounter/Src/Command.cs b/samples/LineCounter/Src/Command.cs
new file mode 100644
index 0000000000..73d0ed8304
--- /dev/null
+++ b/samples/LineCounter/Src/Command.cs
@@ -0,0 +1,24 @@
+/*
+ * Created by SharpDevelop.
+ * User: Daniel Grunwald
+ * Date: 09.05.2006
+ * Time: 17:22
+ */
+
+using System;
+using System.Text;
+using System.Windows.Forms;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Gui;
+
+namespace LineCounterAddin
+{
+ public class ToolCommand1 : AbstractMenuCommand
+ {
+ public override void Run()
+ {
+ WorkbenchSingleton.Workbench.ShowView(new LineCounterViewContent());
+ }
+ }
+}
diff --git a/samples/LineCounter/Src/Extensibility.cs b/samples/LineCounter/Src/Extensibility.cs
new file mode 100644
index 0000000000..228a254830
--- /dev/null
+++ b/samples/LineCounter/Src/Extensibility.cs
@@ -0,0 +1,87 @@
+/*
+ * Created by SharpDevelop.
+ * User: Daniel Grunwald
+ * Date: 18.07.2006
+ * Time: 17:08
+ */
+
+using System;
+using ICSharpCode.Core;
+
+namespace LineCounterAddin
+{
+ // Improvement 2
+
+ public interface ICountingAlgorithm
+ {
+ void CountLines(LineCountInfo info);
+ }
+
+ public class CountingAlgorithmGeneric : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesGeneric(info);
+ }
+ }
+ public class CountingAlgorithmCStyle : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesCStyle(info);
+ }
+ }
+ public class CountingAlgorithmVBStyle : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesVBStyle(info);
+ }
+ }
+ public class CountingAlgorithmXmlStyle : ICountingAlgorithm {
+ public void CountLines(LineCountInfo info) {
+ LineCounterBrowser.CountLinesXMLStyle(info);
+ }
+ }
+
+ public class CountingAlgorithmDoozer : IDoozer
+ {
+ public bool HandleConditions {
+ get {
+ // our doozer cannot handle conditions, let SharpDevelop
+ // do that for us
+ return false;
+ }
+ }
+
+ public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems)
+ {
+ return new CountingAlgorithmDescriptor(codon.AddIn,
+ codon.Properties["extensions"],
+ codon.Properties["class"]);
+ }
+ }
+
+ public class CountingAlgorithmDescriptor
+ {
+ AddIn addIn;
+ internal string[] extensions;
+ string className;
+
+ public CountingAlgorithmDescriptor(AddIn addIn, string extensions, string className)
+ {
+ this.addIn = addIn;
+ this.extensions = extensions.ToLowerInvariant().Split(';');
+ this.className = className;
+ }
+
+ public bool CanCountLines(LineCountInfo info)
+ {
+ return (Array.IndexOf(extensions, info.FileType.ToLowerInvariant()) >= 0);
+ }
+
+ ICountingAlgorithm cachedAlgorithm;
+
+ public ICountingAlgorithm GetAlgorithm()
+ {
+ if (cachedAlgorithm == null) {
+ cachedAlgorithm = (ICountingAlgorithm)addIn.CreateObject(className);
+ }
+ return cachedAlgorithm;
+ }
+ }
+}
diff --git a/samples/LineCounter/Src/ImageListHelper.cs b/samples/LineCounter/Src/ImageListHelper.cs
new file mode 100644
index 0000000000..f2f46597ba
--- /dev/null
+++ b/samples/LineCounter/Src/ImageListHelper.cs
@@ -0,0 +1,45 @@
+/*
+ * Created by SharpDevelop.
+ * User: Daniel Grunwald
+ * Date: 18.07.2006
+ * Time: 15:53
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using ICSharpCode.Core;
+
+namespace LineCounterAddin
+{
+ // Helper class for improvement 1
+
+ ///
+ /// To minimize changes to LineCounterBrowser, we are
+ /// using this helper class to load images from SharpDevelop's
+ /// IconService into our image list on demand.
+ ///
+ public class ImageListHelper
+ {
+ ImageList imageList;
+ Dictionary dict = new Dictionary();
+
+ public ImageListHelper(ImageList imageList)
+ {
+ if (imageList == null)
+ throw new ArgumentNullException("imageList");
+ this.imageList = imageList;
+ }
+
+ public int GetIndex(string imageName)
+ {
+ int index;
+ if (!dict.TryGetValue(imageName, out index)) {
+ index = imageList.Images.Count;
+ imageList.Images.Add(IconService.GetBitmap(imageName));
+ dict[imageName] = index;
+ }
+ return index;
+ }
+ }
+}
diff --git a/samples/LineCounter/Src/LineCounterBrowser.Designer.cs b/samples/LineCounter/Src/LineCounterBrowser.Designer.cs
new file mode 100644
index 0000000000..7879d80647
--- /dev/null
+++ b/samples/LineCounter/Src/LineCounterBrowser.Designer.cs
@@ -0,0 +1,469 @@
+namespace LineCounterAddin
+{
+ partial class LineCounterBrowser
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LineCounterBrowser));
+ System.Windows.Forms.ListViewGroup listViewGroup1 = new System.Windows.Forms.ListViewGroup("Grand Totals", System.Windows.Forms.HorizontalAlignment.Left);
+ System.Windows.Forms.ListViewGroup listViewGroup2 = new System.Windows.Forms.ListViewGroup("Project Totals", System.Windows.Forms.HorizontalAlignment.Left);
+ this.tscMain = new System.Windows.Forms.ToolStripContainer();
+ this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+ this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
+ this.tsprgTotal = new System.Windows.Forms.ToolStripProgressBar();
+ this.toolStripLabel2 = new System.Windows.Forms.ToolStripLabel();
+ this.tsprgTask = new System.Windows.Forms.ToolStripProgressBar();
+ this.tstxtLinesCounted = new System.Windows.Forms.ToolStripTextBox();
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.lvFileList = new System.Windows.Forms.ListView();
+ this.chFilename = new System.Windows.Forms.ColumnHeader();
+ this.chFileTotalLines = new System.Windows.Forms.ColumnHeader();
+ this.chFileTotalCode = new System.Windows.Forms.ColumnHeader();
+ this.chFileTotalComment = new System.Windows.Forms.ColumnHeader();
+ this.chFileExt = new System.Windows.Forms.ColumnHeader();
+ this.chMode = new System.Windows.Forms.ColumnHeader();
+ this.cmsFileList = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.tsmiArrange = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiGroupByType = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiGroupByProj = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
+ this.tsmiNoGrouping = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiRecalculate_FileList = new System.Windows.Forms.ToolStripMenuItem();
+ this.imgFileTypes = new System.Windows.Forms.ImageList(this.components);
+ this.lvSummary = new System.Windows.Forms.ListView();
+ this.chProject = new System.Windows.Forms.ColumnHeader();
+ this.chTotalLines = new System.Windows.Forms.ColumnHeader();
+ this.chCodeLines = new System.Windows.Forms.ColumnHeader();
+ this.chComments = new System.Windows.Forms.ColumnHeader();
+ this.chBlankLines = new System.Windows.Forms.ColumnHeader();
+ this.chNetLines = new System.Windows.Forms.ColumnHeader();
+ this.imgProjectTypes = new System.Windows.Forms.ImageList(this.components);
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.tsmiLineCounter = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiOptions = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiRecalculate = new System.Windows.Forms.ToolStripMenuItem();
+ this.tscMain.BottomToolStripPanel.SuspendLayout();
+ this.tscMain.ContentPanel.SuspendLayout();
+ this.tscMain.TopToolStripPanel.SuspendLayout();
+ this.tscMain.SuspendLayout();
+ this.toolStrip1.SuspendLayout();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.cmsFileList.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tscMain
+ //
+ //
+ // tscMain.BottomToolStripPanel
+ //
+ this.tscMain.BottomToolStripPanel.Controls.Add(this.toolStrip1);
+ //
+ // tscMain.ContentPanel
+ //
+ this.tscMain.ContentPanel.Controls.Add(this.splitContainer1);
+ this.tscMain.ContentPanel.Size = new System.Drawing.Size(600, 351);
+ this.tscMain.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tscMain.Location = new System.Drawing.Point(0, 0);
+ this.tscMain.Name = "tscMain";
+ this.tscMain.Size = new System.Drawing.Size(600, 400);
+ this.tscMain.TabIndex = 0;
+ this.tscMain.Text = "toolStripContainer1";
+ //
+ // tscMain.TopToolStripPanel
+ //
+ this.tscMain.TopToolStripPanel.Controls.Add(this.menuStrip1);
+ //
+ // toolStrip1
+ //
+ this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None;
+ this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.toolStripLabel1,
+ this.tsprgTotal,
+ this.toolStripLabel2,
+ this.tsprgTask,
+ this.tstxtLinesCounted});
+ this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+ this.toolStrip1.Name = "toolStrip1";
+ this.toolStrip1.Size = new System.Drawing.Size(600, 25);
+ this.toolStrip1.Stretch = true;
+ this.toolStrip1.TabIndex = 1;
+ //
+ // toolStripLabel1
+ //
+ this.toolStripLabel1.Name = "toolStripLabel1";
+ this.toolStripLabel1.Size = new System.Drawing.Size(80, 22);
+ this.toolStripLabel1.Text = "Total Progress:";
+ //
+ // tsprgTotal
+ //
+ this.tsprgTotal.Name = "tsprgTotal";
+ this.tsprgTotal.Size = new System.Drawing.Size(150, 22);
+ //
+ // toolStripLabel2
+ //
+ this.toolStripLabel2.Name = "toolStripLabel2";
+ this.toolStripLabel2.Size = new System.Drawing.Size(78, 22);
+ this.toolStripLabel2.Text = "Task Progress:";
+ //
+ // tsprgTask
+ //
+ this.tsprgTask.Name = "tsprgTask";
+ this.tsprgTask.Size = new System.Drawing.Size(150, 22);
+ //
+ // tstxtLinesCounted
+ //
+ this.tstxtLinesCounted.Name = "tstxtLinesCounted";
+ this.tstxtLinesCounted.Size = new System.Drawing.Size(100, 25);
+ this.tstxtLinesCounted.ToolTipText = "Lines counted so far";
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.lvFileList);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.lvSummary);
+ this.splitContainer1.Size = new System.Drawing.Size(600, 351);
+ this.splitContainer1.SplitterDistance = 255;
+ this.splitContainer1.TabIndex = 0;
+ //
+ // lvFileList
+ //
+ this.lvFileList.AllowColumnReorder = true;
+ this.lvFileList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.chFilename,
+ this.chFileTotalLines,
+ this.chFileTotalCode,
+ this.chFileTotalComment,
+ this.chFileExt,
+ this.chMode});
+ this.lvFileList.ContextMenuStrip = this.cmsFileList;
+ this.lvFileList.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lvFileList.FullRowSelect = true;
+ this.lvFileList.GridLines = true;
+ this.lvFileList.HideSelection = false;
+ this.lvFileList.Location = new System.Drawing.Point(0, 0);
+ this.lvFileList.Name = "lvFileList";
+ this.lvFileList.Size = new System.Drawing.Size(600, 255);
+ this.lvFileList.SmallImageList = this.imgFileTypes;
+ this.lvFileList.TabIndex = 0;
+ this.lvFileList.UseCompatibleStateImageBehavior = false;
+ this.lvFileList.View = System.Windows.Forms.View.Details;
+ this.lvFileList.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lvFileList_ColumnClick);
+ //
+ // chFilename
+ //
+ this.chFilename.Text = "File";
+ this.chFilename.Width = 192;
+ //
+ // chFileTotalLines
+ //
+ this.chFileTotalLines.Text = "Total Lines";
+ this.chFileTotalLines.Width = 90;
+ //
+ // chFileTotalCode
+ //
+ this.chFileTotalCode.Text = "Code Lines";
+ this.chFileTotalCode.Width = 90;
+ //
+ // chFileTotalComment
+ //
+ this.chFileTotalComment.Text = "Comments";
+ this.chFileTotalComment.Width = 90;
+ //
+ // chFileExt
+ //
+ this.chFileExt.Text = "Extension";
+ this.chFileExt.Width = 64;
+ //
+ // chMode
+ //
+ this.chMode.Text = "Sum-Mode";
+ this.chMode.Width = 70;
+ //
+ // cmsFileList
+ //
+ this.cmsFileList.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiArrange,
+ this.tsmiRecalculate_FileList});
+ this.cmsFileList.Name = "cmsFileList";
+ this.cmsFileList.Size = new System.Drawing.Size(130, 48);
+ //
+ // tsmiArrange
+ //
+ this.tsmiArrange.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiGroupByType,
+ this.tsmiGroupByProj,
+ this.toolStripMenuItem1,
+ this.tsmiNoGrouping});
+ this.tsmiArrange.Name = "tsmiArrange";
+ this.tsmiArrange.Size = new System.Drawing.Size(129, 22);
+ this.tsmiArrange.Text = "Arrange";
+ //
+ // tsmiGroupByType
+ //
+ this.tsmiGroupByType.Checked = true;
+ this.tsmiGroupByType.CheckOnClick = true;
+ this.tsmiGroupByType.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.tsmiGroupByType.Name = "tsmiGroupByType";
+ this.tsmiGroupByType.ShortcutKeyDisplayString = "CTRL-G,T";
+ this.tsmiGroupByType.Size = new System.Drawing.Size(208, 22);
+ this.tsmiGroupByType.Text = "Group by type";
+ this.tsmiGroupByType.Click += new System.EventHandler(this.tsmiGroupByType_Click);
+ //
+ // tsmiGroupByProj
+ //
+ this.tsmiGroupByProj.CheckOnClick = true;
+ this.tsmiGroupByProj.Name = "tsmiGroupByProj";
+ this.tsmiGroupByProj.ShortcutKeyDisplayString = "CTRL-G,P";
+ this.tsmiGroupByProj.Size = new System.Drawing.Size(208, 22);
+ this.tsmiGroupByProj.Text = "Group by project";
+ this.tsmiGroupByProj.Click += new System.EventHandler(this.tsmiGroupByProj_Click);
+ //
+ // toolStripMenuItem1
+ //
+ this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+ this.toolStripMenuItem1.Size = new System.Drawing.Size(205, 6);
+ //
+ // tsmiNoGrouping
+ //
+ this.tsmiNoGrouping.CheckOnClick = true;
+ this.tsmiNoGrouping.Name = "tsmiNoGrouping";
+ this.tsmiNoGrouping.ShortcutKeyDisplayString = "CTRL-G,0";
+ this.tsmiNoGrouping.Size = new System.Drawing.Size(208, 22);
+ this.tsmiNoGrouping.Text = "Do not group";
+ this.tsmiNoGrouping.Click += new System.EventHandler(this.tsmiNoGrouping_Click);
+ //
+ // tsmiRecalculate_FileList
+ //
+ this.tsmiRecalculate_FileList.Name = "tsmiRecalculate_FileList";
+ this.tsmiRecalculate_FileList.Size = new System.Drawing.Size(129, 22);
+ this.tsmiRecalculate_FileList.Text = "Recalculate";
+ this.tsmiRecalculate_FileList.Click += new System.EventHandler(this.tsmiRecalculate_FileList_Click);
+ //
+ // imgFileTypes
+ //
+ this.imgFileTypes.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imgFileTypes.ImageStream")));
+ this.imgFileTypes.TransparentColor = System.Drawing.Color.Transparent;
+ this.imgFileTypes.Images.SetKeyName(0, "Default.png");
+ this.imgFileTypes.Images.SetKeyName(1, "FileCS.png");
+ this.imgFileTypes.Images.SetKeyName(2, "FileVB.png");
+ this.imgFileTypes.Images.SetKeyName(3, "FileVJ.png");
+ this.imgFileTypes.Images.SetKeyName(4, "FileCPP.png");
+ this.imgFileTypes.Images.SetKeyName(5, "FileC.png");
+ this.imgFileTypes.Images.SetKeyName(6, "FileH.png");
+ this.imgFileTypes.Images.SetKeyName(7, "JavaScript.png");
+ this.imgFileTypes.Images.SetKeyName(8, "FileCD.png");
+ this.imgFileTypes.Images.SetKeyName(9, "FileRESX.png");
+ this.imgFileTypes.Images.SetKeyName(10, "FileCSS.png");
+ this.imgFileTypes.Images.SetKeyName(11, "FileHTM.png");
+ this.imgFileTypes.Images.SetKeyName(12, "FileXML.png");
+ this.imgFileTypes.Images.SetKeyName(13, "FileXSL.png");
+ this.imgFileTypes.Images.SetKeyName(14, "FileXSD.png");
+ this.imgFileTypes.Images.SetKeyName(15, "FileCONFIG.png");
+ this.imgFileTypes.Images.SetKeyName(16, "FileASAX.png");
+ this.imgFileTypes.Images.SetKeyName(17, "FileASCX.png");
+ this.imgFileTypes.Images.SetKeyName(18, "FileASMX.png");
+ this.imgFileTypes.Images.SetKeyName(19, "fileASPX.png");
+ //
+ // lvSummary
+ //
+ this.lvSummary.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.chProject,
+ this.chTotalLines,
+ this.chCodeLines,
+ this.chComments,
+ this.chBlankLines,
+ this.chNetLines});
+ this.lvSummary.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lvSummary.FullRowSelect = true;
+ listViewGroup1.Header = "Grand Totals";
+ listViewGroup1.Name = "lvgAllProj";
+ listViewGroup2.Header = "Project Totals";
+ listViewGroup2.Name = "lvgEachProj";
+ this.lvSummary.Groups.AddRange(new System.Windows.Forms.ListViewGroup[] {
+ listViewGroup1,
+ listViewGroup2});
+ this.lvSummary.HideSelection = false;
+ this.lvSummary.Location = new System.Drawing.Point(0, 0);
+ this.lvSummary.Name = "lvSummary";
+ this.lvSummary.Size = new System.Drawing.Size(600, 92);
+ this.lvSummary.SmallImageList = this.imgProjectTypes;
+ this.lvSummary.TabIndex = 0;
+ this.lvSummary.UseCompatibleStateImageBehavior = false;
+ this.lvSummary.View = System.Windows.Forms.View.Details;
+ //
+ // chProject
+ //
+ this.chProject.Text = "Project";
+ this.chProject.Width = 146;
+ //
+ // chTotalLines
+ //
+ this.chTotalLines.Text = "Total Lines";
+ this.chTotalLines.Width = 90;
+ //
+ // chCodeLines
+ //
+ this.chCodeLines.Text = "Code Lines";
+ this.chCodeLines.Width = 90;
+ //
+ // chComments
+ //
+ this.chComments.Text = "Comments";
+ this.chComments.Width = 90;
+ //
+ // chBlankLines
+ //
+ this.chBlankLines.Text = "Blank Lines";
+ this.chBlankLines.Width = 90;
+ //
+ // chNetLines
+ //
+ this.chNetLines.Text = "Net Lines";
+ this.chNetLines.Width = 90;
+ //
+ // imgProjectTypes
+ //
+ this.imgProjectTypes.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imgProjectTypes.ImageStream")));
+ this.imgProjectTypes.TransparentColor = System.Drawing.Color.Transparent;
+ this.imgProjectTypes.Images.SetKeyName(0, "Solution.png");
+ this.imgProjectTypes.Images.SetKeyName(1, "ProjectCS.png");
+ this.imgProjectTypes.Images.SetKeyName(2, "ProjectVB.png");
+ this.imgProjectTypes.Images.SetKeyName(3, "ProjectVC.png");
+ this.imgProjectTypes.Images.SetKeyName(4, "ProjectVJ.png");
+ this.imgProjectTypes.Images.SetKeyName(5, "ProjectWeb.png");
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Dock = System.Windows.Forms.DockStyle.None;
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiLineCounter});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(600, 24);
+ this.menuStrip1.TabIndex = 0;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // tsmiLineCounter
+ //
+ this.tsmiLineCounter.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiOptions,
+ this.tsmiRecalculate});
+ this.tsmiLineCounter.Name = "tsmiLineCounter";
+ this.tsmiLineCounter.Size = new System.Drawing.Size(80, 20);
+ this.tsmiLineCounter.Text = "Line Counter";
+ //
+ // tsmiOptions
+ //
+ this.tsmiOptions.Name = "tsmiOptions";
+ this.tsmiOptions.Size = new System.Drawing.Size(129, 22);
+ this.tsmiOptions.Text = "Options";
+ //
+ // tsmiRecalculate
+ //
+ this.tsmiRecalculate.Name = "tsmiRecalculate";
+ this.tsmiRecalculate.Size = new System.Drawing.Size(129, 22);
+ this.tsmiRecalculate.Text = "Recalculate";
+ this.tsmiRecalculate.Click += new System.EventHandler(this.tsmiRecalculate_FileList_Click);
+ //
+ // LineCounterBrowser
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.tscMain);
+ this.Name = "LineCounterBrowser";
+ this.Size = new System.Drawing.Size(600, 400);
+ this.tscMain.BottomToolStripPanel.ResumeLayout(false);
+ this.tscMain.BottomToolStripPanel.PerformLayout();
+ this.tscMain.ContentPanel.ResumeLayout(false);
+ this.tscMain.TopToolStripPanel.ResumeLayout(false);
+ this.tscMain.TopToolStripPanel.PerformLayout();
+ this.tscMain.ResumeLayout(false);
+ this.tscMain.PerformLayout();
+ this.toolStrip1.ResumeLayout(false);
+ this.toolStrip1.PerformLayout();
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ this.splitContainer1.ResumeLayout(false);
+ this.cmsFileList.ResumeLayout(false);
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ToolStripContainer tscMain;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem tsmiLineCounter;
+ private System.Windows.Forms.ToolStripMenuItem tsmiOptions;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.ToolStripMenuItem tsmiRecalculate;
+ private System.Windows.Forms.ListView lvSummary;
+ private System.Windows.Forms.ColumnHeader chProject;
+ private System.Windows.Forms.ListView lvFileList;
+ private System.Windows.Forms.ColumnHeader chTotalLines;
+ private System.Windows.Forms.ColumnHeader chCodeLines;
+ private System.Windows.Forms.ColumnHeader chComments;
+ private System.Windows.Forms.ColumnHeader chBlankLines;
+ private System.Windows.Forms.ColumnHeader chNetLines;
+ private System.Windows.Forms.ColumnHeader chFilename;
+ private System.Windows.Forms.ColumnHeader chFileTotalLines;
+ private System.Windows.Forms.ColumnHeader chFileTotalCode;
+ private System.Windows.Forms.ColumnHeader chFileTotalComment;
+ private System.Windows.Forms.ColumnHeader chFileExt;
+ private System.Windows.Forms.ContextMenuStrip cmsFileList;
+ private System.Windows.Forms.ToolStripMenuItem tsmiArrange;
+ private System.Windows.Forms.ToolStripMenuItem tsmiGroupByType;
+ private System.Windows.Forms.ToolStripMenuItem tsmiGroupByProj;
+ private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem tsmiNoGrouping;
+ private System.Windows.Forms.ToolStripMenuItem tsmiRecalculate_FileList;
+ private System.Windows.Forms.ImageList imgProjectTypes;
+ private System.Windows.Forms.ToolStrip toolStrip1;
+ private System.Windows.Forms.ToolStripLabel toolStripLabel1;
+ private System.Windows.Forms.ToolStripProgressBar tsprgTotal;
+ private System.Windows.Forms.ToolStripLabel toolStripLabel2;
+ private System.Windows.Forms.ToolStripProgressBar tsprgTask;
+ private System.Windows.Forms.ToolStripTextBox tstxtLinesCounted;
+ private System.Windows.Forms.ImageList imgFileTypes;
+ private System.Windows.Forms.ColumnHeader chMode;
+ }
+}
diff --git a/samples/LineCounter/Src/LineCounterBrowser.cs b/samples/LineCounter/Src/LineCounterBrowser.cs
new file mode 100644
index 0000000000..7b60d1a321
--- /dev/null
+++ b/samples/LineCounter/Src/LineCounterBrowser.cs
@@ -0,0 +1,1255 @@
+// LineCounterBrowser is from the CodeProject article
+// "Line Counter - Writing a Visual Studio 2005 Add-In" by Jon Rista
+// http://www.codeproject.com/useritems/LineCounterAddin.asp
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Text;
+using System.Windows.Forms;
+
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace LineCounterAddin
+{
+ ///
+ /// Line Counter add-in user interface.
+ ///
+ public partial class LineCounterBrowser : UserControl
+ {
+ #region Nested Classes
+ abstract class ListViewItemComparer : System.Collections.IComparer
+ {
+ public abstract int Compare(ListViewItem item1, ListViewItem item2);
+
+ public ListView SortingList;
+ public int Column;
+
+ #region IComparer Members
+ int System.Collections.IComparer.Compare(object x, object y)
+ {
+ if (x is ListViewItem && y is ListViewItem)
+ {
+ int diff = Compare((ListViewItem)x, (ListViewItem)y);
+ if (SortingList.Sorting == SortOrder.Descending)
+ diff *= -1;
+
+ return diff;
+ }
+ else
+ {
+ throw new ArgumentException("One or both of the arguments are not ListViewItem objects.");
+ }
+ }
+ #endregion
+ }
+
+ ///
+ /// Compares items based on file name.
+ ///
+ class FileNameComparer : ListViewItemComparer
+ {
+
+ public override int Compare(ListViewItem item1, ListViewItem item2)
+ {
+ return String.Compare(item1.Text, item2.Text, false);
+ }
+ }
+
+ ///
+ /// Compares items based on total lines primarily, and
+ /// the filename secondarily.
+ ///
+ class FileLinesComparer : ListViewItemComparer
+ {
+
+ public override int Compare(ListViewItem item1, ListViewItem item2)
+ {
+ string string1 = item1.SubItems[Column].Text;
+ string string2 = item2.SubItems[Column].Text;
+
+ if (string1 != null && string2 != null)
+ {
+ int total1 = int.Parse(string1);
+ int total2 = int.Parse(string2);
+
+ // Compare the totals...
+ int diff = total1 - total2;
+
+ // If totals are equal...
+ if (diff == 0)
+ {
+ // Compare the filenames
+ diff = String.Compare(item1.Text, item2.Text, false);
+ }
+
+ return diff;
+ }
+
+ return 0;
+ }
+ }
+
+ ///
+ /// Compares items based on file extension.
+ ///
+ class FileExtensionComparer : ListViewItemComparer
+ {
+
+ public override int Compare(ListViewItem item1, ListViewItem item2)
+ {
+ string string1 = item1.SubItems[4].Text;
+ string string2 = item2.SubItems[4].Text;
+
+ return String.Compare(string1, string2, true);
+ }
+ }
+ #endregion
+
+ #region Constructor
+ ///
+ /// Construct the line counter user interface and
+ /// the countable file type mappings (to icons and
+ /// counting algorithms).
+ ///
+ public LineCounterBrowser()
+ {
+ InitializeComponent();
+
+ #if IMPR1
+ projectImageListHelper = new ImageListHelper(imgProjectTypes);
+ fileImageListHelper = new ImageListHelper(imgFileTypes);
+ #endif
+
+ // Map project types to icons for use in the projects list
+ m_projIconMappings = new Dictionary();
+ m_projIconMappings.Add("{00000000-0000-0000-0000-000000000000}", 0);
+ m_projIconMappings.Add("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", 1); // C#
+ m_projIconMappings.Add("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}", 2); // VB
+ m_projIconMappings.Add("{00000001-0000-0000-0000-000000000000}", 5);
+
+ // List all the countable file types (so we don't try to count .dll's,
+ // images, executables, etc.
+
+ m_countableTypes = new System.Collections.Specialized.StringCollection();
+ #if IMPR2
+ countingAlgorithms = AddInTree.BuildItems
+ ("/AddIns/LineCounter/CountingAlgorithms", this);
+ // Iterate through algorithms to fill list of known countable types
+ foreach (CountingAlgorithmDescriptor desc in countingAlgorithms) {
+ m_countableTypes.AddRange(desc.extensions);
+ }
+ #else
+ m_countableTypes.Add("*");
+ m_countableTypes.Add(".cs");
+ m_countableTypes.Add(".vb");
+ m_countableTypes.Add(".vj");
+ m_countableTypes.Add(".cpp");
+ m_countableTypes.Add(".cc");
+ m_countableTypes.Add(".cxx");
+ m_countableTypes.Add(".c");
+ m_countableTypes.Add(".hpp");
+ m_countableTypes.Add(".hh");
+ m_countableTypes.Add(".hxx");
+ m_countableTypes.Add(".h");
+ m_countableTypes.Add(".js");
+ m_countableTypes.Add(".cd");
+ m_countableTypes.Add(".resx");
+ m_countableTypes.Add(".res");
+ m_countableTypes.Add(".css");
+ m_countableTypes.Add(".htm");
+ m_countableTypes.Add(".html");
+ m_countableTypes.Add(".xml");
+ m_countableTypes.Add(".xsl");
+ m_countableTypes.Add(".xslt");
+ m_countableTypes.Add(".xsd");
+ m_countableTypes.Add(".config");
+ m_countableTypes.Add(".asax");
+ m_countableTypes.Add(".ascx");
+ m_countableTypes.Add(".asmx");
+ m_countableTypes.Add(".aspx");
+ m_countableTypes.Add(".ashx");
+ m_countableTypes.Add(".idl");
+ m_countableTypes.Add(".odl");
+ m_countableTypes.Add(".txt");
+ m_countableTypes.Add(".sql");
+ #endif
+
+ // Map file extensions to icons for use in the file list
+ m_fileIconMappings = new Dictionary(33);
+ m_fileIconMappings.Add("*", 0);
+ m_fileIconMappings.Add(".cs", 1);
+ m_fileIconMappings.Add(".vb", 2);
+ m_fileIconMappings.Add(".vj", 3);
+ m_fileIconMappings.Add(".cpp", 4);
+ m_fileIconMappings.Add(".cc", 4);
+ m_fileIconMappings.Add(".cxx", 4);
+ m_fileIconMappings.Add(".c", 5);
+ m_fileIconMappings.Add(".hpp", 6);
+ m_fileIconMappings.Add(".hh", 6);
+ m_fileIconMappings.Add(".hxx", 6);
+ m_fileIconMappings.Add(".h", 6);
+ m_fileIconMappings.Add(".js", 7);
+ m_fileIconMappings.Add(".cd", 8);
+ m_fileIconMappings.Add(".resx", 9);
+ m_fileIconMappings.Add(".res", 9);
+ m_fileIconMappings.Add(".css", 10);
+ m_fileIconMappings.Add(".htm", 11);
+ m_fileIconMappings.Add(".html", 11);
+ m_fileIconMappings.Add(".xml", 12);
+ m_fileIconMappings.Add(".xsl", 13);
+ m_fileIconMappings.Add(".xslt", 13);
+ m_fileIconMappings.Add(".xsd", 14);
+ m_fileIconMappings.Add(".config", 15);
+ m_fileIconMappings.Add(".asax", 16);
+ m_fileIconMappings.Add(".ascx", 17);
+ m_fileIconMappings.Add(".asmx", 18);
+ m_fileIconMappings.Add(".aspx", 19);
+ m_fileIconMappings.Add(".ashx", 0);
+ m_fileIconMappings.Add(".idl", 0);
+ m_fileIconMappings.Add(".odl", 0);
+ m_fileIconMappings.Add(".txt", 0);
+ m_fileIconMappings.Add(".sql", 0);
+
+ // Prepare counting algorithm mappings
+ CountLines countLinesGeneric = new CountLines(CountLinesGeneric);
+ CountLines countLinesCStyle = new CountLines(CountLinesCStyle);
+ CountLines countLinesVBStyle = new CountLines(CountLinesVBStyle);
+ CountLines countLinesXMLStyle = new CountLines(CountLinesXMLStyle);
+
+ m_countAlgorithms = new Dictionary(33);
+ m_countAlgorithms.Add("*", countLinesGeneric);
+ m_countAlgorithms.Add(".cs", countLinesCStyle);
+ m_countAlgorithms.Add(".vb", countLinesVBStyle);
+ m_countAlgorithms.Add(".vj", countLinesCStyle);
+ m_countAlgorithms.Add(".js", countLinesCStyle);
+ m_countAlgorithms.Add(".cpp", countLinesCStyle);
+ m_countAlgorithms.Add(".cc", countLinesCStyle);
+ m_countAlgorithms.Add(".cxx", countLinesCStyle);
+ m_countAlgorithms.Add(".c", countLinesCStyle);
+ m_countAlgorithms.Add(".hpp", countLinesCStyle);
+ m_countAlgorithms.Add(".hh", countLinesCStyle);
+ m_countAlgorithms.Add(".hxx", countLinesCStyle);
+ m_countAlgorithms.Add(".h", countLinesCStyle);
+ m_countAlgorithms.Add(".idl", countLinesCStyle);
+ m_countAlgorithms.Add(".odl", countLinesCStyle);
+ m_countAlgorithms.Add(".txt", countLinesGeneric);
+ m_countAlgorithms.Add(".xml", countLinesXMLStyle);
+ m_countAlgorithms.Add(".xsl", countLinesXMLStyle);
+ m_countAlgorithms.Add(".xslt", countLinesXMLStyle);
+ m_countAlgorithms.Add(".xsd", countLinesXMLStyle);
+ m_countAlgorithms.Add(".config", countLinesXMLStyle);
+ m_countAlgorithms.Add(".res", countLinesGeneric);
+ m_countAlgorithms.Add(".resx", countLinesXMLStyle);
+ m_countAlgorithms.Add(".aspx", countLinesXMLStyle);
+ m_countAlgorithms.Add(".ascx", countLinesXMLStyle);
+ m_countAlgorithms.Add(".ashx", countLinesXMLStyle);
+ m_countAlgorithms.Add(".asmx", countLinesXMLStyle);
+ m_countAlgorithms.Add(".asax", countLinesXMLStyle);
+ m_countAlgorithms.Add(".htm", countLinesXMLStyle);
+ m_countAlgorithms.Add(".html", countLinesXMLStyle);
+ m_countAlgorithms.Add(".css", countLinesCStyle);
+ m_countAlgorithms.Add(".sql", countLinesGeneric);
+ m_countAlgorithms.Add(".cd", countLinesGeneric);
+ }
+ #endregion
+
+ #region Variables
+ private List m_summaryList;
+ private Dictionary m_projIconMappings;
+ private Dictionary m_fileIconMappings;
+ private Dictionary m_countAlgorithms;
+ private System.Collections.Specialized.StringCollection m_countableTypes;
+
+ #if IMPR1
+ ImageListHelper fileImageListHelper;
+ ImageListHelper projectImageListHelper;
+ #endif
+ #if IMPR2
+ List countingAlgorithms;
+ #endif
+ #endregion
+
+ #region Handlers
+ private int lastSortColumn = -1; // Track the last clicked column
+
+ ///
+ /// Sorts the ListView by the clicked column, automatically
+ /// reversing the sort order on subsequent clicks of the
+ /// same column.
+ ///
+ ///
+ /// Provides the index of the clicked column.
+ private void lvFileList_ColumnClick(object sender, ColumnClickEventArgs e)
+ {
+ // Define a variable of the abstract (generic) comparer
+ ListViewItemComparer comparer = null;
+
+ // Create an instance of the specific comparer in the 'comparer'
+ // variable. Since each of the explicit comparer classes is
+ // derived from the abstract case class, polymorphism applies.
+ switch (e.Column)
+ {
+ // Line count columns
+ case 1:
+ case 2:
+ case 3:
+ comparer = new FileLinesComparer();
+ break;
+ // The file extension column
+ case 4:
+ comparer = new FileExtensionComparer();
+ break;
+ // All other columns sort by file name
+ default:
+ comparer = new FileNameComparer();
+ break;
+ }
+
+ // Set the sorting order
+ if (lastSortColumn == e.Column)
+ {
+ if (lvFileList.Sorting == SortOrder.Ascending)
+ {
+ lvFileList.Sorting = SortOrder.Descending;
+ }
+ else
+ {
+ lvFileList.Sorting = SortOrder.Ascending;
+ }
+ }
+ else
+ {
+ lvFileList.Sorting = SortOrder.Ascending;
+ }
+ lastSortColumn = e.Column;
+
+ // Send the comparer the list view and column being sorted
+ comparer.SortingList = lvFileList;
+ comparer.Column = e.Column;
+
+ // Attach the comparer to the list view and sort
+ lvFileList.ListViewItemSorter = comparer;
+ lvFileList.Sort();
+ }
+
+ ///
+ /// Sets the file listing mode to No Grouping,
+ /// and recounts.
+ ///
+ ///
+ ///
+ /// FIX THIS: Add a helper to simply repopulate
+ /// the list view with existing count data if it exists!!!
+ private void tsmiNoGrouping_Click(object sender, EventArgs e)
+ {
+ tsmiGroupByProj.Checked = false;
+ tsmiGroupByType.Checked = false;
+
+ SumSolution();
+ }
+
+ ///
+ /// Sets the file listing mode to Group by Project,
+ /// and recounts.
+ ///
+ ///
+ ///
+ /// FIX THIS: Add a helper to simply repopulate
+ /// the list view with existing count data if it exists!!!
+ private void tsmiGroupByProj_Click(object sender, EventArgs e)
+ {
+ tsmiGroupByType.Checked = false;
+ tsmiNoGrouping.Checked = false;
+
+ SumSolution();
+ }
+
+ ///
+ /// Sets the file listing mode to Group by Type,
+ /// and recounts.
+ ///
+ ///
+ ///
+ /// FIX THIS: Add a helper to simply repopulate
+ /// the list view with existing count data if it exists!!!
+ private void tsmiGroupByType_Click(object sender, EventArgs e)
+ {
+ tsmiGroupByProj.Checked = false;
+ tsmiNoGrouping.Checked = false;
+
+ SumSolution();
+ }
+
+ ///
+ /// Forces a recount of all files in all projects, and
+ /// updates the view.
+ ///
+ ///
+ ///
+ private void tsmiRecalculate_FileList_Click(object sender, EventArgs e)
+ {
+ ScanSolution();
+ SumSolution();
+ }
+ #endregion
+
+ #region Helpers
+ #region Line Counting Methods
+ ///
+ /// Count each line in a text file, logging
+ /// blank lines.
+ ///
+ /// The file information data to use.
+ internal static void CountLinesGeneric(LineCountInfo info)
+ {
+ StreamReader sr = new StreamReader(info.FileName);
+
+ string line;
+ while ((line = sr.ReadLine()) != null)
+ {
+ info.LineCountInfoDetails.Add("TotalLines", 1);
+ if (line.Trim() == string.Empty)
+ {
+ info.LineCountInfoDetails.Add("BlankLines", 1);
+ }
+
+ info.SumMode = "Generic";
+ }
+
+ sr.Close();
+ }
+
+ ///
+ /// Count each line in a c-style source file, scanning
+ /// for single and multi-line comments, code, and blank lines.
+ ///
+ /// The file information data to use.
+ /// This algorithm was originally created by Oz Solomon,
+ /// for his PLC line counter add-in for Visual Studio 2002/2003.
+ internal static void CountLinesCStyle(LineCountInfo info)
+ {
+ try
+ {
+ StreamReader reader = new StreamReader(info.FileName);
+
+ string line;
+ bool multiLineComment = false;
+ bool hasCode = false;
+ bool hasComments = false;
+ while ((line = reader.ReadLine()) != null)
+ {
+ ParseCLine(line, ref multiLineComment, ref hasCode, ref hasComments);
+
+ if (hasComments)
+ {
+ info.LineCountInfoDetails.Add("normcmtlines", 1);
+ }
+
+ if (hasCode)
+ {
+ info.LineCountInfoDetails.Add("codelines", 1);
+ }
+
+ if (!hasCode && !hasComments)
+ {
+ info.LineCountInfoDetails.Add("blanklines", 1);
+ }
+
+ info.LineCountInfoDetails.Add("totallines", 1);
+ }
+
+ reader.Close();
+
+ info.SumMode = "C-Style";
+ }
+ catch
+ {
+ }
+ }
+
+ ///
+ /// Count each line in a vb-style source file, scanning
+ /// for comments, code, and blank lines.
+ ///
+ /// The file information data to use.
+ /// This algorithm was originally created by Oz Solomon,
+ /// for his PLC line counter add-in for Visual Studio 2002/2003.
+ internal static void CountLinesVBStyle(LineCountInfo info)
+ {
+ try
+ {
+ StreamReader reader = new StreamReader(info.FileName);
+
+ string line;
+ bool multiLineComment = false;
+ bool hasCode = false;
+ bool hasComments = false;
+ while ((line = reader.ReadLine()) != null)
+ {
+ ParseVBLine(line, ref multiLineComment, ref hasCode, ref hasComments);
+
+ if (hasComments)
+ {
+ info.LineCountInfoDetails.Add("normcmtlines", 1);
+ }
+
+ if (hasCode)
+ {
+ info.LineCountInfoDetails.Add("codelines", 1);
+ }
+
+ if (!hasCode && !hasComments)
+ {
+ info.LineCountInfoDetails.Add("blanklines", 1);
+ }
+
+ info.LineCountInfoDetails.Add("totallines", 1);
+ }
+
+ reader.Close();
+
+ info.SumMode = "Visual Basic";
+ }
+ catch
+ {
+ }
+ }
+
+ ///
+ /// Count each line in an xml source file, scanning
+ /// for comments, code, and blank lines.
+ ///
+ /// The file information data to use.
+ /// This algorithm is based on one created by Oz Solomon,
+ /// for his PLC line counter add-in for Visual Studio 2002/2003.
+ internal static void CountLinesXMLStyle(LineCountInfo info)
+ {
+ try
+ {
+ StreamReader reader = new StreamReader(info.FileName);
+
+ string line;
+ bool multiLineComment = false;
+ bool hasCode = false;
+ bool hasComments = false;
+ while ((line = reader.ReadLine()) != null)
+ {
+ ParseXMLLine(line, ref multiLineComment, ref hasCode, ref hasComments);
+
+ if (hasComments)
+ {
+ info.LineCountInfoDetails.Add("normcmtlines", 1);
+ }
+
+ if (hasCode)
+ {
+ info.LineCountInfoDetails.Add("codelines", 1);
+ }
+
+ if (!hasCode && !hasComments)
+ {
+ info.LineCountInfoDetails.Add("blanklines", 1);
+ }
+
+ info.LineCountInfoDetails.Add("totallines", 1);
+ }
+
+ reader.Close();
+
+ info.SumMode = "XML";
+ }
+ catch
+ {
+ }
+ }
+
+ ///
+ /// Determines if the two input characters ch and chNext
+ /// match the given pair of characters a and b.
+ ///
+ /// First char requirement.
+ /// Second char requirement.
+ /// First char to test.
+ /// Second char to test.
+ ///
+ private static bool IsPair(char a, char b, char ch, char chNext)
+ {
+ return (ch == a && chNext == b);
+ }
+
+ ///
+ /// Parses a c-style code line for comments, code, and blanks.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// This algorithm was originally created by Oz Solomon,
+ /// for his PLC line counter add-in for Visual Studio 2002/2003.
+ private static void ParseCLine(string line, ref bool multiLineComment, ref bool hasCode, ref bool hasComments)
+ {
+ bool inString = false;
+ bool inTwoPairSequence = false;
+
+ hasComments = multiLineComment;
+ hasCode = false;
+
+ for (int i = 0; i < line.Length; i++)
+ {
+ char ch = line[i];
+ char chNext = (i < line.Length - 1 ? line[i + 1] : '\0');
+
+ // Process a single-line comment
+ if (IsPair('/', '/', ch, chNext) && !multiLineComment && !inString)
+ {
+ hasComments = true;
+ return;
+ }
+
+ // Process start of a multiline comment
+ else if (IsPair('/', '*', ch, chNext) && !multiLineComment && !inString)
+ {
+ multiLineComment = true;
+ hasComments = true;
+ ++i;
+ }
+
+ // Process end of a multiline comment
+ else if (IsPair('*', '/', ch, chNext) && !inString)
+ {
+ multiLineComment = false;
+ ++i;
+ }
+
+ // Process escaped character
+ else if (ch == '\\' && !multiLineComment)
+ {
+ ++i;
+ hasCode = true;
+ }
+
+ // Process string
+ else if (ch == '"' && !multiLineComment)
+ {
+ inString = !inString;
+ hasCode = true;
+ }
+
+ else if (!multiLineComment)
+ {
+ if (!Char.IsWhiteSpace(ch))
+ {
+ hasCode = true;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Parses a vb-style code line for comments, code and blanks.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// This algorithm was originally created by Oz Solomon,
+ /// for his PLC line counter add-in for Visual Studio 2002/2003.
+ private static void ParseVBLine(string line, ref bool multiLineComment, ref bool hasCode, ref bool hasComments)
+ {
+ bool inString = false;
+ bool inTwoPairSequence = false;
+
+ multiLineComment = false;
+
+ line = line.Trim();
+
+ if (line.Length == 0)
+ {
+ hasCode = false;
+ hasComments = false;
+ return;
+ }
+
+ if (line[0] == '\'')
+ {
+ hasCode = false;
+ hasComments = true;
+ return;
+ }
+
+ if (line.IndexOf('\'') != -1)
+ {
+ hasCode = true;
+ hasComments = true;
+ return;
+ }
+
+ hasCode = true;
+ hasComments = true;
+ }
+
+ ///
+ /// Parses an xml-style code line for comments, markup, and blanks.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// This algorithm is based on one created by Oz Solomon,
+ /// for his PLC line counter add-in for Visual Studio 2002/2003.
+ private static void ParseXMLLine(string line, ref bool multiLineComment, ref bool hasCode, ref bool hasComments)
+ {
+ bool inString = false;
+ bool inTwoPairSequence = false;
+
+ hasComments = multiLineComment;
+ hasCode = false;
+
+ for (int i = 0; i < line.Length; i++)
+ {
+ char ch1 = line[i];
+ char ch2 = (i < line.Length-1 ? line[i + 1] : '\0');
+ char ch3 = (i+1 < line.Length-1 ? line[i + 2] : '\0');
+ char ch4 = (i+2 < line.Length-1 ? line[i + 3] : '\0');
+
+ // Process start of XML comment
+ if (IsPair('<', '!', ch1, ch2) && IsPair('-', '-', ch3, ch4) && !multiLineComment && !inString)
+ {
+ multiLineComment = true;
+ hasComments = true;
+ i += 3;
+ }
+
+ // Process end of XML comment
+ else if (IsPair('-', '-', ch1, ch2) && ch3 == '>' && !inString)
+ {
+ multiLineComment = false;
+ i += 2;
+ }
+
+ // Process string
+ else if (ch3 == '"' && !multiLineComment)
+ {
+ inString = !inString;
+ hasCode = true;
+ }
+
+ else if (!multiLineComment)
+ {
+ if (!Char.IsWhiteSpace(ch1))
+ {
+ hasCode = true;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Scanning and Summation Methods
+ ///
+ /// Scans the solution and creates a hierarchy of
+ /// support objects for each project and file
+ /// within each project.
+ ///
+ private void ScanSolution()
+ {
+ if (m_summaryList == null)
+ m_summaryList = new List();
+
+ m_summaryList.Clear();
+
+ Solution solution = ProjectService.OpenSolution;
+ if (solution != null) // OpenSolution is null when no solution is opened
+ {
+ FileInfo fiSolution = new FileInfo(solution.FileName);
+ LineCountSummary summary = new LineCountSummary("All Projects", m_projIconMappings["{00000000-0000-0000-0000-000000000000}"]);
+ m_summaryList.Add(summary);
+
+ // Configure progress bars
+ tsprgTotal.Minimum = 0;
+ tsprgTotal.Step = 1;
+ tsprgTask.Minimum = 0;
+ tsprgTask.Step = 1;
+
+ List projects = new List(solution.Projects);
+ tsprgTotal.Maximum = projects.Count;
+ tsprgTask.Value = 0;
+ foreach (IProject fiProject in projects) {
+ tsprgTotal.PerformStep();
+ string projName, lang;
+ if (fiProject.FileName.IndexOf("://") != -1)
+ {
+ projName = fiProject.FileName; // this is a web project
+ lang = "{00000001-0000-0000-0000-000000000000}";
+ } else {
+ projName = fiProject.Name;
+ lang = fiProject.TypeGuid;
+ }
+
+ int iconIndex;
+ #if IMPR1
+ iconIndex = projectImageListHelper.GetIndex(IconService.GetImageForProjectType(fiProject.Language ?? "defaultLanguageName"));
+ #else
+ m_projIconMappings.TryGetValue(lang, out iconIndex); // default icon 0
+ #endif
+ summary = new LineCountSummary(projName, iconIndex);
+ m_summaryList.Add(summary);
+
+ tsprgTask.Maximum = 0;
+ tsprgTotal.Value = 0;
+ ScanProjectItems(fiProject.Items, summary);
+ }
+
+ tsprgTask.Value = tsprgTask.Maximum;
+ tsprgTotal.Value = tsprgTotal.Maximum;
+ }
+ else
+ {
+ MessageBox.Show("There is no solution open in SharpDevelop.", "Line Counter");
+ }
+ }
+
+ ///
+ /// Scans the project items (files, usually) of
+ /// a project's ProjectItems collection.
+ ///
+ /// The ProjectItems collection to scan.
+ /// The root summary data object that these
+ /// files belong to.
+ private void ScanProjectItems(List projectItems, LineCountSummary summary)
+ {
+ tsprgTask.Maximum += projectItems.Count;
+ foreach (ProjectItem projectItem in projectItems)
+ {
+ tsprgTask.PerformStep();
+ if (!(projectItem is FileProjectItem)) {
+ // Skip references and other special MSBuild things
+ continue;
+ }
+ string projectFile = projectItem.FileName;
+ if (!Directory.Exists(projectFile))
+ {
+ int iconIndex = 0;
+ #if IMPR1
+ iconIndex = fileImageListHelper.GetIndex(IconService.GetImageForFile(projectFile));
+ #else
+ m_fileIconMappings.TryGetValue(Path.GetExtension(projectFile), out iconIndex);
+ #endif
+ summary.FileLineCountInfo.Add(new LineCountInfo(projectFile, iconIndex, summary));
+ }
+ }
+ }
+
+ ///
+ /// Performs a complete counting and summation of all lines
+ /// in all projects and files.
+ ///
+ private void SumSolution()
+ {
+ try
+ {
+ // Clean the list
+ lvSummary.Items.Clear();
+ lvFileList.Items.Clear();
+ lvFileList.Groups.Clear();
+
+ // Configure progress bars
+ tsprgTotal.Minimum = 0;
+ tsprgTotal.Step = 1;
+ tsprgTask.Minimum = 0;
+ tsprgTask.Step = 1;
+
+ // Skip if there are no projects
+ if (m_summaryList == null || (m_summaryList != null && m_summaryList.Count == 1))
+ {
+ MessageBox.Show("There are no projects loaded to summarize.", "Line Counter");
+ return;
+ }
+
+ // Get all projects summary
+ LineCountSummary allProjects = m_summaryList[0];
+ allProjects.LineCountSummaryDetails.Reset();
+ AddSummaryListItem(allProjects, lvSummary.Groups["lvgAllProj"]);
+
+ tsprgTotal.Maximum = m_summaryList.Count;
+ tsprgTotal.Value = 0;
+ for (int s = 1; s < m_summaryList.Count; s++)
+ {
+ tsprgTotal.PerformStep();
+
+ LineCountSummary summary = m_summaryList[s];
+ summary.LineCountSummaryDetails.Reset();
+ AddSummaryListItem(summary, lvSummary.Groups["lvgEachProj"]);
+
+ tsprgTask.Maximum = summary.FileLineCountInfo.Count;
+ tsprgTask.Value = 0;
+ for (int i = 0; i < summary.FileLineCountInfo.Count; i++)
+ {
+ tsprgTask.PerformStep();
+
+ LineCountInfo info = summary.FileLineCountInfo[i];
+ if (m_countableTypes.Contains(info.FileType))
+ {
+ info.LineCountInfoDetails.Reset();
+ #if IMPR2
+ foreach (CountingAlgorithmDescriptor desc in countingAlgorithms) {
+ if (desc.CanCountLines(info)) {
+ desc.GetAlgorithm().CountLines(info);
+ break;
+ }
+ }
+ #else
+ try
+ {
+ CountLines counter = m_countAlgorithms[info.FileType];
+ counter(info);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ Console.WriteLine(ex.StackTrace);
+ }
+ #endif
+ info.LineCountInfoDetails.Summarize();
+
+ allProjects.LineCountSummaryDetails.Add(info.LineCountInfoDetails);
+ summary.LineCountSummaryDetails.Add(info.LineCountInfoDetails);
+
+ tstxtLinesCounted.Text = allProjects.LineCountSummaryDetails.TotalLines.ToString();
+
+ AddFileListItem(info);
+ }
+ }
+
+ summary.LineCountSummaryDetails.Summarize();
+ LineCountDetails details = summary.LineCountSummaryDetails;
+ summary.LinkedListViewItem.SubItems[1].Text = details.TotalLines.ToString();
+ summary.LinkedListViewItem.SubItems[2].Text = details.CodeLines.ToString();
+ summary.LinkedListViewItem.SubItems[3].Text = details.CommentLines.ToString();
+ summary.LinkedListViewItem.SubItems[4].Text = details.BlankLines.ToString();
+ summary.LinkedListViewItem.SubItems[5].Text = details.NetLines.ToString();
+ details = null;
+ }
+
+ allProjects.LineCountSummaryDetails.Summarize();
+ LineCountDetails totals = allProjects.LineCountSummaryDetails;
+ allProjects.LinkedListViewItem.SubItems[1].Text = totals.TotalLines.ToString();
+ allProjects.LinkedListViewItem.SubItems[2].Text = totals.CodeLines.ToString();
+ allProjects.LinkedListViewItem.SubItems[3].Text = totals.CommentLines.ToString();
+ allProjects.LinkedListViewItem.SubItems[4].Text = totals.BlankLines.ToString();
+ allProjects.LinkedListViewItem.SubItems[5].Text = totals.NetLines.ToString();
+
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ Debug.WriteLine(ex.StackTrace);
+ }
+
+ tsprgTotal.Value = tsprgTotal.Maximum;
+ }
+
+ ///
+ /// Obsolete. Useless. Dissapeared.
+ ///
+ private void PrepareFileListGroups()
+ {
+ lvFileList.Groups.Clear();
+ if (tsmiGroupByType.Checked)
+ {
+
+ }
+ else if (tsmiGroupByProj.Checked)
+ {
+ }
+ }
+
+ ///
+ /// Adds a summary item to the projects list view.
+ ///
+ /// The summary data object to reference.
+ /// The summary list view group this item
+ /// should be listed under.
+ private void AddSummaryListItem(LineCountSummary summary, ListViewGroup group)
+ {
+ ListViewItem lvi = new ListViewItem();
+ lvi.Text = summary.ProjectName;
+ lvi.SubItems.Add("0");
+ lvi.SubItems.Add("0");
+ lvi.SubItems.Add("0");
+ lvi.SubItems.Add("0");
+ lvi.SubItems.Add("0");
+
+ lvi.Tag = summary;
+ lvi.ImageIndex = summary.IconIndex;
+ //lvi.StateImageIndex = summary.IconIndex;
+ lvi.Group = group;
+
+ summary.LinkedListViewItem = lvi;
+
+ lvSummary.Items.Add(lvi);
+ }
+
+ ///
+ /// Adds a file information item to the file list view.
+ ///
+ /// The file information data object.
+ private void AddFileListItem(LineCountInfo info)
+ {
+ FileInfo fileInfo = new FileInfo(info.FileName);
+
+ ListViewItem lvi = new ListViewItem();
+ lvi.Text = fileInfo.Name;
+ lvi.SubItems.Add(info.LineCountInfoDetails.TotalLines.ToString());
+ lvi.SubItems.Add(info.LineCountInfoDetails.CodeLines.ToString());
+ lvi.SubItems.Add(info.LineCountInfoDetails.CommentLines.ToString());
+ lvi.SubItems.Add(info.FileType);
+ lvi.SubItems.Add(info.SumMode);
+
+ lvi.Tag = info;
+
+ lvi.ImageIndex = info.IconIndex;
+ //lvi.StateImageIndex = iconIndex;
+
+
+ if (tsmiGroupByType.Checked)
+ {
+ ListViewGroup group = lvFileList.Groups["groupType" + info.FileType.Substring(1)];
+ if (group == null)
+ {
+ group = new ListViewGroup("groupType" + info.FileType.Substring(1), info.FileType.Substring(1).ToUpper() + " Files");
+ lvFileList.Groups.Add(group);
+ }
+
+ lvi.Group = group;
+ }
+ else if (tsmiGroupByProj.Checked)
+ {
+ ListViewGroup group = lvFileList.Groups["groupProj" + info.ProjectSummary.ProjectName];
+ if (group == null)
+ {
+ group = new ListViewGroup("groupProj" + info.ProjectSummary.ProjectName, info.ProjectSummary.ProjectName + " Files");
+ lvFileList.Groups.Add(group);
+ }
+
+ lvi.Group = group;
+ }
+
+ lvFileList.Items.Add(lvi);
+ }
+ #endregion
+ #endregion
+ }
+
+ #region Support Structures
+ // Delegate for pluggable line counting methods
+ delegate void CountLines(LineCountInfo info);
+
+ ///
+ /// Encapsulates line count sum details.
+ ///
+ public class LineCountDetails
+ {
+ public LineCountDetails()
+ {
+ Reset();
+ }
+
+ private int m_totalLines;
+ private int m_codeLines;
+ private int m_commentLines;
+ private int m_doccmtLines;
+ private int m_normcmtLines;
+ private int m_blankLines;
+ private int m_netLines;
+
+ public int TotalLines
+ {
+ get { return m_totalLines; }
+ }
+
+ public int CodeLines
+ {
+ get { return m_codeLines; }
+ }
+
+ public int CommentLines
+ {
+ get { return m_commentLines; }
+ }
+
+ public int DocCommentLines
+ {
+ get { return m_doccmtLines; }
+ }
+
+ public int NormalCommentLines
+ {
+ get { return m_normcmtLines; }
+ }
+
+ public int BlankLines
+ {
+ get { return m_blankLines; }
+ }
+
+ public int NetLines
+ {
+ get { return m_netLines; }
+ }
+
+ public void Reset()
+ {
+ m_totalLines = 0;
+ m_codeLines = 0;
+ m_commentLines = 0;
+ m_doccmtLines = 0;
+ m_normcmtLines = 0;
+ m_blankLines = 0;
+ m_netLines = 0;
+ }
+
+ public void Summarize()
+ {
+ m_commentLines = m_doccmtLines + m_normcmtLines;
+ m_netLines = m_totalLines - m_blankLines;
+ }
+
+ public void Add(string toWhat, int amount)
+ {
+ if (toWhat == null)
+ toWhat = "totallines";
+
+ toWhat = toWhat.ToLower();
+ switch (toWhat)
+ {
+ case "totallines": m_totalLines += amount; break;
+ case "codelines": m_codeLines += amount; break;
+ case "doccmtlines": m_doccmtLines += amount; break;
+ case "normcmtlines": m_normcmtLines += amount; break;
+ case "blanklines": m_blankLines += amount; break;
+ }
+ }
+
+ public void Add(LineCountDetails details)
+ {
+ m_totalLines += details.m_totalLines;
+ m_codeLines += details.m_codeLines;
+ m_doccmtLines += details.m_doccmtLines;
+ m_normcmtLines += details.m_normcmtLines;
+ m_blankLines += details.m_blankLines;
+ }
+ }
+
+ ///
+ /// Wraps a project and the line count total detail
+ /// for that project. Enumerates all of the files
+ /// within that project.
+ ///
+ public class LineCountSummary
+ {
+ public LineCountSummary(string projName, int iconIndex)
+ {
+ m_fileLineCountInfo = new List();
+ m_lineCountSummaryDetails = new LineCountDetails();
+ m_projectName = projName;
+ m_iconIndex = iconIndex;
+ }
+
+ private List m_fileLineCountInfo;
+ private LineCountDetails m_lineCountSummaryDetails;
+ private string m_projectName;
+ private int m_iconIndex;
+
+ internal ListViewItem LinkedListViewItem;
+
+ public string ProjectName
+ {
+ get { return m_projectName; }
+ }
+
+ public int IconIndex
+ {
+ get { return m_iconIndex; }
+ }
+
+ public LineCountDetails LineCountSummaryDetails
+ {
+ get { return m_lineCountSummaryDetails; }
+ }
+
+ public List FileLineCountInfo
+ {
+ get { return m_fileLineCountInfo; }
+ }
+ }
+
+ ///
+ /// Wraps a project source code file and the line
+ /// count info for that file. Also provides details
+ /// about the file type and what icon should be shown
+ /// for the file in the UI.
+ ///
+ public class LineCountInfo
+ {
+ public LineCountInfo(string fileName, int iconIndex)
+ {
+ m_fileName = fileName;
+ m_fileType = Path.GetExtension(fileName);
+ m_iconIndex = iconIndex;
+ m_sumMode = "Generic";
+
+ m_lineCountInfoDetails = new LineCountDetails();
+ }
+
+ public LineCountInfo(string fileName, int iconIndex, LineCountSummary projectSummary) : this(fileName, iconIndex)
+ {
+ m_projectSummary = projectSummary;
+ }
+
+ private LineCountDetails m_lineCountInfoDetails;
+ private string m_fileName;
+ private string m_fileType;
+ private int m_iconIndex;
+ private LineCountSummary m_projectSummary;
+ private string m_sumMode;
+
+ public string FileName
+ {
+ get { return m_fileName; }
+ }
+
+ public string FileType
+ {
+ get { return m_fileType; }
+ }
+
+ public int IconIndex
+ {
+ get { return m_iconIndex; }
+ }
+
+ public string SumMode
+ {
+ get { return m_sumMode; }
+ set { m_sumMode = value; }
+ }
+
+ public LineCountDetails LineCountInfoDetails
+ {
+ get { return m_lineCountInfoDetails; }
+ }
+
+ public LineCountSummary ProjectSummary
+ {
+ get { return m_projectSummary; }
+ }
+ }
+ #endregion
+}
diff --git a/samples/LineCounter/Src/LineCounterBrowser.resx b/samples/LineCounter/Src/LineCounterBrowser.resx
new file mode 100644
index 0000000000..8357e1a487
--- /dev/null
+++ b/samples/LineCounter/Src/LineCounterBrowser.resx
@@ -0,0 +1,780 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 365, 17
+
+
+ 126, 17
+
+
+ 464, 17
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
+ LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+ ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAI
+ cAAAAk1TRnQBSQFMAgEBFAEAARgBAAEEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
+ AwABYAMAAQEBAAEgBgABYP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AKgABdQIhAeABgAEy
+ ATAB7QQAAVUCBQGaAZUBVQFWAf9wAAG3AaIBkwH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4
+ Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/0wA
+ AYABNAEzAfIBsQFlAWkB/wFzAj8B/wGVAVUBVgH/AXMCPwH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/
+ AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wgAAQMBngHeAf8BAwGeAd4B/wED
+ AZ4B3gH/AQMBngHeAf8BAwGeAd4B/wEDAZ4B3gH/AQMBngHeAf8BAwGeAd4B/wEDAZ4B3gH/AQMBngHe
+ Af8BAwGeAd4B/wEDAZ4B3gH/AQMBngHeAf8BAwGeAd4B/xAAATwCAgFiAfcB5QHcAf8BtwGiAZMB/wG3
+ AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGT
+ Af8BZgFMATgB/wgAAaQBigF7Af8BegFhAU0B/wF4AV4BSwH/AXYBXAFIAf8BdAFaAUUB/wFyAVcBQwH/
+ AXABVQFBAf8BbgFTAT8B/wFrAVEBPQH/AWoBTwE7Af8BaQFOATkB/wFnAU0BOAH/AWcBTQE4Af8BZgFL
+ ATYB/wQAAZgBWgFYAf8BfAI7AfkBwAFxAW0B/wG7AWQBYQH/Ab0BZgFdAf8B2gFzAXIB/wHEAmYB/wGW
+ AVwBVQH/AXABOAE5Af8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AWYBTAE4
+ Af8IAAEDAZ4B3gH/AdgD/wHTAf8B/gH/Ac4D/wHJA/8BxQP/AcAB/wH+Af8BvAH/Af4B/wG3A/8BswH/
+ Af4B/wGwAf8B/gH/Aa0B/wH+Af8BqgH/Af4B/wEDAZ4B3gH/CAABrALVAf8BrgG0AawB/wGuAZkBigH/
+ AfkB6QHiAf8B+AHmAd0B/wH3AeIB2AH/AfUB3gHTAf8B9AHbAc4B/wHzAdcBygH/AfIB1AHFAf8B8QHQ
+ AcEB/wHwAc0BvAH/AbcBogGTAf8BZgFMATgB/wgAAaQBigF7Af8BxwP/AYoB4wH1Af8BggHgAfQB/wF8
+ AdwB9AH/AXMB2QH0Af8BagHVAfMB/wFhAdEB8wH/AVgBzgHzAf8BTgHJAfEB/wFFAcYB8AH/AT0BwgHx
+ Af8BPQHCAfEB/wFoAU4BOAH/BAAB3AGHAYYB/wHAAXgBegH/AdwBhwGGAf8BigFUAVUB/wG+AZkBlwH/
+ AcUBhAGCAf8BxAJmAf8BsQFZAVoB/wGxAVkBWgH/AfMB1wHKAf8B8gHUAcUB/wHxAdABwQH/AfABzQG8
+ Af8BtwGiAZMB/wFmAUwBOAH/CAABAwGeAd4B/wHUA/8BPQGfAVkB/wFCAYABSgH/AToBcAFBAf8BMgFh
+ ATkB/wEqAVMBMgH/AbQB/wH+Af8BsAH/Af4B/wGrAf8B/gH/AacB/wH+Af8BpwH/Af4B/wGsAf8B/gH/
+ AQMBngHeAf8QAAE8AgIBYgH5Ae4B6AH/AUIBgAFKAf8BOgFwAUEB/wEyAWEBOQH/ASsBUwEzAf8BkgFX
+ AVkB/wGAAUYBRwH/AXEBOQE6Af8B8QHRAcIB/wG3AaIBkwH/AWYBTAE4Af8IAAGsAZEBggH/AdQD/wHO
+ A/8ByAH/Af4B/wHEAf8B/gH/Ab4D/wG5A/8BtAH/Af4B/wGwAf8B/gH/AasB/wH+Af8BpwH/Af4B/wGn
+ Af8B/gH/AVUBzAHyAf8BbQFTAT4B/wQAAQ0CAQEQAdMBhwGGAf8B4AGPAY0B/wF1AkEB/wHZAcQBwAH/
+ AdUBtAGxAf8BzQJxAf8BsQFZAVoB/wHyAdUBywH/AfUB2wHQAf8B8wHYAcsB/wHyAdUBxgH/AfEB0QHC
+ Af8BtwGiAZMB/wFmAUwBOAH/CAABAwGeAd4B/wHZAf8B/gH/AU0BqQFmAf8B4QHVAc4B/wHWAcYBvgH/
+ AcwBuAGtAf8BMQFgAToB/wG6Af8B/gH/AbYB/wH+Af8BsQH/Af4B/wGsAf8B/gH/AawB/wH+Af8BsAH/
+ Af4B/wEDAZ4B3gH/CAABrALVAf8BrgG0AawB/wGuAZkBigH/AfsB8gHtAf8BRAGkAV8C/wH4A/8B+AL/
+ ATIBYQE6Av8B+AP/AfgC/wGAAUUBRgH/AfMB1QHHAf8BtwGiAZMB/wFmAUwBOAH/CAABsAGXAYcB/wHZ
+ Af8B/gH/AdUD/wHPAf8B/gH/AcoB/wH+Af8BxwGyAaUB/wG/Af8B/gH/AboB/wH+Af8BtgH/Af4B/wGx
+ Af8B/gH/AawB/wH+Af8BrAH/Af4B/wFiAdEB8wH/AXEBVgFCAf8EAAHdAZABjgH/AeUBpAGmAf8B8AKo
+ Af8BqgFuAXEB/wGDAVgBVwH/AZMCYQH/AcIBbwFwAf8BsQFZAVoB/wFwATgBOQH/AfYB4QHVAf8B9QHc
+ AdEB/wH0AdgBzAH/AfMB1QHHAf8BtwGiAZMB/wFmAUwBOAH/CAABAwGeAd4B/wHfA/8BXQG0AXMB/wHq
+ AeEB3AH/AZkBNgEDAf8B1AHEAbsB/wE6AXABQQH/AcEB/wH+Af8B/AGSAWAB/wHPAXUBRwH/AaYBWwE2
+ Af8BsgH/Af4B/wG0Af8B/gH/AQMBngHeAf8QAAE8AgIBYgH8AfYB8wH/AU8BqgFoAv8B+AP/AfgC/wE6
+ AXEBQQL/AfgD/wH4Av8BkgJYAf8B8wHaAc0B/wG3AaIBkwH/AWYBTAE4Af8IAAG1AZsBjAH/Ad8D/wGz
+ AZkBiwH/AbMBmgGKAf8B0AH/Af4B/wHGAbEBpgH/AcYB/wH+Af8BwAGqAZ0B/wGzAZkBiwH/AaYBiwF9
+ Af8BmwGBAXIB/wGyAf8B/gH/AW4B1wHzAf8BdAFbAUcB/wQAAXgCIwHDAb0CagHzAbQCYgHnAe0BqQGo
+ Af8B3QGJAYYB/wHWAYABegH/AcIBbwFwAf8BwAJ1Af8BvQF1AXYB/wH3AeUB2wH/AfYB4QHXAf8B9AHe
+ AdMB/wHzAdoBzQH/AbcBogGTAf8BZgFMATgB/wgAAQMBngHeAf8B5QP/AW0BvgGBAf8B8gHtAesB/wHo
+ Ad8B2gH/Ad4B0AHKAf8BQgGBAUoB/wHHAf8B/gH/AcEB/wH+Af8BvAH/Af4B/wG4Af8B/gH/AbgB/wH+
+ Af8BuQH/Af4B/wEDAZ4B3gH/CAABrALVAf8BrgG0AawB/wGuAZkBigH/AdABtgGYAf8BfwF+AVEB/wGu
+ AXgBWAH/AbwBmAGEAf8BYQFRAYAB/wEwAScBcAH/ASYBHAFlAf8BHwETAV0B/wH1Ad8B0wH/AbcBogGT
+ Af8BZgFMATgB/wgAAboBoQGTAf8B5QP/AeED/wHcA/8B1wH/Af4B/wHHAbIBpgH/AcwB/wH+Af8B9wHz
+ AfEB/wHqAeEB3QH/AdsBzgHGAf8BnAGBAXIB/wG4Af8B/gH/AXoB2wH0Af8BeAFeAUsB/wwAAbQBYgFl
+ AesB2wGfAZ4B/wHQAYIBgQH/Ac4BgQF9Af8BuQFyAXMB/wH6AfAB6wH/AfoB7QHnAf8B+AHpAeEB/wH3
+ AeUB3QH/AfYB4gHYAf8B9QHfAdMB/wG3AaIBkwH/AWYBTAE4Af8IAAEDAZ4B3gH/AesB/wH+Af8BfQHH
+ AYsB/wFwAcABgQH/AWIBtwF5Af8BVQGvAWwB/wFHAaYBYQH/Ac0B/wH+Af8ByAH/Af4B/wHDA/8BvQH/
+ Af4B/wG9Af8B/gH/Ab4B/wH+Af8BAwGeAd4B/xAAAfMBwgGrAf8B1QGBAU8B/wE0AZoBDAH/AWUBgQEl
+ Af8BwAFeASwB/wGlAZcBhQL/AfgD/wH4Av8BKAEfAWcB/wH2AeIB2gH/AbcBogGTAf8BZgFMATgB/wgA
+ Ab4BpwGZAf8B6wH/Af4B/wGzAZkBiwH/AbMBmQGKAf8B3AH/Af4B/wHHAbEBpgH/AdID/wHNAf8B/gH/
+ AcgB/wH+Af8BwwP/Ab0B/wH+Af8BvQH/Af4B/wGCAeAB9QH/AXwBYgFQAf8MAAHdAZwBmwH/AdMBlAGO
+ Af8B/QH2AfUB/wHOAYEBfQH/Ab0BdQF2Af8B/AH0AfAB/wH7AfEB7QH/AfoB7gHoAf8B+AHqAeQB/wH3
+ AecB3wH/AfYB4gHaAf8BtwGiAZMB/wFmAUwBOAH/CAABAwGeAd4B/wHwA/8BPQGfAVkB/wFCAYABSgH/
+ AToBcAFBAf8BMgFhATkB/wEqAVMBMgH/AdMD/wHOAf8B/gH/AcgD/wHDAf8B/gH/AcMB/wH+Af8BwwH/
+ Af4B/wEDAZ4B3gH/EAAB9AGbAXYB/wGBAYYBNAH/AVwBrwEOAf8ByAGCAScB/wFWAX8BLQH/AUYBmwEo
+ Av8B+AP/AfgC/wE3AS4BdgH/AfgB6AHfAf8BtwGiAZMB/wFmAUwBOAH/CAABwgGrAZ8B/wHwA/8B7AP/
+ AecD/wHjA/8BxwGxAaUB/wHYAf8B/gH/AcABqgGdAf8BswGZAYsB/wGmAYsBfQH/AZsBgQFyAf8BwwH/
+ Af4B/wGNAeQB9gH/AYABZwFUAf8QAAHDAa4BngH/A/4B/wH+Af0B/AH/Af0B+gH4Af8B/QH4AfUB/wH8
+ AfQB8QH/AfsB8gHtAf8B+gHuAekB/wH5AesB5QH/AfgB6AHfAf8BtwGiAZMB/wFmAUwBOAH/CAABAwGe
+ Ad4B/wH0A/8BTQGpAWYB/wHhAdUBzgH/AdYBxgG+Af8BzAG4Aa0B/wExAWABOgH/AdkD/wHVA/8BzwP/
+ AcoB/wH+Af8BygH/Af4B/wHIA/8BAwGeAd4B/xAAAacBlQFiAf8BAwG0ASoB/wKdATwC/wF5AToB/wFl
+ Aa8BEQH/AT0BugEbAf8BZAFpAd0B/wFWAVwB2QH/AUgBQgGFAf8B+QHsAeYB/wG3AaIBkwH/AWYBTAE4
+ Af8IAAHGAbABpAH/AfQD/wGzAZkBiwH/AbMBmQGLAf8B6AP/AccBsQGmAf8B3wP/AfcB8wHxAf8B6gHh
+ Ad0B/wHbAc4BxgH/AZwBgQFyAf8BygH/Af4B/wGYAegB9gH/AYIBbAFZAf8QAAHIAbIBowr/Af0B/AH/
+ Af0B+wH5Af8B/QH5AfYB/wH8AfUB8gH/AfsB8gHuAf8B+wHvAeoB/wH5AewB5gH/AbcBogGTAf8BZgFM
+ ATgB/wgAAQMBngHeAf8B+AP/AV0BtAFzAf8B6gHhAdwB/wGZATYBAwH/AdQBxAG7Af8BOgFwAUEB/wHf
+ A/8B/AGSAWAB/wHPAXUBRwH/AaYBWwE2Af8B0AH/Af4B/wHNA/8BAwGeAd4B/xAAAaYB0AGfAf8BOwH4
+ AXIB/wGXAekBjwH/AcEBpwFVAf8BvAGZARsB/wGWAdUBdwH/Af0B+QH3Af8B/AH2AfMB/wH7AfQB7wH/
+ AbcBogGTAf8BtwGiAZMB/wFnAU0BOQH/CAABygG1AasB/wH4A/8B9QP/AfED/wHuA/8B6QP/AeQD/wHf
+ A/8B2wH/Af4B/wHVAf8B/gH/AdAB/wH+Af8B0AH/Af4B/wGfAesB9wH/AYYBcQFfAf8QAAHMAbYBpw7/
+ Av0B/wH+AfsB+gH/Af0B+QH3Af8B/AH2AfMB/wH7AfQB7wH/AbcBogGTAf8BtwGiAZMB/wFnAU0BOQH/
+ CAABAwGeAd4B/wH8A/8BbQG+AYEB/wHyAe0B6wH/AegB3wHaAf8B3gHQAcoB/wFCAYEBSgH/AeYD/wHg
+ A/8B2wP/AdcD/wHXA/8B0gP/AQMBngHeAf8QAAHQAcgBsQH/Ac0B6QHAAf8BowHwAZkB/wE9AdwBZwH/
+ AdwBvgGMAf8B8AH2AesB/wH+AvsB/wH9AfkB+AH/AbcBogGTAf8BZwFNATkB/wFnAU0BOQH/AWcBTQE5
+ Af8IAAHOAbwBsQH/AfwD/wEDATYC/wHqAZ0BeQH/AeoBkwFrAf8B6gGKAVsB/wHqAYEBTQH/AeYBegFC
+ Af8B3gFyATkB/wHUAWoBMwH/AccBYgEvAf8B1wP/AacB7gH3Af8BiwF2AWQB/xAAAdEBuwGrEv8B/gH9
+ Af8B/gL7Af8B/QH5AfgB/wG3AaIBkwH/AWcBTQE5Af8BZwFNATkB/wFnAU0BOQH/CAABAwGeAd4F/wF9
+ AccBiwH/AXABwAGBAf8BYgG3AXkB/wFVAa8BbAH/AUcBpgFhAf8B6wH/Af4B/wHmA/8B4gP/Ad0D/wHd
+ A/8B2AP/AQMBngHeAf8QAAHVAb8Brxb/Av4B/wH+AfwB+wH/AbkBpAGVAf8B1AHFAboB/wFmAUwBOAH/
+ AVsBDQEMAakIAAHUAcIBuQX/AccBsQGmAf8BtAGZAYoB/wGhAYYBdwH/AfMD/wHvA/8B6wH/Af4B/wHm
+ A/8B4gP/Ad0D/wHdA/8BqwHwAfcB/wGQAXsBaQH/EAAB1QG/Aa8W/wL+Af8B/gH8AfsB/wG5AaQBlQH/
+ AdQBxQG6Af8BZgFMATgB/wFbAQ0BDAGpCAABAwGeAd4J/wH+A/8B+gP/AfcD/wHzA/8B8AP/AewD/wHn
+ Af8B/gH/AeID/wHeA/8B3gP/AQMBngHeAf8QAAHYAcIBshv/Af4B/wHAAasBnAH/AWYBTAE4Af8BWwEN
+ AQwBqAwAAdgByQHACf8B/gP/AfoD/wH3A/8B8wP/AfAD/wHsA/8B5wH/Af4B/wHiA/8B3gP/Ad4D/wGU
+ AYABbwH/EAAB2AHCAbIb/wH+Af8BwAGrAZwB/wFmAUwBOAH/AVsBDQEMAagMAAEDAZ4B3gH/AQMBngHe
+ Af8BAwGeAd4B/wEDAZ4B3gH/AQMBngHeAf8BAwGeAd4B/wEDAZ4B3gH/AQMBngHeAf8BAwGeAd4B/wED
+ AZ4B3gH/AQMBngHeAf8BAwGeAd4B/wEDAZ4B3gH/AQMBngHeAf8QAAHYAcIBsgH/AdgBwgGyAf8B2AHC
+ AbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHUAb4BrgH/Ac8BuQGpAf8ByQGzAaQB/wFPAgYBixAA
+ Ad0BzwHIAf8B2gHLAcIB/wHWAcYBvQH/AdIBwQG3Af8B0AG8AbIB/wHMAbgBrQH/AckBswGpAf8BxgGw
+ AaQB/wHDAawBoAH/AcABqQGcAf8BvQGlAZcB/wG6AaEBkwH/AboBoQGTAf8BmQGCAXQB/xAAAdgBwgGy
+ Af8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdQBvgGuAf8BzwG5AakB/wHJ
+ AbMBpAH/AU8CBgGL0AABtwGiAZMB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4
+ Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFm
+ AUwBOAH/CAABtwGiAZMB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFM
+ ATgB/yQAAaQBigF7Af8BegFhAU0B/wF4AV4BSwH/AXYBXAFIAf8BdAFaAUUB/wFyAVcBQwH/AXABVQFB
+ Af8BbgFTAT8B/wFrAVEBPQH/AWoBTwE7Af8BaQFOATkB/wFnAU0BOAH/AWYBSwE2Af8MAAG3AaIBkwH/
+ AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFM
+ ATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/xAAAbcBogGTAf8B9wHlAdwB/wHdAc8ByAH/AdgByQHB
+ Af8B0wHCAbkB/wHPAbwBsgH/AcoBtgGqAf8BxgGwAaQB/wHCAasBngH/Ab4BpgGYAf8BugGgAZIB/wG0
+ AZoBjAH/AbABlQGGAf8BZgFMATgB/wgAAbcBogGTAf8B+QHtAecB/wHnAd4B2QH/AeQB2AHSAf8B3wHR
+ AcsB/wHZAcsBwwH/AWYBTAE4Af8kAAGkAYoBewH/AccD/wGKAeMB9QH/AYIB4AH0Af8BfAHcAfQB/wFz
+ AdkB9AH/AWoB1QHzAf8BYQHRAfMB/wFYAc4B8wH/AU4ByQHxAf8BRQHGAfAB/wE9AcIB8QH/AWgBTgE4
+ Af8MAAG3AaIBkwH/AfcB5QHcAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/
+ AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BZgFMATgB/xAAAbcBogGTAf8B+QHpAeIB/wH5
+ AekB4gH/AfkB6QHiAf8B+AHmAd0B/wH3AeIB2AH/AfUB3gHTAf8B9AHbAc4B/wHzAdcBygH/AfIB1AHF
+ Af8B8QHQAcEB/wHwAc0BvAH/AbYBnAGOAf8BZgFMATgB/wgAAbcBogGTAf8B+wHzAe8B/wH6Ae0B5wH/
+ AfgB5wHfAf8B0QG7Aa4B/wHAAbABpgH/AWYBTAE4Af8BKwIBAUABKwIBAUABKwIBAUABKwIBAUABKwIB
+ AUAQAAGoAY0BfwH/Ac0D/wHIA/8BwgH/Af4B/wG9Af8B/gH/AbgD/wGzAf8B/gH/Aa8D/wGrA/8BpwH/
+ Af4B/wGjAf8B/gH/AUgBxwHxAf8BawFQATsB/wwAAbcBogGTAf8B+QHpAeIB/wH4AeYB3QH/AfcB4gHY
+ Af8B9QHeAdMB/wH0AdsBzgH/AfMB1wHKAf8B8gHUAcUB/wHvAcwBuwH/AdsBnQF9Af8BewF6AS8B/wFg
+ AWsBNwH/AZ8BZQFBAf8BeQEhARQB1QEOAgEBEQQAAbcBogGTAf8B+QHuAegB/wH5Ae4B6AH/AfkB7gHo
+ Af8B6gGPAWMB/wHqAYQBUgH/AeYBewFCAf8B3wFyATkB/wHSAWkBMwH/AcEBYAEtAf8B8gHVAcYB/wHx
+ AdEBwgH/AbwBowGVAf8BZgFMATgB/wgAAboBpQGWAf8B/QH4AfUB/wH8AfMB7wH/AbcBogGTAf8BZgFM
+ ATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wErAgEBQBAA
+ AawBkQGCAf8B1AP/Ac8BZwExAf8BugFdASsB/wGlAVMBKAH/AZMBSgElAf8BuQP/Ac8BZwExAf8BugFd
+ ASsB/wGlAVMBKAH/AZMBSgElAf8BVQHMAfIB/wFtAVMBPgH/DAABtwGiAZMB/wH5Ae4B6AH/AfgB6gHj
+ Af8B+AHmAd4B/wH3AeMB2QH/AfUB3wHVAf8B9QHbAdAB/wHzAdgBywH/AesBsgGUAf8B9QGJAV0B/wGG
+ AYEBPAH/ASoBiwEfAf8BaAFxATcB/wGtAWgBQwH/AZABWgFQAecEAAG3AaIBkwH/AfsB8gHtAf8B+wHy
+ Ae0B/wH7AfIB7QH/AfoB7gHpAf8B+QHqAeQB/wH4AecB4AH/AfcB5AHaAf8B9gHhAdUB/wH1AdwB0QH/
+ AfQB2AHMAf8B8wHVAccB/wHCAaoBngH/AWYBTAE4Af8IAAG+AakBmgH/Af4B/AH6Af8B/QH3AfUB/wG3
+ AaIBkwH/AfgB5wHgAf8B2gHMAcQB/wHUAcMBuwH/Ac4BvAGxAf8ByQG1AakB/wHEAa0BoQH/AWYBTAE4
+ Af8BKwIBAUAQAAGwAZcBhwH/AdkB/wH+Av8BrAGBAf8B8wHYAcwB/wHwAc4BvgH/AaUBUgEoAf8BvwH/
+ Af4C/wGsAYEB/wHzAdgBzAH/AfABzgG+Af8BpQFSASgB/wFiAdEB8wH/AXEBVgFCAf8MAAG3AaIBkwH/
+ AfsB8gHtAf8B5gF7AUMB/wHeAXEBOQH/AfgB5wHgAf8BxAGuAaIB/wHAAakBnAH/AbsBogGVAf8B8wGa
+ AXQB/wG9AYMBYQH/AVkBkQFAAf8BawGhAS8B/wGwAX8BRAH/AWIBagFBAf8BNwF7ASUB/wQAAbcBogGT
+ Af8B/AH2AfMB/wH8AfYB8wH/AfwB9gHzAf8B6gGPAWMB/wHqAYQBUgH/AeYBewFCAf8B3wFyATkB/wHS
+ AWkBMwH/AcEBYAEtAf8B9AHeAdMB/wHzAdoBzQH/AccBsQGlAf8BZgFMATgB/wgAAcMBrgGeBf8B/gH8
+ AfsB/wG3AaIBkwH/AfoB7QHnAf8B+gHtAecB/wH6Ae0B5wH/AfoB7QHnAf8B+gHtAecB/wHJAbUBqgH/
+ AWYBTAE4Af8BKwIBAUAQAAG1AZsBjAH/Ad8E/wG0AYsC/wGoAXwC/wGbAWkB/wH3AY4BXAH/AcYB/wH+
+ Av8BtAGLAv8BqAF8Av8BmwFpAf8B9wGOAVwB/wFuAdcB8wH/AXQBWwFHAf8MAAG3AaIBkwH/AfwB9gHz
+ Af8B+wHyAe4B/wH7Ae8B6gH/AfkB6wHmAf8B+QHoAeEB/wH3AeUB2wH/AfYB4QHXAf8B3gGcAXkB/wFL
+ AZYBTQH/AWABpAFMAf8B0gGRAWEB/wHeAYYBXAH/AVYBkQEtAf8BNQGUARoB/wQAAboBpQGWAf8B/QH5
+ AfYB/wH9AfkB9gH/Af0B+QH2Af8B/AH2AfMB/wH8AfMB7wH/AfoB8AHrAf8B+gHtAecB/wH4AekB4QH/
+ AfcB5QHdAf8B9gHiAdgB/wH1Ad8B0wH/AcwBuAGuAf8BZgFMATgB/wgAAdkByQHAAf8B0wHCAbkB/wHN
+ AbsBsQH/AbsBpgGXAf8B+wHyAe4B/wEYARYBgAH/Aa4BogG+Af8B9gHiAdgB/wHHAbUBwQH/AdABvQG0
+ Af8BZgFMATgB/wErAgEBQBAAAboBoQGTAf8B5QP/AeED/wHcA/8BlwGBAXIB/wHRA/8BzAH/Af4B/wHH
+ Af8B/gH/AW0BUgE+Af8BvAH/Af4B/wG4Af8B/gH/AXoB2wH0Af8BeAFeAUsB/wwAAboBpQGWAf8B/QH5
+ AfYB/wHmAXsBQwH/Ad4BcQE5Af8B+gHwAesB/wHEAa4BogH/AcABqAGcAf8BuwGiAZQB/wGdAZwBbQH/
+ AUkByQFuAf8BdQHNAYcB/wGwAbEBgQH/AeYBkQFkAf8BmAGaATsB/wFtAbABWQH8BAABvgGpAZoB/wH+
+ AfwB+wH/Af4B/AH7Af8BpQFSASgB/wH9AfkB+AH/AasBuAGRAf8BVwF7ATAB/wGKAXMBSwH/Ac4BsQGe
+ Af8B+AHqAeQB/wGlAVIBKAH/AfYB4gHaAf8B0gHAAbgB/wFmAUwBOAH/FAABwQGrAZwB/wH9AfcB9QH/
+ AcUBvAHRAf8BGAEWAYAB/wGsAaEBvwH/AgMBdwH/AdYBxgG9Af8BZgFMATgB/wErAgEBQBAAAb4BpwGZ
+ Af8B6wH/Af4B/wHmA/8B4QP/AaQBjgGBAf8BlwGBAXIB/wGKAXUBYwH/AYEBaAFVAf8BdQFcAUkB/wHD
+ A/8BvQH/Af4B/wGCAeAB9QH/AXwBYgFQAf8MAAG+AakBmgH/Af4B/AH7Af8B/QH5AfgB/wH9AfcB9AH/
+ AfwB9AHwAf8B+wHxAe0B/wH6Ae4B6AH/AfgB6gHkAf8B1gHaAcAB/wF6AdwBkQH/AcoB9AHFAf8BugHk
+ AbEB/wGUAa0BcgH/AboBigFBAf8BWgEQAQoBqQQAAcMBrgGeAf8D/gH/AaUBUgEoAf8D/gH/Af4B/QH8
+ Af8BgQGCAT4B/wGQAZMBRQH/AXMBegE0Af8BeQGnAWoB/wH6Ae4B6QH/AfkB6wHlAf8BpQFSASgB/wHZ
+ AckBwQH/AWYBTAE4Af8UAAHHAbIBowH/Af4B+wH5Af8B+wH0AfEB/wHGAb4B0wH/ARgBFwGBAf8BMgEv
+ AYkB/wHWAcYBvQH/AWYBTAE4Af8BKwIBAUAQAAHCAasBnwH/AfAD/wHsA/8B5wP/AeMD/wHeA/8BlwGB
+ AXIB/wHTA/8BzgH/Af4B/wHIA/8BwwH/Af4B/wGNAeQB9gH/AYABZwFUAf8MAAHDAa4BngH/A/4B/wHm
+ AXsBQwH/Ad4BcQE5Af8B/QH4AfUB/wHEAa4BogH/AcABqAGbAf8BuwGiAZQB/wG2AZwBjQH/AeEB4AHG
+ Af8BwAHWAakB/wGGAcoBiwH/AVQBPgEfAdMBSgEEAQMBggEOAgEBEQQAAcgBsgGjCf8BpQFSASgF/wFm
+ AbYBZQH/AcMByAGdAf8BogGRAT0B/wGcAcYBigH/AfsB8gHuAf8BpQFSASgB/wH5AewB5gH/Ad8B0gHM
+ Af8BZgFMATgB/xQAAc8BuQGpA/8B/gH/AcoBxwHdAf8CAwF3Af8BOAE2AY4B/wIDAXcB/wHdAc8ByAH/
+ AWcBTQE5Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8IAAHGAbABpAH/AfQD/wHwA/8B7QP/Ad4BcQE5
+ Af8BzwFnATEB/wG6AV0BKwH/AaUBUwEoAf8BkwFKASUB/wHPA/8BygH/Af4B/wGYAegB9gH/AYIBbAFZ
+ Af8MAAHIAbIBowr/Af0B/AH/Af0B+wH5Af8B/QH5AfYB/wH8AfUB8gH/AfsB8gHuAf8B+wHvAeoB/wH5
+ AewB5gH/AbcBogGTAf8BZgFMATgB/xAAAcwBtgGnEf8B1gHyAdIB/wGZAcoBiwH/AawBrwF/Af8B7wHx
+ AeYB/wH8AfYB8wH/AfsB9AHvAf8B6gHiAd0B/wHlAdsB1QH/AWcBTQE5Af8UAAHUAb4Brwr/Av0C/wL9
+ Af8IAAFnAU0BOQH/AYEBvAHFAf8BfwHdAfQB/wFmAUwBOAH/CAABygG1AasB/wH4A/8B9QP/AfEE/wGk
+ AXYB/wH3AeMB2wH/AfMB2AHMAf8B8AHOAb4B/wGlAVIBKAH/AdUB/wH+Af8B0AH/Af4B/wGfAesB9wH/
+ AYYBcQFfAf8MAAHMAbYBpwX/AeYBewFDAf8B3gFxATkC/wL9Af8BxQGuAaIB/wHAAakBmwH/AfwB9gHz
+ Af8B+wH0Ae8B/wG3AaIBkwH/AbcBogGTAf8BZwFNATkB/xAAAdEBuwGrGv8B/gH9Af8B/gL7Af8B/QH5
+ AfgB/wG3AaIBkwH/AWcBTQE5Af8BZwFNATkB/wFnAU0BOQH/FAAB2AHCAbIR/wgAAWcBTQE5Af8BwAH/
+ Af4B/wGGAeEB9QH/AWYBTAE4Af8IAAHOAbwBsQH/AfwD/wH5A/8B9QT/AawBgQH/AfwB9AHwAf8B+QHq
+ AeMB/wH1Ad4B0wH/AboBXAErAf8B2wP/AdcD/wGnAe4B9wH/AYsBdgFkAf8MAAHRAbsBqxL/Af4B/QH/
+ Af4C+wH/Af0B+QH4Af8BtwGiAZMB/wFnAU0BOQH/AWcBTQE5Af8BZwFNATkB/xAAAdUBvwGvHv8C/gH/
+ Af4B/AH7Af8BuQGkAZUB/wHUAcUBugH/AWYBTAE4Af8BWwENAQwBqRQAAdgBwgGyAf8B2AHCAbIB/wHU
+ Ab8BrgH/AdQBvwGuAf8BzgG4AakB/wHIAbIBowH/Ac4BuAGpAf8ByAGyAaMB/wHMAf8B/gH/AZAB5QH1
+ Af8BZgFMATgB/wgAAdQBwgG5Bf8B/QP/AfoE/wG0AYsC/wGoAXwC/wGbAWkB/wH3AY4BXAH/Ac4BZwEx
+ Af8B4gP/Ad0D/wGrAfAB9wH/AZABewFpAf8MAAHVAb8Brxb/Av4B/wH+AfwB+wH/AbkBpAGVAf8B1AHF
+ AboB/wFmAUwBOAH/AVsBDQEMAakQAAHYAcIBsiP/Af4B/wHAAasBnAH/AWYBTAE4Af8BWwENAQwBqCgA
+ Ab4BqQGaAf8B+QP/Ae8D/wHlA/8B2AH/Af4B/wGYAegB9QH/AWYBTAE4Af8IAAHYAckBwAn/Af4D/wH6
+ A/8B9wP/AfMD/wHwA/8B7AP/AecB/wH+Af8B4gP/Ad4D/wGUAYABbwH/DAAB2AHCAbIb/wH+Af8BwAGr
+ AZwB/wFmAUwBOAH/AVsBDQEMAagUAAHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGy
+ Af8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B1AG+Aa4B/wHPAbkBqQH/AckBswGkAf8BTwIGAYssAAHD
+ Aa4BngX/AfgD/wHwA/8B5QP/AdkD/wFmAUwBOAH/CAAB3QHPAcgB/wHaAcsBwgH/AdYBxgG9Af8B0gHB
+ AbcB/wHQAbwBsgH/AcwBuAGtAf8ByQGzAakB/wHGAbABpAH/AcMBrAGgAf8BwAGpAZwB/wG9AaUBlwH/
+ AboBoQGTAf8BmQGCAXQB/wwAAdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHY
+ AcIBsgH/AdQBvgGuAf8BzwG5AakB/wHJAbMBpAH/AU8CBgGLdAAB2QHJAcAB/wHTAcIBuQH/Ac0BuwGx
+ Af8ByQG0AakB/wHFAa8BogH/AcEBqQGcAf8BrQGSAYMB/4QAAS4CAQFGAZMBZQFMAf8BjgFgAUcB/wGI
+ AVsBQgH/AYEBVAE6Af8BLgIBAUYIAAEuAgEBRgGTAWUBTAH/AY4BYAFHAf8BiAFbAUIB/wGBAVQBOgH/
+ AS4CAQFGVAABtwGiAZMB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFM
+ ATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8MAAG3AaIBkwH/AWYBTAE4
+ Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFm
+ AUwBOAH/AWYBTAE4Af8BZgFMATgB/wgAAaUBeAFdAf8B/QH4AfYB/wH8AfQB8AH/AfoB7wHpAf8B+QHp
+ AeMB/wGGAVoBQAH/AWYBTAE4Af8BZgFMATgB/wGlAXgBXQH/Af0B+AH2Af8B/AH0AfAB/wH6Ae8B6QH/
+ AfkB6QHjAf8BhgFaAUAB/wwAAbcBogGTAf8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFm
+ AUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8gAAG3AaIBkwH/AfcB5QHcAf8BtwGi
+ AZMB/wHaAcwBxQH/AdcBxwG+Af8B0wHCAbkB/wHPAb0BswH/AcwBtwGtAf8ByAGzAagB/wHFAa8BowH/
+ AcIBqwGeAf8BZgFMATgB/wwAAbcBogGTAf8BtAH/Af4B/wFwAdcB8wH/AWcB0wHzAf8BXgHQAfIB/wFV
+ AcwB8gH/AUwByQHyAf8BQgHFAfEB/wE6AcEB8AH/ATIBvQHvAf8BKgG6Ae4B/wFmAUwBOAH/CAABsgGC
+ AWkB/wHdAaUBhQH/AeABrgGRAf8B5gG6AaIB/wHrAccBtQH/AZIBZQFLAf8BtwGiAZMB/wG3AaIBkwH/
+ AbIBggFpAf8B3QGlAYUB/wHgAa4BkQH/AeYBugGiAf8B6wHHAbUB/wGSAWUBSwH/DAABtwGiAZMB/wH8
+ AfQB8gH/AeEB3AHYAf8B4AHXAdIB/wHfAdIBygH/Ad8BzgHDAf8B3QHIAbsB/wHcAcMBswH/AcUBrwGj
+ Af8BZgFMATgB/yAAAbcBogGTAf8B+QHpAeIB/wH4AeYB3QH/AfcB4gHYAf8B9QHeAdMB/wH0AdsBzgH/
+ AfMB1wHKAf8B8gHUAcUB/wHhAYEBTwH/Ab4BawFBAf8BxQGvAaMB/wFmAUwBOAH/DAABtwGiAZMB/wG8
+ Af8B/gH/AbYB/wH+Af8BsgH/Af4B/wGuAf8B/gH/AakB/wH+Af8BpgH/Af4B/wGiAf8B/gH/AZ8B/wH+
+ Af8BnAH/Af4B/wE0Ab4B7wH/AWYBTAE4Af8IAAG7AYsBcQH/Ad0BpQGFAf8B4QGtAZEB/wHmAboBogH/
+ AeoByAG1Af8BoAFzAVgB/wH1Ad4B0wH/AfQB2wHOAf8BuwGLAXEB/wHdAaUBhQH/AeEBrQGRAf8B5gG6
+ AaIB/wHqAcgBtQH/AaABcwFYAf8MAAG3AaIBkwH/Af0B+AH1Af8B/AH0AfEB/wH7AfEB7QH/AfoB7gHn
+ Af8B+AHpAeIB/wH3AeUB3QH/AVYBfgGTAf8BTQFaAWkB/wFHAVQBYwH/AUIBTgFeAf8BPgFKAVgB/wE7
+ AUYBVQH/ATkBQwFRAf8BNwFBAU4B/wwAAbcBogGTAf8B+QHuAegB/wG3AaIBkwH/AfgB5gHeAf8B9wHj
+ AdkB/wH1Ad8B1QH/AfUB2wHQAf8B8wHYAcsB/wH8AZIBYQH/AeEBgAFPAf8ByQG0AagB/wFmAUwBOAH/
+ DAABtwGiAZMB/wHCA/8BvQH/Af4B/wG4Af8B/gH/AbQB/wH+Af8BsAH/Af4B/wGrAf8B/gH/AagB/wH+
+ Af8BpAH/Af4B/wGhAf8B/gH/AT8BwwHxAf8BZgFMATgB/wgAASMCAQExAbwBjAFzAf8BvAGMAXMB/wG6
+ AYkBcAH/AbIBggFpAf8B4gHIAcIB/wH3AeMB2QH/AfUB3wHVAf8B4AG/AbYB/wG8AYwBcwH/AbwBjAFz
+ Af8BugGJAXAB/wGyAYIBaQH/AcsBrQGiAf8MAAG+AakBmgH/Av4B/QH/AWYBTAE4Af8B/QH4AfUB/wFm
+ AUwBOAH/AfsB8QHtAf8BZgFMATgB/wFeAYUBnAH/AcQB+QHHAf8BmgHfAaYB/wFyAcYBgQH/AUMBrgFg
+ Af8BPQGBAUQB/wGBAXYBXQH/ATkBRAFSAf8BFgIBARwBTwECAQwBqgEqAQQBTAHsAaQBnQG4Af8B+wHy
+ Ae0B/wH6Ae4B6QH/AYgBgAGwAf8BDwENAXwB/wIEAXcB/wFNAUUBkQH/AfUB3AHRAf8B9AHYAcwB/wHz
+ AdUBxwH/AcwBuAGuAf8BZgFMATgB/wwAAbcBogGTAf8ByQH/Af4B/wHFAf8B/gH/AcIB9AHvAf8B0AG2
+ AZgB/wF/AX4BUQH/Aa4BeAFYAf8BvAGYAYQB/wGuAeMB3QH/AaYB/wH+Af8BSQHIAfEB/wFmAUwBOAH/
+ EAABtwGiAZMB/wFmAUwBOAH/AfoB7gHpAf8B+QHqAeQB/wH4AecB4AH/AfcB5AHaAf8B9gHhAdUB/wH1
+ AdwB0QH/AfQB2AHMAf8BZgFMATgB/wHNAbcBqgH/AbgBnwGQAf8MAAHDAa4BngX/Af4C/QH/Af4B+wH5
+ Af8B/QH4AfUB/wH8AfQB8QH/AfsB8QHtAf8BZQGOAaQB/wFDAa4BYAH/AbwB7AHGAf8BiwHXAZ4B/wE9
+ AYEBRAH/AagBmgGPAf8BeAFjAVgB/wE8AUcBVQH/BAABIQIBAS0CAwF3Af8BzwHGAckB/wH5AfMB8gH/
+ AeAB1wHQAf8B0gHHAdYB/wEbARgBgQH/ARIBEAF9Af8B9wHlAdsB/wH2AeEB1wH/AVABVgHXAf8BOwFB
+ AdEB/wHQAb0BtAH/AWYBTAE4Af8MAAG3AaIBkwH/AdAD/wHMA/8B8wHCAasB/wHVAYEBTwH/AT4BhQEi
+ Af8BYAF1ATMB/wGqAWYBQwH/AaUBlwGFAf8BqwH/Af4B/wFVAcwB8gH/AWYBTAE4Af8QAAG3AaIBkwH/
+ AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFMATgB/wFmAUwBOAH/AWYBTAE4Af8BZgFM
+ ATgB/wFmAUwBOAH/Ac0BtwGqAf8BgQFpAVYB/wwAAcgBsgGjBf8BZgFMATgC/wH9AfwB/wFmAUwBOAH/
+ Af0B9wH2Af8BZgFMATgB/wFtAZcBrQH/AfUB4wHeAf8BQwGuAWAB/wE9AYEBRAH/AbgBngGIAf8BrQGL
+ AXYB/wHYAawBjQH/AUABSwFaAf8EAAEIAgEBCQFPAQIBCgGkASgBIgF+Af8BZgFhAaUB/wFlAV8BpAH/
+ AUIBPAGRAf8CAwF3Af8BgwF9Aa8B/wH1AeYB4AH/AfcB5QHdAf8BbwF2AeAB/wFYAV4B2QH/AdUBwwG7
+ Af8BZgFMATgB/wwAAboBpQGWAf8B2AP/AdMB/wH+Af8B9AGbAXYB/wF4AX0BQQH/AV4BlwEnAf8BsAGB
+ AUAB/wFWAXMBOQH/AU8BigE6Af8BsgH/Af4B/wFhAdAB8gH/AWYBTAE4Af8QAAG6AaUBlgH/Af0B+QH2
+ Af8B/AH2AfMB/wH8AfMB7wH/AfoB8AHrAf8BZgFMATgB/wH4AekB4QH/AfcB5QHdAf8B9gHiAdgB/wH1
+ Ad8B0wH/Ac0BtwGqAf8BZgFMATgB/wwAAcwBtgGnDf8B/gH9AfwB/wH+AfoB+QH/Af0B+AH2Af8BcwGf
+ AbMB/wH5Ae8B7AH/AfUB4wHeAf8B8AHUAcwB/wHTAcgB2QH/AXcBhgHFAf8B6QHEAbkB/wFFAVEBYAH/
+ CAABOwEBAQIBYQIDAXcB/wHNAcsB4QH/AZwBlgG1Af8CAwF3Af8BFQETAYAB/wHaAdEB3QH/AfoB7gHo
+ Af8B+AHqAeQB/wH3AecB3wH/AfYB4gHaAf8B2AHJAcEB/wFmAUwBOAH/DAABvgGpAZoB/wHfA/8B2gP/
+ AacBlQFiAf8BFAGjATQB/wKOAUsB/wHnAYEBUgH/AWQBlwEpAf8BSwGiATMB/wG5A/8BbAHVAfMB/wFm
+ AUwBOAH/EAABvgGpAZoB/wH+AfwB+wH/AdwCyQH/AZMBZQFMAf8BjgFgAUcB/wGIAVsBQgH/AYQBVwE+
+ Af8BgQFUAToB/wHYAbwBtgH/AfYB4gHaAf8BzQG3AaoB/wFmAUwBOAH/DAAB2QHJAcAB/wHTAcIBuQH/
+ Ac0BuwGxAf8ByQG0AakB/wHFAa8BogH/AcEBqQGcAf8BvAGjAZUB/wF5AacBuwH/AfwB9gH1Af8B+QHv
+ AewB/wH3AekB4QH/AXIBlQHjAf8BRAGVAekB/wF6AYkBxwH/AUoBWAFmAf8IAAETAgEBGAIDAXcB/wHf
+ Ad0B7QH/AacBogHMAf8CAwF3Af8BcQFrAaoB/wH7AfMB8QH/AfsB8gHtAf8B+gHuAekB/wE8AZ8BWAH/
+ ASYBkQFFAf8B3AHOAcgB/wFmAUwBOAH/DAABwwGuAZ4B/wHmA/8B4gP/AaYB0AGfAf8BWAHcAX8B/wGj
+ AdwBnQH/AbEBnwFmAf8BpAGMATQB/wGbAccBgwH/AcAD/wF3AdoB9AH/AWYBTAE4Af8QAAHDAa4BngH/
+ A/4B/wGlAXgBXQH/Af0B+AH2Af8B/AH0AfAB/wH6Ae8B6QH/AfkB6QHjAf8B9wHkAdoB/wGGAVoBQAH/
+ AfgB6AHfAf8BzQG3AaoB/wFmAUwBOAH/FAABwwGuAZ4B/wHYAekB7AH/AdgB6QHsAf8B2AHpAewB/wHY
+ AekB7AH/AX4BrQG/Bf8B/AH2AfUB/wH8AfYB9QH/AckB1AH0Af8BfAGfAekB/wHcAdQB3gH/AVIBYAFu
+ Af8MAAFeAVMBiwH/AZ8BmwHJAf8BHAEYAXwB/wERARABfgH/AcIBvgHZAf8B/QH5AfYB/wH8AfUB8gH/
+ AfsB8gHuAf8BUAGrAWgB/wE2AZsBUwH/AeEB1AHOAf8BZgFMATgB/wwAAcgBsgGjAf8B7QP/AegD/wHe
+ AfkB7gH/Ac0B6QHAAf8BrQHjAaYB/wFVAcQBcwH/AdABuwGYAf8BxQH3Ae0B/wHHAf8B/gH/AYEB3gH1
+ Af8BZgFMATgB/xAAAcgBsgGjBf8BsgGCAWkB/wHdAaUBhQH/AeABrgGRAf8B5gG6AaIB/wHrAccBtQH/
+ Ae8B1QHGAf8BkgFlAUsB/wH5AewB5gH/Ac0BtwGqAf8BZgFMATgB/xQAAcgBsgGjAf8B2AHpAewB/wHY
+ AekB7AH/AdgB6QHsAf8B2AHpAewB/wGBAbIBxAH/AX4BrQHAAf8BeQGnAbsB/wF0AZ8BtAH/AWwBlwGt
+ Af8BZQGOAaUB/wFeAYQBnAH/AVYBfgGTAf8MAAHPAcUBzgH/AgMBdwH/AgMBdwH/AU8BTAGcAf8B/gL8
+ Af8B/gH7AfoB/wH9AfkB9wH/AfwB9gHzAf8B+wH0Ae8B/wHoAd8B2gH/AeQB2QHUAf8BZwFNATkB/wwA
+ AcwBtgGnAf8B8wP/Ae8B/wH+Af8B6wH/Af4B/wHmA/8B4gH/Af4B/wHdA/8B2QP/AdQD/wGRAeUB9QH/
+ AYkB4gH1Af8BZwFNATkB/xAAAcwBtgGnBf8BuwGLAXEB/wHdAaUBhQH/AeEBrQGRAf8B5gG6AaIB/wHq
+ AcgBtQH/Ae8B1AHGAf8BoAFzAVgB/wHdAdQBzAH/Ac0BtwGqAf8BZwFNATkB/xQAAcwBtgGnAf8B2AHp
+ AewB/wHYAekB7AH/AdgB6QHsAf8B2AHpAewB/wHYAekB7AH/AdgB6QHsAf8B2AHpAewB/wHYAekB7AH/
+ AWYBTAE4Af8YAAHRAbsBqwH/AS8BLQGMAf8BCwEJAXoB/wHDAcAB3wb/Af4B/QH/Af4C+wH/Af0B+QH4
+ Af8BtwGiAZMB/wFnAU0BOQH/AWcBTQE5Af8BZwFNATkB/wwAAdEBuwGrAf8B9wP/AfQD/wHwA/8B7QP/
+ AegD/wHkA/8B3wP/AbcBogGTAf8BZwFNATkB/wFnAU0BOQH/AWcBTQE5Af8QAAHRAbsBqwX/AegC3AH/
+ AbwBjAFzAf8BvAGMAXMB/wG6AYkBcAH/AbYBhgFtAf8BsgGCAWkB/wHdAc8BzAH/AbUBqgGgAf8BZwFN
+ ATkB/wFnAU0BOQH/FAAB/wHCAaIC/wG8AZgC/wGzAYoC/wGoAXwC/wGeAW0B/wH9AZIBYAH/Ae4BhwFV
+ Af8B2gF8AUwB/wHGAW8BQwH/AbIBYwE8Af8YAAHVAb8BrwH/AcQBwQHeAf8BcAFtAbAB/wHgAdcB0AX/
+ AbcBogGTAv8C/gH/AbcBogGTAf8BuQGkAZUB/wHUAcUBugH/AWYBTAE4Af8BWwENAQwBqQwAAdUBvwGv
+ Af8B/AP/AfkD/wH2A/8B8gP/Ae4B/wH+Af8B6gP/AeYB/wH+Af8BuQGkAZUB/wHUAcUBugH/AWYBTAE4
+ Af8BWwENAQwBqRAAAdUBvwGvFv8C/gH/Af4B/AH7Af8BzAG9AbMB/wGuAZoBjAH/AWYBTAE4Af8BWwEN
+ AQwBqRQAAf8BvgGbAv8BwgGiAf8B/gHAAZ8B/wH9Ab0BmgH/AfwBuQGWAf8B+wG1AZAB/wH6AbABiwH/
+ AfkBqwGEAf8B8wGVAWgB/wHNAWgBNAH/GAAB2AHCAbIb/wH+Af8BwAGrAZwB/wFmAUwBOAH/AVsBDQEM
+ AagQAAHYAcIBsgX/AfwD/wH6A/8B9wP/AfQD/wHxA/8B7AP/AcABqwGcAf8BZgFMATgB/wFbAQ0BDAGo
+ FAAB2AHCAbIb/wH+Af8BwAGrAZwB/wFmAUwBOAH/AVsBDQEMAagYAAH/Ab4BmwL/AbcBkQL/AbABhQL/
+ AagBewL/AZ8BbwL/AZcBZQH/AfcBjgFcAf8B6wGEAVQB/wHcAX0BTQH/AcsBcwFGAf8YAAHYAcIBsgH/
+ AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHUAb4BrgH/Ac8BuQGpAf8ByQGz
+ AaQB/wFPAgYBixQAAdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/
+ AdQBvgGuAf8BzwG5AakB/wHJAbMBpAH/AU8CBgGLGAAB2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHC
+ AbIB/wHYAcIBsgH/AdgBwgGyAf8B1AG+Aa4B/wHPAbkBqQH/AckBswGkAf8BTwIGAYv/AKEAAbcBogGT
+ Af8BagFQATwB/wFqAVABPAH/AWoBUAE8Af8BagFQATwB/wFqAVABPAH/AWoBUAE8Af8BagFQATwB/wFq
+ AVABPAH/AWoBUAE8Af8BagFQATwB/wFqAVABPAH/EAABtwGiAZMB/wFrAVEBPQH/AWsBUQE9Af8BawFR
+ AT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/
+ AWsBUQE9Af8IAAG3AaIBkwH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFr
+ AVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/xAAAbcBogGTAf8BawFR
+ AT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/
+ AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/GAABtwGiAZMF/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3
+ AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wFqAVABPAH/EAABtwGi
+ AZMB/wH3AeUB3AH/AdgBxwG/Af8B1QHEAbwB/wHSAcABtwH/Ac8BvQGzAf8BzQG5Aa8B/wHLAbYBqwH/
+ AcgBswGoAf8BxgGvAaMB/wHDAawBoAH/AWsBUQE9Af8IAAG3AaIBkwH/AfcB5QHcAf8BtwGiAZMB/wG3
+ AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGT
+ Af8BawFRAT0B/xAAAbcBogGTAf8B8wHWAckB/wHxAdEBwgH/AfABzQG8Af8B7wHJAbcB/wHuAcYBswH/
+ Ae0BwwGvAf8B7QHDAa8B/wHtAcMBrwH/Ae0BwwGvAf8B7QHDAa8B/wFrAVEBPQH/GAABtwGiAZMJ/wH8
+ AfoB+QH/AfwB+gH5Af8B9wHxAe4B/wHxAecB4QH/AewB3QHVAf8B5gHTAckB/wHhAcoBvQH/AbcBogGT
+ Af8BagFQATwB/wQAAQIDAQEEAgEBBAEHAgEBCAG5AaUBlgH/AfkB6gHjAf8B+AHmAd0B/wH3AeIB2AH/
+ AfUB3gHTAf8B9AHbAc4B/wHzAdcBygH/AfIB1AHFAf8B8QHQAcEB/wHwAc0BvAH/AccBsQGlAf8BawFR
+ AT0B/wgAAbcBogGTAf8B+QHpAeIB/wH4AecB3gH/AfgB5AHbAf8B9gHiAdkB/wH2AeEB1gH/AfUB3QHS
+ Af8B8wHYAcoB/wHyAdIBwwH/AfABzQG9Af8BtwGiAZMB/wFrAVEBPQH/EAABtwGiAZMB/wH5AekB4gH/
+ AfgB5wHeAf8B9wHkAdoB/wH2AeEB1wH/AfUB3gHSAf8B9AHbAc8B/wHzAdgBygH/AfIB0wHFAf8B8QHP
+ Ab4B/wHtAcMBrwH/AWsBUQE9Af8IAAErAgEBPwFIAX8BjwH/ATwBaQF9Af8BMAFcAXEB/wEwAVwBcQH/
+ ATABXAFxAf8BLQFZAW4B/wE8AWMBewH/ATEBXQFzAf8B+gH3AfUB/wH1Ae0B6QH/Ae8B4wHcAf8B6gHZ
+ AdEB/wHkAc8BxAH/AbcBogGTAf8BagFQATwB/wEFAgEBBQEQAgEBEwEfAgECKgIBAT4BzwHBAbgB/wH6
+ AfIB7QH/AfkB7QHmAf8B+AHnAeAB/wH3AeMB2QH/AfUB3wHVAf8B9QHbAdAB/wHzAdgBywH/AfIB1QHG
+ Af8B8QHRAcIB/wHKAbUBqgH/AWsBUQE9Af8IAAG3AaIBkwH/AfkB7gHpAf8B+QHsAeYB/wH6AewB5gH/
+ AfoB7QHmAf8B+QHsAecB/wH5AekB4gH/AfYB4wHaAf8B9AHbAc4B/wHyAdMBxQH/AbcBogGTAf8BawFR
+ AT0B/xAAAbcBogGTAf8B+QHuAegB/wH4AesB5QH/AfkB6gHjAf8B+QHqAeMB/wH4AegB4QH/AfgB5QHd
+ Af8B9gHjAdkB/wH1Ad0B0QH/AfMB1gHJAf8B7QHEAbEB/wFrAVEBPQH/CAABQQF7AYwB/wGpAdYB3wH/
+ AbgB6AHzAf8BrwHlAfIB/wGvAeUB8gH/Aa8B5QHyAf8BpQHcAesB/wFIAYEBkQH/AUkBpAHRAf8BPwF/
+ AZEB/wH4AfMB8AH/AfIB6QHjAf8B7QHfAdgB/wHnAdUBywH/AbcBogGTAf8BagFQATwB/wESAgEBFwEp
+ AgEBPAFAAgEBbAFUAgIBpQHmAcwBtQH/AfgB7gHmAf8B/AH0AfEB/wH6Ae4B6QH/AfgB6AHiAf8B9wHk
+ AdoB/wH2AeEB1QH/AfUB3AHSAf8B9AHZAc0B/wHzAdUByAH/Ac0BuwGwAf8BawFRAT0B/wgAAbcBogGT
+ Af8B+wHzAe8B/wH7AfIB7wH/AeMBzwHBAf8BoAF0AUsB/wGBAUIBCgH/AY8BWwEqAf8ByAGlAYsB/wH3
+ AeIB2QH/AfQB2QHMAf8BtwGiAZMB/wFrAVEBPQH/EAABtwGiAZMB/wH7AfIB7QH/AfsB8AHsAf8B+wHx
+ Ae0B/wGuAVcBCAH/AeYBxwGvAf8B+wHxAewB/wGuAVcBCAH/AeQBvwGlAf8B9gHeAdMB/wHuAcUBsgH/
+ AWsBUQE9Af8IAAFnAZQBqgH/AVUBhAGaAf8BTQGBAZMB/wFeAYkBoAH/AV4BiQGgAf8BXgGJAaAB/wFa
+ AYMBmgH/AWIBhAGcAf8BTQGrAdkB/wFDAYEBnQH/AfsB+AH3Af8B9gHvAesB/wHwAeUB3wH/AesB2wHT
+ Af8BtwGiAZMB/wFqAVABPAH/ASYCAQE3AUkCAgKEASoBFQHuAa4BVwEIAf8BrgFXAQgB/wGuAVcBCAH/
+ Ad0BtgGVAf8B/AH0AfEB/wH6Ae8B6wH/AfkB6gHjAf8B+AHnAd4B/wH3AeMB2gH/AfUB4gHYAf8B9AHd
+ AdEB/wHSAcEBtwH/AWsBUQE9Af8IAAG4AaMBlQH/Af0B+AH1Af8B/QH3AfUB/wGPAVwBKwH/AcIBoAGF
+ Af8B/QH4AfUB/wHKAaoBkQH/AYEBQgEKAf8B7wHbAdAB/wH0Ad4B0gH/AbcBogGTAf8BawFRAT0B/xAA
+ AbcBogGTAf8B/AH2AfMB/wH8AfQB8QH/Af0B9gHzAf8BrgFXAQgB/wHpAcwBtgH/Af0B+QH2Af8BrgFX
+ AQgB/wHmAcUBrAH/AfcB5QHcAf8B7gHGAbMB/wFrAVEBPQH/EAABVgICAa0BhwHUAewB/wFlAcEB6gH/
+ AWUBwQHqAf8BWgG5AecB/wFUAbQB4wH/AUYBhAGiAf8BZwGLAZ0B/wH+Af0B/AH/AfkB9QHyAf8B9AHr
+ AeYB/wHuAeEB2gH/AbcBogGTAf8BagFQATwB/wE4AgEBWQFnAQsBCAHUAa4BVwEIAf8BhAE3ATAB6gH2
+ Ae8B6QH/Ab4BegE7Af8BuQFuASkB/wH+AfoB+AH/AecBygGzAf8B/AHzAe8B/wH6Ae8B6gH/AfoB7QHo
+ Af8B5QHDAakB/wH4AegB4AH/AdsBzAHGAf8BcQFXAUQB/wgAAbwBpwGZAf8B/gH7AfgB/wHkAdQByAH/
+ AYEBQgEKAf8B9QHtAegB/wH9AfcB9AH/AfsB8QHsAf8B8gHiAdoB/wH4AegB4AH/AfYB4gHXAf8BtwGi
+ AZMB/wFrAVEBPQH/EAABugGlAZYB/wH9AfkB9gH/Af0B+AH2Af8B/gH5AfcB/wGuAVcBCAH/AekBzwG6
+ Af8B/gL9Af8BrgFXAQgB/wHmAcgBsAH/AfgB6QHhAf8B7wHIAbYB/wFrAVEBPQH/DAABJAIBATIBRwF+
+ AY4B/wGFAdkB8wH/AXgBzQHvAf8BbAHEAesB/wFhAb4B6QH/AUIBgQGWAf8BewGhAbQJ/wH8AfoB+QH/
+ AfcB8QHuAf8B8QHnAeEB/wG3AaIBkwH/AWoBUAE8Af8BQQIBAXEBjgEyARkB8QGjAVcBIQH7AV0CBQHC
+ AfEB7AHpAf8B9AHnAdsB/wH+Av0B/wH+Af0B/AH/Aa4BVwEIAf8B/QH5AfcB/wH9AfcB9AH/AfwB9gH0
+ Af8BrgFXAQgB/wH7AfIB7gH/AeMB2AHSAf8BdQFdAUoB/wgAAcABrAGdAf8B/gH9AfwB/wHcAcgBuQH/
+ AYEBQgEKAf8B/gH7AfoB/wH9AfcB9QH/AfwB8wHvAf8B+gHwAewB/wH4AesB5QH/AfcB5AHdAf8BtwGi
+ AZMB/wFrAVEBPQH/EAABvgGpAZoB/wH+AfwB+wH/Af0C+gH/Af4B+wH6Af8BrgFXAQgB/wHZAa0BiAH/
+ AfoB8gHtAf8BrgFXAQgB/wHmAcgBsAH/AfgB6QHjAf8B8AHLAboB/wFrAVEBPQH/DAABYwGQAaIB/wF8
+ AaABrQH/AZYB5AH3Af8BiQHcAfUB/wGBAdQB8QH/AXIBxQHoAf8BQgGBAZYB/wHwAfUB9wn/A/4B/wH6
+ AfcB9QH/AfUB7QHpAf8BtwGiAZMB/wFqAVABPAH/AUMCAQFzAY4BNgEbAfIBqgFdATgB+gFaAgQBuQHw
+ AesB5wH/A/4B/wH0AeUB2gH/Aa4BVwEIAf8BrgFXAQgB/wGuAVcBCAH/AfQB5QHaAf8BrgFXAQgB/wGu
+ AVcBCAH/Aa4BVwEIAf8B3QHEAbEB/wF7AWQBUgH/CAABxAGwAaAB/wP+Af8B9QHxAewB/wGBAUIBCgH/
+ AeQB1gHKAf8B/gH6AfkB/wH1AesB5QH/AcEBnQGBAf8B8gHjAdsB/wH5AeoB4gH/AbcBogGTAf8BawFR
+ AT0B/xAAAcMBrgGeAf8D/gH/Af4C/QH/Af4B/AH7Af8BrgFXAQgB/wHOAZUBbgH/Aa4BVwEIAf8BwwGB
+ AUoB/wH7AfMB7wH/AfkB7AHkAf8B8AHOAb0B/wFrAVEBPQH/DAABcQGOAZ0B/gGvAfMB/QH/AakB8AH9
+ Af8BoQHrAfoB/wGWAeQB+AH/ATsBfQGUAf8BWgGkAcUB/wE/AXYBhAH/AT8BcgGBDf8B+gH3AfUB/wG3
+ AaIBkwH/AWoBUAE8Af8BOwIBAWABbAEQAQsB3QGuAVcBCAH/AWsCFAHZAfoB+AH3Af8B2QGtAYgB/wHj
+ AcIBpgL/Av4B/wGuAVcBCAH/Af4B/AH7Af8B/gH6AfkB/wH9AfkB+AH/Aa4BVwEIAf8B/AH2AfMB/wHo
+ Ad8B2gH/AXUBXQFKAf8IAAHIAbMBpAn/AboBlQGAAf8BjwFcASsB/wHCAaIBhwH/AaABdQFMAf8BlwFo
+ ATsB/wH7Ae8B6gH/AfkB7AHmAf8BtwGiAZMB/wFrAVEBPQH/EAAByAGyAaMK/wH+Af0B/wGuAVcBCAH/
+ AekBzwG5Af8B/gH7AfkB/wH8AfcB9AH/AfwB8gHuAf8B+QHtAegB/wHxAdEBwgH/AWsBUQE9Af8MAAE0
+ AV8BcwH8Aa0B8QH7Af8BsAH0Af4B/wGvAfMB/gH/AaYB7gH7Af8BLgFoAYEB/wFaAaQBxQH/AWYBsgHT
+ Af8BIwFQAWQJ/wH9AfwB+wH/AbcBogGTAf8BtwGiAZMB/wFrAVEBPQH/ASsCAQE/AU8CAgGZAZ8BTQEW
+ AfwBswFKARcB/QG9AXgBOQH/Aa4BVwEIAf8B3AGzAZEF/wHtAdgBxgH/Af4C/AH/Af4B+wH5Af8B/QH5
+ AfcB/wHuAdoBygH/Ae0B5gHiAf8B5wHdAdkB/wFxAVgBRQH/CAABzAG2AacN/wHdAcoBuwH/AcMBogGI
+ Af8BwgGhAYcB/wH1AewB5wH/AfsB9AHvAf8BtwGiAZMB/wG3AaIBkwH/AWwBUgE+Af8QAAHMAbYBpw3/
+ AdkBrAGHAf8B8wHmAdoB/wH+AfsB+QH/AfwB9wH1Af8B+wH1AfAB/wH0Ad0B0QH/AfMB1wHJAf8BbAFS
+ AT4B/wwAARkCAQEgAYEBrQHAAf8BfQGnAboB/wF4AZ8BtAH/AXABlwGtAf8BaQGOAaQB/wE3AWkBfQH/
+ ATkBagF+Df8BtwGiAZMB/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wEXAgEBHQEwAgECSgICAYgBZAIH
+ AdAB1AGmAYEB/wHfAbkBmQ7/Af4B/QH/Af4C+wH/Af0B+QH4Af8BvgGrAZ4B/wF2AV4BSwH/AXEBWAFE
+ Af8BbAFSAT4B/wgAAdEBuwGrEv8C/gH/Af4C/AH/Af0B+gH5Af8BtwGiAZMB/wFsAVIBPgH/AWwBUgE+
+ Af8BbAFSAT4B/xAAAdEBuwGrEv8B/gH9Af8B/gL7Af8B/QH5AfgB/wG3AaIBkwH/AWwBUgE+Af8BbAFS
+ AT4B/wFsAVIBPgH/GAAB1QG/Aa8d/wG5AaQBlQH/AdQBxQG6Af8BawFRAT0B/wFMAgIBjAEHAgEBCAEW
+ AgEBHAEnAgEBOAE0AgEBUgHvAecB4Bb/Av4B/wH+AfwB+wH/AboBpQGWAf8B1AHFAbsB/wFsAVIBPgH/
+ AVYCAgGpCAAB1QG/Aa8W/wL+Af8B/gH8AfsB/wG5AaQBlQH/AdQBxQG6Af8BawFRAT0B/wFWAgIBqRAA
+ AdUBvwGvFv8C/gH/Af4B/AH7Af8BuQGkAZUB/wHUAcUBugH/AWsBUQE9Af8BVgICAakYAAHYAcIBsh3/
+ AcABqwGcAf8BawFRAT0B/wFLAgIBiwgAAQQCAQEEAQkCAQEKAQ8CAQESAdsBxwG4G/8B/gH/AcABqwGc
+ Af8BawFRAT0B/wFWAgIBqAwAAdgBwgGyG/8B/gH/AcABqwGcAf8BawFRAT0B/wFWAgIBqBQAAdgBwgGy
+ G/8B/gH/AcABqwGcAf8BawFRAT0B/wFWAgIBqBwAAdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGy
+ Af8B2AHCAbIB/wHYAcIBsgH/AdQBvgGuAf8BzwG5AakB/wHJAbMBpAH/AUsCAgGLGAAB2AHCAbIB/wHY
+ AcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B1AG+Aa4B/wHPAbkBqQH/AckBswGk
+ Af8BSwICAYsQAAHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHU
+ Ab4BrgH/Ac8BuQGpAf8ByQGzAaQB/wFLAgIBixgAAdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGy
+ Af8B2AHCAbIB/wHYAcIBsgH/AdQBvgGuAf8BzwG5AakB/wHJAbMBpAH/AUsCAgGLWAABtwGiAZMB/wFr
+ AVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9
+ Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8UAAG3AaIBkwH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/
+ AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFR
+ AT0B/xAAAbcBogGTAf8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9
+ Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/FAABtwGiAZMB/wFrAVEBPQH/
+ AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFRAT0B/wFrAVEBPQH/AWsBUQE9Af8BawFR
+ AT0B/wFrAVEBPQH/AWsBUQE9Af8IAAG3AaIBkwH/AfcB5QHcAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGT
+ Af8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BawFRAT0B/xQA
+ AbcBogGTAf8B9wHlAdwB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGi
+ AZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wFrAVEBPQH/EAABtwGiAZMB/wH3AeUB3AH/AbcBogGT
+ Af8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3
+ AaIBkwH/AWsBUQE9Af8UAAG3AaIBkwH/AfcB5QHcAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGi
+ AZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BawFRAT0B/wgAAbcBogGT
+ Af8B+QHpAeIB/wH4AeYB3QH/AfcB4gHYAf8B9QHeAdMB/wH0AdsBzgH/AfMB1wHKAf8B8gHUAcUB/wHx
+ AdABwQH/AfABzQG8Af8BtwGiAZMB/wFrAVEBPQH/FAABtwGiAZMB/wH5AekB4gH/AfgB5gHdAf8B9wHi
+ AdgB/wH1Ad4B0wH/AfQB2wHOAf8B8wHXAcoB/wHyAdQBxQH/AfEB0AHBAf8B8AHNAbwB/wG3AaIBkwH/
+ AWsBUQE9Af8QAAG3AaIBkwH/AfkB6QHiAf8B+AHmAd0B/wH3AeIB2AH/AfUB3gHTAf8B9AHbAc4B/wHz
+ AdcBygH/AfIB1AHFAf8B8QHQAcEB/wHwAc0BvAH/AbcBogGTAf8BawFRAT0B/xQAAbcBogGTAf8B+QHp
+ AeIB/wH4AeYB3QH/AfcB4gHYAf8B9QHeAdMB/wH0AdsBzgH/AfMB1wHKAf8B8gHUAcUB/wHxAdABwQH/
+ AfABzQG8Af8BtwGiAZMB/wFrAVEBPQH/CAABtwGiAZMB/wH5Ae4B6AH/AfgB6gHjAf8B+AHmAd4B/wH3
+ AeMB2QH/AfUB3wHVAf8B9QHbAdAB/wHzAdgBywH/AfIB1QHGAf8B8QHRAcIB/wG3AaIBkwH/AWsBUQE9
+ Af8UAAG3AaIBkwH/AfkB7gHoAf8BvgGqAZwB/wG1AaEBkwH/AawBlwGIAf8BogGNAYEB/wGaAYMBegH/
+ AZEBgQFxAf8BigF7AWkB/wHxAdEBwgH/AbcBogGTAf8BawFRAT0B/xAAAbcBogGTAf8B+QHuAegB/wH4
+ AeoB4wH/AfgB5gHeAf8B9wHjAdkB/wH1Ad8B1QH/AfUB2wHQAf8B8wHYAcsB/wHyAdUBxgH/AfEB0QHC
+ Af8BtwGiAZMB/wFrAVEBPQH/FAABtwGiAZMB/wH5Ae4B6AH/AcsBuAGrAf8BxAGwAaMB/wG5AaQBlgH/
+ AawBlwGHAf8BngGIAX8B/wGQAYABbwH/AYIBcQFfAf8B8QHRAcIB/wG3AaIBkwH/AWsBUQE9Af8IAAG3
+ AaIBkwH/AfsB8gHtAf8B2AFyAToB/wHQAW0BOQH/AcQBaAE1Af8BtwFhATMB/wGnAVkBMAH/AZoBUwEt
+ Af8BjgFNASoB/wHzAdUBxwH/AbcBogGTAf8BawFRAT0B/xQAAbcBogGTAf8B+wHyAe0B/wH6Ae4B6QH/
+ AfkB6gHkAf8B+AHnAeAB/wH3AeQB2gH/AfYB4QHVAf8B9QHcAdEB/wH0AdgBzAH/AfMB1QHHAf8BtwGi
+ AZMB/wFrAVEBPQH/EAABtwGiAZMB/wH7AfIB7QH/AdQBxAG6Af8BzwG8AbEB/wHJAbQBqQH/AcQBrgGi
+ Af8BwAGpAZwB/wG7AaIBlQH/AbUBnAGNAf8B8wHVAccB/wG3AaIBkwH/AWsBUQE9Af8UAAG3AaIBkwH/
+ AfsB8gHtAf8B+gHuAekB/wH5AeoB5AH/AfgB5wHgAf8B9wHkAdoB/wH2AeEB1QH/AfUB3AHRAf8B9AHY
+ AcwB/wHzAdUBxwH/AbcBogGTAf8BawFRAT0B/wgAAbcBogGTAf8B/AH2AfMB/wH7AfIB7gH/AfsB7wHq
+ Af8B+QHrAeYB/wH5AegB4QH/AfcB5QHbAf8B9gHhAdcB/wH0Ad4B0wH/AfMB2gHNAf8BtwGiAZMB/wFr
+ AVEBPQH/CAABGgIBASMBRQIBAXkBWgIEAboB7AHmAeIB/wH+AfsB+gH/AeQB2wHVAf8B3QHUAc4B/wHC
+ AbIBpwH/AaUBkQGCAf8BmgGDAXoB/wGRAYEBcQH/AYoBewFpAf8B8wHaAc0B/wG3AaIBkwH/AWsBUQE9
+ Af8QAAG3AaIBkwH/AfwB9gHzAf8B/AH2AfMB/wH+Af0B/AH/Af4C/QH/Af4B/QH8Af8B+wHzAe4B/wH3
+ AeUB3AH/AfQB3gHTAf8B8wHaAc0B/wG3AaIBkwH/AWsBUQE9Af8IAAEXAgEBHgE4AgEBWwE4AgEBWwHF
+ AbQBqAH/Af0B+gH4Af8B8QHsAegB/wHeAdMBywH/AcIBrwGjAf8BywG+AbQB/wHZAdABygH/Aa8BngGR
+ Af8BggFxAV8B/wHzAdoBzQH/AbcBogGTAf8BawFRAT0B/wgAAboBpQGWAf8B/QH5AfYB/wHYAXIBOgH/
+ AdABbgE4Af8BxAFoATUB/wG3AWEBMwH/AagBWgEwAf8BmgFTASwB/wGOAU0BKgH/AfUB3wHTAf8BtwGi
+ AZMB/wFrAVEBPQH/CAABRQIBAXkBqQGGAX4B9gEIAZkBCAH/AQgBmQEIAf8B4gHuAeIB/wH7Af0B+wH/
+ AQ0BlwENAf8B0AHiAc8B/wH9AfcB9AH/AfoB7gHoAf8B9wHlAd4B/wH2AeIB2AH/AfUB3wHTAf8BtwGi
+ AZMB/wFrAVEBPQH/EAABugGlAZYB/wH9AfkB9gH/AfwB+wH6Af8BywFuAQgB/wHLAW4BCAH/AcsBbgEI
+ Af8B6AG9AZ0B/wHpAeAB3AH/AbUBmwGNAf8B9QHfAdMB/wG3AaIBkwH/AWsBUQE9Af8IAAFKAgIBhQGV
+ AaoC/wGVAaoC/wH8AvsB/wG5AccC/wEIATsC/wG5AccD/wL+Af8B1AHdAv8BDQE/Bv8B+wH0AfAB/wH4
+ AegB3wH/AbcBogGTAf8BawFRAT0B/wgAAb4BqQGaAf8B/gH8AfsB/wH9AfkB+AH/Af0B9wH0Af8B/AH0
+ AfAB/wH7AfEB7QH/AfoB7gHoAf8B+AHqAeQB/wH3AecB3wH/AfYB4gHaAf8BtwGiAZMB/wFrAVEBPQH/
+ CAABWgIEAboBIgGjASIB/wGpAYYBfgH2AfcB9QHzAf8BngHYAZ4B/wEQAZkBEAH/AQkBlQEJAf8BrwHO
+ Aa4B/wEKAZUBCgH/AecB7QHiAf8B+AHrAeYB/wH3AecB3wH/AfYB4gHaAf8BtwGiAZMB/wFrAVEBPQH/
+ DAABWAIDAbMB9gHzAfED/wH+Av8C/gH/AcsBbgEIAv8C/gL/Af4B/QH/AcsBbgEIAf8B/QH6AfgB/wH3
+ AecB3wH/AfYB4gHaAf8BtwGiAZMB/wFrAVEBPQH/BAABDAIBAQ4E/wEIATsC/wEIATsG/wEIATsC/wHO
+ AdgC/wEIATsC/wHOAdgC/wEIATsC/wEJATwC/wHZAeEC/wEKAT0C/wH+Av0B/wG6AaYBmAH/AWsBUQE9
+ Af8IAAHDAa4BngH/A/4B/wHYAXIBOgH/AdABbgE4Af8BxAFoATYB/wG3AWEBMwH/AacBWgEvAf8BmQFT
+ AS0B/wGOAU0BKgH/AfgB6AHfAf8BtwGiAZMB/wFrAVEBPQH/CAABYgIHAcgBCAGZAQgB/wF8AigB4wH4
+ AfUB8wn/AQsBlgELAf8BCgGVAQoB/wEJAZQBCQH/AeAB6wHeAf8B+wHyAe8B/wH5AesB5QH/AfgB6AHf
+ Af8BtwGiAZMB/wFrAVEBPQH/DAABegIlAeIB2QGQAWIB/wHZAZEBYgH/Af0C/AH/AcsBbgEIAf8BywFu
+ AQgB/wHLAW4BCAH/AfIB2QHGAf8B8QHsAekB/wG2AZwBjQH/AfgB6AHfAf8BtwGiAZMB/wFrAVEBPQH/
+ BAABPAIBAWQBzgHYAv8BCAE7Av8BCAE7Av8BzgHYCv8BCAE7Av8BzgHYAv8B2AHgAv8BCwE9Av8BCgE9
+ Av8BCQE8Av8B2QHhAv8B0QHEAboB/wFrAVEBPQH/CAAByAGyAaMK/wH9AfwB/wH9AfsB+QH/Af0B+QH2
+ Af8B/AH1AfIB/wH7AfIB7gH/AfsB7wHqAf8B+QHsAeYB/wG3AaIBkwH/AWsBUQE9Af8IAAFaAgQBugEI
+ AZkBCAH/AakBhgF+AfYB+AH2AfQB/wGBAckBgQH/ARABmQEQAf8BCwGWAQsB/wHrAfMB6gH/AQkBlAEJ
+ Af8BCwGWAQsB/wH9AfgB9gH/AfsB7wHqAf8B+QHsAeYB/wG3AaIBkwH/AWsBUQE9Af8IAAEPAgEBEgG3
+ Ao8B9gHLAW4BCAH/AcsBbgEIAv8C/gH/AcsBbgEIA/8B/gL/Av4B/wHLAW4BCAH/Af4B/AH7Af8B+wHv
+ AeoB/wH5AewB5gH/AbcBogGTAf8BawFRAT0B/wQAAYUCOQHoAQgBOwL/AaYBuAL/AaYBuAL/AQgBOwr/
+ AQgBOwL/Ac4B2AL/AQgBOwL/AQsBPQb/AQkBPAL/AQsBPQL/AeUB3gHYAf8BawFRAT0B/wgAAcwBtgGn
+ Bf8B2AFyAToB/wHQAW4BOAH/AcQBaAE1Af8BtwFhATIB/wGoAVoBMAH/AfwB9gHzAf8B+wH0Ae8B/wG3
+ AaIBkwH/AbcBogGTAf8BbAFSAT4B/wgAAUcCAQF+AakBhgF+AfYBIgGjASIB/wEIAZkBCAH/AeIB7gHi
+ Af8B4gHuAeIB/wEJAZQBCQH/AQ0BlwENAf8BCAGZAQgB/wHLAd8BygH/Af0B+gH5Af8B+wH0Ae8B/wG3
+ AaIBkwH/AbcBogGTAf8BbAFSAT4B/wgAAWACBQHHAdABpQGXAfsBywFuAQgB/wHLAW4BCAH/AfEB2AHG
+ Af8BywFuAQgB/wHLAW4BCAH/AcsBbgEIAf8B6AG9AZ0B/wH+AfsB+QH/AfsB9AHvAf8BtwGiAZMB/wG3
+ AaIBkwH/AWwBUgE+Af8EAAFvAhUB2gEIATsK/wEIATsK/wEIATsC/wHOAdgC/wHIAdMC/wEJATwC/wEN
+ AT8C/wEIATsC/wHdAeQC/wHlAd4B2AH/AWwBUgE+Af8IAAHRAbsBqxL/Af4B/QH/Af4C+wH/Af0B+QH4
+ Af8BtwGiAZMB/wFsAVIBPgH/AWwBUgE+Af8BbAFSAT4B/wgAASECAQEuAU8CAgGZAWACBQHEAfQB7wHs
+ Cf8BEQGZAREB/wHfAewB3wH/AQgBlAEIAf8BEQGZAREB/wH+AvwB/wG3AaIBkwH/AWwBUgE+Af8BbAFS
+ AT4B/wFsAVIBPgH/CAABtQKFAfUBywFuAQgB/wHbAZcBbAH/AdsBlwFsAf8BywFuAQgO/wL+Af8B/QH6
+ AfkB/wG3AaIBkwH/AWwBUgE+Af8BbAFSAT4B/wFsAVIBPgH/BAABMAIBAUkBTQICAZEBMAIBAUkBMAIB
+ AUkB6wHiAdsR/wHlAeoC/wEIATsC/wHPAdkC/wEIATsC/wEIATsC/wHGAbwBtQH/AWwBUgE+Af8IAAHV
+ Ab8Brxb/Av4B/wH+AfwB+wH/AbkBpAGVAf8B1AHFAboB/wFrAVEBPQH/AVYCAgGpCAABBAIBAQQBCQIB
+ AQoBBAIBAQQB1gHAAbAR/wEPAZgBDwH/Ad8B7AHfAf8B/gL9Af8BuQGkAZUB/wHUAcUBugH/AWsBUQE9
+ Af8BbAIUAeIIAAGwAXwBewH0AcsBbgEIAf8C/QH8Af8C/gH9Af8BywFuAQgO/wL+Af8B/gH8AfsB/wG5
+ AaQBlQH/AdQBxQG6Af8BawFRAT0B/wFsAhQB4hQAAdUBvwGvGf8B5wHsAv8BCAE7Av8B6QHtAv8BlwGG
+ AYAB/wFWAgIBqQgAAdgBwgGyG/8B/gH/AcABqwGcAf8BawFRAT0B/wFWAgIBqBgAAdgBwgGyG/8B/gH/
+ AcABqwGcAf8BawFRAT0B/wFuAhMB4QwAAVoCBAG5AWoCDwHUAfQB7gHqG/8B/gH/AcABqwGcAf8BawFR
+ AT0B/wFuAhMB4RgAAdgBwgGyG/8B/gH/AecB3wHZAf8BlwGGAYAB/wFVAgIBqgwAAdgBwgGyAf8B2AHC
+ AbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdQBvgGuAf8BzwG5AakB/wHJAbMBpAH/
+ AUsCAgGLHAAB2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B1AG+
+ Aa4B/wHPAbkBqQH/AckBswGkAf8BYQIGAcoYAAHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/
+ AdgBwgGyAf8B2AHCAbIB/wHUAb4BrgH/Ac8BuQGpAf8ByQGzAaQB/wFhAgYByhwAAdgBwgGyAf8B2AHC
+ AbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdQBvgGuAf8BzwG5AakB/wHJAbMBpAH/
+ AUsCAgGL/wAJAAFCAU0BPgcAAT4DAAEoAwABQAMAAWADAAEBAQABAQYAAQMWAAP/gQAByQP/AeABAQL/
+ AcABAQGAAQEB4AEBAYABAQEAAQEBgAEBAYABAQGAAQEBAAEBAYABAQHgAQEBgAEBAQABAQGAAQEBgAEB
+ AYABAQEAAQEBgAEBAeABAQGAAQEBAAEBAYABAQGAAQEBgAEBAcABAQGAAQEB4AEBAYABAQHAAQEBgAEB
+ AeABAQGAAQEB4AEBAYABAQHgAQEBgAEBAeABAQGAAQEB4AEBAYABAQHgAQEBgAEBAeABAQGAAQEB4AEB
+ AYABAQHgAQEBgAEBAeABAQGAAQEB4AEDAYABAQHgAQMBgAEBAeABBwGAAQEB4AEHBv8BgAEBAYAB/wGA
+ AQMBgAEHAYABAQGAAf8BgAEDAYABBwGAAQEBgAEHAYABAwGAAQABgAEBAYABBwGAAQMBgAEAAYABAQGA
+ AQcBgAEDAYABAAGAAQEBgAEHAYABAwGAAQABgAEBAYABBwGAAQMBgAEAAYABAQHwAQcBgAEDAYABAAGA
+ AQEB8AEHAYABAwGAAQABgAEBAfABAQGAAQMBgAEHAYABAQHwAWEBgAEDAYABBwGAAQEB8AFhAYABAwGA
+ AQcBgAEBAfABAQGAAQMBgAEHAYABAwH/AQEBgAEDAYABDwGAAQcB/wEBAYABAwGAAR8D/wEBBP8CAwL/
+ AeABAQHAAQMBAAEDAYABHwHgAQEBwAEDAQABAwGAAR8B4AEBAcABAwEAAQMBgAEAAeABAQHAAQMBAAED
+ AYACAAEBAcABAwHAAQMBgAEAAYABAQHAAQMBwAEDAYABAAGAAQEBwAEDAcABAwGAAQABwAEBAcABAwHA
+ AQMBgAEAAcABAQHAAQMBwAEDAeABAAHgAQEBwAEDAcABAwHgAQAB4AEBAcABAwHAAQMB4AEHAeABAQHA
+ AQMBwAEDAeABBwHgAQEBwAEDAcABAwHgAQcB4AEDAcABBwHAAQcB4AEHAeABBwHAAQ8BwAEPDP8B8AEA
+ AfABAAHAAQMBwAEDAfABAAHwAQABwAEDAcABAwHwAQABgAEAAcABAwHAAQMEAAHAAQMBwAEDBAABwAED
+ AcABAwQAAcABAwHAAQMBwAMAAcABAwHAAQMBgAMAAcABAwHAAQMBgAMAAcABAwHAAQMBgAMAAcABAwHA
+ AQMBgAMAAcABAwHAAQMBgAMAAcABAwHAAQMB8AMAAcABAwHAAQMB8AEBAYABAQHAAQcBwAEHAfABAwHw
+ AQMBwAEPAcABDwL/AcABAwHgAQEB4AEBAfABAAHAAQMB4AEBAeABAQHwAQABwAEDAeABAQHgAQEB8AEA
+ AcABAwHgAQEB4AEBAfABAAHAAQMB4AEBAeABAQHwAQABwAEDAQABAQHgAQEBgAEAAcABAwEAAQEB4AEB
+ AYABAAHAAQMBAAEBAcABAQIAAcABAwEAAQEBwAEBAgABwAEDAQABAQGAAQECAAHAAQMBAAEBAYABAQIA
+ AcABAwEAAQEBgAEBAgABwAEDAQABAQGAAQEB8AEAAcABBwHgAQMBgAEDAfABAQHAAQ8B4AEHAeABBwHw
+ AQMI/ws=
+
+
+
+ 231, 17
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
+ LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+ ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABm
+ IwAAAk1TRnQBSQFMAgEBBgEAAQkBAAEEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
+ AwABIAMAAQEBAAEgBgABIGoAAbcBogGTAf8BZwFNATkB/wFnAU0BOQH/AWcBTQE5Af8BZwFNATkB/wFn
+ AU0BOQH/AWcBTQE5Af8BZwFNATkB/wFnAU0BOQH/AWcBTQE5Af/YAAG3AaIBkwH/Aa0B5wH5Af8B4QHc
+ AdgB/wHgAdcB0gH/Ad8B0gHKAf8B3wHOAcMB/wHdAcgBuwH/AdwBwwGzAf8BxQGvAaMB/wFnAU0BOQH/
+ gAABtwGiAZMB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFw
+ AVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/IAABtwGi
+ AZMB/wG8AesB+gH/Aa4B6AH5Af8BnwHjAfgB/wGRAd8B9wH/AYMB2wH2Af8BewHYAfUB/wFwAdUB9AH/
+ AcgBtAGpAf8BZwFNATkB/4AAAbcBogGTAf8B/QH4AfYB/wHhAdwB2AH/AeAB1wHSAf8B3wHSAcoB/wHf
+ Ac4BwwH/Ad0ByAG7Af8B3AHDAbMB/wHbAb8BrQH/AdsBuwGnAf8B2wG7AacB/wHbAbsBpwH/Ac8BtAGj
+ Af8BcAFWAUIB/xAAARACAQEUAUECAQFwAVoBCQEFAbcBewE2ASMB6gG3AaIBkwH/AcoB7wH7Af8BtwGi
+ AZMB/wGtAegB+QH/AbcBogGTAf8BkQHfAfcB/wG3AaIBkwH/AXsB1wH1Af8BzAG5Aa4B/wFnAU0BOQH/
+ gAABtwGiAZMB/wH9AfsB+QH/Af0B+QH3Af8B/QH5AfcB/wH8AfcB8wH/AfsB8gHtAf8B/AHzAfAB/wH9
+ AfkB9gH/AfsB8AHrAf8B9wHlAdwB/wH5AeoB5AH/AfsB8QHsAf8B3AHJAb0B/wFwAVYBQgH/DAABJAIB
+ ATMBXAEIAQcBsAGFAXYBLwH/AV4BdgElAf8BVgFkAUAB/wG6AaUBlgH/AdgB9AH8Af8BygHwAfsB/wG8
+ AewB+gH/Aa0B6AH5Af8BnwHjAfgB/wGRAd8B9wH/AYMB3AH2Af8B0AG+AbQB/wFnAU0BOQH/gAABtwGi
+ AZMB/wH+AvwC/wH9AfwB/wGVAaoC/wGVAaoD/wL+Af8BuQHHAv8BDQFAAv8BuQHHAv8B/gH9AfwB/wHU
+ Ad0C/wESAUQG/wHCAbgBsAH/AS8CAQFIBAABEAIBARQBXgEJAQcBsAHnAYUBVwH/AckBgAFEAf8BXAGH
+ ARwB/wEzAYUBIQH/Ab4BqQGaAf8B4wH3Af0B/wG3AaIBkwH/AcoB8AH7Af8BtwGiAZMB/wGtAegB+QH/
+ AbcBogGTAf8BkQHfAfcB/wHUAcQBuwH/AWcBTQE5Af+AAAG3AaIBkwL/Av4F/wENAUAC/wENAUAG/wEN
+ AUAC/wHOAdgC/wENAUAC/wHOAdgC/wENAUAC/wEOAUEC/wHZAeEC/wEPAUIC/wF+AiwB7gEKAgEBCwFC
+ AgEBcQH0AY8BYQH/Ae0BjAFfAf8BwwGBAVgB/wFSAX4BPQH/ATgBmAEhAf8BwwGuAZ4B/wHvAfsB/gH/
+ AeQB9wH9Af8B2AH0AfwB/wHKAfAB+wH/AbwB7AH6Af8BrgHoAfkB/wGfAeMB+AH/AdkBygHCAf8BZwFN
+ ATkB/4AAAboBpQGWBf8BzgHYAv8BDQFAAv8BDQFAAv8BzgHYCv8BDQFAAv8BzgHYAv8B2AHgAv8BEAFC
+ Av8BDwFCAv8BDgFBAv8B2QHhAv8BOQIBAV0BZQENAQoBuQH5AZYBaQH/AdwBjQFlAf8BawF4AU8B/wFU
+ AaEBNQH/AU4BowEtAf8ByAGyAaMB/wH4Af0C/wG3AaIBkwH/AeQB9wH9Af8BtwGiAZMB/wHKAe8B+wH/
+ AbcBogGTAf8BrQHoAfkB/wHdAdAByQH/AWcBTQE5Af+AAAG+AakBmgX/AQ0BQAL/AaYBuAL/AaYBuAL/
+ AQ0BQAP/Av4F/wENAUAC/wHOAdgC/wENAUAC/wEQAUIG/wEOAUEC/wEQAUIC/wFTAgIBpAG2AVIBPAHr
+ AegBlwFtAf8BYAF0AVoB/wFgAZYBSAH/AV4BrAE8Af8BkwGgAT0B/wHMAbYBpwX/AfgB/QH+Af8B7wH6
+ Af4B/wHkAfcB/QH/AdgB8wH8Af8BygHwAfsB/wG8AesB+gH/Aa4B6AH5Af8BZwFNATkB/4AAAcMBrgGe
+ Bf8BDQFACv8BDQFAA/8C/gL/Af4B/QH/AQ0BQAL/Ac4B2AL/AcgB0wL/AQ4BQQL/ARIBRAL/AQ0BQAL/
+ Ad0B5AL/AVMCAgGkAbYBVwFAAewCgQFeAf8BPgGhAUUB/wFWAbMBRgH/AY0BkQFcAf8B5AGUAW4C/wHC
+ AaIC/wG8AZgC/wGzAYoC/wGoAX0C/wGeAW4B/wH9AZIBYQH/Ae4BhwFWAf8B2gF9AU0B/wHGAXABRAH/
+ AbIBZAE9Af+AAAHIAbIBow3/A/4C/wL+Af8B/gH8AfsB/wH+AfoB+AH/Af4B+wH6Af8B/QH5AfcB/wHl
+ AeoC/wENAUAC/wHPAdkC/wENAUAC/wENAUAC/wFTAgIBoQFoAREBDQG9AWcBmAFWAf8BRAHFAWMB/wFI
+ AckBbgH/AXcBnQFxAf8BtgGfAW0C/wG+AZsC/wHCAaIB/wH+AcABnwH/Af0BvQGaAf8B/AG5AZYB/wH7
+ AbUBkAH/AfoBsAGLAf8B+QGrAYQB/wHzAZUBaQH/Ac0BaQE1Af+AAAHMAbYBpxP/Af4B/wH+AvwB/wH+
+ AfoB+QH/Af0B9wH1Af8B+wH0AfEB/wH8AfYB8wH/Af4B+gH4Af8B5wHsAv8BDQFAAv8B6QHtAv8BNgIB
+ AVUBRQIBAXkBVgG4AWoB/wFeAdYBgQH/AY0B4QGbAf8BggHjAZ4B/wGeAdABkwL/Ab4BmwL/AbcBkQL/
+ AbABhQL/AagBfAL/AZ8BcAL/AZcBZgH/AfcBjgFdAf8B6wGEAVUB/wHcAX4BTgH/AcsBdAFHAf+AAAES
+ ATwB3AH/ARIBOwHaAf8BFAE5AdIB/wEVATcBygH/ARcBNQHAAf8BGAEzAbUB/wEbAS8BqQH/AR0BLQGd
+ Af8BHwEqAZEB/wEhAScBhgH/ASMBJQGBAf8BKwEoAYEB/wF0AXABmgH/AagBpAHDAf8BNgIBAVUBBgIB
+ AQYBEwIBARgBVwESAQoBuwF7Ad8BlgH/AcQB7AG3Af8B0wHzAcoB/wHrAfcB1QH/AbAB5AGmAf8BggGU
+ AWQB/wHVAZQBRAH/Aa0BjwE2Af8BVgELAQMBsAEQAgEBFJAAAREBPQHiAf8BiQGgAf0B/wGCAZsB/AH/
+ AYEBkwH6Af8BegGJAfoB/wFtAYEB+AH/AWABgAH2Af8BUgF1AfQB/wFDAWkB8gH/ATYBXgHxAf8BKQFT
+ Ae8B/wEdAUoB7gH/ARQBQgHsAf8BKAEeAW0B/wwAASgCAQE7AV0BFAEMAbsBvwHsAbYB/wHeAfYBzAH/
+ AYABqQFsAf8BeQHYAYkB/wFHAa0BZQH/AYYBgQE8Af8BXwEIAQcBsQEkAgEBM5QAARIBOwHcAf8BEgE7
+ AdkB/wEUATkB0gH/ARUBOAHJAf8BFgE0AcAB/wEYATIBtQH/ARsBLwGpAf8BHQEtAZ0B/wEfASoBkQH/
+ ASEBJwGGAf8BIwElAYEB/wElASIBfQH/ASYBIAF0Af8BKAEeAWwB/xAAARQCAQEZAUYBAgEBAXwBZQEZ
+ ARQBwAGCAX0BWQHtAVsBdQFKAewBVQESAQoBvAFDAgEBcwERAgEBFf8ArQABPAIBAWMBtQFrASoB/AFP
+ AWcB2wH/AWIBBQEPAeYIAAEVAb8C/wEVAb8C/wFBAXsBYAH8AToCAQFfxAABjgJ/Af4BWQFVAVMB/wFY
+ AVQBUgH/AVgBVAFRAf8BgQFwAV4B/wHXAYkBOQH/Ad4BmwFKAf8BRgF4AecB/wEwAVIB4wH/ASgBNQG0
+ Af8BQwGKAdoB/wEiAccB/gH/AUQB0gH5Af8BZAHNAZUB/wFBAaYBeAH/AUkBWQFBAf6AAAG3AaIBkwH/
+ AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFW
+ AUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/
+ AX4BNQEyAfQK/wH8Af8BhgGOAW4B/wHNAYEBPAH/AecBvwGcAf8BlAGtAfAB/wE9AXUB9gH/ATUBUwHg
+ Af8BJwE2AbkB/wFDAYoB2gH/AYEByQHhAf8BggHRAaQB/wFLAbwBgQH/ATwBmQFxAf8EAAG3AaIBkwH/
+ AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFW
+ AUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8IAAG3AaIBkwH/AXABVgFC
+ Af8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8BcAFWAUIB/wFw
+ AVYBQgH/AXABVgFCAf8BcAFWAUIB/wFwAVYBQgH/AXABVgFCAf8EAAG3AaIBkwH/AeEB3AHYAf8B4QHc
+ AdgB/wHgAdcB0gH/Ad8B0gHKAf8B3wHOAcMB/wHdAcgBuwH/AdwBwwGzAf8B2wG/Aa0B/wHbAbsBpwH/
+ AdsBuwGnAf8B2wG7AacB/wHbAbsBpwH/AdsBuwGnAf8BzwG0AaMB/wFwAVYBQgH/AXYCJAHwBv8B/gL/
+ Af0B+wH/AUYBoQF0Af8BYwGcAXAB/wH8AfMB7AH/AfsB7wHnAf8BOAGRAfIB/wFDAXMB8gH/ATQBUAHd
+ Af8BJQE3Ab0B/wH3AdoBxwH/AfYB1gHCAf8BgwGbAWQB/wFMAX8BYQH+BAABtwGiAZMB/wH9AfgB9gH/
+ AeEB3AHYAf8B4AHXAdIB/wHfAdIBygH/Ad8BzgHDAf8B3QHIAbsB/wHcAcMBswH/AdsBvwGtAf8B2wG7
+ AacB/wHbAbsBpwH/AdsBuwGnAf8BzwG0AaMB/wFwAVYBQgH/CAABtwGiAZMB/wH9AfgB9gH/AeEB3AHY
+ Af8B4AHXAdIB/wHfAdIBygH/Ad8BzgHDAf8B5gHXAc4B/wH6AfYB8wH/AfsB+QH3Af8B+wH4AfYB/wHu
+ Ad8B1QH/AeABxAGyAf8BzwG0AaMB/wFwAVYBQgH/BAABtwGiAZMB/wH9AfkB9gH/Af0B9wH1Af8B/QH2
+ AfMB/wH8AfQB8QH/AfwB8wHvAf8B+wHyAe0B/wH7AfAB6wH/AfoB8AHpAf8B+QHuAecB/wH5AewB5gH/
+ AUMBdAGOAf8BQwF0AY4B/wH4AekB4AH/Ac8BtAGjAf8BcAFWAUIB/wF2AiQB8An/Av4B/wFpAbYBiAH/
+ AVMBygGJAf8BRwGwAYEB/wEyAcMB4gH/AV8B1AH9Af8BUgGUAfoB/wE9AXIB7wH/ATABTQHhAf8BOQE4
+ Aa8B/wHWAYQBRAH/Ad0BjAE7Af8BjQFfASoB/AQAAbcBogGTAf8B/QH7AfkB/wH9AfkB9wH/Af0B+gH4
+ Af8B/gH7AfoB/wH+AfsB+QH/Af0B9wH0Af8B/AH1AfIB/wH7AfMB7wH/AfgB6QHiAf8B9QHeAdUB/wH0
+ AdsBzgH/Ac8BtAGjAf8BcAFWAUIB/wgAAbcBogGTAf8B/QH7AfkB/wH9AfgB9gH/AfwB9QHyAf8B+gHy
+ Ae0B/wH6Ae8B6QH/Af4B/AH7Af8BywFzAQ0B/wHLAXMBDQH/AcsBcwENAf8B6QG+AZ0B/wH6Ae4B6AH/
+ Ac8BtAGjAf8BcAFWAUIB/wQAAbcBogGTAf8B/gH6AfcB/wH9AfgB9gH/AfwB+AH1Af8B/QH2AfMB/wH7
+ AfQB8QH/AfsB8wHwAf8B+wHyAe0B/wH6AfEB6wH/AfoB7wHqAf8B+QHtAecB/wFoAdsC/wFBAXwBkwH/
+ AfgB6gHjAf8BzwG0AaMB/wFwAVYBQgH/AXYCJAHwDP8B2AHxAeIB/wF9Ac4BmgH/AWABzgGZAf8BSgHY
+ AfwB/wFJAdcC/wEVAb8C/wGEAaQB7QH/ATgBbwHzAf8BRgFjAdcB/wHiAZgBQgH/AeIBnwFbAf8BYAEU
+ AQsB8gQAAbcBogGTAf8B/gL8Af8B/gL8Af8B4gHuAeIB/wENAZkBDQH/AQ0BmQENAf8B4gHtAeEB/wH7
+ AfwB+gH/ARIBlwESAf8B0AHhAc4B/wH7AfEB7AH/AfcB5gHcAf8B0AG1AaQB/wFwAVYBQgH/CAABtwGi
+ AZMB/wH+AvwB/wH+AfoB+QH/Af0B+QH2Af8B/gH7AfoB/wH+AfoB+AH/Af4C/QH/AcsBcwENAf8B/gH9
+ AfwB/wH+AfwB+wH/AcsBcwENAf8B/QH3AfQB/wHPAbQBowH/AXABVgFCAf8EAAG3AaIBkwH/Af4B+wH5
+ Af8B/QH6AfgB/wH9AfgB9gH/Af0B9wH1Af8B/QH2AfMB/wH7AfUB8QH/AfsB8wHvAf8B+wHyAe4B/wEw
+ AZUBpQH/ATMBjAGhAf8BbwHfAf4B/wE8AYEBlgH/AUABfAGSAf8BRAF1AY8B/wFwAVYBQgH/AXYCJAHw
+ EP8B2AHwAeIB/wF5AcoBoAH/ASQBxAL/ASQBxAL/AfwB7wHnAf8B+wHrAeEB/wGBAaIB7wH/AVoBgQHq
+ Af8B4gGzAYEB/wHpAcgBqgH/AVcBCgEJAfAEAAG3AaIBkwL/Av4C/wL+Af8BJwGjAScB/wHiAe4B4gL/
+ Af4B/QH/AZ4B2AGeAf8BFQGZARUB/wEOAZUBDgH/Aa4BzQGsAf8BDwGVAQ8B/wHlAekB3QH/AdIBuAGo
+ Af8BcAFWAUIB/wgAAbcBogGTAv8C/gH/Af4B/QH7Af8C/gH9Af8B2gGSAWgB/wHaAZIBaAL/Af4B/QH/
+ AcsBcwENAf8BywFzAQ0B/wHLAXMBDQH/AfIB2AHGAf8B/AH2AfMB/wHPAbQBowH/AXABVgFCAf8EAAG6
+ AaUBlgH/Af4B/AH7Af8B/gH7AfoB/wH+AfoB+AH/Af0B+AH2Af8B/AH3AfQB/wH9AfYB8wH/AfwB9AHx
+ Af8B/AHzAe8B/wGIAfUC/wGBAe8B/gH/AX4B6AL/AXMB4gL/AWsB3QL/AUQBdQGPAf8BcAFWAUIB/wF2
+ AiQB8BH/Af4C/wH+AfwB+gH/Af4B+QH1Af8B/QH2AfEB/wH8AfIB6wH/AfwB7gHlAf8B+gHqAd8B/wH6
+ AeUB2AH/AfkB4AHSAf8B6gHUAcMB/wFXAQoBCQHwBAABugGlAZYJ/wENAZkBDQL/Av4C/wL+Bv8C/QH/
+ ARABlgEQAf8BDwGVAQ8B/wEOAZQBDgH/Ad8B6QHcAf8B3AHLAcEB/wFwAVYBQgH/CAABugGlAZYG/wL+
+ Bf8BywFzAQ0B/wHLAXMBDQL/Af4B/QH/AcsBcwENAv8C/QH/Af4B/QH8Af8BywFzAQ0B/wH9AfgB9gH/
+ AdABuQGrAf8BcAFWAUIB/wQAAb4BqQGaAf8B/gH9AfwB/wH+AfwB+gH/Af4B+wH5Af8B/QH6AfgB/wH9
+ AfgB9wH/AfwB9wH1Af8BQwF0AY4B/wFDAXQBjgH/AfsB9AHvAf8B+wHyAe4B/wGDAfIB/gH/ATQBjAGh
+ Af8B+gHtAegB/wHRAcEBtgH/AXABVgFCAf8BdgIkAfAV/wH+Af0B/wH+AfoB+QH/Af4B+AH1Af8B/QH0
+ Ae8B/wH8AfEB6QH/AfsB7AHjAf8B+gHoAd0B/wH5AeQB1gH/AeoB1gHIAf8BVwEKAQkB8AQAAb4BqQGa
+ Cf8BDQGZAQ0B/wHiAe4B4gL/Av4B/wGBAckBgQH/ARUBmQEVAf8BEAGWARAB/wHqAfIB6gH/AQ4BlAEO
+ Af8BEAGWARAB/wHmAd0B1wH/AXABVgFCAf8IAAG+AakBmgn/AfMB2wHJAf8BywFzAQ0B/wHLAXMBDQH/
+ AfMB2gHIAf8BywFzAQ0B/wHLAXMBDQH/AcsBcwENAf8B6QG+AZ4B/wH7AfMB7gH/AdEBwQG2Af8BcAFW
+ AUIB/wQAAcMBrgGeAv8C/gH/Af4B/QH8Af8B/gH8AfsB/wH9AfsB+gH/Af0B+QH4Af8B/AH4AfcB/wFo
+ AdsC/wFBAXwBkwH/AfwB9AHxAf8B+wH0Ae8B/wGSAfsB/gH/ATABlQGlAf8B+gHvAeoB/wHRAcEBtgH/
+ AXABVgFCAf8BdgIkAfAZ/wH9AfwB/wH+AfoB+AH/Af0B9wHzAf8B/AHzAe0B/wH8Ae8B5wH/AfoB6wHh
+ Af8B+gHnAdsB/wHqAdkBywH/AVcBCgEJAfAEAAHDAa4Bngn/AeIB7gHiAf8BJwGjAScB/wENAZkBDQH/
+ AeIB7gHiAf8B4gHuAeEB/wEOAZQBDgH/ARIBlwESAf8BDQGZAQ0B/wHKAd0ByAH/AecB3gHYAf8BcAFW
+ AUIB/wgAAcMBrgGeCf8BywFzAQ0B/wHdAZsBdgH/Ad0BmwF2Af8BywFzAQ0C/wL+Av8B/gH9Av8C/QH/
+ AfwB9gHzAf8B+QHrAeUB/wHRAcEBtgH/AXABVgFCAf8EAAHIAbIBowL/Av4C/wH+Af0B/wH+Af0B/AH/
+ Af4B/AH7Af8BMAGVAaUB/wEzAYwBoQH/AW8B3wH+Af8BPAGBAZYB/wFAAXwBkgH/AUQBdQGPAf8B+wHz
+ Ae8B/wH6AfIB7gH/AfsB8AHsAf8B0QHBAbYB/wFwAVYBQgH/AXICIQHwHf8C/gL/AfsB+gH/Af4B+AH1
+ Af8B/QH1Ae8B/wH8AfEB6AH/AfsB7AHiAf8B6gHfAdQB/wFXAQoBCQHwBAAByAGyAaMT/wH+Af8C/gH9
+ Av8C/gH/ARYBmQEWAf8B3wHsAd8B/wENAZQBDQH/ARYBmQEWAf8B6wHkAeAB/wFwAVYBQgH/CAAByAGy
+ AaMJ/wHLAXMBDQn/AcsBcwENAv8B/gH9Af8B/AH1AfEB/wH7AfIB7QH/AfoB7gHpAf8B+QHqAeQB/wHR
+ AcEBtgH/AXABVgFCAf8EAAG+AakBmgH/BAAB/gH/Af4C/wH+Af0B/wH+Af0B/AH/AYgB9QL/AYEB7wH+
+ Af8BfgHoAv8BcwHiAv8BawHdAv8BRAF1AY8B/wH8AfQB8QH/AfsB8wHvAf8B+wHyAe0B/wHfAc4BwwH/
+ AXABVgFCAf8BfAEyAS8B9AH3AfAB7AH/AfwB9gH0Af8B/AH2AfMB/wH7AfUB8gH/AfoB9AHxAf8B+gH0
+ AfAB/wH6AfIB7gH/AfoB8gHuAf8B+gHwAeoB/wH5Ae0B5gH/AfkB6gHhAf8B+AHmAdwB/wH4AeMB1gH/
+ AeYB1gHJAf8BXQIHAewEAAHMAbYBpxP/Af4B/wH+AvwB/wH+AvsC/wL9A/8B/gH/ARQBmAEUAf8B3wHr
+ Ad4B/wH8AfQB8AH/AXABVgFCAf8IAAHMAbYBpxP/Af4C/wL+Af8B/gL7Af8B/QH3AfUB/wH7AfQB8QH/
+ AfsB8QHtAf8B+gHuAegB/wH5AeoB4wH/AXABVgFCAf8EAAHDAa4BngH/CAAB/gP/Af4C/QH/Af4C/AH/
+ Af4B+wH6Af8BgwHyAf4B/wE0AYwBoQH/Af0B+AH2Af8B/AH3AfUB/wH8AfYB8wH/AfwB9AHxAf8B+wH0
+ AfAB/wHfAc4BwwH/AXABVgFCAf8BiAE6ATQB9QHwAbEBkgH/AfQBsgGRAf8B6AGfAYEB/wHhAZABdQH/
+ Ad0BiAFqAf8B3AGHAWgB/wHaAYMBZAH/AdgBgQFfAf8B1wGBAVsB/wHWAYEBWAH/AdUBgQFWAf8B1AGB
+ AVQB/wHUAYEBUwH/AcoBfQFOAf8BYAEOAQkB8QQAAW0BugFzAf8BagG1AXAB/wFmAa8BbQH/AWIBpgFp
+ Af8BXgGeAWQB/wFZAZUBYAH/AVQBjAFbAf8BTwGDAVYB/wFeAYcBZQH/AYgBqQGNAf8BtQHIAbgB/wGS
+ AaoBlQH/AVQBeAFaAf8BMwFaATsB/wgAAeoBqgGLAf8B6gGqAYsB/wHqAaoBiwH/AekBpQGEAf8B6QGf
+ AYEB/wHnAZcBewH/AeYBjgFvAf8B5QGGAWMB/wHjAYEBVwH/AeMBgQFNAf8B4gF/AUYB/wHiAX8BRgH/
+ AeIBfwFGAf8ByAFvATwB/wQAAbwBYgExAf8BvAFiATEB/wG8AWIBMQH/AbwBYgExAf8BugFaASYB/wG6
+ AVEBFQH/AbcBRAENAf8BkgH7Af4B/wEwAZUBpQH/AbEBGgENAf8BsQEPAQ0B/wGvAg0B/wGvAg0B/wGv
+ Ag0B/wGvAg0B/wGGAg0B/wHYAaoBkgH/AfwBwAGgAf8B/AG9AZsB/wH5AbYBlAH/AfUBsAGLAf8B8QGp
+ AYUB/wHuAaQBgQH/AewBoAGBAf8B6wGcAX8B/wHnAZUBeAH/AeQBjwFyAf8B4QGLAWsB/wHfAYYBZgH/
+ Ad0BggFhAf8BzgGBAVkB/wFFATUBKwH/BAABbQG6AXMB/wFAAcsBdAH/AT0BxwFvAf8BOwHBAWoB/wE4
+ AboBYwH/ATQBswFbAf8BMAGqAVIB/wErAaIBSgH/AScBmQFBAf8BIwGQATkB/wEgAYgBMQH/ARwBggEq
+ Af8BGQGBASQB/wEzAVoBOwH/CAAB6gGqAYsC/wHCAaIB/wH+AcABnwH/Af0BvQGaAf8B/AG5AZYB/wH7
+ AbUBkAH/AfoBsAGLAf8B+QGrAYQB/wH4AacBgQH/AfYBogGBAf8B9QGdAX4B/wH1AZkBdwH/AfMBlQFy
+ Af8BzQFyAT4B/wQAAbwBYgExAf8B3gGBAVYB/wHeAYEBVgH/AdwBgQFRAf8B2wGBAUkB/wHZAXsBQgH/
+ AdcBdAE5Af8B1gFsATEB/wHUAWQBJgH/AdMBXgEaAf8BzwFWAREB/wHOAU4BDQH/Ac4BRwENAf8BywFB
+ AQ0B/wHLAUEBDQH/AY4CDQH/AWACAwHTAV4CAwHKAWUCBQHcAWMCAwHQAWICAwHUAYEBIwEZAfEBegEd
+ ARcB8AFuAQ4BCwHoAWQCBAHaAWMCAwHSAWECAwHMAWECAwHMAWECAwHMAWECAwHMAWECAwHRAWQCBAHd
+ BAABbQG6AXMB/wFqAbUBcAH/AWYBrwFtAf8BYgGmAWkB/wFeAZ4BZAH/AVkBlQFgAf8BVAGMAVsB/wFP
+ AYMBVgH/AUoBgQFSAf8BRQF8AU0B/wFAAXMBRwH/ATwBagFDAf8BNwFhAT4B/wEzAVoBOwH/CAAB6gGq
+ AYsB/wHqAaoBiwH/AeoBqgGLAf8B6gGqAYsB/wHqAaYBhgH/AekBoQGBAf8B6AGbAYEB/wHnAZQBeQH/
+ AeYBjgFvAf8B5QGHAWUB/wHkAYEBWwH/AeQBgQFTAf8B4wGBAUsB/wHiAX8BRgH/BAABvAFiATEB/wG8
+ AWIBMQH/AbwBYgExAf8BvAFiATEB/wG8AWIBMQH/AbwBXAEpAf8BugFUAR0B/wG5AUoBDwH/AbcBPwEN
+ Af8BtgE2AQ0B/wG0ASoBDQH/AbIBIQENAf8BsgEXAQ0B/wGxAQ8BDQH/AbEBDwENAf8BrwINAf//AAEA
+ AUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/8BAAL/AfwFAAL/AfwGAAEDAfwGAAED
+ AcAGAAEDAYAGAAEBOQABDwUAAQMBgAEfBQABAwHAAT8EAAT/BAAB+AFhBv8CAAT/BAABgAEBAYABAQQA
+ AYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQA
+ AYABAQGAAQEEAAGAAQEBgAEBAUADAAGAAQEBgAEBAWADAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGA
+ AQECAAj/Cw==
+
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/samples/LineCounter/Src/LineCounterViewContent.cs b/samples/LineCounter/Src/LineCounterViewContent.cs
new file mode 100644
index 0000000000..27d504645c
--- /dev/null
+++ b/samples/LineCounter/Src/LineCounterViewContent.cs
@@ -0,0 +1,35 @@
+/*
+ * Created by SharpDevelop.
+ * User: Daniel Grunwald
+ * Date: 09.05.2006
+ * Time: 17:53
+ */
+
+using System;
+using System.Windows.Forms;
+using ICSharpCode.SharpDevelop.Gui;
+
+namespace LineCounterAddin
+{
+ ///
+ /// Description of the view content
+ ///
+ public class LineCounterViewContent : AbstractViewContent
+ {
+ LineCounterBrowser browser = new LineCounterBrowser();
+
+ ///
+ /// The representing the view.
+ ///
+ public override Control Control {
+ get {
+ return browser;
+ }
+ }
+
+ public LineCounterViewContent()
+ {
+ this.TitleName = "Line Counter";
+ }
+ }
+}