Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure?

Multi-History Selector

Description
This macro will allow you to combine and paste multiple items from the clipboard history list.
Language
C#.net
Minimum Version
Created By
Alex399
Contributors
-
Date Created
19h ago
Date Last Modified
19h ago

Macro Code

using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;

public static class ClipboardFusionHelper
{
    // --- Localization ---
    private static string _currentLanguage = "en"; // Default language
    private static readonly Dictionary<string, Dictionary<string, string>> _translations = new Dictionary<string, Dictionary<string, string>>
    {
        {
            "ru", new Dictionary<string, string>
            {
                { "FormTitle", "Мульти-вставка из истории (Двойной клик для отметки)" },
                { "ReverseOrderCheckBox", "Объединить в обратном порядке" },
                { "SeparatorLabel", "Разделитель:" },
                { "OkButton", "OK" },
                { "PasteButton", "Вставить" },
                { "CancelButton", "Отмена" },
                { "SelectAllMenuItem", "Выбрать все" },
                { "DeselectAllMenuItem", "Снять выделение" },
                { "ErrorLoadingHistoryPrefix", "Ошибка загрузки истории:" },
                { "HistoryIsEmpty", "История буфера обмена пуста." },
                { "ErrorLoadingHistoryMessage", "Ошибка загрузки истории: {0} См. лог для деталей." }, 
                { "ErrorProcessingSelectionMessage", "Ошибка при обработке выбора: {0}" }, 
                { "SetClipboardLogMessage", "MultiPastUtil: Попытка установить текст в буфер обмена (успех: {0}). Результат: {1}" }, // {0} bool, {1} text
                { "ErrorSavingSettingsLog", "Ошибка сохранения настроек MultiPastUtil: {0}" } 
            }
        },
        {
            "en", new Dictionary<string, string>
            {
                { "FormTitle", "Multi-Paste from History (Double-click to check)" },
                { "ReverseOrderCheckBox", "Combine in reverse order" },
                { "SeparatorLabel", "Separator:" },
                { "OkButton", "OK" },
                { "PasteButton", "Paste" },
                { "CancelButton", "Cancel" },
                { "SelectAllMenuItem", "Select All" },
                { "DeselectAllMenuItem", "Deselect All" },
                { "ErrorLoadingHistoryPrefix", "Error loading history:" },
                { "HistoryIsEmpty", "Clipboard history is empty." },
                { "ErrorLoadingHistoryMessage", "Error loading history: {0} See log for details." },
                { "ErrorProcessingSelectionMessage", "Error processing selection: {0}" },
                { "SetClipboardLogMessage", "MultiPastUtil: Attempted to set clipboard text (success: {0}). Result: {1}" },
                { "ErrorSavingSettingsLog", "Error saving MultiPastUtil settings: {0}" }
            }
        }
        // You can add other languages here
    };

    // Method to get localized string
    private static string GetLocalizedString(string key, params object[] args)
    {
        string format = key; // By default, return the key if nothing is found

        // Try to find translation for current language
        if (_translations.TryGetValue(_currentLanguage, out var langDict) && langDict.TryGetValue(key, out var translation))
        {
            format = translation;
        }
        // If there is no translation for current language, try to find for English (fallback)
        else if (_currentLanguage != "en" && _translations.TryGetValue("en", out var enLangDict) && enLangDict.TryGetValue(key, out var enTranslation))
        {
            format = enTranslation;
        }

        // Format string if arguments are passed
        try
        {
            return args.Length > 0 ? string.Format(format, args) : format;
        }
        catch (FormatException ex)
        {
             BFS.General.LogText($"Localization format error for key '{key}': {ex.Message}");
             return format; // Return unformatted string in case of error
        }
    }

    // Method to set language
    public static void SetLanguage(string languageCode)
    {
        if (_translations.ContainsKey(languageCode))
        {
            _currentLanguage = languageCode;
            BFS.General.LogText($"MultiPastUtil language set to: {languageCode}");
            
            // Save language selection in settings for future runs
            try 
            {
                BFS.ScriptSettings.WriteValue(SettingLanguage, languageCode);
            }
            catch (Exception ex)
            {
                BFS.General.LogText($"Не удалось сохранить настройку языка: {ex.Message}");
            }
        }
        else
        {
             BFS.General.LogText($"MultiPastUtil language '{languageCode}' not found.");
        }
    }
    // --- End of Localization ---

    // This variable will store the user's choice
    private static string _resultText = null;

    // Define constants
    private const int DefaultFormWidth = 800;
    private const int DefaultFormHeight = 450;
    private const int DefaultListBoxWidth = 200;
    private const int HistoryItemsToLoad = 100;
    private const int ButtonPanelHeight = 30;
    private const int TopPanelHeight = 30;
    private const int ButtonWidth = 75;
    private const int SplitterWidth = 5;
    private const int SplitterMinSize = 100;
    private const int SplitterMinExtra = 150;
    private const string DefaultSeparator = "\r\n";

    // Keys for settings
    private const string SettingFormWidth = "MultiPastUtil_FormWidth";
    private const string SettingFormHeight = "MultiPastUtil_FormHeight";
    private const string SettingListBoxWidth = "MultiPastUtil_ListBoxWidth";
    private const string SettingLanguage = "MultiPastUtil_Language"; // Add key for language

    // Helper function to read settings
    private static int ReadIntSetting(string key, int defaultValue)
    {
        try
        {
            // Try to read value
            string stringValue = BFS.ScriptSettings.ReadValue(key);
            // Try to convert to int
            if (int.TryParse(stringValue, out int value) && value > 50) // Add minimum check
            {
                return value;
            }
        }
        catch (Exception ex)
        {
            // Log error if needed
            BFS.General.LogText($"Ошибка чтения настройки '{key}': {ex.Message}");
        }
        // Return default value if something went wrong
        return defaultValue;
    }

    public static string ProcessText(string text)
    {
        _resultText = text;
        
        // Read language from settings, if it exists
        try
        {
            string savedLanguage = BFS.ScriptSettings.ReadValue(SettingLanguage);
            if (!string.IsNullOrEmpty(savedLanguage) && _translations.ContainsKey(savedLanguage))
            {
                _currentLanguage = savedLanguage; // Set saved language
            }
        }
        catch (Exception ex)
        {
            BFS.General.LogText($"Не удалось прочитать настройку языка: {ex.Message}");
        }

        // Read saved sizes
        int formWidth = ReadIntSetting(SettingFormWidth, DefaultFormWidth);
        int formHeight = ReadIntSetting(SettingFormHeight, DefaultFormHeight);
        int listBoxWidth = ReadIntSetting(SettingListBoxWidth, DefaultListBoxWidth);

        // Wrap form in using
        using (Form form = new Form())
        {
            form.Text = GetLocalizedString("FormTitle"); // Use localization
            form.ClientSize = new Size(formWidth, formHeight);
            form.StartPosition = FormStartPosition.CenterScreen;
            
            // Create main table to place all elements
            TableLayoutPanel mainLayout = new TableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 1,
                RowCount = 4, // Menu, top panel, main area, bottom button panel
            };
            
            // Configure rows: menu and top panel fixed height, main area stretches, bottom button panel fixed height
            mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Menu
            mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Top panel
            mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); // Main area (stretched)
            mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // Bottom button panel
            
            // Clear all controls
            form.Controls.Clear();
            // Add only main table to form
            form.Controls.Add(mainLayout);
            
            // --- Initialize main panels and controls in advance --- 
            FlowLayoutPanel topPanel = new FlowLayoutPanel 
            { 
                Height = TopPanelHeight, 
                Dock = DockStyle.Fill, 
                FlowDirection = FlowDirection.LeftToRight,
                Padding = new Padding(5, 5, 5, 0),
                AutoSize = true
            };

            Panel buttonPanel = new Panel { Height = ButtonPanelHeight, Dock = DockStyle.Bottom };

            CheckedListBox checkedListBox = new CheckedListBox
            {
                Dock = DockStyle.Fill,
                CheckOnClick = false,
                HorizontalScrollbar = true,
                IntegralHeight = false
            };

            // --- End of preliminary initialization ---

            // Create menu for form (again using MenuStrip)
            MenuStrip menuStrip = new MenuStrip();
            menuStrip.Dock = DockStyle.Top;
            
            ToolStripMenuItem languageMenu = new ToolStripMenuItem("Language / Язык");
            
            ToolStripMenuItem ruMenuItem = new ToolStripMenuItem("Русский") { Name = "ruMenuItem" };
            ToolStripMenuItem enMenuItem = new ToolStripMenuItem("English") { Name = "enMenuItem" };
            
            // Set marks for current language
            ruMenuItem.Checked = _currentLanguage == "ru";
            enMenuItem.Checked = _currentLanguage == "en"; 
            
            // Then set event handlers for both menu items
            ruMenuItem.Click += (sender, e) =>
            {
                if (_currentLanguage != "ru")
                {
                    SetLanguage("ru");
                    UpdateFormLanguage(form);
                }
            };
            
            enMenuItem.Click += (sender, e) =>
            {
                if (_currentLanguage != "en")
                {
                    SetLanguage("en");
                    UpdateFormLanguage(form);
                }
            };
            
            // Add menu items
            languageMenu.DropDownItems.Add(ruMenuItem);
            languageMenu.DropDownItems.Add(enMenuItem);
            menuStrip.Items.Add(languageMenu);

            // Add MenuStrip to first table cell
            mainLayout.Controls.Add(menuStrip, 0, 0);

            // --- Fill and add top panel (already created) ---
            Label separatorLabel = new Label
            {
                Name = "separatorLabel",
                Text = GetLocalizedString("SeparatorLabel"),
                AutoSize = true,
                TextAlign = ContentAlignment.MiddleLeft,
                Margin = new Padding(10, 5, 0, 0)
            };
            
            TextBox separatorTextBox = new TextBox 
            { 
                Width = 100,
                Margin = new Padding(5, 3, 0, 0) 
            };
            
            // Empty label for spacing
            Label spacerLabel = new Label 
            { 
                Width = 20,
                Text = "", 
                AutoSize = false
            };

            CheckBox reverseOrderCheckBox = new CheckBox {
                Name = "reverseOrderCheckBox",
                Text = GetLocalizedString("ReverseOrderCheckBox"),
                AutoSize = true,
                Margin = new Padding(0, 3, 0, 0)
            };

            // Add elements to top panel in left-to-right order
            topPanel.Controls.Add(separatorLabel);
            topPanel.Controls.Add(separatorTextBox);
            topPanel.Controls.Add(spacerLabel);
            topPanel.Controls.Add(reverseOrderCheckBox);

            // Add top panel to second table cell
            mainLayout.Controls.Add(topPanel, 0, 1);

            // --- Fill and add button panel (already created) ---
            Button okButton = new Button { Text = GetLocalizedString("OkButton"), DialogResult = DialogResult.OK, Dock = DockStyle.Right, Width = ButtonWidth }; 
            Button cancelButton = new Button { Text = GetLocalizedString("CancelButton"), DialogResult = DialogResult.Cancel, Dock = DockStyle.Right, Width = ButtonWidth }; 
            buttonPanel.Controls.AddRange(new Control[] { okButton, cancelButton });
            
            // Add button panel to last table cell
            mainLayout.Controls.Add(buttonPanel, 0, 3);

            // Create SplitContainer for main area (list on left, text on right)
            SplitContainer splitContainer = new SplitContainer
            {
                Dock = DockStyle.Fill,
                Orientation = Orientation.Vertical,
                SplitterWidth = SplitterWidth,
            };
            
            // Add SplitContainer to third (main) table cell
            mainLayout.Controls.Add(splitContainer, 0, 2);

            // Add CheckedListBox to left panel of SplitContainer
            splitContainer.Panel1.Controls.Add(checkedListBox);

            // RichTextBox
            RichTextBox richTextBox = new RichTextBox
            {
                Dock = DockStyle.Fill,
                ReadOnly = true,
                BorderStyle = BorderStyle.FixedSingle,
                WordWrap = true
            };

            // Add RichTextBox to right panel of SplitContainer
            splitContainer.Panel2.Controls.Add(richTextBox);

            // Context menu
            ContextMenuStrip contextMenu = new ContextMenuStrip();
            ToolStripMenuItem selectAllMenuItem = new ToolStripMenuItem(GetLocalizedString("SelectAllMenuItem")) { Name = "selectAllMenuItem" };
            ToolStripMenuItem deselectAllMenuItem = new ToolStripMenuItem(GetLocalizedString("DeselectAllMenuItem")) { Name = "deselectAllMenuItem" };
            contextMenu.Items.AddRange(new ToolStripItem[] { selectAllMenuItem, deselectAllMenuItem });
            checkedListBox.ContextMenuStrip = contextMenu;

            // "Select All" handler
            selectAllMenuItem.Click += (sender, e) =>
            {
                for (int i = 0; i < checkedListBox.Items.Count; i++)
                {
                    string itemText = checkedListBox.Items[i].ToString();
                    // Skip service messages (use key for check)
                    if (!itemText.StartsWith(GetLocalizedString("ErrorLoadingHistoryPrefix")) && itemText != GetLocalizedString("HistoryIsEmpty"))
                    {
                        checkedListBox.SetItemChecked(i, true);
                    }
                }
            };

            // "Deselect All" handler
            deselectAllMenuItem.Click += (sender, e) =>
            {
                for (int i = 0; i < checkedListBox.Items.Count; i++)
                {
                    checkedListBox.SetItemChecked(i, false);
                }
            };

            // Load and fill list
            List<string> historyItemsForList = new List<string>();
            try
            {
                int totalItems = BFS.ClipboardFusion.GetHistoryItemCount();
                if (totalItems > 0)
                {
                    // Determine how many items to load (not more than available, and not more than limit)
                    int countToLoad = Math.Min(totalItems, HistoryItemsToLoad);

                    // Load the latest N items (from index 0 to countToLoad - 1)
                    for (int i = 0; i < countToLoad; i++)
                    {
                        // Get each item by index (0 = latest)
                        string historyItem = BFS.ClipboardFusion.GetHistoryText(i);
                        historyItemsForList.Add(historyItem ?? string.Empty);
                    }
                }

                checkedListBox.Items.Clear(); // Clear before adding

                if (historyItemsForList.Count > 0)
                {
                    // Add all items at once
                    checkedListBox.Items.AddRange(historyItemsForList.ToArray());
                    // Pre-select first item (latest) (UX)
                    checkedListBox.SelectedIndex = 0;
                }
                else
                {
                    checkedListBox.Items.Add(GetLocalizedString("HistoryIsEmpty")); // Localization
                }
            }
            catch (Exception ex)
            {
                checkedListBox.Items.Clear();
                string errorMsg = GetLocalizedString("ErrorLoadingHistoryPrefix") + $" {ex.Message}"; // Localization + details
                checkedListBox.Items.Add(errorMsg);
                BFS.Dialog.ShowMessageError(GetLocalizedString("ErrorLoadingHistoryMessage", ex.Message)); // Localization with formatting
                BFS.General.LogText($"Ошибка в макросе MultiPastUtil при получении истории: {ex.ToString()}");
            }

            // Event handlers
             checkedListBox.SelectedIndexChanged += (sender, e) =>
             {
                 if (checkedListBox.SelectedItem != null)
                 {
                     string selectedText = checkedListBox.SelectedItem.ToString();
                     // Use keys for check
                     if (!selectedText.StartsWith(GetLocalizedString("ErrorLoadingHistoryPrefix")) && selectedText != GetLocalizedString("HistoryIsEmpty"))
                     {
                         richTextBox.Text = selectedText;
                     }
                     else
                     {
                         richTextBox.Text = string.Empty;
                     }
                 }
                 else
                 {
                     richTextBox.Text = string.Empty;
                 }
             };

             // Double click handler
             // Only handles toggling the checkbox
             checkedListBox.DoubleClick += (sender, e) =>
             {
                 // Get index of element under cursor at moment of double click
                 // Use MouseEventArgs if available, otherwise rely on SelectedIndex
                 int index = -1;
                 if (e is MouseEventArgs me) // Check if there is mouse information
                 {
                    index = checkedListBox.IndexFromPoint(me.Location);
                 }
                 else // Backup variant (less accurate if click was not exactly on an item)
                 {
                    index = checkedListBox.SelectedIndex;
                 }


                 // Check if clicked on an existing item
                 if (index != -1 && index < checkedListBox.Items.Count)
                 {
                     string itemText = checkedListBox.Items[index].ToString();
                     // Prevent marking service messages (use keys)
                     if (!itemText.StartsWith(GetLocalizedString("ErrorLoadingHistoryPrefix")) && itemText != GetLocalizedString("HistoryIsEmpty"))
                     {
                         // Invert checkbox state for this item
                         checkedListBox.SetItemChecked(index, !checkedListBox.GetItemChecked(index));
                     }
                 }
             };

            // Button handlers
            SetupButtonHandlers(form, okButton, cancelButton, checkedListBox, reverseOrderCheckBox, separatorTextBox, text); // Pass original text

            // Form closing handler to save settings
            form.FormClosing += (sender, e) =>
            {
                try
                {
                    // Save current sizes only if window is not minimized
                    if (form.WindowState == FormWindowState.Normal)
                    {
                        BFS.ScriptSettings.WriteValue(SettingFormWidth, form.ClientSize.Width.ToString());
                        BFS.ScriptSettings.WriteValue(SettingFormHeight, form.ClientSize.Height.ToString());
                        // Take list width directly from control, since splitter changes it
                        BFS.ScriptSettings.WriteValue(SettingListBoxWidth, checkedListBox.Width.ToString());
                    }
                }
                catch (Exception ex)
                {
                     BFS.General.LogText(GetLocalizedString("ErrorSavingSettingsLog", ex.ToString())); // Localization
                     // Don't interrupt closing form due to saving error
                }
            };

            // Show form
            form.ShowDialog();
        } // form will be disposed here automatically

        return _resultText;
    }

    // Method for centralized UI update when language changes
    private static void UpdateFormLanguage(Form form)
    {
        if (form == null) return;

        // Update form title
        form.Text = GetLocalizedString("FormTitle");

        // --- Find and update controls ---
        // Find controls in main layout (TableLayoutPanel)
        TableLayoutPanel mainLayout = form.Controls.OfType<TableLayoutPanel>().FirstOrDefault();
        if (mainLayout == null) return; // Unable to find main layout

        // 1. Top panel (FlowLayoutPanel)
        FlowLayoutPanel topPanel = mainLayout.Controls.OfType<FlowLayoutPanel>().FirstOrDefault();
        if (topPanel != null)
        {
            var separatorLabel = topPanel.Controls.OfType<Label>().FirstOrDefault(lbl => lbl.Name == "separatorLabel");
            if (separatorLabel != null) separatorLabel.Text = GetLocalizedString("SeparatorLabel");

            var reverseCheckBox = topPanel.Controls.OfType<CheckBox>().FirstOrDefault(chk => chk.Name == "reverseOrderCheckBox");
            if (reverseCheckBox != null) reverseCheckBox.Text = GetLocalizedString("ReverseOrderCheckBox");
        }

        // 2. Button panel (Panel with DockStyle.Bottom)
        Panel buttonPanel = mainLayout.Controls.OfType<Panel>().FirstOrDefault(p => p.Dock == DockStyle.Bottom);
        if (buttonPanel != null)
        {
            var okButton = buttonPanel.Controls.OfType<Button>().FirstOrDefault(btn => btn.DialogResult == DialogResult.OK);
            if (okButton != null) okButton.Text = GetLocalizedString("OkButton");

            var cancelButton = buttonPanel.Controls.OfType<Button>().FirstOrDefault(btn => btn.DialogResult == DialogResult.Cancel);
            if (cancelButton != null) cancelButton.Text = GetLocalizedString("CancelButton");
        }

        // 3. Context menu (in CheckedListBox inside SplitContainer)
        SplitContainer splitContainer = mainLayout.Controls.OfType<SplitContainer>().FirstOrDefault();
        CheckedListBox checkedListBox = splitContainer?.Panel1.Controls.OfType<CheckedListBox>().FirstOrDefault();
        if (checkedListBox?.ContextMenuStrip != null)
        {
            var selectAll = checkedListBox.ContextMenuStrip.Items.OfType<ToolStripMenuItem>().FirstOrDefault(mi => mi.Name == "selectAllMenuItem");
            if (selectAll != null) selectAll.Text = GetLocalizedString("SelectAllMenuItem");

            var deselectAll = checkedListBox.ContextMenuStrip.Items.OfType<ToolStripMenuItem>().FirstOrDefault(mi => mi.Name == "deselectAllMenuItem");
            if (deselectAll != null) deselectAll.Text = GetLocalizedString("DeselectAllMenuItem");
        }

        // 4. Main menu (MenuStrip)
        MenuStrip menuStrip = mainLayout.Controls.OfType<MenuStrip>().FirstOrDefault();
        if (menuStrip != null)
        {
            // Find menu items by name
            var ruMenuItem = menuStrip.Items.OfType<ToolStripMenuItem>()
                                    .SelectMany(item => item.DropDownItems.OfType<ToolStripMenuItem>())
                                    .FirstOrDefault(mi => mi.Name == "ruMenuItem");
            var enMenuItem = menuStrip.Items.OfType<ToolStripMenuItem>()
                                    .SelectMany(item => item.DropDownItems.OfType<ToolStripMenuItem>())
                                    .FirstOrDefault(mi => mi.Name == "enMenuItem");

            // Update their state Checked
            if (ruMenuItem != null) ruMenuItem.Checked = (_currentLanguage == "ru");
            if (enMenuItem != null) enMenuItem.Checked = (_currentLanguage == "en");
        }
    }

    // Helper method to update individual control
    private static void UpdateControlLanguage(Control control)
    {
        if (control is CheckBox checkBox)
        {
            // Update text of checkboxes according to their content
            if (checkBox.Text.Contains("Объединить в обратном порядке") || checkBox.Text.Contains("Combine in reverse order"))
            {
                checkBox.Text = GetLocalizedString("ReverseOrderCheckBox");
            }
        }
        else if (control is Label label)
        {
            // Update text of labels
            if (label.Text.Contains("Разделитель") || label.Text.Contains("Separator"))
            {
                label.Text = GetLocalizedString("SeparatorLabel");
            }
        }
        else if (control is Button button)
        {
            // Update buttons
            if (button.Text == "OK" || button.Text == "ОК")
            {
                button.Text = GetLocalizedString("OkButton");
            }
            else if (button.Text.Contains("Отмена") || button.Text.Contains("Cancel"))
            {
                button.Text = GetLocalizedString("CancelButton");
            }
        }
    }

    // Code of helper methods
    private static void SetupContextMenuHandlers(CheckedListBox checkedListBox) { /* ... */ }
    private static void LoadHistory(CheckedListBox checkedListBox) { /* ... */ }
    private static void SetupButtonHandlers(Form form, Button okButton, Button cancelButton, CheckedListBox checkedListBox, CheckBox reverseOrderCheckBox, TextBox separatorTextBox, string originalText)
    {
        // Button handler for OK button
        okButton.Click += (sender, e) =>
        {
            try
            {
                // Get only real selected items (use keys for filtering)
                var selectedItems = checkedListBox.CheckedItems.OfType<string>()
                                                .Where(item => !item.StartsWith(GetLocalizedString("ErrorLoadingHistoryPrefix")) && item != GetLocalizedString("HistoryIsEmpty"))
                                                .ToList();

                string finalResult = string.Empty;
                if (selectedItems.Count > 0)
                {
                    // Check reverse order checkbox
                    if (reverseOrderCheckBox.Checked)
                    {
                        selectedItems.Reverse(); // Reverse the list
                    }

                    // Определяем разделитель
                    string separator = string.IsNullOrEmpty(separatorTextBox.Text)
                                        ? DefaultSeparator // Use constant "\r\n"
                                        : "\r\n" + separatorTextBox.Text + "\r\n"; // Use user text

                    // Join with selected separator
                    finalResult = string.Join(separator, selectedItems);
                }
                else
                {
                    // If nothing is selected, you can either return an empty string, or the original text
                    // Now return an empty string
                    finalResult = string.Empty; // or finalResult = originalText;
                }

                // Assign the result to the static variable
                _resultText = finalResult;

                // Log the result (optional)
                BFS.General.LogText(GetLocalizedString("SetClipboardLogMessage", true, finalResult));
                
                // The form will close automatically, since DialogResult = OK
            }
            catch (Exception ex)
            {                
                BFS.Dialog.ShowMessageError(GetLocalizedString("ErrorProcessingSelectionMessage", ex.Message));
                BFS.General.LogText($"Ошибка в MultiPastUtil okButton.Click: {ex.ToString()}");
                _resultText = originalText; // Return original text in case of error
                // Do not close the form at error, allow user to fix
                form.DialogResult = DialogResult.None; // Reset DialogResult, so the form does not close automatically
            }
        };

        // Button handler for Cancel button (already works through DialogResult = Cancel)
        // Additional actions are not required, simply closes the form.
        // You can add logic to reset _resultText at cancellation, if needed:
        cancelButton.Click += (sender, e) =>
        {            
            _resultText = originalText; // Reset the result to the original at cancellation
        };
    }
}