/// <summary> /// Calculates location in the virtual space of the character at specified index. /// </summary> /// <returns>The location of the character at specified index.</returns> /// <exception cref="ArgumentOutOfRangeException">Specified index was out of range.</exception> public override Point GetVirPosFromIndex(IGraphics g, int lineIndex, int columnIndex) { if (lineIndex < 0) { throw new ArgumentOutOfRangeException("lineIndex(" + lineIndex + ")"); } if (columnIndex < 0) { throw new ArgumentOutOfRangeException("columnIndex(" + columnIndex + ")"); } Point pos = new Point(); // set value for when the columnIndex is 0 pos.X = 0; pos.Y = (lineIndex * LineSpacing) + (LinePadding >> 1); // if the location is not the head of the line, calculate x-coord. if (0 < columnIndex) { // get partial content of the line which exists before the caret int lineBegin, lineEnd; LineLogic.GetLineRangeWithEol(Document.InternalBuffer, PLHI, lineIndex, out lineBegin, out lineEnd); string leftPart = Document.GetTextInRange(lineBegin, lineBegin + columnIndex); // measure the characters pos.X = MeasureTokenEndX(g, leftPart, pos.X); } return(pos); }
static bool ShouldUnindentWithBackspace(IUserInterface ui) { Document doc = ui.Document; int caret = ui.CaretIndex; // If the caret is at beginning of a line, or the character before to be removed is not // a space, should not. if (caret == 0 //NO_NEED//|| LineLogic.IsEolChar(doc[caret-1]) || doc[caret - 1] != ' ') { return(false); } // Is the caret is at end of a line or at non-whitespace character? if (caret == doc.Length || LineLogic.IsEolChar(doc[caret]) || " \t".IndexOf(doc[caret]) < 0) { // And isn't there a non-whitespace character before the caret? int lineBegin = doc.GetLineHeadIndexFromCharIndex(caret); for (int i = lineBegin; i < caret; i++) { if (" \t".IndexOf(doc[i]) < 0) { return(false); // There is; do not unindent } } return(true); } return(false); }
/// <summary> /// Calculates screen line/column index from char-index. /// </summary> /// <exception cref="ArgumentOutOfRangeException">Specified index was out of range.</exception> public override void GetLineColumnIndexFromCharIndex(int charIndex, out int lineIndex, out int columnIndex) { if (charIndex < 0 || Document.Length < charIndex) { throw new ArgumentOutOfRangeException("charIndex", "Invalid index was given (charIndex:" + charIndex + ", document.Length:" + Document.Length + ")."); } LineLogic.GetLineColumnIndexFromCharIndex( Document.InternalBuffer, PLHI, charIndex, out lineIndex, out columnIndex ); }
/// <summary> /// Gets the index of the first char in the screen line /// which contains the specified char-index. /// </summary> /// <exception cref="ArgumentOutOfRangeException">Specified index was out of range.</exception> public override int GetLineHeadIndexFromCharIndex(int charIndex) { if (charIndex < 0 || Document.Length < charIndex) { throw new ArgumentOutOfRangeException("charIndex", "Invalid index was given (charIndex:" + charIndex + ", document.Length:" + Document.Length + ")."); } return(LineLogic.GetLineHeadIndexFromCharIndex( Document.InternalBuffer, PLHI, charIndex )); }
/// <summary> /// Calculates location in the virtual space of the character at specified index. /// </summary> /// <returns>The location of the character at specified index.</returns> /// <exception cref="ArgumentOutOfRangeException">Specified index was out of range.</exception> public override Point GetVirPosFromIndex(IGraphics g, int index) { int line, column; LineLogic.GetLineColumnIndexFromCharIndex( Document.InternalBuffer, PLHI, index, out line, out column ); return(GetVirPosFromIndex(g, line, column)); }
/// <summary> /// Calculates char-index from screen line/column index. /// </summary> /// <exception cref="ArgumentOutOfRangeException">Specified index was out of range.</exception> public override int GetCharIndexFromLineColumnIndex(int lineIndex, int columnIndex) { if (lineIndex < 0 || LineCount < lineIndex) { throw new ArgumentOutOfRangeException("lineIndex", "Invalid index was given (lineIndex:" + lineIndex + ", LineCount:" + LineCount + ")."); } if (columnIndex < 0) { throw new ArgumentOutOfRangeException("columnIndex", "Invalid index was given (columnIndex:" + columnIndex + ")."); } return(LineLogic.GetCharIndexFromLineColumnIndex( Document.InternalBuffer, PLHI, lineIndex, columnIndex )); }
/// <summary> /// Gets char-index of the char at the point specified by location in the virtual space. /// </summary> /// <returns>The index of the character at specified location.</returns> public override int GetIndexFromVirPos(IGraphics g, Point pt) { int lineIndex, columnIndex; int drawableTextLen; // calc line index lineIndex = (pt.Y / LineSpacing); if (lineIndex < 0) { lineIndex = 0; } else if (PLHI.Count <= lineIndex && Document.LineCount != 0) { // the point indicates beyond the final line. // treat as if the final line was specified lineIndex = PLHI.Count - 1; } // calc column index columnIndex = 0; if (0 < pt.X) { int begin, end; string line; bool isWrapLine = false; // get content of the line LineLogic.GetLineRange(Document.InternalBuffer, PLHI, lineIndex, out begin, out end); line = Document.GetTextInRange(begin, end); if (end + 1 < Document.Length && !LineLogic.IsEolChar(Document[end])) { isWrapLine = true; } // calc maximum length of chars in line int rightLimitX = pt.X; int leftPartWidth = MeasureTokenEndX(g, line, 0, rightLimitX, out drawableTextLen); columnIndex = drawableTextLen; // if the location is nearer to the NEXT of that char, // we should return the index of next one. if (drawableTextLen < line.Length) { string nextChar = line[drawableTextLen].ToString(); int nextCharWidth = MeasureTokenEndX(g, nextChar, leftPartWidth) - leftPartWidth; if (leftPartWidth + nextCharWidth / 2 < pt.X) // == "x of middle of next char" < "x of click in virtual text area" { columnIndex = drawableTextLen + 1; } } // if the whole line can be drawn and is a wrapped line, // decrease column to avoid indicating invalid position else if (isWrapLine) { columnIndex--; } } return(LineLogic.GetCharIndexFromLineColumnIndex(Document.InternalBuffer, PLHI, lineIndex, columnIndex)); }
internal override void HandleContentChanged(object sender, ContentChangedEventArgs e) { // [*1] if replacement breaks or creates // a combining character sequence at left boundary of the range, // at least one grapheme cluster left must be redrawn. // // One case of that e.OldText has combining char at first: // aa^aa --(replace [2, 4) to "AA")--> aaAAa // // One case of that e.NewText has combining char at first: // aaaa --(replace [2, 3) to "^A")--> aa^Aa Point invalidStartPos; int invalidStartIndex; Rectangle invalidRect1 = new Rectangle(); Rectangle invalidRect2 = new Rectangle(); using (IGraphics g = _UI.GetIGraphics()) { // calculate where to start invalidation invalidStartIndex = e.Index; if (Document.IsCombiningCharacter(e.OldText, 0) || Document.IsCombiningCharacter(e.NewText, 0)) { // [*1] invalidStartIndex = GetLineHeadIndexFromCharIndex( invalidStartIndex ); } // get graphical position of the place invalidStartPos = GetVirPosFromIndex(g, invalidStartIndex); VirtualToScreen(ref invalidStartPos); // update indicator graphic on horizontal ruler UpdateHRuler(g); // invalidate the part at right of the old selection invalidRect1.X = invalidStartPos.X; invalidRect1.Width = VisibleSize.Width - invalidRect1.X; invalidRect1.Y = invalidStartPos.Y - (LinePadding >> 1); invalidRect1.Height = LineSpacing; // invalidate all lines below caret // if old text or new text contains multiple lines if (LineLogic.IsMultiLine(e.OldText) || LineLogic.IsMultiLine(e.NewText)) { //NO_NEED//invalidRect2.X = 0; invalidRect2.Y = invalidRect1.Bottom; invalidRect2.Width = VisibleSize.Width; invalidRect2.Height = VisibleSize.Height - invalidRect2.Top; } // invalidate the range Invalidate(invalidRect1); if (0 < invalidRect2.Height) { Invalidate(invalidRect2); } // update left side of text area DrawDirtBar(g, invalidRect1.Top, Document.GetLineIndexFromCharIndex(e.Index)); UpdateLineNumberWidth(g); //DO_NOT//base.HandleContentChanged( sender, e ); } }
/// <summary> /// Pastes clipboard content at where the caret is at. /// </summary> public static void Paste(IUserInterface ui) { Document doc = ui.Document; string clipboardText; int begin, end; int insertIndex; TextDataType dataType; // do nothing if the document is read-only if (doc.IsReadOnly) { Plat.Inst.MessageBeep(); return; } // get clipboard content clipboardText = Plat.Inst.GetClipboardText(out dataType); if (clipboardText == null) { return; } // limit the content in a single line if it's in single line mode if (ui.IsSingleLineMode) { int eolIndex = clipboardText.IndexOfAny(new char[] { '\r', '\n' }); if (0 <= eolIndex) { clipboardText = clipboardText.Remove(eolIndex, clipboardText.Length - eolIndex); } } // begin grouping edit action doc.BeginUndo(); // delete currently selected text before insertion doc.GetSelection(out begin, out end); if (doc.RectSelectRanges != null) { //--- case of rectangle selection --- // delete selected text doc.DeleteRectSelectText(); ui.View.Invalidate(); } else if (begin != end) { //--- case of normal selection --- // delete selected text doc.Replace(""); } // paste according type of the text data if (dataType == TextDataType.Rectangle) { //--- rectangle text data --- Point insertPos; int rowBegin; int rowEnd; string rowText; string padding; // Insert every row at same column position insertPos = ui.View.GetVirPosFromIndex(doc.CaretIndex); rowBegin = 0; rowEnd = LineLogic.NextLineHead(clipboardText, rowBegin); while (0 <= rowEnd) { // get this row content if (clipboardText[rowEnd - 1] == '\n') { if (clipboardText[rowEnd - 2] == '\r') { rowText = clipboardText.Substring(rowBegin, rowEnd - rowBegin - 2); } else { rowText = clipboardText.Substring(rowBegin, rowEnd - rowBegin - 1); } } else if (clipboardText[rowEnd - 1] == '\r') { rowText = clipboardText.Substring(rowBegin, rowEnd - rowBegin - 1); } else { rowText = clipboardText.Substring(rowBegin, rowEnd - rowBegin); } // pad tabs if needed padding = UiImpl.GetNeededPaddingChars(ui, insertPos, false); // insert this row insertIndex = ui.View.GetIndexFromVirPos(insertPos); doc.Replace(padding.ToString() + rowText, insertIndex, insertIndex); // goto next line insertPos.Y += ui.LineSpacing; rowBegin = rowEnd; rowEnd = LineLogic.NextLineHead(clipboardText, rowBegin); } } else { //--- normal or line text data --- // calculate insertion index insertIndex = begin; if (dataType == TextDataType.Line) { // make the insertion point to caret line head if it is line data type insertIndex = doc.GetLineHeadIndexFromCharIndex(begin); } // insert doc.Replace(clipboardText, insertIndex, insertIndex); } // end grouping UNDO action doc.EndUndo(); // move caret if (ui.UsesStickyCaret == false) { ui.View.SetDesiredColumn(); } ui.ScrollToCaret(); }