internal void Combine(Line first, Line second) { LineTag last; int shift; // strip the ending off of the first lines text first.text.Length = first.text.Length - LineEndingLength (first.ending); // Combine the two tag chains into one last = first.tags; // Maintain the line ending style first.ending = second.ending; while (last.Next != null) { last = last.Next; } // need to get the shift before setting the next tag since that effects length shift = last.Start + last.Length - 1; last.Next = second.tags; last.Next.Previous = last; // Fix up references within the chain last = last.Next; while (last != null) { last.Line = first; last.Start += shift; last = last.Next; } // Combine both lines' strings first.text.Insert(first.text.Length, second.text.ToString()); first.Grow(first.text.Length); // Remove the reference to our (now combined) tags from the doomed line second.tags = null; // Renumber lines DecrementLines(first.line_no + 2); // first.line_no + 1 will be deleted, so we need to start renumbering one later // Mop up first.recalc = true; first.height = 0; // This forces RecalcDocument/UpdateView to redraw from this line on first.Streamline(lines); // Update Caret, Selection, etc if (caret.line == second) { caret.Combine(first, shift); } if (selection_anchor.line == second) { selection_anchor.Combine(first, shift); } if (selection_start.line == second) { selection_start.Combine(first, shift); } if (selection_end.line == second) { selection_end.Combine(first, shift); } #if Debug Line check_first; Line check_second; check_first = GetLine(first.line_no); check_second = GetLine(check_first.line_no + 1); Console.WriteLine("Pre-delete: Y of first line: {0}, second line: {1}", check_first.Y, check_second.Y); #endif this.Delete(second); #if Debug check_first = GetLine(first.line_no); check_second = GetLine(check_first.line_no + 1); Console.WriteLine("Post-delete Y of first line: {0}, second line: {1}", check_first.Y, check_second.Y); #endif }
// Insert multi-line text at the given position; use formatting at insertion point for inserted text internal void Insert(Line line, int pos, Line insert, bool select) { Line current; LineTag tag; int offset; int lines; Line first; // Handle special case first if (insert.right == null) { // Single line insert document.Split(line, pos); if (insert.tags == null) { return; // Blank line } //Insert our tags at the end tag = line.tags; while (tag.Next != null) { tag = tag.Next; } offset = tag.Start + tag.Length - 1; tag.Next = insert.tags; line.text.Insert(offset, insert.text.ToString()); // Adjust start locations tag = tag.Next; while (tag != null) { tag.Start += offset; tag.Line = line; tag = tag.Next; } // Put it back together document.Combine(line.line_no, line.line_no + 1); if (select) { document.SetSelectionStart (line, pos, false); document.SetSelectionEnd (line, pos + insert.text.Length, false); } document.UpdateView(line, pos); return; } first = line; lines = 1; current = insert; while (current != null) { if (current == insert) { // Inserting the first line we split the line (and make space) document.Split(line.line_no, pos); //Insert our tags at the end of the line tag = line.tags; if (tag != null && tag.Length != 0) { while (tag.Next != null) { tag = tag.Next; } offset = tag.Start + tag.Length - 1; tag.Next = current.tags; tag.Next.Previous = tag; tag = tag.Next; } else { offset = 0; line.tags = current.tags; line.tags.Previous = null; tag = line.tags; } line.ending = current.ending; } else { document.Split(line.line_no, 0); offset = 0; line.tags = current.tags; line.tags.Previous = null; line.ending = current.ending; tag = line.tags; } // Adjust start locations and line pointers while (tag != null) { tag.Start += offset - 1; tag.Line = line; tag = tag.Next; } line.text.Insert(offset, current.text.ToString()); line.Grow(line.text.Length); line.recalc = true; line = document.GetLine(line.line_no + 1); // FIXME? Test undo of line-boundaries if ((current.right == null) && (current.tags.Length != 0)) { document.Combine(line.line_no - 1, line.line_no); } current = current.right; lines++; } // Recalculate our document document.UpdateView(first, lines, pos); return; }
internal void InsertPicture (Line line, int pos, RTF.Picture picture) { //LineTag next_tag; LineTag tag; int len; len = 1; // Just a place holder basically line.text.Insert (pos, "I"); PictureTag picture_tag = new PictureTag (line, pos + 1, picture); tag = LineTag.FindTag (line, pos); picture_tag.CopyFormattingFrom (tag); /*next_tag = */tag.Break (pos + 1); picture_tag.Previous = tag; picture_tag.Next = tag.Next; tag.Next = picture_tag; // // Picture tags need to be surrounded by text tags // if (picture_tag.Next == null) { picture_tag.Next = new LineTag (line, pos + 1); picture_tag.Next.CopyFormattingFrom (tag); picture_tag.Next.Previous = picture_tag; } tag = picture_tag.Next; while (tag != null) { tag.Start += len; tag = tag.Next; } line.Grow (len); line.recalc = true; UpdateView (line, pos); }