/// <summary>
        /// This creates an instance of the WPF spell checker for the given text box
        /// </summary>
        /// <param name="textBox">The text box to initialize</param>
        private static void AddWpfSpellChecker(TextBox textBox)
        {
            // Don't do anything if the default spell checker is enabled or it's read-only
            if (!textBox.SpellCheck.IsEnabled && !textBox.IsReadOnly)
            {
                lock (syncRoot)
                {
                    // Create the shared configuration and dictionary on first use
                    if (configuration == null)
                    {
                        configuration = new SpellCheckerConfiguration();
                        configuration.Load(SpellingConfigurationFile.GlobalConfigurationFilename);

                        var globalDictionaries = configuration.DictionaryLanguages.Select(l =>
                                                                                          GlobalDictionary.CreateGlobalDictionary(l, configuration.AdditionalDictionaryFolders,
                                                                                                                                  configuration.RecognizedWords)).Where(d => d != null).Distinct().ToList();

                        dictionary = new SpellingDictionary(globalDictionaries, configuration.IgnoredWords);
                    }

                    // Ignore it if disabled or it's an excluded text box
                    string name = ElementName(textBox);

                    if (!configuration.EnableWpfTextBoxSpellChecking || configuration.VisualStudioExclusions.Any(
                            v => v.IsMatch(name)))
                    {
                        return;
                    }
                }

                var wsc = new WpfTextBoxSpellChecker(textBox);

                wpfSpellCheckers.AddOrUpdate(textBox, wsc, (k, v) => wsc);
            }
        }
Example #2
0
        /// <summary>
        /// This is used to generate the configuration for the instance
        /// </summary>
        /// <returns>The configuration to use or null if the file should not be spell checked (disabled or not a
        /// type of file that can be spell checked such as a binary file).</returns>
        public SpellCheckerConfiguration GenerateConfiguration(IEnumerable <string> codeAnalysisFiles)
        {
            var config = new SpellCheckerConfiguration();

            try
            {
                foreach (var c in this.ConfigurationFiles)
                {
                    config.Load(c.Value);
                }

                // Merge any code analysis dictionary settings
                if (codeAnalysisFiles != null)
                {
                    foreach (string cad in codeAnalysisFiles)
                    {
                        if (File.Exists(cad))
                        {
                            config.ImportCodeAnalysisDictionary(cad);
                        }
                    }
                }

                // If wanted, set the language based on the resource filename
                if (config.DetermineResourceFileLanguageFromName &&
                    Path.GetExtension(this.Filename).Equals(".resx", StringComparison.OrdinalIgnoreCase))
                {
                    // Localized resource files are expected to have filenames in the format
                    // BaseName.Language.resx (i.e. LocalizedForm.de-DE.resx).
                    string ext = Path.GetExtension(Path.GetFileNameWithoutExtension(this.Filename));

                    if (ext.Length > 1)
                    {
                        ext = ext.Substring(1);

                        SpellCheckerDictionary match;

                        if (SpellCheckerDictionary.AvailableDictionaries(
                                config.AdditionalDictionaryFolders).TryGetValue(ext, out match))
                        {
                            // Clear any existing dictionary languages and use just the one that matches the
                            // file's language.
                            config.DictionaryLanguages.Clear();
                            config.DictionaryLanguages.Add(match.Culture);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // Ignore errors, we just won't load the configurations after the point of failure
                System.Diagnostics.Debug.WriteLine(ex);
            }

            return((!config.IncludeInProjectSpellCheck || config.ShouldExcludeFile(this.CanonicalName) ||
                    IsBinaryFile(this.CanonicalName)) ? null : config);
        }
        /// <summary>
        /// Generate the configuration for all parent items
        /// </summary>
        /// <returns>The generated configuration to use</returns>
        /// <remarks>The configuration is a merger of the global settings plus any solution, project, and folder
        /// settings related to but excluding the current configuration file.  This allows us to determine the
        /// inherited additional dictionary folders to use.</remarks>
        private SpellCheckerConfiguration GenerateParentConfiguration()
        {
            Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();

            ProjectItem projectItem, fileItem;
            string      filename, projectPath;

            // Start with the global configuration
            var config = new SpellCheckerConfiguration();

            if (isGlobal)
            {
                return(config);
            }

            try
            {
                config.Load(SpellingConfigurationFile.GlobalConfigurationFilename);

                if (configType == ConfigurationType.Solution)
                {
                    return(config);
                }

                var dte2 = Utility.GetServiceFromPackage <DTE2, SDTE>(true);

                if (dte2 != null && dte2.Solution != null && !String.IsNullOrWhiteSpace(dte2.Solution.FullName))
                {
                    var solution = dte2.Solution;

                    // See if there is a solution configuration
                    filename    = solution.FullName + ".vsspell";
                    projectItem = solution.FindProjectItemForFile(filename);

                    if (projectItem != null)
                    {
                        config.Load(filename);
                    }

                    if (configType == ConfigurationType.Project)
                    {
                        return(config);
                    }

                    // Find the project item for the file we are opening
                    if (configType != ConfigurationType.Folder)
                    {
                        projectItem = solution.FindProjectItemForFile(Path.Combine(configFilePath, relatedFilename));
                    }
                    else
                    {
                        projectItem = solution.FindProjectItemForFile(Path.Combine(configFilePath, relatedFilename + ".vsspell"));
                    }

                    if (projectItem != null)
                    {
                        fileItem = projectItem;

                        // If we have a project (we should), see if it has settings
                        if (projectItem.ContainingProject != null &&
                            !String.IsNullOrWhiteSpace(projectItem.ContainingProject.FullName))
                        {
                            filename    = projectItem.ContainingProject.FullName + ".vsspell";
                            projectItem = solution.FindProjectItemForFile(filename);

                            if (projectItem != null)
                            {
                                config.Load(filename);
                            }

                            // Get the full path based on the project.  The configuration filename will refer to
                            // the actual path which may be to a linked file outside the project's folder
                            // structure.
                            projectPath = Path.GetDirectoryName(filename);
                            filename    = Path.GetDirectoryName((string)fileItem.Properties.Item("FullPath").Value);

                            // Search for folder-specific configuration files
                            if (filename.StartsWith(projectPath, StringComparison.OrdinalIgnoreCase))
                            {
                                // Then check subfolders.  No need to check the root folder as the project
                                // settings cover it.
                                if (filename.Length > projectPath.Length)
                                {
                                    foreach (string folder in filename.Substring(projectPath.Length + 1).Split('\\'))
                                    {
                                        projectPath = Path.Combine(projectPath, folder);
                                        filename    = Path.Combine(projectPath, folder + ".vsspell");

                                        if (configType == ConfigurationType.Folder &&
                                            Path.GetFileNameWithoutExtension(filename) == relatedFilename)
                                        {
                                            return(config);
                                        }

                                        projectItem = solution.FindProjectItemForFile(filename);

                                        if (projectItem != null)
                                        {
                                            config.Load(filename);
                                        }
                                    }
                                }
                            }

                            // If the item looks like a dependent file item, look for a settings file related to
                            // the parent file item.
                            if (fileItem.Collection != null && fileItem.Collection.Parent != null)
                            {
                                projectItem = fileItem.Collection.Parent as ProjectItem;

                                if (projectItem != null && projectItem.Kind == EnvDTE.Constants.vsProjectItemKindPhysicalFile)
                                {
                                    filename    = (string)projectItem.Properties.Item("FullPath").Value + ".vsspell";
                                    projectItem = solution.FindProjectItemForFile(filename);

                                    if (projectItem != null)
                                    {
                                        config.Load(filename);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // Ignore errors, we just won't load the configurations after the point of failure
                System.Diagnostics.Debug.WriteLine(ex);
            }

            return(config);
        }