///<summary>Break a tag into two with identical attributes; pos is 1-based; returns tag starting at >pos< or null if end-of-line</summary> public LineTag Break(int pos) { LineTag new_tag; #if DEBUG // Sanity if (pos < this.Start) { throw new Exception("Breaking at a negative point"); } #endif #if DEBUG if (pos > End) { throw new Exception("Breaking past the end of a line"); } #endif new_tag = new LineTag(line, pos); new_tag.CopyFormattingFrom(this); new_tag.next = this.next; this.next = new_tag; new_tag.previous = this; if (new_tag.next != null) { new_tag.next.previous = new_tag; } return(new_tag); }
// start_pos = 1-based // end_pos = 1-based public Line Duplicate(Line start_line, int start_pos, Line end_line, int end_pos) { Line ret; Line line; Line current; LineTag tag; LineTag current_tag; int start; int end; int tag_start; line = new Line (start_line.document, start_line.ending); ret = line; for (int i = start_line.line_no; i <= end_line.line_no; i++) { current = document.GetLine(i); if (start_line.line_no == i) { start = start_pos; } else { start = 0; } if (end_line.line_no == i) { end = end_pos; } else { end = current.text.Length; } if (end_pos == 0) continue; // Text for the tag line.text = new StringBuilder (current.text.ToString (start, end - start)); // Copy tags from start to start+length onto new line current_tag = current.FindTag (start + 1); while ((current_tag != null) && (current_tag.Start <= end)) { if ((current_tag.Start <= start) && (start < (current_tag.Start + current_tag.Length))) { // start tag is within this tag tag_start = start; } else { tag_start = current_tag.Start; } tag = new LineTag(line, tag_start - start + 1); tag.CopyFormattingFrom (current_tag); current_tag = current_tag.Next; // Add the new tag to the line if (line.tags == null) { line.tags = tag; } else { LineTag tail; tail = line.tags; while (tail.Next != null) { tail = tail.Next; } tail.Next = tag; tag.Previous = tail; } } if ((i + 1) <= end_line.line_no) { line.ending = current.ending; // Chain them (we use right/left as next/previous) line.right = new Line (start_line.document, start_line.ending); line.right.left = line; line = line.right; } } return ret; }
///<summary>Split line at given tag and position into two lines</summary> ///if more space becomes available on previous line internal void Split(Line line, LineTag tag, int pos) { LineTag new_tag; Line new_line; bool move_caret; bool move_sel_start; bool move_sel_end; move_caret = false; move_sel_start = false; move_sel_end = false; #if DEBUG SanityCheck(); if (tag.End < pos) throw new Exception ("Split called with the wrong tag"); #endif // Adjust selection and cursors if (caret.line == line && caret.pos >= pos) { move_caret = true; } if (selection_start.line == line && selection_start.pos > pos) { move_sel_start = true; } if (selection_end.line == line && selection_end.pos > pos) { move_sel_end = true; } // cover the easy case first if (pos == line.text.Length) { Add (line.line_no + 1, String.Empty, line.alignment, tag.Font, tag.Color, line.ending); new_line = GetLine (line.line_no + 1); if (move_caret) { caret.line = new_line; caret.tag = new_line.tags; caret.pos = 0; if (selection_visible == false) { SetSelectionToCaret (true); } } if (move_sel_start) { selection_start.line = new_line; selection_start.pos = 0; selection_start.tag = new_line.tags; } if (move_sel_end) { selection_end.line = new_line; selection_end.pos = 0; selection_end.tag = new_line.tags; } #if DEBUG SanityCheck (); #endif return; } // We need to move the rest of the text into the new line Add (line.line_no + 1, line.text.ToString (pos, line.text.Length - pos), line.alignment, tag.Font, tag.Color, line.ending); // Now transfer our tags from this line to the next new_line = GetLine(line.line_no + 1); line.recalc = true; new_line.recalc = true; //make sure that if we are at the end of a tag, we start on the begining //of a new one, if one exists... Stops us creating an empty tag and //make the operation easier. if (tag.Next != null && (tag.Next.Start - 1) == pos) tag = tag.Next; if ((tag.Start - 1) == pos) { int shift; // We can simply break the chain and move the tag into the next line // if the tag we are moving is the first, create an empty tag // for the line we are leaving behind if (tag == line.tags) { new_tag = new LineTag(line, 1); new_tag.CopyFormattingFrom (tag); line.tags = new_tag; } if (tag.Previous != null) { tag.Previous.Next = null; } new_line.tags = tag; tag.Previous = null; tag.Line = new_line; // Walk the list and correct the start location of the tags we just bumped into the next line shift = tag.Start - 1; new_tag = tag; while (new_tag != null) { new_tag.Start -= shift; new_tag.Line = new_line; new_tag = new_tag.Next; } } else { int shift; new_tag = new LineTag (new_line, 1); new_tag.Next = tag.Next; new_tag.CopyFormattingFrom (tag); new_line.tags = new_tag; if (new_tag.Next != null) { new_tag.Next.Previous = new_tag; } tag.Next = null; shift = pos; new_tag = new_tag.Next; while (new_tag != null) { new_tag.Start -= shift; new_tag.Line = new_line; new_tag = new_tag.Next; } } if (move_caret) { caret.line = new_line; caret.pos = caret.pos - pos; caret.tag = caret.line.FindTag(caret.pos); if (selection_visible == false) { SetSelectionToCaret (true); move_sel_start = false; move_sel_end = false; } } if (move_sel_start) { selection_start.line = new_line; selection_start.pos = selection_start.pos - pos; if (selection_start.Equals(selection_end)) selection_start.tag = new_line.FindTag(selection_start.pos); else selection_start.tag = new_line.FindTag (selection_start.pos + 1); } if (move_sel_end) { selection_end.line = new_line; selection_end.pos = selection_end.pos - pos; selection_end.tag = new_line.FindTag(selection_end.pos); } CharCount -= line.text.Length - pos; line.text.Remove(pos, line.text.Length - pos); #if DEBUG SanityCheck (); #endif }
///<summary>Break a tag into two with identical attributes; pos is 1-based; returns tag starting at >pos< or null if end-of-line</summary> public LineTag Break (int pos) { LineTag new_tag; #if DEBUG // Sanity if (pos < this.Start) throw new Exception ("Breaking at a negative point"); #endif #if DEBUG if (pos > End) throw new Exception ("Breaking past the end of a line"); #endif new_tag = new LineTag(line, pos); new_tag.CopyFormattingFrom (this); new_tag.next = this.next; this.next = new_tag; new_tag.previous = this; if (new_tag.next != null) new_tag.next.previous = new_tag; return new_tag; }