void Command_Database_GetSproc()
        {
            ValidateConnection();

            var results = new List <string>();

            foreach (var selection in Selections)
            {
                var sproc  = GetString(selection);
                var result = "Success";
                try
                {
                    var text = "";
                    using (var command = dbConnection.CreateCommand())
                    {
                        command.CommandText = $"sp_helptext '{sproc}'";
                        using (var reader = command.ExecuteReader())
                            while (reader.Read())
                            {
                                text += reader.GetString(0);
                            }
                    }

                    TabsParent.Add(displayName: sproc, bytes: Coder.StringToBytes(text, Coder.CodePage.UTF8), codePage: Coder.CodePage.UTF8, contentType: ParserType.SQL, modified: false);
                }
                catch (Exception ex) { result = ex.Message; }
                results.Add($"{sproc}: {result}");
            }
            ReplaceSelections(results);
        }
        void Command_Diff_CopyLeftRight(bool moveLeft)
        {
            if (DiffTarget == null)
            {
                throw new Exception("Diff not in progress");
            }

            var target = TabsParent.GetIndex(this) < DiffTarget.TabsParent.GetIndex(DiffTarget) ? this : DiffTarget;
            var source = target == this ? DiffTarget : this;

            if (!moveLeft)
            {
                Helpers.Swap(ref target, ref source);
            }

            // If both tabs are active only do this from the target tab
            var bothActive = TabsParent.TabIsActive(DiffTarget);

            if ((bothActive) && (target != this))
            {
                return;
            }

            var strs = source.GetSelectionStrings();

            target.ReplaceSelections(strs);
            // If both tabs are active queue an empty edit so undo will take both back to the same place
            if (bothActive)
            {
                source.ReplaceSelections(strs);
            }
        }
        void Command_Diff_NextPrevious(bool next, bool shiftDown)
        {
            if (DiffTarget == null)
            {
                throw new Exception("Diff not in progress");
            }

            if ((TabsParent.GetIndex(this) < DiffTarget.TabsParent.GetIndex(DiffTarget)) && (DiffTarget.Active))
            {
                return;
            }

            var lines = Selections.AsParallel().AsOrdered().Select(range => GetDiffNextPrevious(range, next)).ToList();

            for (var pass = 0; pass < 2; ++pass)
            {
                var target = pass == 0 ? this : DiffTarget;
                var sels   = lines.Select(tuple => new Range(target.Data.GetOffset(tuple.Item2, 0, true), target.Data.GetOffset(tuple.Item1, 0, true))).ToList();
                if (shiftDown)
                {
                    sels.AddRange(target.Selections);
                }
                target.SetSelections(sels);
            }
        }
        void Command_File_Open_Selected()
        {
            var files = RelativeSelectedFiles();

            foreach (var file in files)
            {
                TabsParent.Add(file);
            }
        }
 void Command_Window_TabIndex(bool activeOnly)
 {
     ReplaceSelections((TabsParent.GetIndex(this, activeOnly) + 1).ToString());
 }
 void Command_File_New_FromSelections() => GetSelectionStrings().ForEach((str, index) => TabsParent.Add(displayName: $"Selection {index + 1}", bytes: Coder.StringToBytes(str, Coder.CodePage.UTF8), codePage: Coder.CodePage.UTF8, contentType: ContentType, modified: false));
        void Command_Position_Goto(GotoType gotoType, bool selecting, PositionGotoDialog.Result result)
        {
            var values = GotoRange.GetPositionsData(GetVariableExpressionResults <string>(result.Expression), gotoType);

            if (!values.Any())
            {
                return;
            }

            var hasFiles = values.First().File != null;

            if (values.Any(x => (x.File != null) != hasFiles))
            {
                throw new Exception("Either all locations must have files or none");
            }

            var valuesByFile = new List <List <GotoRange> >();
            var fileMap      = new Dictionary <string, List <GotoRange> >(StringComparer.OrdinalIgnoreCase);

            foreach (var value in values)
            {
                List <GotoRange> list;
                if (result.OpenFilesOnce)
                {
                    var key = value.File ?? "";
                    if (!fileMap.ContainsKey(key))
                    {
                        fileMap[key] = list = new List <GotoRange>();
                        valuesByFile.Add(list);
                    }
                    else
                    {
                        list = fileMap[key];
                    }
                }
                else
                {
                    list = new List <GotoRange>();
                    valuesByFile.Add(list);
                }
                list.Add(value);
            }

            if (hasFiles)
            {
                var invalidFiles = valuesByFile.Select(list => list.First().File).NonNull().Where(file => !File.Exists(file)).ToList();
                if (invalidFiles.Any())
                {
                    throw new Exception($"The following files could not be found: {string.Join("\n", invalidFiles)}");
                }
            }

            var active = new HashSet <TextEditor>();

            foreach (var list in valuesByFile)
            {
                var useTE = list.First().File == null ? this : TabsParent.Add(list.First().File);
                active.Add(useTE);

                var sels      = useTE.Selections.ToList();
                var positions = list;

                if ((sels.Count == 0) && ((gotoType == GotoType.Line) || (gotoType == GotoType.Position)))
                {
                    sels.Add(useTE.BeginRange);
                }
                if (sels.Count == 1)
                {
                    sels = sels.Resize(positions.Count, sels[0]).ToList();
                }
                if (positions.Count == 1)
                {
                    positions = positions.Expand(sels.Count, positions[0]).ToList();
                }
                if (positions.Count != sels.Count)
                {
                    throw new Exception("Expression count doesn't match selection count");
                }

                useTE.SetSelections(sels.AsParallel().AsOrdered().Select((range, ctr) => positions[ctr].GetRange(useTE, range, selecting)).ToList());
            }

            if (hasFiles)
            {
                foreach (var item in TabsParent.Items)
                {
                    item.Active = active.Contains(item);
                }
                TabsParent.TopMost = active.First();
            }
        }