/// <summary> /// Requests to invalidate area covered by given text range. /// </summary> /// <param name="g">graphic drawing interface to be used.</param> /// <param name="beginIndex">Begin text index of the area to be invalidated.</param> /// <param name="endIndex">End text index of the area to be invalidated.</param> public override void Invalidate(IGraphics g, int beginIndex, int endIndex) { DebugUtl.Assert(0 <= beginIndex, "cond: 0 <= beginIndex(" + beginIndex + ")"); DebugUtl.Assert(beginIndex <= endIndex, "cond: beginIndex(" + beginIndex + ") <= endIndex(" + endIndex + ")"); DebugUtl.Assert(endIndex <= Document.Length, "endIndex(" + endIndex + ") must not exceed document length (" + Document.Length + ")"); if (beginIndex == endIndex) { return; } int beginLineHead, endLineHead; int beginL, endL, dummy; // get needed coordinates GetLineColumnIndexFromCharIndex(beginIndex, out beginL, out dummy); GetLineColumnIndexFromCharIndex(endIndex, out endL, out dummy); beginLineHead = GetLineHeadIndex(beginL); // switch invalidation logic by whether the invalidated area is multiline or not if (beginL != endL) { endLineHead = GetLineHeadIndex(endL); // this is needed for invalidating multiline selection Invalidate_MultiLines(g, beginIndex, endIndex, beginL, endL, beginLineHead, endLineHead); } else { Invalidate_InLine(g, beginIndex, endIndex, beginL, beginLineHead); } }
/// <summary> /// Ensures the buffer is capable to insert data. /// </summary> /// <exception cref="System.OutOfMemoryException">There is no enough memory to expand buffer.</exception> void EnsureSpaceForInsertion(int insertLength) { DebugUtl.Assert(_Data != null); DebugUtl.Assert(0 <= insertLength); // to avoid all gaps are filled by inserted data, expand buffer if (_GapLen <= insertLength) { // move gap to the end MoveGapTo(_Data.Length - _GapLen); // calculate buffer size to be expanded int newSize = _Data.Length; do { if (0 < _GrowSize) { newSize += _GrowSize; } else { newSize *= 2; } }while(newSize < _Count + insertLength); // expand buffer ResizeArray(ref _Data, newSize); __set_insanity_data__(_GapPos, newSize); // update info _GapLen = newSize - _Count; } }
/// <summary> /// Inserts elements at specified index. /// </summary> /// <param name="insertIndex">target location of insertion</param> /// <param name="values">elements which contains the elements to be inserted</param> /// <param name="valueBegin">index of the first elements to be inserted</param> /// <param name="valueEnd">index of the end position (one after last elements)</param> /// <exception cref="ArgumentOutOfRangeException">invalid index was given</exception> public virtual void Insert(int insertIndex, T[] values, int valueBegin, int valueEnd) { // [case 1: Insert(1, "foobar", 0, 4)] // ABCDE___FGHI (gappos:5, gaplen:3) // ABCDEFGHI___ (gappos:9, gaplen:3) // ABCDEFGHI_______ (gappos:9, gaplen:7) // A_______BCDEFGHI (gappos:1, gaplen:7) // Afoob___BCDEFGHI (gappos:5, gaplen:3) DebugUtl.Assert(0 <= insertIndex, "Invalid index was given (insertIndex:" + insertIndex + ")."); DebugUtl.Assert(values != null, "Null was given to 'values'."); int insertLen = valueEnd - valueBegin; // make sufficient gap at insertion point EnsureSpaceForInsertion(insertLen); MoveGapTo(insertIndex); // insert Array.Copy(values, valueBegin, _Data, insertIndex, insertLen); // update _Count += insertLen; _GapPos += insertLen; _GapLen -= insertLen; __dump__(String.Format("Insert({0}, {1}..., {2}, {3})", insertIndex, values[0], valueBegin, valueEnd)); __check_sanity__(); }
void Invalidate_InLine(IGraphics g, int begin, int end, int beginL, int beginLineHead) { DebugUtl.Assert(g != null, "null was given to PropView.Invalidate_InfLine."); DebugUtl.Assert(0 <= begin, "cond: 0 <= begin(" + begin + ")"); DebugUtl.Assert(begin <= end, "cond: begin(" + begin + ") <= end(" + end + ")"); DebugUtl.Assert(end <= Document.Length, "cond: end(" + end + ") <= Document.Length(" + Document.Length + ")"); DebugUtl.Assert(0 <= beginL, "cond: 0 <= beginL(" + beginL + ")"); DebugUtl.Assert(beginL <= this.LineCount, "cond: beginL(" + beginL + ") <= IView.LineCount(" + this.LineCount + ")"); DebugUtl.Assert(beginLineHead <= begin, "cond: beginLineHead(" + beginLineHead + ") <= begin(" + begin + ")"); Debug.Assert(TextUtil.IsDividableIndex(Document.InternalBuffer, begin)); Debug.Assert(TextUtil.IsDividableIndex(Document.InternalBuffer, end)); Debug.Assert(TextUtil.IsDividableIndex(Document.InternalBuffer, beginLineHead)); if (begin == end) { return; } Rectangle rect = new Rectangle(); // calculate position of the invalid rect rect.X = MeasureTokenEndX(g, new TextSegment(beginLineHead, begin), 0); rect.Y = YofLine(beginL); // calculate width and height of the invalid rect rect.Width = MeasureTokenEndX(g, new TextSegment(begin, end), rect.X) - rect.X; rect.Height = LineSpacing; Debug.Assert(0 <= rect.Width); // invalidate rect.X -= (ScrollPosX - XofTextArea); Invalidate(rect); }
static void FindEntityEnd(Document doc, int startIndex, out int endIndex, out bool wasEntity) { DebugUtl.Assert(startIndex < doc.Length); DebugUtl.Assert(doc[startIndex] == '&'); endIndex = startIndex + 1; while (endIndex < doc.Length) { char ch = doc[endIndex]; if ((ch < 'A' || 'Z' < ch) && (ch < 'a' || 'z' < ch) && (ch < '0' || '9' < ch) && (ch != '#')) { if (ch == ';') { endIndex++; wasEntity = true; return; } else { wasEntity = false; return; } } endIndex++; } wasEntity = false; return; }
/// <summary> /// Copies items to other array object. /// </summary> public void CopyTo(int begin, int end, T[] array, int arrayIndex) { DebugUtl.Assert(0 <= begin && begin < end && end <= Count, "invalid range [" + begin + ", " + end + ") was given. (Count:" + Count + ")"); DebugUtl.Assert(array != null, "parameter 'array' must not be null."); DebugUtl.Assert(0 <= arrayIndex && arrayIndex < array.Length, "parameter 'arrayIndex' is out of range. (arrayIndex:" + arrayIndex + ", array.Length:" + array.Length + ")"); DebugUtl.Assert(end - begin <= array.Length - arrayIndex, "size of the given array is not sufficient. (begin:" + begin + ", end:" + end + ", arrayIndex:" + arrayIndex + ", array.Length:" + array.Length + ")"); if (end <= _GapPos) { Array.Copy(_Data, begin, array, arrayIndex, end - begin); // [begin, end) } else if (begin < _GapPos) { int gapBegin = _GapPos; int gapEnd = _GapPos + _GapLen; Array.Copy(_Data, begin, array, arrayIndex, gapBegin - begin); // [begin, gapBegin) Array.Copy(_Data, gapEnd, array, arrayIndex + (gapBegin - begin), _GapLen + end - gapEnd); // [gapEnd, gapLen+end) } else { Array.Copy(_Data, _GapLen + begin, array, arrayIndex, end - begin); // [gapLen+begin, gapLen+end) } }
/// <summary> /// Inserts an element at specified index. /// </summary> /// <exception cref="ArgumentException">invalid index was given</exception> public virtual void Insert(int insertIndex, T value) { // [case 1: Insert(1, "#")] // ABCDE___FGHI (gappos:5, gaplen:3) // ABCDEFGHI___ (gappos:9, gaplen:3) // ABCDEFGHI_______ (gappos:9, gaplen:7) // A_______BCDEFGHI (gappos:1, gaplen:7) // A#______BCDEFGHI (gappos:5, gaplen:3) DebugUtl.Assert(0 <= insertIndex, "Invalid index was given (insertIndex:" + insertIndex + ")."); DebugUtl.Assert(value != null, "Null was given to 'values'."); // make sufficient gap for insertion EnsureSpaceForInsertion(1); MoveGapTo(insertIndex); // insert _Data[insertIndex] = value; // update info _Count += 1; _GapPos += 1; _GapLen -= 1; __dump__(String.Format("Insert({0}, {1})", insertIndex, value)); __check_sanity__(); }
void Invalidate_InLine(IGraphics g, int begin, int end, int beginL, int beginLineHead) { DebugUtl.Assert(g != null, "null was given to PropView.Invalidate_InfLine."); DebugUtl.Assert(0 <= begin, "cond: 0 <= begin(" + begin + ")"); DebugUtl.Assert(begin <= end, "cond: begin(" + begin + ") <= end(" + end + ")"); DebugUtl.Assert(end <= Document.Length, "cond: end(" + end + ") <= Document.Length(" + Document.Length + ")"); DebugUtl.Assert(0 <= beginL, "cond: 0 <= beginL(" + beginL + ")"); DebugUtl.Assert(beginL <= this.LineCount, "cond: beginL(" + beginL + ") <= IView.LineCount(" + this.LineCount + ")"); DebugUtl.Assert(beginLineHead <= begin, "cond: beginLineHead(" + beginLineHead + ") <= begin(" + begin + ")"); if (begin == end) { return; } Rectangle rect = new Rectangle(); string textBeforeSelBegin; string textSelected; // calculate position of the invalid rect textBeforeSelBegin = Document.GetTextInRangeRef(ref beginLineHead, ref begin); rect.X = MeasureTokenEndX(g, textBeforeSelBegin, 0); rect.Y = YofLine(beginL); // calculate width and height of the invalid rect textSelected = Document.GetTextInRangeRef(ref begin, ref end); rect.Width = MeasureTokenEndX(g, textSelected, rect.X) - rect.X; rect.Height = LineSpacing; Debug.Assert(0 <= rect.Width); // invalidate rect.X -= (ScrollPosX - XofTextArea); Invalidate(rect); }
/// <summary> /// Calculate index of the previous word. /// </summary> public static int Calc_PrevWord(IViewInternal view) { int index; int startIndex; Document doc = view.Document; // if the caret is at the head of document, return head of document index = doc.CaretIndex - 1; if (index <= 0) { return(0); } // skip whitespace startIndex = index; if (Utl.IsWhiteSpace(doc, index)) { index = doc.WordProc.PrevWordStart(doc, index) - 1; if (index < 0) { return(0); } } DebugUtl.Assert(0 <= index && index <= doc.Length); // if EOL code comes, return just before them if (Utl.IsEol(doc, index)) { if (startIndex != index) { // do not skip this EOL code // if this was detected after skipping whitespaces return(index + 1); } else if (doc[index] == '\r') { return(index); } else { DebugUtl.Assert(doc[index] == '\n'); if (0 <= index - 1 && doc[index - 1] == '\r') { return(index - 1); } else { return(index); } } } // seek to previous word starting position index = doc.WordProc.PrevWordStart(doc, index); return(index); }
/// <summary> /// Finds previous occurrence of a text pattern. /// </summary> /// <param name="value">The String to find.</param> /// <param name="begin">The begin index of the search range.</param> /// <param name="end">The end index of the search range.</param> /// <param name="matchCase">Whether the search should be case-sensitive or not.</param> /// <returns>Search result object if found, otherwise null if not found.</returns> public SearchResult FindPrev(string value, int begin, int end, bool matchCase) { // If the gap exists before the search starting position, // it must be moved to after the starting position. int start, length; int foundIndex; StringComparison compType; DebugUtl.Assert(value != null); DebugUtl.Assert(begin <= end); DebugUtl.Assert(end <= _Count); // if empty string is the value to search, just return search start index if (value.Length == 0) { return(new SearchResult(end, end)); } // convert begin/end indexes to start/length indexes start = end - 1; length = end - begin; if (start < 0 || length <= 0) { return(null); } // calculate start index in the gapped buffer if (_GapPos < begin) { // the gap exists before search range so the gap is not needed to be moved start += _GapLen; } else if (_GapPos < end) { // the gap exists in the search range so the gap must be moved MoveGapTo(end); } //NO_NEED//else if( end <= _GapPos ) {} // nothing to do in this case // find compType = (matchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase); foundIndex = new String(_Data).LastIndexOf(value, start, length, compType); if (foundIndex == -1) { return(null); } // calculate found index not in gapped buffer but in content if (_GapPos < end) { foundIndex -= _GapLen; } // return found index return(new SearchResult(foundIndex, foundIndex + value.Length)); }
/// <summary> /// Finds a text pattern. /// </summary> /// <param name="value">The String to find.</param> /// <param name="begin">Begin index of the search range.</param> /// <param name="end">End index of the search range.</param> /// <param name="matchCase">Whether the search should be case-sensitive or not.</param> /// <returns>Search result object if found, otherwise null if not found.</returns> public SearchResult FindNext(string value, int begin, int end, bool matchCase) { // If the gap exists after the search starting position, // it must be moved to before the starting position. int start, length; int foundIndex; StringComparison compType; DebugUtl.Assert(value != null); DebugUtl.Assert(0 <= begin); DebugUtl.Assert(begin <= end); DebugUtl.Assert(end <= _Count); // convert begin/end indexes to start/length indexes start = begin; length = end - begin; if (length <= 0) { return(null); } // move the gap if necessary if (_GapPos <= begin) { // the gap exists before search range so the gap is not needed to be moved //DO_NOT//MoveGapTo( somewhere ); start += _GapLen; } else if (_GapPos < end) { // the gap exists IN the search range so the gap must be moved MoveGapTo(begin); start += _GapLen; } //NO_NEED//else if( end <= _GapPos ) {} // nothing to do in this case // find compType = (matchCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); foundIndex = new String(_Data).IndexOf(value, start, length, compType); if (foundIndex == -1) { return(null); } // calculate found index not in gapped buffer but in content if (_GapPos < end) { foundIndex -= _GapLen; } // return found index return(new SearchResult(foundIndex, foundIndex + value.Length)); }
/// <summary> /// Gets an element at specified index. /// </summary> public T GetAt(int index) { DebugUtl.Assert(0 <= index && index < _Count, "argument out of range: requested index is " + index + " but _Count is " + _Count); if (index < _GapPos) { return(_Data[index]); } else { return(_Data[_GapLen + index]); } }
public static int GetCharIndexFromLineColumnIndex(TextBuffer text, SplitArray <int> lhi, int lineIndex, int columnIndex) { DebugUtl.Assert(text != null && lhi != null && 0 <= lineIndex && 0 <= columnIndex, "invalid arguments were given"); DebugUtl.Assert(lineIndex < lhi.Count, String.Format( "too large line index was given (given:{0} actual" + " line count:{1})", lineIndex, lhi.Count)); int lineHeadIndex = lhi[lineIndex]; # if DEBUG
/// <summary> /// Overwrites an element at specified index. /// </summary> public void SetAt(T value, int index) { DebugUtl.Assert(index < _Count); if (index < _GapPos) { _Data[index] = value; } else { _Data[_GapLen + index] = value; } __dump__(String.Format("SetAt({0}, {1})", value, index)); __check_sanity__(); }
/// <summary> /// Removes an element. /// </summary> public bool Remove(T item) { DebugUtl.Assert(item != null, "parameter 'item' must not be null."); // find the item int index = IndexOf(item); if (index < 0) { return(false); } // remove the item RemoveAt(index); return(true); }
bool SchemeStartsFromHere(Document doc, int index) { DebugUtl.Assert(doc != null); DebugUtl.Assert(0 <= index); DebugUtl.Assert(index < doc.Length); foreach (string scheme in _SchemeTriggers) { if (StartsWith(doc, index, scheme)) { return(true); } } return(false); }
/// <summary> /// Paints content to a graphic device. /// </summary> /// <param name="g">graphic drawing interface to be used.</param> /// <param name="clipRect">clipping rectangle that covers all invalidated region (in client area coordinate)</param> public override void Paint(IGraphics g, Rectangle clipRect) { // [*1] if the graphic of a line should be redrawn by owner draw, // Azuki does not redraw the line but invalidate // the area of the line and let it be drawn on next drawing chance // so that the graphic will not flicker. DebugUtl.Assert(g != null, "invalid argument; IGraphics is null"); DebugUtl.Assert(FontInfo != null, "invalid state; FontInfo is null"); DebugUtl.Assert(Document != null, "invalid state; Document is null"); int selBegin, selEnd; Point pos = new Point(); int longestLineLength = 0; bool shouldRedraw1, shouldRedraw2; // prepare off-screen buffer # if !DRAW_SLOWLY
bool StartsWith(Document doc, int index, string text) { DebugUtl.Assert(doc != null); DebugUtl.Assert(0 <= index); DebugUtl.Assert(index < doc.Length); DebugUtl.Assert(text != null); for (int i = 0; i < text.Length; i++) { if (doc.Length <= (index + i) || text[i] != doc[index + i]) { return(false); } } return(true); }
/// <summary> /// Find a text pattern by regular expression. /// </summary> /// <param name="regex">A Regex object expressing the text pattern.</param> /// <param name="begin">The search starting position.</param> /// <param name="end">Index of where the search must be terminated</param> /// <returns></returns> /// <remarks> /// This method find a text pattern /// expressed by a regular expression in the current content. /// The text matching process continues for the index /// specified with the <paramref name="end"/> parameter /// and does not stop at line ends nor null-characters. /// </remarks> public SearchResult FindNext(Regex regex, int begin, int end) { int start, length; Match match; DebugUtl.Assert(regex != null); DebugUtl.Assert(begin <= end); DebugUtl.Assert(end <= _Count); // in any cases, search length is "end - begin". length = end - begin; // determine where the gap should be moved to if (end <= _GapPos) { // search must stop before reaching the gap so there is no need to move gap start = begin; } else { // search may not stop before reaching to the gap // so move gap to ensure there is no gap in the search range start = begin + _GapLen; MoveGapTo(begin); } // find match = regex.Match(new String(_Data), start, length); if (match.Success == false) { return(null); } // return found index if (start == begin) { return(new SearchResult(match.Index, match.Index + match.Length)); } else { return(new SearchResult(match.Index - _GapLen, match.Index - _GapLen + match.Length)); } }
public SearchResult FindPrev(Regex regex, int begin, int end) { int start, length; Match match; DebugUtl.Assert(regex != null); DebugUtl.Assert(begin <= end); DebugUtl.Assert(end <= _Count); DebugUtl.Assert((regex.Options & RegexOptions.RightToLeft) != 0); // convert begin/end indexes to start/length length = end - begin; if (end <= _GapPos) { // search must stop before reaching the gap so there is no need to move gap start = begin; } else { // search may not stop before reaching to the gap // so move gap to ensure there is no gap in the search range start = begin + _GapLen; MoveGapTo(begin); } // find match = regex.Match(new String(_Data), start, length); if (match.Success == false) { return(null); } // return found index if (start == begin) { return(new SearchResult(match.Index, match.Index + match.Length)); } else { return(new SearchResult(match.Index - _GapLen, match.Index - _GapLen + match.Length)); } }
/// <summary> /// Search for an item using binary-search algorithm. /// </summary> /// <returns> /// The index of the 'item' if found, otherwise bit-reversed value of /// the index of the first element which was greater than the 'item.' /// </returns> public int BinarySearch(T item, Comparison <T> compare) { DebugUtl.Assert(compare != null); if (Count == 0) { return(~(0)); } int left = 0; int right = Count; int middle; for (;;) { middle = left + ((right - left) >> 1); int result = compare(GetAt(middle), item); if (0 < result) { if (right == middle) { return(~(middle)); } right = middle; } else if (result < 0) { if (left == middle) { return(~(middle + 1)); } left = middle; } else { return(middle); } } }
/// <summary> /// Overwrites elements from "replaceIndex" with specified range [valueBegin, valueEnd) of values. /// </summary> public virtual void Replace(int replaceIndex, T[] values, int valueBegin, int valueEnd) { DebugUtl.Assert(0 <= replaceIndex, "Invalid index was given (replaceIndex:" + replaceIndex + ")."); DebugUtl.Assert(values != null); DebugUtl.Assert(0 <= valueEnd && valueEnd <= values.Length, "Invalid index was given (valueEnd:" + valueEnd + ")."); DebugUtl.Assert(0 <= valueBegin && valueBegin <= valueEnd, "Invalid index was given (valueBegin:" + valueBegin + ", valueEnd:" + valueEnd + ")."); DebugUtl.Assert(replaceIndex + valueEnd - valueBegin <= _Count, "Invalid indexes were given (<" + replaceIndex + ":replaceIndex> + <" + (valueEnd - valueBegin) + ":valueEnd - valueBegin> <= <" + _Count + ":_Count> ?)."); // [case 1: Replace(1, "foobar", 0, 4)] // ABC___DEFGHI (gappos:3, gaplen:3) // ABCDEF___GHI (gappos:6, gaplen:3) // Afooba___GHI (gappos:6, gaplen:3) int replaceLen = valueEnd - valueBegin; // move gap to the location just after replacing ends MoveGapTo(replaceIndex + replaceLen); // overwrite elements Array.Copy(values, valueBegin, _Data, replaceIndex, replaceLen); __dump__(String.Format("Replace({0}, {1}..., {2}, {3})", replaceIndex, values[0], valueBegin, valueEnd)); __check_sanity__(); }
/// <summary> /// Removes elements at specified range [begin, end). /// </summary> public virtual void RemoveRange(int begin, int end) { // [case 1: Delete(4, 5)] // A___BCDEFGHI (gappos:1, gaplen:3) // ABCD___EFGHI (gappos:4, gaplen:3) // ABCD_____GHI (gappos:4, gaplen:5) // [case 2: Delete(4, 5)] // ABCDEFG___HI (gappos:7, gaplen:3) // ABCDEF___GHI (gappos:6, gaplen:3) // ABCF_____GHI (gappos:4, gaplen:5) DebugUtl.Assert(0 <= begin, "Invalid range was given [" + begin + ", " + end + ")"); DebugUtl.Assert(0 <= end, "Invalid range was given [" + begin + ", " + end + ")"); DebugUtl.Assert(begin < end, "invalid range was given [" + begin + ", " + end + ")"); // delete int deleteLen = end - begin; if (_GapPos < begin) { // move gap's end to the delete location and expand gap MoveGapTo(begin); __set_insanity_data__(_GapPos + _GapLen, _GapPos + _GapLen + deleteLen); _GapLen += deleteLen; } else { // move gap's head next to the delete range and expand gap (backward) MoveGapTo(end); _GapPos -= deleteLen; _GapLen += deleteLen; __set_insanity_data__(_GapPos, _GapPos + deleteLen); } // update info _Count -= deleteLen; __dump__(String.Format("RemoveRange({0}, {1})", begin, end)); __check_sanity__(); }
/// <summary> /// Removes an item at specified index. /// </summary> /// <param name='index'>Index of the item to be removed.</param> /// <exception cref='ArgumentOutOfRangeException'> /// <paramref name="index"/> is out of valid range. /// </exception> public void RemoveAt(int index) { if (index < 0 || _TotalCount <= index) { throw new ArgumentOutOfRangeException("index", "Specified index is out of valid range. (" + "index:" + index + ", this.Count:" + Count + ")"); } int nodeIndex; int indexInNode; // find the node which contains the item at specified index FindNodeIndex(index, out nodeIndex, out indexInNode); // if the node contains only the item to be removed, // remove the node itself. if (_Nodes[nodeIndex].Length <= 1) { DebugUtl.Assert(indexInNode == 0, "indexInNode must be 0 on this context but" + " actually {0}. Something is wrong...", indexInNode); _Nodes.RemoveAt(nodeIndex); if (0 <= nodeIndex - 1 && nodeIndex < _Nodes.Count && _Nodes[nodeIndex - 1].Value.Equals(_Nodes[nodeIndex].Value)) { // combine this node, the previous node, and the next node _Nodes[nodeIndex - 1].Length += _Nodes[nodeIndex].Length; _Nodes.RemoveAt(nodeIndex); } } else { _Nodes[nodeIndex].Length--; } _TotalCount--; __check_sanity__(); }
/// <summary> /// Moves 'gap' to specified location. /// </summary> protected void MoveGapTo(int index) { // [case 1: MoveGapTo(1)] // ABCDE___FGHI (gappos:5, gaplen:3, part2pos:3) // A___BCDEFGHI (gappos:1, gaplen:3, part2pos:3) // [case 2: MoveGapTo(6)] // ABCD___EFGHI (gappos:4, gaplen:3) // ABCDEF___GHI (gappos:2, gaplen:3) DebugUtl.Assert(index <= _Data.Length - _GapLen, String.Format("condition: index({0}) <= _Data.Length({1}) - _GapLen({2})", index, _Data.Length, _GapLen)); if (index < _GapPos) { Array.Copy(_Data, index, _Data, index + _GapLen, Part1Len - index); __set_insanity_data__(index, index + _GapLen); _GapPos = index; } else if (_GapPos < index) { Array.Copy(_Data, _GapPos + _GapLen, _Data, _GapPos, index - _GapPos); _GapPos = index; __set_insanity_data__(_GapPos, _GapPos + _GapLen); } }
void HandleSelectionChanged_OnExpandSelInLine(IGraphics g, SelectionChangedEventArgs e, int begin, int end, int beginL) { DebugUtl.Assert(beginL < LineCount); Document doc = Document; Rectangle rect = new Rectangle(); int beginLineHead; string token = String.Empty; // if anchor was moved, invalidate largest range made with four indexes if (e.OldAnchor != doc.AnchorIndex) { begin = Utl.Min(e.OldAnchor, e.OldCaret, doc.AnchorIndex, doc.CaretIndex); end = Utl.Max(e.OldAnchor, e.OldCaret, doc.AnchorIndex, doc.CaretIndex); Invalidate(begin, end); return; } // get chars at left of invalid rect beginLineHead = GetLineHeadIndex(beginL); if (beginLineHead < begin) { token = Document.GetTextInRangeRef(ref beginLineHead, ref begin); } // calculate invalid rect rect.X = MeasureTokenEndX(g, token, 0); rect.Y = YofLine(beginL); token = Document.GetTextInRangeRef(ref beginLineHead, ref end); rect.Width = MeasureTokenEndX(g, token, 0) - rect.X; rect.Height = LineSpacing; // invalidate rect.X -= (ScrollPosX - XofTextArea); Invalidate(rect); }
void HandleSelectionChanged_OnExpandSelInLine(IGraphics g, SelectionChangedEventArgs e, int begin, int end, int beginL) { DebugUtl.Assert(beginL < LineCount); Debug.Assert(TextUtil.IsDividableIndex(Document.InternalBuffer, begin)); Debug.Assert(TextUtil.IsDividableIndex(Document.InternalBuffer, end)); var doc = Document; var rect = new Rectangle(); // if anchor was moved, invalidate largest range made with four indexes if (e.OldAnchor != doc.AnchorIndex) { begin = Utl.Min(e.OldAnchor, e.OldCaret, doc.AnchorIndex, doc.CaretIndex); end = Utl.Max(e.OldAnchor, e.OldCaret, doc.AnchorIndex, doc.CaretIndex); Invalidate(begin, end); return; } // calculate location of invalid rectangle var beginLineHead = GetLineHeadIndex(beginL); if (beginLineHead < begin) { rect.X = MeasureTokenEndX(g, new TextSegment(beginLineHead, begin), 0); } rect.Y = YofLine(beginL); // calculate width of invalid rectangle rect.Width = MeasureTokenEndX(g, new TextSegment(beginLineHead, end), 0) - rect.X; rect.Height = LineSpacing; // invalidate rect.X -= (ScrollPosX - XofTextArea); Invalidate(rect); }
void Invalidate_MultiLines(IGraphics g, int begin, int end, int beginLine, int endLine, int beginLineHead, int endLineHead) { DebugUtl.Assert(g != null, "null was given to PropView.Invalidate_MultiLines."); DebugUtl.Assert(0 <= begin, "cond: 0 <= begin(" + begin + ")"); DebugUtl.Assert(begin <= end, "cond: begin(" + begin + ") <= end(" + end + ")"); DebugUtl.Assert(end <= Document.Length, "cond: end(" + end + ") <= Document.Length(" + Document.Length + ")"); DebugUtl.Assert(0 <= beginLine, "cond: 0 <= beginLine(" + beginLine + ")"); DebugUtl.Assert(beginLine < endLine, "cond: beginLine(" + beginLine + ") < endLine(" + endLine + ")"); DebugUtl.Assert(endLine <= this.LineCount, "cond: endLine(" + endLine + ") <= IView.LineCount(" + this.LineCount + ")"); DebugUtl.Assert(beginLineHead <= begin, "cond: beginLineHead(" + beginLineHead + ") <= begin(" + begin + ")"); DebugUtl.Assert(beginLineHead < endLineHead, "cond: beginLineHead(" + beginLineHead + " < endLineHead(" + endLineHead + ")"); DebugUtl.Assert(endLineHead <= end, "cond: endLineHead(" + endLineHead + ") <= end(" + end + ")"); if (begin == end) { return; } Rectangle upper, lower, middle; var doc = Document; // calculate upper part of the invalid area upper = new Rectangle(); if (FirstVisibleLine <= beginLine) // if not visible, no need to invalidate { upper.X = MeasureTokenEndX(g, new TextSegment(beginLineHead, begin), 0) - (ScrollPosX - XofTextArea); upper.Y = YofLine(beginLine); upper.Width = VisibleSize.Width - upper.X; upper.Height = LineSpacing; } // calculate lower part of the invalid area lower = new Rectangle(); if (FirstVisibleLine <= endLine) // if not visible, no need to invalidate { lower.X = XofTextArea; lower.Y = YofLine(endLine); lower.Width = MeasureTokenEndX(g, new TextSegment(endLineHead, end), 0) - ScrollPosX; lower.Height = LineSpacing; } // calculate middle part of the invalid area middle = new Rectangle(); if (FirstVisibleLine < beginLine + 1) { middle.Y = YofLine(beginLine + 1); } middle.X = XofTextArea; middle.Width = VisibleSize.Width; middle.Height = lower.Y - middle.Y; // invalidate three rectangles if (0 < upper.Height) { Invalidate(upper); } if (0 < middle.Height) { Invalidate(middle); } if (0 < lower.Height) { Invalidate(lower); } }
/// <summary> /// Parse and highlight keywords. /// </summary> /// <param name="doc">Document to highlight.</param> /// <param name="dirtyBegin">Index to start highlighting. On return, start index of the range to be invalidated.</param> /// <param name="dirtyEnd">Index to end highlighting. On return, end index of the range to be invalidated.</param> public void Highlight(Document doc, ref int dirtyBegin, ref int dirtyEnd) { if (dirtyBegin < 0 || doc.Length < dirtyBegin) { throw new ArgumentOutOfRangeException("dirtyBegin"); } if (dirtyEnd < 0 || doc.Length < dirtyEnd) { throw new ArgumentOutOfRangeException("dirtyEnd"); } char nextCh; int index, nextIndex; // Determine range to highlight dirtyBegin = Utl.FindReparsePoint(_ReparsePoints, dirtyBegin); dirtyEnd = Utl.FindReparseEndPoint(doc, dirtyEnd); // seek each tags index = 0; while (0 <= index && index < dirtyEnd) { if (Utl.TryHighlight(doc, _Enclosures, index, dirtyEnd, null, out nextIndex)) { Utl.EntryReparsePoint(_ReparsePoints, index); index = nextIndex; } else if (doc[index] == '<') { Utl.EntryReparsePoint(_ReparsePoints, index); // set class for '<' doc.SetCharClass(index, CharClass.Delimiter); index++; if (dirtyEnd <= index) { return; } // if next char is '?' or '/', highlight it too nextCh = doc[index]; if (nextCh == '?' || nextCh == '/' || nextCh == '!') { doc.SetCharClass(index, CharClass.Delimiter); index++; if (dirtyEnd <= index) { return; } } // skip whitespaces while (Char.IsWhiteSpace(doc[index])) { doc.SetCharClass(index, CharClass.Normal); index++; if (dirtyEnd <= index) { return; } } // highlight element name nextIndex = Utl.FindNextToken(doc, index, DefaultWordCharSet); for (int i = index; i < nextIndex; i++) { doc.SetCharClass(i, CharClass.ElementName); } index = nextIndex; // highlight attributes while (index < dirtyEnd && doc[index] != '>') { // highlight enclosing part if this token begins a part if (Utl.TryHighlight(doc, _Enclosures, index, dirtyEnd, null, out nextIndex)) { // successfully highlighted. skip to next. index = nextIndex; continue; } // this token is normal class; reset classes and seek to next token nextIndex = Utl.FindNextToken(doc, index, DefaultWordCharSet); for (int i = index; i < nextIndex; i++) { doc.SetCharClass(i, CharClass.Attribute); } index = nextIndex; } // highlight '>' if (index < dirtyEnd) { doc.SetCharClass(index, CharClass.Delimiter); if (1 <= index && doc[index - 1] == '/') { doc.SetCharClass(index - 1, CharClass.Delimiter); } index++; } } else if (doc[index] == '&') { int seekEndIndex; bool wasEntity; CharClass klass; // find end position of this token FindEntityEnd(doc, index, out seekEndIndex, out wasEntity); DebugUtl.Assert(0 <= seekEndIndex && seekEndIndex <= doc.Length); // highlight this token klass = wasEntity ? CharClass.Entity : CharClass.Normal; for (int i = index; i < seekEndIndex; i++) { doc.SetCharClass(i, klass); } index = seekEndIndex; } else { // normal character. doc.SetCharClass(index, CharClass.Normal); index++; } } }
public int GetMailToEnd(Document doc, int startIndex) { if (doc == null) { throw new ArgumentNullException("doc"); } if (startIndex < 0 || doc.Length < startIndex) { throw new ArgumentOutOfRangeException("startIndex"); } int index = startIndex; int lineEnd; char ch; if (doc.Length <= startIndex) { return(-1); } // prepare parsing int lineHeadIndex = doc.GetLineHeadIndexFromCharIndex(startIndex); lineEnd = lineHeadIndex + doc.GetLineLengthFromCharIndex(lineHeadIndex); DebugUtl.Assert(lineEnd <= doc.Length); //local-part: if (index < lineEnd) { ch = doc[index]; if (GetMailToEnd_IsLocalPartChar(ch) == false) { return(-1); } index++; } while (index < lineEnd) { ch = doc[index]; if (ch == '@') { break; } if (GetMailToEnd_IsLocalPartChar(ch) == false) { return(-1); } index++; } if (lineEnd <= index) { return(-1); } //at-mark: DebugUtl.Assert(doc[index] == '@'); index++; //domain: // parse first character of domain part if (index < lineEnd) { ch = doc[index]; if (GetMailToEnd_IsDomainChar(ch) == false) { return(-1); } index++; } else { return(-1); } // parse remainings of domain part while (index < lineEnd) { ch = doc[index]; if (GetMailToEnd_IsDomainChar(ch) == false) { return(index); } index++; } return(index); }