Skip to content

Commit

Permalink
Fix #130: Implement FindText()
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmetsait committed Jul 12, 2024
1 parent 1537659 commit 8941ded
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 4 deletions.
32 changes: 32 additions & 0 deletions Scintilla.NET/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ public static class NativeMethods
public const int SC_TYPE_STRING = 2;

// Search flags
public const int SCFIND_NONE = 0x0;
public const int SCFIND_WHOLEWORD = 0x2;
public const int SCFIND_MATCHCASE = 0x4;
public const int SCFIND_WORDSTART = 0x00100000;
Expand Down Expand Up @@ -610,6 +611,7 @@ public static class NativeMethods
public const int SCI_GETTARGETEND = 2193;
public const int SCI_REPLACETARGET = 2194;
public const int SCI_REPLACETARGETRE = 2195;
public const int SCI_FINDTEXTFULL = 2196;
public const int SCI_SEARCHINTARGET = 2197;
public const int SCI_SETSEARCHFLAGS = 2198;
public const int SCI_GETSEARCHFLAGS = 2199;
Expand Down Expand Up @@ -2146,6 +2148,13 @@ public struct Sci_CharacterRange
public int cpMax;
}

[StructLayout(LayoutKind.Sequential)]
public struct Sci_CharacterRangeFull
{
public nint cpMin;
public nint cpMax;
}

[StructLayout(LayoutKind.Sequential)]
public struct Sci_NotifyHeader
{
Expand All @@ -2161,6 +2170,29 @@ public struct Sci_TextRange
public IntPtr lpstrText;
}

[StructLayout(LayoutKind.Sequential)]
public struct Sci_TextRangeFull
{
public Sci_CharacterRangeFull chrg;
public IntPtr lpstrText;
}

[StructLayout(LayoutKind.Sequential)]
public struct Sci_TextToFind
{
public Sci_CharacterRange chrg;
public IntPtr lpstrText;
public Sci_CharacterRange chrgText;
}

[StructLayout(LayoutKind.Sequential)]
public struct Sci_TextToFindFull
{
public Sci_CharacterRangeFull chrg;
public IntPtr lpstrText;
public Sci_CharacterRangeFull chrgText;
}

[StructLayout(LayoutKind.Sequential)]
public struct SCNotification
{
Expand Down
33 changes: 33 additions & 0 deletions Scintilla.NET/Scintilla.cs
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,39 @@ public void ExecuteCmd(Command sciCommand)
DirectMessage(cmd);
}

/// <summary>
/// Search text in document without changing the current selection.
/// The <paramref name="searchFlags"/> argument controls the search type, which includes regular expression searches.
/// You can search backwards to find the previous occurrence of a search string by setting the end of the search range before the start.
/// </summary>
/// <param name="searchFlags">Specifies the how patterns are matched when performing the search.</param>
/// <param name="text">String to search for.</param>
/// <param name="start">Beginning of </param>
/// <param name="end"></param>
/// <returns>The position of the found text if it succeeds or <c>-1</c> if the search fails.</returns>
public unsafe int FindText(SearchFlags searchFlags, string text, int start, int end)
{
int bytePos = 0;
byte[] bytes = Helpers.GetBytes(text ?? string.Empty, Encoding, zeroTerminated: true);

fixed (byte* bp = bytes)
{
NativeMethods.Sci_TextToFind textToFind = new NativeMethods.Sci_TextToFind() {
chrg = new NativeMethods.Sci_CharacterRange() {
cpMin = Lines.CharToBytePosition(Helpers.Clamp(start, 0, TextLength)),
cpMax = Lines.CharToBytePosition(Helpers.Clamp(end, 0, TextLength)),
},
lpstrText = new IntPtr(bp),
};
bytePos = DirectMessage(NativeMethods.SCI_FINDTEXT, (IntPtr)searchFlags, new IntPtr(&textToFind)).ToInt32();
}

if (bytePos == -1)
return bytePos;

return Lines.ByteToCharPosition(bytePos);
}

/// <summary>
/// Performs the specified fold action on the entire document.
/// </summary>
Expand Down
11 changes: 7 additions & 4 deletions Scintilla.NET/SearchFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,35 @@ namespace ScintillaNET;
public enum SearchFlags
{
/// <summary>
/// Matches every instance of the search string.
/// Case-insensitive literal match.
/// </summary>
None = 0,
None = NativeMethods.SCFIND_NONE,

/// <summary>
/// A match only occurs with text that matches the case of the search string.
/// </summary>
MatchCase = NativeMethods.SCFIND_MATCHCASE,

/// <summary>
/// A match only occurs if the characters before and after are not word characters.
/// A match only occurs if the characters before and after are not word characters as defined by <see cref="Scintilla.WordChars"/>.
/// </summary>
WholeWord = NativeMethods.SCFIND_WHOLEWORD,

/// <summary>
/// A match only occurs if the character before is not a word character.
/// A match only occurs if the character before is not a word character as defined by <see cref="Scintilla.WordChars"/>.
/// </summary>
WordStart = NativeMethods.SCFIND_WORDSTART,

/// <summary>
/// The search string should be interpreted as a regular expression.
/// Uses Scintilla's base implementation unless combined with <see cref="Cxx11Regex"/>.
/// Regular expressions will only match ranges within a single line, never matching over multiple lines.
/// </summary>
Regex = NativeMethods.SCFIND_REGEXP,

/// <summary>
/// Treat regular expression in a more POSIX compatible manner by interpreting bare '(' and ')' for tagged sections rather than "\(" and "\)".
/// Has no effect when <see cref="Cxx11Regex"/> is set.
/// </summary>
Posix = NativeMethods.SCFIND_POSIX,

Expand All @@ -45,6 +47,7 @@ public enum SearchFlags
/// The <see cref="Scintilla.Status" /> property can queried to determine if the regular expression is invalid.
/// The ECMAScript flag is set on the regex object and documents will exhibit Unicode-compliant behaviour.
/// Regular expressions will only match ranges within a single line, never matching over multiple lines.
/// Must also have <see cref="Regex"/> set.
/// </summary>
Cxx11Regex = NativeMethods.SCFIND_CXX11REGEX
}

0 comments on commit 8941ded

Please sign in to comment.