using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using FastReport.Utils; using FastReport.Design; using FastReport.Design.PageDesigners.Code; #if !MONO using FastReport.Editor; #endif namespace FastReport.Forms { internal partial class SearchReplaceForm : BaseDialogForm { private Designer designer; private bool replace; private bool firstSearch; private int index; private static string[] FLastSearch; private static string[] FLastReplace; private static bool FMatchCase; private static bool FMatchWholeWord; public bool Replace { get { return replace; } set { replace = value; pnReplace.Visible = value; pnReplaceButton.Visible = value; PerformLayout(); ClientSize = new Size(gbOptions.Right + gbOptions.Left, (value ? pnReplaceButton.Bottom : pnFindButton.Bottom) + 4); } } private List FindText(string text, int startIndex) { string textToFind = cbxFind.Text; bool matchCase = cbMatchCase.Checked; bool wholeWord = cbMatchWholeWord.Checked; List ranges = new List(); string nonWordChars = " `-=[];',./~!@#$%^&*()+{}:\"<>?\\|"; while (startIndex < text.Length) { int i = text.IndexOf(textToFind, startIndex, matchCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); if (i >= 0) { bool skip = false; if (wholeWord) { if (i > 0 && nonWordChars.IndexOf(text[i - 1]) != -1) skip = true; if (i < text.Length - 1 && nonWordChars.IndexOf(text[i + 1]) != -1) skip = true; } if (!skip) ranges.Add(new CharacterRange(i, textToFind.Length)); startIndex = i + textToFind.Length; } else break; } return ranges; } private void FindNext(bool replace, bool replaceAll) { bool found = false; if (designer.ActiveReportTab.ActivePage == null) { #if !MONO // search in the code tab SyntaxEdit Edit = (designer.ActiveReportTab.ActivePageDesigner as CodePageDesigner).Edit; if (firstSearch) Edit.FirstSearch = true; SearchOptions options = SearchOptions.None; if (cbMatchCase.Checked) options |= SearchOptions.CaseSensitive; if (cbMatchWholeWord.Checked) options |= SearchOptions.WholeWordsOnly; if (Edit.Selection.SelectedText == cbxFind.Text && replace && !replaceAll) { Edit.Selection.SelectedText = cbxReplace.Text; found = true; } else { while (true) { if (Edit.Find(cbxFind.Text, options)) { found = true; if (replace) Edit.Selection.SelectedText = cbxReplace.Text; if (!replaceAll) break; } else break; } } #endif } else { ObjectCollection allObjects = designer.ActiveReportTab.ActivePage.AllObjects; for (; index < allObjects.Count; index++) { Base c = allObjects[index]; string text = ""; if (c is TextObject) text = (c as TextObject).Text; else if (c is RichObject) text = (c as RichObject).Text; List ranges = FindText(text, 0); if (ranges.Count > 0) { found = true; if (!replaceAll) { designer.SelectedObjects.Clear(); designer.SelectedObjects.Add(c); designer.SelectionChanged(null); } if (replace) { int correction = 0; foreach (CharacterRange range in ranges) { text = text.Remove(range.First + correction, range.Length); text = text.Insert(range.First + correction, cbxReplace.Text); correction += cbxReplace.Text.Length - range.Length; } if (c is TextObject) (c as TextObject).Text = text; else if (c is RichObject) (c as RichObject).Text = text; } if (!replaceAll) { index++; break; } } } } if (found && replace) designer.SetModified(null, "Change"); if (firstSearch) { if (!found) FRMessageBox.Information(Res.Get("Forms,SearchReplace,NotFound")); firstSearch = false; } else { if (!found) FRMessageBox.Information(Res.Get("Forms,SearchReplace,NoMoreFound")); } } private void cbxFind_TextChanged(object sender, EventArgs e) { bool enabled = !String.IsNullOrEmpty(cbxFind.Text); btnFindNext.Enabled = enabled; btnReplace.Enabled = enabled; btnReplaceAll.Enabled = enabled; } private void btnFindNext_Click(object sender, EventArgs e) { FindNext(false, false); } private void btnReplace_Click(object sender, EventArgs e) { FindNext(true, false); } private void btnReplaceAll_Click(object sender, EventArgs e) { FindNext(true, true); } private void SearchReplaceForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Escape) Close(); } private void SearchReplaceForm_FormClosed(object sender, FormClosedEventArgs e) { Done(); } private void Init() { if (FLastSearch != null) { foreach (string s in FLastSearch) { cbxFind.Items.Add(s); } } if (FLastReplace != null) { foreach (string s in FLastReplace) { cbxReplace.Items.Add(s); } } cbMatchCase.Checked = FMatchCase; cbMatchWholeWord.Checked = FMatchWholeWord; firstSearch = true; index = 0; cbxFind_TextChanged(this, EventArgs.Empty); Config.RestoreFormState(this); } private void Done() { List items = new List(); foreach (object item in cbxFind.Items) { items.Add(item.ToString()); } if (items.IndexOf(cbxFind.Text) == -1) items.Add(cbxFind.Text); FLastSearch = items.ToArray(); foreach (object item in cbxReplace.Items) { items.Add(item.ToString()); } if (items.IndexOf(cbxReplace.Text) == -1) items.Add(cbxReplace.Text); FLastReplace = items.ToArray(); FMatchCase = cbMatchCase.Checked; FMatchWholeWord = cbMatchWholeWord.Checked; Config.SaveFormState(this); } public override void Localize() { base.Localize(); MyRes res = new MyRes("Forms,SearchReplace"); Text = res.Get(""); lblFind.Text = res.Get("Find"); lblReplace.Text = res.Get("Replace"); gbOptions.Text = res.Get("Options"); cbMatchCase.Text = res.Get("MatchCase"); cbMatchWholeWord.Text = res.Get("MatchWholeWord"); btnFindNext.Text = res.Get("FindNext"); btnReplace.Text = res.Get("ReplaceBtn"); btnReplaceAll.Text = res.Get("ReplaceAll"); } public SearchReplaceForm(Designer designer, bool isReplace) { this.designer = designer; InitializeComponent(); Localize(); replace = isReplace; Init(); UIUtils.CheckRTL(this); } } }