Click here to Skip to main content
15,860,943 members
Articles / Programming Languages / C#

CodeDom Assistant

Rate me:
Please Sign up or sign in to vote.
4.84/5 (26 votes)
21 Sep 20074 min read 136.5K   6.6K   82  
Generating CodeDom Code By Parsing C# or VB
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing;
using System.Text.RegularExpressions;
namespace ScintillaNet
{
	[TypeConverterAttribute(typeof(System.ComponentModel.ExpandableObjectConverter))]
	public class FindReplace : ScintillaHelperBase
	{
		internal FindReplace(Scintilla scintilla) : base(scintilla) 
		{
			_marker = scintilla.Markers[10];
			_marker.SetSymbolInternal(MarkerSymbol.Arrows);
			_indicator = scintilla.Indicators[16];
			_indicator.Color = Color.Purple;
			_indicator.Style = IndicatorStyle.RoundBox;

			_window = new FindReplaceDialog();
			_window.Scintilla = scintilla;

			_incrementalSearcher = new IncrementalSearcher();
			_incrementalSearcher.Scintilla = scintilla;
			_incrementalSearcher.Visible = false;
			scintilla.Controls.Add(_incrementalSearcher);
		}

		internal bool ShouldSerialize()
		{
			return ShouldSerializeFlags() ||
				ShouldSerializeIndicator() ||
				ShouldSerializeMarker();
		}
		private string _lastFindString = null;
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public string LastFindString
		{
			get
			{
				return _lastFindString;
			}
			set
			{
				_lastFindString = value;
				_lastFindRegex = null;
			}
		}

		private Regex _lastFindRegex = null;
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public Regex LastFindRegex
		{
			get
			{
				return _lastFindRegex;
			}
			set
			{
				_lastFindRegex = value;
				_lastFindString = null;
			}
		}

		private FindReplaceDialog _window;
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public FindReplaceDialog Window
		{
			get
			{
				return _window;
			}
			set
			{
				_window = value;
			}
		}

		private IncrementalSearcher _incrementalSearcher;
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public IncrementalSearcher IncrementalSearcher
		{
			get
			{
				return _incrementalSearcher;
			}
			set
			{
				_incrementalSearcher = value;
			}
		}



		#region Flags
		private SearchFlags _flags;
		[Editor(typeof(ScintillaNet.Design.FlagEnumUIEditor), typeof(System.Drawing.Design.UITypeEditor))]
		public SearchFlags Flags
		{
			get
			{
				return _flags;
			}
			set
			{
				_flags = value;
			}
		}

		private bool ShouldSerializeFlags()
		{
			return _flags != SearchFlags.Empty;
		}

		private void ResetFlags()
		{
			_flags = SearchFlags.Empty;
		} 
		#endregion

		#region Marker
		private Marker _marker;
		public Marker Marker
		{
			get
			{
				return _marker;
			}
			set
			{
				_marker = value;
			}
		}

		private bool ShouldSerializeMarker()
		{
			return _marker.Number != 10 || _marker.ForeColor != Color.White || _marker.BackColor != Color.Black || _marker.Symbol != MarkerSymbol.Arrows;
		}

		private void ResetMarker()
		{
			_marker.Reset();
			_marker.Number = 10;
		}
		
		#endregion

		#region Indicator
		private Indicator _indicator;
		public Indicator Indicator
		{
			get
			{
				return _indicator;
			}
			set
			{
				_indicator = value;
			}
		}

		private bool ShouldSerializeIndicator()
		{
			return _indicator.Number != 16 || _indicator.Color != Color.Purple || _indicator.IsDrawnUnder;
		}

		private void ResetIndicator()
		{
			_indicator.Reset();
		} 
		#endregion

		#region Find
		public Range Find(string searchString)
		{
			return Find(0, NativeScintilla.GetTextLength(), searchString, _flags);
		}

		public Range Find(string searchString, bool searchUp)
		{
			if (searchUp)
				return Find(NativeScintilla.GetTextLength(), 0, searchString, _flags);
			else
				return Find(0, NativeScintilla.GetTextLength(), searchString, _flags);
		}

		public Range Find(string searchString, SearchFlags searchflags)
		{
			return Find(0, NativeScintilla.GetTextLength(), searchString, searchflags);
		}

		public Range Find(string searchString, SearchFlags searchflags, bool searchUp)
		{
			if (searchUp)
				return Find(NativeScintilla.GetTextLength(), 0, searchString, searchflags);
			else
				return Find(0, NativeScintilla.GetTextLength(), searchString, searchflags);
		}

		public Range Find(Range rangeToSearch, string searchString)
		{
			return Find(rangeToSearch.Start, rangeToSearch.End, searchString, _flags);
		}

		public Range Find(Range rangeToSearch, string searchString, bool searchUp)
		{
			if (searchUp)
				return Find(rangeToSearch.End, rangeToSearch.Start, searchString, _flags);
			else
				return Find(rangeToSearch.Start, rangeToSearch.End, searchString, _flags);
		}

		public Range Find(Range rangeToSearch, string searchString, SearchFlags searchflags)
		{
			return Find(rangeToSearch.Start, rangeToSearch.End, searchString, searchflags);
		}

		public Range Find(Range rangeToSearch, string searchString, SearchFlags searchflags, bool searchUp)
		{
			if (searchUp)
				return Find(rangeToSearch.End, rangeToSearch.Start, searchString, searchflags);
			else
				return Find(rangeToSearch.Start, rangeToSearch.End, searchString, searchflags);
		}

		public unsafe Range Find(int startPos, int endPos, string searchString, SearchFlags flags)
		{
			TextToFind ttf = new TextToFind();
			ttf.chrg.cpMin = startPos;
			ttf.chrg.cpMax = endPos;

			fixed (byte* pb = UTF8Encoding.UTF8.GetBytes(searchString))
			{
				ttf.lpstrText = (IntPtr)pb;
				int pos = NativeScintilla.FindText((int)flags, ref ttf);
				if (pos >= 0)
				{
					return new Range(pos, pos + searchString.Length, Scintilla);
				}
				else
				{
					return null;
				}
			}
		}

		public Range Find(Regex findExpression)
		{
			return Find(new Range(0, NativeScintilla.GetTextLength(), Scintilla),  findExpression, false);
		}

		public Range Find(Regex findExpression, bool searchUp)
		{
			return Find(new Range(0, NativeScintilla.GetTextLength(), Scintilla), findExpression, searchUp);
		}

		public Range Find(int startPos, int endPos, Regex findExpression)
		{
			return Find(new Range(startPos, endPos, Scintilla), findExpression, false);
		}

		public Range Find(int startPos, int endPos, Regex findExpression, bool searchUp)
		{
			return Find(new Range(startPos, endPos, Scintilla), findExpression, searchUp);
		}

		public Range Find(Range r, Regex findExpression)
		{
			return Find(r, findExpression, false);
		}

		public Range Find(Range r, Regex findExpression, bool searchUp)
		{
			//	Single line and Multi Line in RegExp doesn't really effect
			//	whether or not a match will include newline charaters. This 
			//	means we can't do a line by line search. We have to search
			//	the entire range becuase it could potentially match the 
			//	entire range.
				
			Match m = findExpression.Match(r.Text);

			if (!m.Success)
				return null;

			if (searchUp)
			{
				//	Since we can't search backwards with RegExp we
				//	have to search the entire string and return the 
				//	last match. Not the most efficient way of doing
				//	things but it works.
				Range range = null;
				while (m.Success)
				{
					range = new Range(r.Start + m.Index, r.Start + m.Index + m.Length, Scintilla);
					m = m.NextMatch();
				}
				return range;
			}

			return new Range(r.Start + m.Index, r.Start + m.Index + m.Length, Scintilla);
		}



		#endregion

		#region FindAll
		public List<Range> FindAll(string searchString)
		{
			return FindAll(searchString, _flags);
		}

		public List<Range> FindAll(string searchString, SearchFlags flags)
		{
			return FindAll(0, NativeScintilla.GetTextLength(), searchString, flags);
		}

		public List<Range> FindAll(Range rangeToSearch, string searchString)
		{
			return FindAll(rangeToSearch.Start, rangeToSearch.End, searchString, _flags);
		}

		public List<Range> FindAll(Range rangeToSearch, string searchString, SearchFlags flags)
		{
			return FindAll(rangeToSearch.Start, rangeToSearch.End, searchString, _flags);
		}

		public List<Range> FindAll(int startPos, int endPos, string searchString, SearchFlags flags)
		{
			List<Range> res = new List<Range>();

			while (true)
			{
				Range r = Find(startPos, endPos, searchString, flags);
				if (r == null)
				{
					break;
				}
				else
				{
					res.Add(r);
					startPos = r.End;
				}
			}
			return res;
		}

		public List<Range> FindAll(Regex findExpression)
		{
			return FindAll(0, NativeScintilla.GetTextLength(), findExpression);
		}

		public List<Range> FindAll(int startPos, int endPos, Regex findExpression)
		{
			return FindAll(new Range(startPos, endPos, Scintilla), findExpression);
		}

		public List<Range> FindAll(Range rangeToSearch, Regex findExpression)
		{
			List<Range> res = new List<Range>();

			while (true)
			{
				Range r = Find(rangeToSearch, findExpression);
				if (r == null)
				{
					break;
				}
				else
				{
					res.Add(r);
					rangeToSearch = new Range(r.End, rangeToSearch.End, Scintilla);
				}
			}
			return res;
		}
		#endregion

		#region FindNext
		public Range FindNext(string searchString)
		{
			return FindNext(searchString, true, _flags);
		}

		public Range FindNext(string searchString, bool wrap)
		{
			return FindNext(searchString, wrap, _flags);
		}

		public Range FindNext(string searchString, SearchFlags flags)
		{
			return FindNext(searchString, true, flags);
		}

		public Range FindNext(string searchString, bool wrap, SearchFlags flags)
		{
			Range r = Find(NativeScintilla.GetCurrentPos(), NativeScintilla.GetTextLength(), searchString, flags);
			if (r != null)
				return r;
			else if (wrap)
				return Find(0, NativeScintilla.GetCurrentPos(), searchString, flags);
			else
				return null;
		}

		public Range FindNext(string searchString, bool wrap, SearchFlags flags, Range searchRange)
		{
			int caret = Scintilla.Caret.Position;
			if (!searchRange.PositionInRange(caret))
				return Find(searchRange.Start, searchRange.End, searchString, flags);

			Range r = Find(caret, searchRange.End, searchString, flags);
			if (r != null)
				return r;
			else if (wrap)
				return Find(searchRange.Start, caret, searchString, flags);
			else
				return null;
		}

		public Range FindNext(Regex findExpression)
		{
			return FindNext(findExpression, false);
		}

		public Range FindNext(Regex findExpression, bool wrap)
		{
			Range r = Find(NativeScintilla.GetCurrentPos(), NativeScintilla.GetTextLength(), findExpression);
			if (r != null)
				return r;
			else if (wrap)
				return Find(0, NativeScintilla.GetCurrentPos(), findExpression);
			else
				return null;
		}

		public Range FindNext(Regex findExpression, bool wrap, Range searchRange)
		{
			int caret = Scintilla.Caret.Position;
			if (!searchRange.PositionInRange(caret))
				return Find(searchRange.Start, searchRange.End, findExpression, false);

			Range r = Find(caret, searchRange.End, findExpression);
			if (r != null)
				return r;
			else if (wrap)
				return Find(searchRange.Start, caret, findExpression);
			else
				return null;
		}


		#endregion

		#region ReplaceNext
		public Range ReplaceNext(string searchString, string replaceString)
		{
			return ReplaceNext(searchString, replaceString, true, _flags);
		}

		public Range ReplaceNext(string searchString, string replaceString, bool wrap)
		{
			return ReplaceNext(searchString, replaceString, wrap, _flags);
		}

		public Range ReplaceNext(string searchString, string replaceString, SearchFlags flags)
		{
			return ReplaceNext(searchString, replaceString, true, flags);
		}

		public Range ReplaceNext(string searchString, string replaceString, bool wrap, SearchFlags flags)
		{
			Range r = FindNext(searchString, wrap, flags);

			if (r != null)
			{
				r.Text = replaceString;
				r.End = r.Start + replaceString.Length;
			}

			return r;
		}
		#endregion

		#region FindPrevious
		

		public Range FindPrevious(string searchString)
		{
			return FindPrevious(searchString, true, _flags);
		}

		public Range FindPrevious(string searchString, bool wrap)
		{
			return FindPrevious(searchString, wrap, _flags);
		}

		public Range FindPrevious(string searchString, SearchFlags flags)
		{
			return FindPrevious(searchString, true, flags);
		}

		public Range FindPrevious(string searchString, bool wrap, SearchFlags flags)
		{
			Range r = Find(NativeScintilla.GetAnchor(), 0, searchString, flags);
			if (r != null)
				return r;
			else if (wrap)
				return Find(NativeScintilla.GetTextLength(), NativeScintilla.GetCurrentPos(), searchString, flags);
			else
				return null;
		}

		public Range FindPrevious(string searchString, bool wrap, SearchFlags flags, Range searchRange)
		{
			int caret = Scintilla.Caret.Position;
			if (!searchRange.PositionInRange(caret))
				return Find(searchRange.End, searchRange.Start, searchString, flags);

			int anchor = Scintilla.Caret.Anchor;
			if (!searchRange.PositionInRange(anchor))
			    anchor = caret;

			Range r = Find(anchor, searchRange.Start, searchString, flags);
			if (r != null)
				return r;
			else if (wrap)
				return Find(searchRange.End, anchor, searchString, flags);
			else
				return null;
		}

		public Range FindPrevious(Regex findExpression)
		{
			return FindPrevious(findExpression, false);
		}

		public Range FindPrevious(Regex findExpression, bool wrap)
		{
			Range r = Find(0, NativeScintilla.GetAnchor(), findExpression, true);
			if (r != null)
				return r;
			else if (wrap)
				return Find(NativeScintilla.GetCurrentPos(), NativeScintilla.GetTextLength(), findExpression, true);
			else
				return null;

		}
		public Range FindPrevious(Regex findExpression, bool wrap, Range searchRange)
		{
			int caret = Scintilla.Caret.Position;
			if (!searchRange.PositionInRange(caret))
				return Find(searchRange.Start, searchRange.End, findExpression, true);

			int anchor = Scintilla.Caret.Anchor;
			if (!searchRange.PositionInRange(anchor))
				anchor = caret;

			Range r = Find(searchRange.Start, anchor, findExpression, true);
			if (r != null)
				return r;
			else if (wrap)
				return Find(anchor, searchRange.End, findExpression, true);
			else
				return null;
		}

		#endregion

		#region ReplacePrevious
		public Range ReplacePrevious(string searchString, string replaceString)
		{
			return ReplacePrevious(searchString, replaceString, true, _flags);
		}

		public Range ReplacePrevious(string searchString, string replaceString, bool wrap)
		{
			return ReplacePrevious(searchString, replaceString, wrap, _flags);
		}

		public Range ReplacePrevious(string searchString, string replaceString, SearchFlags flags)
		{
			return ReplacePrevious(searchString, replaceString, true, flags);
		}

		public Range ReplacePrevious(string searchString, string replaceString, bool wrap, SearchFlags flags)
		{
			Range r = FindPrevious(searchString, wrap, flags);

			if (r != null)
			{
				r.Text = replaceString;
				r.End = r.Start + replaceString.Length;
			}

			return r;
		}
		#endregion

		#region ReplaceAll
		public List<Range> ReplaceAll(string searchString, string replaceString)
		{
			return ReplaceAll(searchString, replaceString, _flags);
		}

		public List<Range> ReplaceAll(string searchString, string replaceString, SearchFlags flags)
		{
			return ReplaceAll(0, NativeScintilla.GetTextLength(), searchString, replaceString, flags);
		}

		public List<Range> ReplaceAll(Range rangeToSearch, string searchString, string replaceString)
		{
			return ReplaceAll(rangeToSearch.Start, rangeToSearch.End, searchString, replaceString, _flags);
		}

		public List<Range> ReplaceAll(Range rangeToSearch, string searchString, string replaceString, SearchFlags flags)
		{
			return ReplaceAll(rangeToSearch.Start, rangeToSearch.End, searchString, replaceString, _flags);
		}

		public List<Range> ReplaceAll(int startPos, int endPos, string searchString, string replaceString, SearchFlags flags)
		{
			List<Range> ret = new List<Range>();

			Scintilla.UndoRedo.BeginUndoAction();

			int diff = replaceString.Length - searchString.Length;
			while (true)
			{
				Range r = Find(startPos, endPos, searchString, flags);
				if (r == null)
				{
					break;
				}
				else
				{
					r.Text = replaceString;
					r.End = startPos = r.Start + replaceString.Length;
					endPos += diff;

					ret.Add(r);
				}
			}

			Scintilla.UndoRedo.EndUndoAction();
			return ret;
		}

		public List<Range> ReplaceAll(Regex findExpression, string replaceString)
		{
			return ReplaceAll(0, NativeScintilla.GetTextLength(), findExpression, replaceString);
		}

		public List<Range> ReplaceAll(int startPos, int endPos, Regex findExpression, string replaceString)
		{
			return ReplaceAll(new Range(startPos, endPos, Scintilla), findExpression, replaceString);
		}

		private List<Range> _lastReplaceAllMatches = new List<Range>();
		private string _lastReplaceAllReplaceString = "";
		private Range _lastReplaceAllRangeToSearch = null;
		private int _lastReplaceAllOffset = 0;

		public List<Range> ReplaceAll(Range rangeToSearch, Regex findExpression, string replaceString)
		{
			Scintilla.UndoRedo.BeginUndoAction();

			//	I tried using an anonymous delegate for this but it didn't work too well.
			//	It's too bad because it was a lot cleaner than using member variables as
			//	psuedo globals.
			_lastReplaceAllMatches = new List<Range>();
			_lastReplaceAllReplaceString = replaceString;
			_lastReplaceAllRangeToSearch = rangeToSearch;
			_lastReplaceAllOffset = 0;

			findExpression.Replace(rangeToSearch.Text, new MatchEvaluator(replaceAllEvaluator));

			Scintilla.UndoRedo.EndUndoAction();
			
			//	No use having these values hanging around wasting memory :)
			List<Range> ret = _lastReplaceAllMatches;
			_lastReplaceAllMatches = null;
			_lastReplaceAllReplaceString = null;
			_lastReplaceAllRangeToSearch = null;
			
			return ret;
		}


		private string replaceAllEvaluator(Match m)
		{
			//	So this method is called for every match

			//	We make a replacement in the range based upon
			//	the match range.
			string replacement = m.Result(_lastReplaceAllReplaceString);
			int start = _lastReplaceAllRangeToSearch.Start + m.Index + _lastReplaceAllOffset;
			int end = start + m.Length;

			Range r = new Range(start, end, Scintilla);
			_lastReplaceAllMatches.Add(r);
			r.Text = replacement;

			//	But because we've modified the document, the RegEx
			//	match ranges are going to be different from the
			//	document ranges. We need to compensate
			_lastReplaceAllOffset += replacement.Length - m.Value.Length;
			return replacement;
		}

		#endregion	

		public void ShowFind()
		{
			if (!_window.Visible)
				_window.Show(Scintilla.FindForm());

			_window.tabAll.SelectedTab = _window.tabAll.TabPages["tpgFind"];

			Range selRange = Scintilla.Selection.Range;
			if (selRange.IsMultiLine)
			{
				_window.chkSearchSelectionF.Checked = true;
			}
			else if (selRange.Length > 0)
			{
				_window.cboFindF.Text = selRange.Text;
			}

			_window.cboFindF.Select();
			_window.cboFindF.SelectAll();

		}

		public void ShowReplace()
		{
			if (!_window.Visible)
				_window.Show(Scintilla.FindForm());

			_window.tabAll.SelectedTab = _window.tabAll.TabPages["tpgReplace"];

			Range selRange = Scintilla.Selection.Range;
			if (selRange.IsMultiLine)
			{
				_window.chkSearchSelectionR.Checked = true;
			}
			else if (selRange.Length > 0)
			{
				_window.cboFindR.Text = selRange.Text;
			}

			_window.cboFindR.Select();
			_window.cboFindR.SelectAll();
		}

		public List<MarkerInstance> MarkAll(IList<Range> foundRanges)
		{
			List<MarkerInstance> ret = new List<MarkerInstance>();

			Line lastLine = new Line(Scintilla, -1);
			foreach (Range r in foundRanges)
			{
				//	We can of course have multiple instances of a find on a single
				//	line. We don't want to mark this line more than once.
				Line line = r.StartingLine;
				if (line.Number > lastLine.Number)
					ret.Add(Marker.AddInstanceTo(r.StartingLine));
				lastLine = line;
			}

			return ret;
		}

		public void HighlightAll(IList<Range> foundRanges)
		{
			foreach (Range r in foundRanges)
			{
				r.SetIndicator(Indicator.Number);
			}
		}

		public void ClearAllHighlights()
		{
			Indicator i = Scintilla.FindReplace.Indicator;
			foreach (Range r in i.SearchAll())
			{
				r.ClearIndicator(i);
			}
		}

		public void IncrementalSearch()
		{
			_incrementalSearcher.Show();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions