示例#1
0
		public DrawableLine(IDocument document, LineSegment line, Font monospacedFont, Font boldMonospacedFont)
		{
			this.monospacedFont = monospacedFont;
			this.boldMonospacedFont = boldMonospacedFont;
			if (line.Words != null) {
				foreach (TextWord word in line.Words) {
					if (word.Type == TextWordType.Space) {
						words.Add(SimpleTextWord.Space);
					} else if (word.Type == TextWordType.Tab) {
						words.Add(SimpleTextWord.Tab);
					} else {
						words.Add(new SimpleTextWord(TextWordType.Word, word.Word, word.Bold, word.Color));
					}
				}
			} else {
				words.Add(new SimpleTextWord(TextWordType.Word, document.GetText(line), false, Color.Black));
			}
		}
示例#2
0
		/// <summary>
		/// Get the object, which was inserted under the keyword (line, at offset, with length length),
		/// returns null, if no such keyword was inserted.
		/// </summary>
		public object this[IDocument document, LineSegment line, int offset, int length] {
			get {
				if(length == 0) {
					return null;
				}
				Node next = root;
				
				int wordOffset = line.Offset + offset;
				if (casesensitive) {
					for (int i = 0; i < length; ++i) {
						int index = ((int)document.GetCharAt(wordOffset + i)) % 256;
						next = next[index];
						
						if (next == null) {
							return null;
						}
						
						if (next.color != null && TextUtility.RegionMatches(document, wordOffset, length, next.word)) {
							return next.color;
						}
					}
				} else {
					for (int i = 0; i < length; ++i) {
						int index = ((int)Char.ToUpper(document.GetCharAt(wordOffset + i))) % 256;
						
						next = next[index];
						
						if (next == null) {
							return null;
						}
						
						if (next.color != null && TextUtility.RegionMatches(document, casesensitive, wordOffset, length, next.word)) {
							return next.color;
						}
					}
				}
				return null;
			}
		}
		/// <summary>
		/// Replaces the text in a line.
		/// If only whitespace at the beginning and end of the line was changed, this method
		/// only adjusts the whitespace and doesn't replace the other text.
		/// </summary>
		public static void SmartReplaceLine(IDocument document, LineSegment line, string newLineText)
		{
			if (document == null)
				throw new ArgumentNullException("document");
			if (line == null)
				throw new ArgumentNullException("line");
			if (newLineText == null)
				throw new ArgumentNullException("newLineText");
			string newLineTextTrim = newLineText.Trim(whitespaceChars);
			string oldLineText = document.GetText(line);
			if (oldLineText == newLineText)
				return;
			int pos = oldLineText.IndexOf(newLineTextTrim);
			if (newLineTextTrim.Length > 0 && pos >= 0) {
				document.UndoStack.StartUndoGroup();
				try {
					// find whitespace at beginning
					int startWhitespaceLength = 0;
					while (startWhitespaceLength < newLineText.Length) {
						char c = newLineText[startWhitespaceLength];
						if (c != ' ' && c != '\t')
							break;
						startWhitespaceLength++;
					}
					// find whitespace at end
					int endWhitespaceLength = newLineText.Length - newLineTextTrim.Length - startWhitespaceLength;
					
					// replace whitespace sections
					int lineOffset = line.Offset;
					document.Replace(lineOffset + pos + newLineTextTrim.Length, line.Length - pos - newLineTextTrim.Length, newLineText.Substring(newLineText.Length - endWhitespaceLength));
					document.Replace(lineOffset, pos, newLineText.Substring(0, startWhitespaceLength));
				} finally {
					document.UndoStack.EndUndoGroup();
				}
			} else {
				document.Replace(line.Offset, line.Length, newLineText);
			}
		}
		public virtual void MarkTokens(IDocument document)
		{
			if (Rules.Count == 0) {
				return;
			}
			
			int lineNumber = 0;
			
			while (lineNumber < document.TotalNumberOfLines) {
				LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null);
				if (lineNumber >= document.LineSegmentCollection.Count) { // may be, if the last line ends with a delimiter
					break;                                                // then the last line is not in the collection :)
				}
				
				currentSpanStack = ((previousLine != null && previousLine.HighlightSpanStack != null) ? previousLine.HighlightSpanStack.Clone() : null);
				
				if (currentSpanStack != null) {
					while (!currentSpanStack.IsEmpty && currentSpanStack.Peek().StopEOL)
					{
						currentSpanStack.Pop();
					}
					if (currentSpanStack.IsEmpty) currentSpanStack = null;
				}
				
				currentLine = (LineSegment)document.LineSegmentCollection[lineNumber];
				
				if (currentLine.Length == -1) { // happens when buffer is empty !
					return;
				}
				
				currentLineNumber = lineNumber;
				List<TextWord> words = ParseLine(document);
				// Alex: clear old words
				if (currentLine.Words != null) {
					currentLine.Words.Clear();
				}
				currentLine.Words = words;
				currentLine.HighlightSpanStack = (currentSpanStack==null || currentSpanStack.IsEmpty) ? null : currentSpanStack;
				
				++lineNumber;
			}
			document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
			document.CommitUpdate();
			currentLine = null;
		}
		public HighlightColor GetColor(IDocument document, LineSegment currentSegment, int currentOffset, int currentLength)
		{
			return GetColor(defaultRuleSet, document, currentSegment, currentOffset, currentLength);
		}
		protected virtual HighlightColor GetColor(HighlightRuleSet ruleSet, IDocument document, LineSegment currentSegment, int currentOffset, int currentLength)
		{
			if (ruleSet != null) {
				if (ruleSet.Reference != null) {
					return ruleSet.Highlighter.GetColor(document, currentSegment, currentOffset, currentLength);
				} else {
					return (HighlightColor)ruleSet.KeyWords[document,  currentSegment, currentOffset, currentLength];
				}
			}
			return null;
		}
示例#7
0
		/// <remarks>
		/// Returns true, if the line lineNumber is empty or filled with whitespaces.
		/// </remarks>
		public static bool IsEmptyLine(IDocument document, LineSegment line)
		{
			for (int i = line.Offset; i < line.Offset + line.Length; ++i) {
				char ch = document.GetCharAt(i);
				if (!Char.IsWhiteSpace(ch)) {
					return false;
				}
			}
			return true;
		}
示例#8
0
		// TAB
		public TextWord(IDocument document, LineSegment line, int offset, int length, HighlightColor color, bool hasDefaultColor)
		{
			Debug.Assert(document != null);
			Debug.Assert(line != null);
			Debug.Assert(color != null);
			
			this.document = document;
			this.line  = line;
			this.offset = offset;
			this.length = length;
			this.color = color;
			this.hasDefaultColor = hasDefaultColor;
		}
示例#9
0
		/// <summary>
		/// Is called after another line's content is appended to this line because the newline in between
		/// was deleted.
		/// The DefaultLineManager will call Deleted() on the deletedLine after the MergedWith call.
		/// 
		/// firstLineLength: the length of the line before the merge.
		/// </summary>
		internal void MergedWith(LineSegment deletedLine, int firstLineLength)
		{
			//Console.WriteLine("MergedWith");
			
			if (deletedLine.anchors != null) {
				foreach (TextAnchor a in deletedLine.anchors) {
					a.Line = this;
					AddAnchor(a);
					a.ColumnNumber += firstLineLength;
				}
				deletedLine.anchors = null;
			}
		}
示例#10
0
		public void AddRemovedLine(LineSegment line)
		{
			if (removedLines == null)
				removedLines = new List<LineSegment>();
			removedLines.Add(line);
		}
		protected virtual void OnParsedLine(IDocument document, LineSegment currentLine, List<TextWord> words)
		{
		}
		/// <summary>
		/// returns true, if the get the string s2 at index matches the expression expr
		/// </summary>
		static bool MatchExpr(LineSegment lineSegment, char[] expr, int index, IDocument document, bool ignoreCase)
		{
			for (int i = 0, j = 0; i < expr.Length; ++i, ++j) {
				switch (expr[i]) {
					case '@': // "special" meaning
						++i;
						if (i == expr.Length)
							throw new HighlightingDefinitionInvalidException("Unexpected end of @ sequence, use @@ to look for a single @.");
						switch (expr[i]) {
							case 'C': // match whitespace or punctuation
								if (index + j == lineSegment.Offset || index + j >= lineSegment.Offset + lineSegment.Length) {
									// nothing (EOL or SOL)
								} else {
									char ch = document.GetCharAt(lineSegment.Offset + index + j);
									if (!Char.IsWhiteSpace(ch) && !Char.IsPunctuation(ch)) {
										return false;
									}
								}
								break;
							case '!': // don't match the following expression
								{
									StringBuilder whatmatch = new StringBuilder();
									++i;
									while (i < expr.Length && expr[i] != '@') {
										whatmatch.Append(expr[i++]);
									}
									if (lineSegment.Offset + index + j + whatmatch.Length < document.TextLength) {
										int k = 0;
										for (; k < whatmatch.Length; ++k) {
											char docChar = ignoreCase ? Char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index + j + k)) : document.GetCharAt(lineSegment.Offset + index + j + k);
											char spanChar = ignoreCase ? Char.ToUpperInvariant(whatmatch[k]) : whatmatch[k];
											if (docChar != spanChar) {
												break;
											}
										}
										if (k >= whatmatch.Length) {
											return false;
										}
									}
//									--j;
									break;
								}
							case '-': // don't match the  expression before
								{
									StringBuilder whatmatch = new StringBuilder();
									++i;
									while (i < expr.Length && expr[i] != '@') {
										whatmatch.Append(expr[i++]);
									}
									if (index - whatmatch.Length >= 0) {
										int k = 0;
										for (; k < whatmatch.Length; ++k) {
											char docChar = ignoreCase ? Char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index - whatmatch.Length + k)) : document.GetCharAt(lineSegment.Offset + index - whatmatch.Length + k);
											char spanChar = ignoreCase ? Char.ToUpperInvariant(whatmatch[k]) : whatmatch[k];
											if (docChar != spanChar)
												break;
										}
										if (k >= whatmatch.Length) {
											return false;
										}
									}
//									--j;
									break;
								}
							case '@': // matches @
								if (index + j >= lineSegment.Length || '@' != document.GetCharAt(lineSegment.Offset + index + j)) {
									return false;
								}
								break;
						}
						break;
					default:
						{
							if (index + j >= lineSegment.Length) {
								return false;
							}
							char docChar = ignoreCase ? Char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index + j)) : document.GetCharAt(lineSegment.Offset + index + j);
							char spanChar = ignoreCase ? Char.ToUpperInvariant(expr[i]) : expr[i];
							if (docChar != spanChar) {
								return false;
							}
							break;
						}
				}
			}
			return true;
		}
示例#13
0
		public LineEventArgs(IDocument document, LineSegment lineSegment)
		{
			this.document = document;
			this.lineSegment = lineSegment;
		}
示例#14
0
		public LineLengthChangeEventArgs(IDocument document, LineSegment lineSegment, int moved)
			: base(document, lineSegment)
		{
			this.lengthDelta = moved;
		}
示例#15
0
		internal TextAnchor(LineSegment lineSegment, int columnNumber)
		{
			this.lineSegment = lineSegment;
			this.columnNumber = columnNumber;
		}
示例#16
0
		internal void Delete(ref DeferredEventList deferredEventList)
		{
			// we cannot fire an event here because this method is called while the LineManager adjusts the
			// lineCollection, so an event handler could see inconsistent state
			lineSegment = null;
			deferredEventList.AddDeletedAnchor(this);
		}
示例#17
0
		/// <summary>
		/// Is called after a newline was inserted into this line, splitting it into this and followingLine.
		/// </summary>
		internal void SplitTo(LineSegment followingLine)
		{
			//Console.WriteLine("SplitTo");
			
			if (anchors != null) {
				List<TextAnchor> movedAnchors = null;
				foreach (TextAnchor a in anchors) {
					if (a.MovementType == AnchorMovementType.BeforeInsertion
					    ? a.ColumnNumber > this.Length
					    : a.ColumnNumber >= this.Length)
					{
						a.Line = followingLine;
						followingLine.AddAnchor(a);
						a.ColumnNumber -= this.Length;
						
						if (movedAnchors == null)
							movedAnchors = new List<TextAnchor>();
						movedAnchors.Add(a);
					}
				}
				if (movedAnchors != null) {
					foreach (TextAnchor a in movedAnchors) {
						anchors.Remove(a);
					}
				}
			}
		}
		bool MarkTokensInLine(IDocument document, int lineNumber, ref bool spanChanged)
		{
			currentLineNumber = lineNumber;
			bool processNextLine = false;
			LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null);
			
			currentSpanStack = ((previousLine != null && previousLine.HighlightSpanStack != null) ? previousLine.HighlightSpanStack.Clone() : null);
			if (currentSpanStack != null) {
				while (!currentSpanStack.IsEmpty && currentSpanStack.Peek().StopEOL) {
					currentSpanStack.Pop();
				}
				if (currentSpanStack.IsEmpty) {
					currentSpanStack = null;
				}
			}
			
			currentLine = (LineSegment)document.LineSegmentCollection[lineNumber];
			
			if (currentLine.Length == -1) { // happens when buffer is empty !
				return false;
			}
			
			List<TextWord> words = ParseLine(document);
			
			if (currentSpanStack != null && currentSpanStack.IsEmpty) {
				currentSpanStack = null;
			}
			
			// Check if the span state has changed, if so we must re-render the next line
			// This check may seem utterly complicated but I didn't want to introduce any function calls
			// or allocations here for perf reasons.
			if(currentLine.HighlightSpanStack != currentSpanStack) {
				if (currentLine.HighlightSpanStack == null) {
					processNextLine = false;
					foreach (Span sp in currentSpanStack) {
						if (!sp.StopEOL) {
							spanChanged = true;
							processNextLine = true;
							break;
						}
					}
				} else if (currentSpanStack == null) {
					processNextLine = false;
					foreach (Span sp in currentLine.HighlightSpanStack) {
						if (!sp.StopEOL) {
							spanChanged = true;
							processNextLine = true;
							break;
						}
					}
				} else {
					SpanStack.Enumerator e1 = currentSpanStack.GetEnumerator();
					SpanStack.Enumerator e2 = currentLine.HighlightSpanStack.GetEnumerator();
					bool done = false;
					while (!done) {
						bool blockSpanIn1 = false;
						while (e1.MoveNext()) {
							if (!((Span)e1.Current).StopEOL) {
								blockSpanIn1 = true;
								break;
							}
						}
						bool blockSpanIn2 = false;
						while (e2.MoveNext()) {
							if (!((Span)e2.Current).StopEOL) {
								blockSpanIn2 = true;
								break;
							}
						}
						if (blockSpanIn1 || blockSpanIn2) {
							if (blockSpanIn1 && blockSpanIn2) {
								if (e1.Current != e2.Current) {
									done = true;
									processNextLine = true;
									spanChanged = true;
								}
							} else {
								spanChanged = true;
								done = true;
								processNextLine = true;
							}
						} else {
							done = true;
							processNextLine = false;
						}
					}
				}
			} else {
				processNextLine = false;
			}
			
			//// Alex: remove old words
			if (currentLine.Words!=null) currentLine.Words.Clear();
			currentLine.Words = words;
			currentLine.HighlightSpanStack = (currentSpanStack != null && !currentSpanStack.IsEmpty) ? currentSpanStack : null;
			
			return processNextLine;
		}
示例#19
0
		int GetLogicalColumnInternal(Graphics g, LineSegment line, int start, int end, ref int drawingPos, int targetVisualPosX)
		{
			if (start == end)
				return end;
			Debug.Assert(start < end);
			Debug.Assert(drawingPos < targetVisualPosX);
			
			int tabIndent = Document.TextEditorProperties.TabIndent;
			
			/*float spaceWidth = SpaceWidth;
			float drawingPos = 0;
			LineSegment currentLine = Document.GetLineSegment(logicalLine);
			List<TextWord> words = currentLine.Words;
			if (words == null) return 0;
			int wordCount = words.Count;
			int wordOffset = 0;
			FontContainer fontContainer = TextEditorProperties.FontContainer;
			 */
			FontContainer fontContainer = TextEditorProperties.FontContainer;
			
			List<TextWord> words = line.Words;
			if (words == null) return 0;
			int wordOffset = 0;
			for (int i = 0; i < words.Count; i++) {
				TextWord word = words[i];
				if (wordOffset >= end) {
					return wordOffset;
				}
				if (wordOffset + word.Length >= start) {
					int newDrawingPos;
					switch (word.Type) {
						case TextWordType.Space:
							newDrawingPos = drawingPos + spaceWidth;
							if (newDrawingPos >= targetVisualPosX)
								return IsNearerToAThanB(targetVisualPosX, drawingPos, newDrawingPos) ? wordOffset : wordOffset+1;
							break;
						case TextWordType.Tab:
							// go to next tab position
							drawingPos = (int)((drawingPos + MinTabWidth) / tabIndent / WideSpaceWidth) * tabIndent * WideSpaceWidth;
							newDrawingPos = drawingPos + tabIndent * WideSpaceWidth;
							if (newDrawingPos >= targetVisualPosX)
								return IsNearerToAThanB(targetVisualPosX, drawingPos, newDrawingPos) ? wordOffset : wordOffset+1;
							break;
						case TextWordType.Word:
							int wordStart = Math.Max(wordOffset, start);
							int wordLength = Math.Min(wordOffset + word.Length, end) - wordStart;
							string text = Document.GetText(line.Offset + wordStart, wordLength);
							Font font = word.GetFont(fontContainer) ?? fontContainer.RegularFont;
							newDrawingPos = drawingPos + MeasureStringWidth(g, text, font);
							if (newDrawingPos >= targetVisualPosX) {
								for (int j = 0; j < text.Length; j++) {
									newDrawingPos = drawingPos + MeasureStringWidth(g, text[j].ToString(), font);
									if (newDrawingPos >= targetVisualPosX) {
										if (IsNearerToAThanB(targetVisualPosX, drawingPos, newDrawingPos))
											return wordStart + j;
										else
											return wordStart + j + 1;
									}
									drawingPos = newDrawingPos;
								}
								return wordStart + text.Length;
							}
							break;
						default:
							throw new NotSupportedException();
					}
					drawingPos = newDrawingPos;
				}
				wordOffset += word.Length;
			}
			return wordOffset;
		}
		public virtual void MarkTokens(IDocument document, List<LineSegment> inputLines)
		{
			if (Rules.Count == 0) {
				return;
			}
			
			Dictionary<LineSegment, bool> processedLines = new Dictionary<LineSegment, bool>();
			
			bool spanChanged = false;
			int documentLineSegmentCount = document.LineSegmentCollection.Count;
			
			foreach (LineSegment lineToProcess in inputLines) {
				if (!processedLines.ContainsKey(lineToProcess)) {
					int lineNumber = lineToProcess.LineNumber;
					bool processNextLine = true;
					
					if (lineNumber != -1) {
						while (processNextLine && lineNumber < documentLineSegmentCount) {
							processNextLine = MarkTokensInLine(document, lineNumber, ref spanChanged);
							processedLines[currentLine] = true;
							++lineNumber;
						}
					}
				}
			}
			
			if (spanChanged || inputLines.Count > 20) {
				// if the span was changed (more than inputLines lines had to be reevaluated)
				// or if there are many lines in inputLines, it's faster to update the whole
				// text area instead of many small segments
				document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
			} else {
//				document.Caret.ValidateCaretPos();
//				document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, document.GetLineNumberForOffset(document.Caret.Offset)));
//
				foreach (LineSegment lineToProcess in inputLines) {
					document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineToProcess.LineNumber));
				}
				
			}
			document.CommitUpdate();
			currentLine = null;
		}
示例#21
0
		void SetSegmentLength(LineSegment segment, int newTotalLength)
		{
			int delta = newTotalLength - segment.TotalLength;
			if (delta != 0) {
				lineCollection.SetSegmentLength(segment, newTotalLength);
				OnLineLengthChanged(new LineLengthChangeEventArgs(document, segment, delta));
			}
		}
		/// <summary>
		/// get the string, which matches the regular expression expr,
		/// in string s2 at index
		/// </summary>
		static string GetRegString(LineSegment lineSegment, char[] expr, int index, IDocument document)
		{
			int j = 0;
			StringBuilder regexpr = new StringBuilder();
			
			for (int i = 0; i < expr.Length; ++i, ++j) {
				if (index + j >= lineSegment.Length)
					break;
				
				switch (expr[i]) {
					case '@': // "special" meaning
						++i;
						if (i == expr.Length)
							throw new HighlightingDefinitionInvalidException("Unexpected end of @ sequence, use @@ to look for a single @.");
						switch (expr[i]) {
							case '!': // don't match the following expression
								StringBuilder whatmatch = new StringBuilder();
								++i;
								while (i < expr.Length && expr[i] != '@') {
									whatmatch.Append(expr[i++]);
								}
								break;
							case '@': // matches @
								regexpr.Append(document.GetCharAt(lineSegment.Offset + index + j));
								break;
						}
						break;
					default:
						if (expr[i] != document.GetCharAt(lineSegment.Offset + index + j)) {
							return regexpr.ToString();
						}
						regexpr.Append(document.GetCharAt(lineSegment.Offset + index + j));
						break;
				}
			}
			return regexpr.ToString();
		}
示例#23
0
		// btw. I hate source code duplication ... but this time I don't care !!!!
		float MeasurePrintingHeight(Graphics g, LineSegment line, float maxWidth)
		{
			float xPos = 0;
			float yPos = 0;
			float fontHeight = Font.GetHeight(g);
//			bool  gotNonWhitespace = false;
			curTabIndent = 0;
			FontContainer fontContainer = TextEditorProperties.FontContainer;
			foreach (TextWord word in line.Words) {
				switch (word.Type) {
					case TextWordType.Space:
						Advance(ref xPos, ref yPos, maxWidth, primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight);
//						if (!gotNonWhitespace) {
//							curTabIndent = xPos;
//						}
						break;
					case TextWordType.Tab:
						Advance(ref xPos, ref yPos, maxWidth, TabIndent * primaryTextArea.TextArea.TextView.WideSpaceWidth, fontHeight);
//						if (!gotNonWhitespace) {
//							curTabIndent = xPos;
//						}
						break;
					case TextWordType.Word:
//						if (!gotNonWhitespace) {
//							gotNonWhitespace = true;
//							curTabIndent    += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' ');
//						}
						SizeF drawingSize = g.MeasureString(word.Word, word.GetFont(fontContainer), new SizeF(maxWidth, fontHeight * 100), printingStringFormat);
						Advance(ref xPos, ref yPos, maxWidth, drawingSize.Width, fontHeight);
						break;
				}
			}
			return yPos + fontHeight;
		}
示例#24
0
		void DrawLine(Graphics g, LineSegment line, float yPos, RectangleF margin)
		{
			float xPos = 0;
			float fontHeight = Font.GetHeight(g);
//			bool  gotNonWhitespace = false;
			curTabIndent = 0 ;
			
			FontContainer fontContainer = TextEditorProperties.FontContainer;
			foreach (TextWord word in line.Words) {
				switch (word.Type) {
					case TextWordType.Space:
						Advance(ref xPos, ref yPos, margin.Width, primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight);
//						if (!gotNonWhitespace) {
//							curTabIndent = xPos;
//						}
						break;
					case TextWordType.Tab:
						Advance(ref xPos, ref yPos, margin.Width, TabIndent * primaryTextArea.TextArea.TextView.WideSpaceWidth, fontHeight);
//						if (!gotNonWhitespace) {
//							curTabIndent = xPos;
//						}
						break;
					case TextWordType.Word:
//						if (!gotNonWhitespace) {
//							gotNonWhitespace = true;
//							curTabIndent    += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' ');
//						}
						g.DrawString(word.Word, word.GetFont(fontContainer), BrushRegistry.GetBrush(word.Color), xPos + margin.X, yPos);
						SizeF drawingSize = g.MeasureString(word.Word, word.GetFont(fontContainer), new SizeF(margin.Width, fontHeight * 100), printingStringFormat);
						Advance(ref xPos, ref yPos, margin.Width, drawingSize.Width, fontHeight);
						break;
				}
			}
		}
示例#25
0
		public int GetVisualColumnFast(LineSegment line, int logicalColumn)
		{
			int lineOffset = line.Offset;
			int tabIndent = Document.TextEditorProperties.TabIndent;
			int guessedColumn = 0;
			for (int i = 0; i < logicalColumn; ++i) {
				char ch;
				if (i >= line.Length) {
					ch = ' ';
				} else {
					ch = Document.GetCharAt(lineOffset + i);
				}
				switch (ch) {
					case '\t':
						guessedColumn += tabIndent;
						guessedColumn = (guessedColumn / tabIndent) * tabIndent;
						break;
					default:
						++guessedColumn;
						break;
				}
			}
			return guessedColumn;
		}