void ApplyNewLayout(CircularList <BufferLine> lines, int [] newLayout) { var newLayoutLines = new CircularList <BufferLine> (lines.Length); for (int i = 0; i < newLayout.Length; i++) { newLayoutLines.Push(lines [newLayout [i]]); } // Rearrange the list for (int i = 0; i < newLayoutLines.Length; i++) { lines [i] = newLayoutLines [i]; } lines.Length = newLayout.Length; }
LayoutResult CreateNewLayout(CircularList <BufferLine> lines, int [] toRemove) { var layout = new CircularList <int> (lines.Length); // First iterate through the list and get the actual indexes to use for rows int nextToRemoveIndex = 0; int nextToRemoveStart = toRemove [nextToRemoveIndex]; int countRemovedSoFar = 0; for (int i = 0; i < lines.Length; i++) { if (nextToRemoveStart == i) { int countToRemove = toRemove [++nextToRemoveIndex]; // Tell markers that there was a deletion //lines.onDeleteEmitter.fire ({ // index: i - countRemovedSoFar, // amount: countToRemove //}); i += countToRemove - 1; countRemovedSoFar += countToRemove; nextToRemoveStart = int.MaxValue; if (nextToRemoveIndex < toRemove.Length - 1) { nextToRemoveStart = toRemove [++nextToRemoveIndex]; } } else { layout.Push(i); } } return(new LayoutResult() { Layout = layout.ToArray(), RemovedCount = countRemovedSoFar, }); }
protected static int GetWrappedLineTrimmedLength(CircularList <BufferLine> lines, int row, int cols) { return(GetWrappedLineTrimmedLength(lines [row], row == lines.Length - 1 ? null : lines [row + 1], cols)); }
void Rearrange(List <InsertionSet> toInsert, int countToInsert) { // Rearrange lines in the buffer if there are any insertions, this is done at the end rather // than earlier so that it's a single O(n) pass through the buffer, instead of O(n^2) from many // costly calls to CircularList.splice. if (toInsert.Count > 0) { // Record buffer insert events and then play them back backwards so that the indexes are // correct List <int> insertEvents = new List <int> (); // Record original lines so they don't get overridden when we rearrange the list CircularList <BufferLine> originalLines = new CircularList <BufferLine> (Buffer.Lines.MaxLength); for (int i = 0; i < Buffer.Lines.Length; i++) { originalLines.Push(Buffer.Lines [i]); } int originalLinesLength = Buffer.Lines.Length; int originalLineIndex = originalLinesLength - 1; int nextToInsertIndex = 0; InsertionSet nextToInsert = toInsert [nextToInsertIndex]; Buffer.Lines.Length = Math.Min(Buffer.Lines.MaxLength, Buffer.Lines.Length + countToInsert); int countInsertedSoFar = 0; for (int i = Math.Min(Buffer.Lines.MaxLength - 1, originalLinesLength + countToInsert - 1); i >= 0; i--) { if (!nextToInsert.IsNull && nextToInsert.Start > originalLineIndex + countInsertedSoFar) { // Insert extra lines here, adjusting i as needed for (int nextI = nextToInsert.Lines.Length - 1; nextI >= 0; nextI--) { Buffer.Lines [i--] = nextToInsert.Lines [nextI]; } i++; // Create insert events for later //insertEvents.Add ({ // index: originalLineIndex + 1, // amount: nextToInsert.newLines.length //}); countInsertedSoFar += nextToInsert.Lines.Length; if (nextToInsertIndex < toInsert.Count - 1) { nextToInsert = toInsert [++nextToInsertIndex]; } else { nextToInsert = InsertionSet.Null; } } else { Buffer.Lines [i] = originalLines [originalLineIndex--]; } } /* * // Update markers * let insertCountEmitted = 0; * for (let i = insertEvents.length - 1; i >= 0; i--) { * insertEvents [i].index += insertCountEmitted; * this.lines.onInsertEmitter.fire (insertEvents [i]); * insertCountEmitted += insertEvents [i].amount; * } * * const amountToTrim = Math.max (0, originalLinesLength + countToInsert - this.lines.maxLength); * if (amountToTrim > 0) { * this.lines.onTrimEmitter.fire (amountToTrim); * } */ } }
/// <summary> /// Evaluates and returns indexes to be removed after a reflow larger occurs. Lines will be removed /// when a wrapped line unwraps. /// </summary> /// <param name="lines">The buffer lines</param> /// <param name="oldCols">The columns before resize</param> /// <param name="newCols">The columns after resize</param> /// <param name="bufferAbsoluteY"></param> /// <param name="nullCharacter"></param> int [] GetLinesToRemove(CircularList <BufferLine> lines, int oldCols, int newCols, int bufferAbsoluteY, CharData nullCharacter) { // Gather all BufferLines that need to be removed from the Buffer here so that they can be // batched up and only committed once List <int> toRemove = new List <int> (); for (int y = 0; y < lines.Length - 1; y++) { // Check if this row is wrapped int i = y; BufferLine nextLine = lines [++i]; if (!nextLine.IsWrapped) { continue; } // Check how many lines it's wrapped for List <BufferLine> wrappedLines = new List <BufferLine> (lines.Length - y); wrappedLines.Add(lines [y]); while (i < lines.Length && nextLine.IsWrapped) { wrappedLines.Add(nextLine); nextLine = lines [++i]; } // If these lines contain the cursor don't touch them, the program will handle fixing up wrapped // lines with the cursor if (bufferAbsoluteY >= y && bufferAbsoluteY < i) { y += wrappedLines.Count - 1; continue; } // Copy buffer data to new locations int destLineIndex = 0; int destCol = GetWrappedLineTrimmedLength(Buffer.Lines, destLineIndex, oldCols); int srcLineIndex = 1; int srcCol = 0; while (srcLineIndex < wrappedLines.Count) { int srcTrimmedTineLength = GetWrappedLineTrimmedLength(wrappedLines, srcLineIndex, oldCols); int srcRemainingCells = srcTrimmedTineLength - srcCol; int destRemainingCells = newCols - destCol; int cellsToCopy = Math.Min(srcRemainingCells, destRemainingCells); wrappedLines [destLineIndex].CopyCellsFrom(wrappedLines [srcLineIndex], srcCol, destCol, cellsToCopy); destCol += cellsToCopy; if (destCol == newCols) { destLineIndex++; destCol = 0; } srcCol += cellsToCopy; if (srcCol == srcTrimmedTineLength) { srcLineIndex++; srcCol = 0; } // Make sure the last cell isn't wide, if it is copy it to the current dest if (destCol == 0 && destLineIndex != 0) { if (wrappedLines [destLineIndex - 1].GetWidth(newCols - 1) == 2) { wrappedLines [destLineIndex].CopyCellsFrom(wrappedLines [destLineIndex - 1], newCols - 1, destCol++, 1); // Null out the end of the last row wrappedLines [destLineIndex - 1].ReplaceCells(newCols - 1, 1, nullCharacter); } } } // Clear out remaining cells or fragments could remain; wrappedLines [destLineIndex].ReplaceCells(destCol, newCols, nullCharacter); // Work backwards and remove any rows at the end that only contain null cells int countToRemove = 0; for (int ix = wrappedLines.Count - 1; ix > 0; ix--) { if (ix > destLineIndex || wrappedLines [ix].GetTrimmedLength() == 0) { countToRemove++; } else { break; } } if (countToRemove > 0) { toRemove.Add(y + wrappedLines.Count - countToRemove); // index toRemove.Add(countToRemove); } y += wrappedLines.Count - 1; } return(toRemove.ToArray()); }