/// <summary> /// Handles banning users that user non-ascii characters. /// </summary> /// <param name="config">The configuration for the twitch chat.</param> /// <param name="client">The twitch client.</param> /// <param name="messageInfo">The information on the chat message.</param> /// <returns>True if the message should be passed on, false if it should be discarded.</returns> public bool Handle(TwitchChatConfiguration config, TwitchClient client, OnMessageReceivedArgs messageInfo) { string chatMessage = messageInfo.ChatMessage.Message; // First convert each character into their hex-sequence representation in Unicode. This will catch both // characters outside of the ASCII character set (> 127) and non-emojis. We only allow ASCII characters // and emojis. var convertedMessageCharacters = UnicodeUtilities.ConvertToUnicodeNumber(chatMessage); foreach (var character in convertedMessageCharacters) { // If there is no space, then just evaluate the single character. if (!character.Contains(" ")) { var num = int.Parse(character, NumberStyles.HexNumber); if (num > 127 && !UnicodeUtilities.IsEmoji(character)) { return(false); } continue; } // If there is a space, it can only possibly be an emoji to be valid. if (!UnicodeUtilities.IsEmoji(character)) { return(false); } } return(true); }
static bool IsWord(ITextSnapshot snapshot, int position, int length) { bool valid = position >= 0 && length >= 0 && (uint)(position + length) <= (uint)snapshot.Length; Debug.Assert(valid); if (!valid) { return(false); } var line = snapshot.GetLineFromPosition(position); return(UnicodeUtilities.IsWord(line, position - line.Start.Position, length)); }
IEnumerable <FindResult> FindAllSingleLineReverse(ITextSnapshotLine startLine, ITextSnapshotLine endLine, SnapshotSpan searchRange, string searchPattern, FindOptions options, StringComparison stringComparison, string replacePattern) { Debug.Assert((options & FindOptions.SearchReverse) != 0); int startLineNumber = startLine.LineNumber; var snapshot = searchRange.Snapshot; bool onlyWords = (options & FindOptions.WholeWord) != 0; var regex = (options & FindOptions.UseRegularExpressions) != 0 ? GetRegex(searchPattern, options) : null; for (int lineNumber = endLine.LineNumber; lineNumber >= startLineNumber; lineNumber--) { var line = snapshot.GetLineFromLineNumber(lineNumber); var range = searchRange.Intersection(line.ExtentIncludingLineBreak); if (range == null || range.Value.Length == 0) { continue; } var text = range.Value.GetText(); int index = text.Length; if (regex != null) { foreach (var res in GetRegexResults(regex, range.Value.Start, text, index, searchPattern, options, replacePattern)) { yield return(res); } } else { while (index > 0) { index = text.LastIndexOf(searchPattern, index - 1, index, stringComparison); if (index < 0) { break; } if (!onlyWords || UnicodeUtilities.IsWord(line, range.Value.Start.Position - line.Start.Position + index, searchPattern.Length)) { yield return(new FindResult(range.Value.Start.Position + index, searchPattern.Length, replacePattern)); } index += searchPattern.Length - 1; } } } }
bool CollectEof(ICancellable cnc, TextData td, Rect clip_rect, int top_index) { if (cnc.IsCancellationRequested) { return(false); } var rtb = Rtb; double max_x = double.NaN; Rect end_rect = Rect.Empty; UITaskHelper.Invoke(rtb, () => { var end = rtb.Document.ContentEnd; end_rect = end.GetCharacterRect(LogicalDirection.Forward); // (no width) if (end_rect.Bottom < clip_rect.Top || end_rect.Top > clip_rect.Bottom) { return; } max_x = end_rect.Left; // if no RTL, then return a quick answer var begin_line = end.GetLineStartPosition(0); if (begin_line != null) { var r = new TextRange(begin_line, end); var text = r.Text; bool has_RTL = false; for (int k = 0; k < text.Length; ++k) { if (cnc.IsCancellationRequested) { return; } if (UnicodeUtilities.IsRTL(text[k])) { has_RTL = true; break; } } if (!has_RTL) { return; } } // we have RTL segments that need additional navigation to find the rightmost X for (var tp = end; ;) { if (cnc.IsCancellationRequested) { return; } tp = tp.GetNextInsertionPosition(LogicalDirection.Backward); if (tp == null) { break; } // WORKAROUND for lines like "0ראל", when "0" is matched and highlighted tp = tp.GetInsertionPosition(LogicalDirection.Forward); var rect = tp.GetCharacterRect(LogicalDirection.Forward); if (rect.Bottom < end_rect.Bottom) { break; } if (max_x < rect.Left) { max_x = rect.Left; } } }); if (cnc.IsCancellationRequested) { return(false); } lock (this) { if (double.IsNaN(max_x)) { PositionEof = Rect.Empty; } else { PositionEof = new Rect(new Point(max_x, end_rect.Top), end_rect.Size); PositionEof.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); } } DelayedInvalidateVisual( ); return(true); }
bool CollectEols(ICancellable cnc, TextData td, Rect clip_rect, int top_index) { if (cnc.IsCancellationRequested) { return(false); } var rtb = Rtb; List <Rect> positions_eols = new List <Rect>( ); // lines with no right-to-left segments var matches = EolRegex.Matches(td.Text); for (int i = 0; i < matches.Count; ++i) { if (cnc.IsCancellationRequested) { return(false); } int index = matches[i].Index; if (index < top_index) { continue; } int previous_index = i == 0 ? 0 : matches[i - 1].Index; bool has_RTL = false; for (int k = previous_index; k < index; ++k) { if (cnc.IsCancellationRequested) { return(false); } if (UnicodeUtilities.IsRTL(td.Text[k])) { has_RTL = true; break; } } if (has_RTL) { // RTL needs more navigation to find the rightmost X Rect left_rect = Rect.Empty; double max_x = double.NaN; bool should_continue = false; bool should_break = false; UITaskHelper.Invoke(rtb, () => { TextPointer left = td.TextPointers.GetTextPointer(index); left_rect = left.GetCharacterRect(LogicalDirection.Forward); if (left_rect.Bottom < clip_rect.Top) { should_continue = true; return; } if (left_rect.Top > clip_rect.Bottom) { should_break = true; return; } max_x = left_rect.Left; for (var tp = left.GetInsertionPosition(LogicalDirection.Backward); ;) { if (cnc.IsCancellationRequested) { return; } tp = tp.GetNextInsertionPosition(LogicalDirection.Backward); if (tp == null) { break; } // WORKAROUND for lines like "0ראל", when "0" is matched and highlighted tp = tp.GetInsertionPosition(LogicalDirection.Forward); var rect_b = tp.GetCharacterRect(LogicalDirection.Backward); var rect_f = tp.GetCharacterRect(LogicalDirection.Forward); if (cnc.IsCancellationRequested) { return; } if (rect_b.Bottom < left_rect.Top && rect_f.Bottom < left_rect.Top) { break; } if (rect_b.Bottom > left_rect.Top) { if (max_x < rect_b.Left) { max_x = rect_b.Left; } } if (rect_f.Bottom > left_rect.Top) { if (max_x < rect_f.Left) { max_x = rect_f.Left; } } } }); if (cnc.IsCancellationRequested) { return(false); } if (should_continue) { continue; } if (should_break) { break; } Rect eol_rect = new Rect(new Point(max_x, left_rect.Top), left_rect.Size); eol_rect.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); positions_eols.Add(eol_rect); } else { // no RTL; quick answer Rect eol_rect = Rect.Empty; UITaskHelper.Invoke(rtb, () => { TextPointer left = td.TextPointers.GetTextPointer(index); eol_rect = left.GetCharacterRect(LogicalDirection.Forward); }); if (eol_rect.Bottom < clip_rect.Top) { continue; } if (eol_rect.Top > clip_rect.Bottom) { break; } eol_rect.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); positions_eols.Add(eol_rect); } } if (cnc.IsCancellationRequested) { return(false); } lock (this) { PositionsEols = positions_eols; } DelayedInvalidateVisual( ); return(true); }