// =========================================================================== //  ©2013-2026 WebSupergoo. All rights reserved. // //  This source code is for use exclusively with the ABCpdf product with //  which it is distributed, under the terms of the license for that //  product. Details can be found at // //    http://www.websupergoo.com/ // //  This copyright notice must not be deleted and must be reproduced alongside //  any sections of code extracted from this module. // =========================================================================== using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Diagnostics; using System.Windows.Forms; using WebSupergoo.ABCpdf14.Atoms; namespace WebSupergoo.PDFSurgeon {   public partial class EditText : Form {     public EditText(MainForm parent, ObjectExtractor obj) {       InitializeComponent();       _parent = parent;       _editor = new StreamEditor(obj);     }     private void EditText_Load(object sender, EventArgs e) {       if (_editor.Stream != null && !_editor.Extractor.IsAscii) {         if (_editor.Stream.Compressed) {           const string message = "This object appears to contain compressed data rather than text.\r\n\r\nWould you like to decompress it prior to editing?";           var action = MessageBox.Show(message, "Warning", MessageBoxButtons.YesNoCancel);           if (action == DialogResult.Yes) {             if (!_editor.Stream.Decompress()) {               MessageBox.Show("Unable to decompress object.", "Warning", MessageBoxButtons.OK);               return;             }           }           else if (action == DialogResult.Cancel)             return;         }         else {           const string message = "This object appears to contain data rather than text.\r\n\r\nWould you like to ASCII 85 encode it for editing?";           var action = MessageBox.Show(message, "Warning", MessageBoxButtons.YesNoCancel);           if (action == DialogResult.Yes)             _editor.Stream.CompressAscii85();           else if (action == DialogResult.Cancel)             return;         }       }       Size size = Properties.Settings.Default.EditTextSize;       if (size.Width > 30 && size.Height > 30)         Size = size;       Point pos = Properties.Settings.Default.EditTextPosition;       if (pos.X != 0 && pos.Y != 0) {         pos = new Point(_parent.Location.X + pos.X, _parent.Location.Y + pos.Y);         var rect = Screen.GetBounds(pos);         rect.Inflate(-20, -20);         if (rect.Contains(pos))           Location = pos;       }       _editor.Load();       textBox1.Text = _editor.LiveText;       // Unusual characters may change when put in text box.       _editor.OriginalText = _editor.LiveText = textBox1.Text;       bool isLive = _editor.ContentStream != null;       liveUpdate.Enabled = isLive;       trackBar1.Enabled = isLive;       trackBar2.Enabled = isLive;       formatContent.Enabled = isLive;       openPdf.Enabled = isLive;       Text = $"EditText ID: {_editor.Extractor.Object.ID}";     }     private void EditText_FormClosing(object sender, FormClosingEventArgs e) {       Properties.Settings.Default.EditTextSize = Size;       Properties.Settings.Default.EditTextPosition = new Point(Location.X - _parent.Location.X, Location.Y - _parent.Location.Y);       Properties.Settings.Default.Save();       _parent._editTexts.Remove(_editor.Extractor);     }     private MainForm _parent;     private StreamEditor _editor;     private GraphicsScanner.Fixture _fixture;     private void textBox1_TextChanged(object sender, EventArgs e) {       if (liveUpdate.Checked) {         if (textBox1.Text != _editor.LiveText) {           _editor.CurrentText = textBox1.Text;           _parent.RefreshSelectedImage();           _editor.LiveText = textBox1.Text;         }       }       numericUpDown1.Enabled = false;     }     private void ok_Click(object sender, EventArgs e) {       if ((textBox1.Text != _editor.OriginalText) || (textBox1.Text != _editor.LiveText)) {         _editor.CurrentText = textBox1.Text;         _parent.UpdateContent(_editor.Extractor);         _parent.UpdateImage(_editor.Extractor, true);         _parent.Dirty = true;       }       Close();     }     private void cancel_Click(object sender, EventArgs e) {       if (textBox1.Text != _editor.OriginalText) {         liveUpdate.Checked = true;         textBox1.Text = _editor.OriginalText;       }       Close();     }     private void formatContent_Click(object sender, EventArgs e) {       try {         var s = _editor.FormatContentStream();         if (s == null)           return;         textBox1.Text = s;       }       catch (Exception ex) {         MessageBox.Show("Unable to format content stream. " + ex.Message);       }     }     private void openPdf_Click(object sender, EventArgs e) {       _parent.OpenSnapshot();     }     private void liveUpdate_CheckedChanged(object sender, EventArgs e) {       if (liveUpdate.Checked && _editor.ResourceOwner != null) {         _parent.SelectByObjectID(_editor.ResourceOwner.ID);       }     }     private void trackBar1_Scroll(object sender, EventArgs e) {       double lo = (double)trackBar1.Value / trackBar1.Maximum;       double hi = (double)trackBar2.Value / trackBar2.Maximum;       StringBuilder sb = _editor.GetPartialContentStream(lo, hi);       if (sb != null) {         textBox1.Text = UpdateFromContentStream(sb.ToString(), textBox1.Text);         UpdateSearch();       }     }     private void trackBar2_Scroll(object sender, EventArgs e) {       double lo = (double)trackBar1.Value / trackBar1.Maximum;       double hi = (double)trackBar2.Value / trackBar2.Maximum;       StringBuilder sb = _editor.GetPartialContentStream(lo, hi);       if (sb != null) {         textBox1.Text = UpdateFromContentStream(sb.ToString(), textBox1.Text);         UpdateSearch();       }     }     private void timer1_Tick(object sender, EventArgs e) {       var fixture = _parent.Fixture;       if (fixture != _fixture) {         if (fixture != null) {           string txt = textBox1.Text;           string keyword = "stream";           int start = txt.IndexOf(keyword);           start = start != -1 ? start + keyword.Length : -1;           start = (start != -1) && (txt.Length > start) && (txt[start] == '\r') ? start + 1 : start;           start = (start != -1) && (txt.Length > start) && (txt[start] == '\n') ? start + 1 : start;           if (start != -1) {             int offset = start + fixture.Offset;             int length = Math.Min(textBox1.Text.Length - offset, fixture.Length);             if (length > 0) {               textBox1.Select(offset, length);               textBox1.ScrollToCaret();               textBox1.Focus();             }           }         }         _fixture = fixture;       }     }     private void TextBox2_TextChanged(object sender, EventArgs e)     {       UpdateSearch();     }     private void NumericUpDown1_ValueChanged(object sender, EventArgs e)     {       UpdateSearch();     }     bool _update = true;     private void UpdateSearch()     {       string search = textBox2.Text;       string text = textBox1.Text;       numericUpDown1.Enabled = true;       bool isEmpty = string.IsNullOrEmpty(search);       List<int> positions = new List<int>();       if (!isEmpty)       {         int p1 = 0;         while (true)         {           int p2 = text.IndexOf(search, p1, StringComparison.OrdinalIgnoreCase);           if (p2 == -1)             break;           positions.Add(p2);           p1 = p2 + search.Length;         }         isEmpty = positions.Count == 0;       }       if (!isEmpty)       {         try         {           if (_update) {             _update = false;             numericUpDown1.Maximum = -1;             numericUpDown1.Minimum = -positions.Count;             textBox1.Select(positions[-((int)numericUpDown1.Value) - 1], search.Length);             textBox1.ScrollToCaret();             label3.Text = -(numericUpDown1.Value) + "/" + positions.Count.ToString();           }         }         finally         {           _update = true;         }       }       else {         numericUpDown1.Maximum = 0;         textBox1.Select(0, 0);         label3.Text = "0/0";         numericUpDown1.Enabled = false;       }     }     private static string UpdateFromContentStream(string newContentStream, string originalText) {       string header = originalText.Substring(0, originalText.IndexOf("stream\r\n"));       var dict = (DictAtom)Atom.FromString(header);       dict["Length"] = new NumAtom(newContentStream.Length);       return dict.ToString() + "\r\nstream\r\n" + newContentStream + "\r\nendstream\r\n";     }   } }