⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.java

📁 Java写的文本编辑器
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			else			{				if(style)					gfx.setFont(styles[id].getFont());				else					gfx.setFont(defaultFont);				if(color)				{					tokenBackground = styles[id].getBackgroundColor();					tokenForeground = styles[id].getForegroundColor();				}				else					tokenForeground = foreground;			}			int len = tokens.length;			x = renderer.drawChars(text,off,len,gfx,x,y,expander,				tokenForeground,tokenBackground,background);			off += len;			tokens = tokens.next;		}		return (int)x;	}	/**	 * Returns the syntax tokens for the specified line.	 * @param lineIndex The line number	 * @since jEdit 3.1pre1	 */	public LineInfo markTokens(int lineIndex)	{		LineInfo info = lineInfo[lineIndex];		/* If cached tokens are valid, return 'em */		if(info.tokensValid)			return info;		//long _start = System.currentTimeMillis();		/*		 * Else, go up to 100 lines back, looking for a line with		 * cached tokens. Tokenize from that line to this line.		 */		int start = Math.max(0,lineIndex - 100) - 1;		int end = Math.max(0,lineIndex - 100);		for(int i = lineIndex - 1; i > end; i--)		{			if(lineInfo[i].tokensValid)			{				start = i;				break;			}		}		LineInfo prev;		if(start == -1)			prev = null;		else			prev = lineInfo[start];		//System.err.println("i=" + lineIndex + ",start=" + start);		Element map = getDefaultRootElement();		for(int i = start + 1; i <= lineIndex; i++)		{			info = lineInfo[i];			if(info.tokensValid)			{				prev = info;				continue;			}			Element lineElement = map.getElement(i);			int lineStart = lineElement.getStartOffset();			try			{				getText(lineStart,lineElement.getEndOffset()					- lineStart - 1,seg);			}			catch(BadLocationException e)			{				Log.log(Log.ERROR,this,e);			}			/* Prepare for tokenization */			info.lastToken = null;			ParserRule oldRule = info.context.inRule;			TokenMarker.LineContext oldParent = info.context.parent;			tokenMarker.markTokens(prev,info,seg);			ParserRule newRule = info.context.inRule;			TokenMarker.LineContext newParent = info.context.parent;			info.tokensValid = true;			if(i != lastTokenizedLine)			{				nextLineRequested = false;				lastTokenizedLine = i;			}			nextLineRequested |= (oldRule != newRule || oldParent != newParent);			info.addToken(0,Token.END);			prev = info;		}		if(nextLineRequested && lineCount - lineIndex > 1)		{			linesChanged(lineIndex + 1,lineCount - lineIndex - 1);		}		//System.err.println(System.currentTimeMillis() - _start);		return info;	}	/**	 * Store the width of a line, in pixels.	 * @param lineIndex The line number	 * @param width The width	 * @since jEdit 3.1pre1	 */	public boolean setLineWidth(int lineIndex, int width)	{		LineInfo info = lineInfo[lineIndex];		int oldWidth = info.width;		info.width = width;		return width != oldWidth;	}	/**	 * Returns the maximum line width in the specified line range.	 * The strange mix of physical/virtual line numbers is due to	 * the way the text area paints lines.	 * @param start The first physical line	 * @param len The number of virtual lines from the first line	 * @since jEdit 3.1pre1	 */	public int getMaxLineWidth(int start, int len)	{		int retVal = 0;		int lines = 0;		for(int i = start; ; i++)		{			if(i >= lineCount || lines >= len)				break;			LineInfo info = lineInfo[i];			if(info.visible)			{				retVal = Math.max(lineInfo[i].width,retVal);				lines++;			}		}		return retVal;	}	/*	 * Returns true if the next line should be repainted. This	 * will return true after a line has been tokenized that starts	 * a multiline token that continues onto the next line.	 */	public boolean isNextLineRequested()	{		return nextLineRequested;	}	/**	 * Returns the line info object for the specified line.	 * @since jEdit 3.1pre1	 */	public LineInfo getLineInfo(int line)	{		return lineInfo[line];	}	/**	 * Returns if the specified line is visible.	 * @since jEdit 3.1pre1	 */	public boolean isLineVisible(int line)	{		return lineInfo[line].visible;	}	/**	 * Returns if the specified line begins a fold.	 * @since jEdit 3.1pre1	 */	public boolean isFoldStart(int line)	{		if(line == lineCount - 1)			return false;		// how it works:		// - if a line has a greater fold level than the next,		//   it is a fold		// - if a line is invisible, it is also a fold, even		//   if the fold level is the same (rationale: changing		//   indent levels while folds are collapsed shouldn't		//   create pernamently inaccessable sections)		// - exception to the above: if the line is the last		//   virtual line, don't report it as a fold if the		//   fold levels are the same and the next is invisible,		//   otherwise the last narrowed line will always be		//   a fold start which is silly		// note that the last two cases are temporarily disabled		// in 3.1pre3 because expandFoldAt() doesn't handle them		// properly.		return getFoldLevel(line) < getFoldLevel(line + 1);			/*|| (line != virtualLines[virtualLineCount - 1]			&& !lineInfo[line + 1].visible);*/	}	/**	 * Returns the fold level of the specified line.	 * @since jEdit 3.1pre1	 */	public int getFoldLevel(int line)	{		LineInfo info = lineInfo[line];		if(info.foldLevelValid)			return info.foldLevel;		else		{			boolean changed = false;			// make this configurable!			int tabSize = getTabSize();			Element lineElement = getDefaultRootElement()				.getElement(line);			int start = lineElement.getStartOffset();			try			{				getText(start,lineElement.getEndOffset() - start - 1,seg);			}			catch(BadLocationException bl)			{				Log.log(Log.ERROR,this,bl);			}			int offset = seg.offset;			int count = seg.count;			int whitespace = 0;			if(count == 0)			{				// empty line. inherit previous line's fold level				if(line != 0)					whitespace = getFoldLevel(line - 1);				else					whitespace = 0;			}			else			{				// this is so that lines consisting of only				// whitespace don't cause disruptions				boolean seenNonWhitespace = false;loop:				for(int i = 0; i < count; i++)				{					switch(seg.array[offset + i])					{					case ' ':						whitespace++;						break;					case '\t':						whitespace += (tabSize - whitespace % tabSize);						break;					default:						seenNonWhitespace = true;						break loop;					}				}				if(!seenNonWhitespace)				{					if(line != 0)						whitespace = getFoldLevel(line - 1);					else						whitespace = 0;				}			}			if(info.foldLevel != whitespace)			{				info.foldLevel = whitespace;				fireFoldLevelsChanged(line - 1,line - 1);			}			info.foldLevelValid = true;			return whitespace;		}	}	/**	 * Returns the previous visible line before the specified index, or	 * -1 if no previous lines are visible.	 * @param lineNo The line	 * @since jEdit 3.1pre1	 */	public int getPrevVisibleLine(int lineNo)	{		for(int i = lineNo - 1; i >= 0; i--)		{			if(lineInfo[i].visible)				return i;		}		return -1;	}	/**	 * Returns the next visible line after the specified index, or	 * -1 if no subsequent lines are visible.	 * @param lineNo The line	 * @since jEdit 3.1pre1	 */	public int getNextVisibleLine(int lineNo)	{		for(int i = lineNo + 1; i < lineCount; i++)		{			if(lineInfo[i].visible)				return i;		}		return -1;	}	/**	 * Maps a virtual line number to a physical line number. To simplify	 * matters for text area highlighters, this method maps out-of-bounds	 * line numbers as well.	 * @since jEdit 3.1pre1	 */	public int virtualToPhysical(int lineNo)	{		// debugging code		if((lineNo < virtualLineCount && lineNo >= virtualLines.length)			|| lineNo < 0)			throw new RuntimeException("lineNo = " + lineNo);		if(lineNo >= virtualLineCount)			return lineCount + (lineNo - virtualLineCount);		return virtualLines[lineNo];	}	/**	 * Maps a physical line number to a virtual line number.	 * @since jEdit 3.1pre1	 */	public int physicalToVirtual(int lineNo)	{		int start = 0;		int end = virtualLineCount - 1;		if(lineNo < virtualLines[start])			return start;		else if(lineNo > virtualLines[end])			return end;		// funky binary search		for(;;)		{			switch(end - start)			{			case 0:				if(virtualLines[start] < lineNo)					return start + 1;				else					return start;			case 1:				if(virtualLines[start] < lineNo)				{					if(virtualLines[end] < lineNo)						return end + 1;					else						return end;				}				else					return start;			default:				int pivot = start + (end - start) / 2;				int value = virtualLines[pivot];				if(value == lineNo)					return pivot;				else if(value < lineNo)					start = pivot + 1;				else					end = pivot - 1;				break;			}		}	}	/**	 * Collapse the fold that contains the specified line number.	 * @param line The first line number of the fold	 * @return False if there are no folds in the buffer	 * @since jEdit 3.1pre1	 */	public boolean collapseFoldAt(int line)	{		int initialFoldLevel = getFoldLevel(line);		int start = 0;		int end = lineCount - 1;		if(line != lineCount - 1			&& getFoldLevel(line + 1) > initialFoldLevel)		{			// this line is the start of a fold			start = line + 1;			for(int i = line + 1; i < lineCount; i++)			{				if(getFoldLevel(i) <= initialFoldLevel)				{					end = i - 1;					break;				}			}		}		else		{			boolean ok = false;			// scan backwards looking for the start			for(int i = line - 1; i >= 0; i--)			{				if(getFoldLevel(i) < initialFoldLevel)				{					start = i + 1;					ok = true;					break;				}			}			if(!ok)			{				// no folds in buffer				return false;			}			for(int i = line + 1; i < lineCount; i++)			{				if(getFoldLevel(i) < initialFoldLevel)				{					end = i - 1;					break;				}			}		}		int delta = (end - start + 1);		for(int i = start; i <= end; i++)		{			LineInfo info = lineInfo[i];			if(info.visible)				info.visible = false;			else				delta--;		}		if(delta == 0)		{			// user probably pressed A+BACK_SPACE twice			return false;		}		//System.err.println("collapse from " + start + " to " + end);		// I forgot to do this at first and it took me ages to		// figure out		start = physicalToVirtual(start);		//System.err.println("virtualized start is " + start);		// update virtual -> physical map		virtualLineCount -= delta;		//System.err.println("new virtual line count is " + virtualLineCount);		System.arraycopy(virtualLines,start + delta,virtualLines,start,			virtualLines.length - start - delta);		//System.err.println("copy from " + (start + delta)		//	+ " to " + start);		fireFoldStructureChanged();		return true;	}	/**	 * Expand the fold that begins at the specified line number.	 * @param line The first line number of the fold	 * @param fully If true, fold will be expanded fully, otherwise	 * only one level will be expanded	 * @param textArea Text area for scrolling purposes	 * @return False if there are no folds in the buffer	 * @since jEdit 3.3pre3	 */	public boolean expandFoldAt(int line, boolean fully, JEditTextArea textArea)	{		int initialFoldLevel = getFoldLevel(line);		int start = 0;		int end = lineCount - 1;		if(line != lineCount - 1			&& lineInfo[line].visible			&& !lineInfo[line + 1].visible			&& getFoldLevel(line + 1) > initialFoldLevel)		{			// this line is the start of a fold			start = line + 1;			for(int i = line + 1; i < lineCount; i++)			{				if(lineInfo[i].visible && getFoldLevel(i) <= initialFoldLevel)				{					end = i - 1;					break;				}			}		}		else		{			/* if(lineInfo[line].visible)			{				// the user probably pressed A+ENTER twice				return false;			} */			boolean ok = false;			// scan backwards looking for the start			for(int i = line - 1; i >= 0; i--)			{				if(lineInfo[i].visible && getFoldLevel(i) < initialFoldLevel)				{					start = i + 1;					ok = true;					break;				}			}			if(!ok)			{				// no folds in buffer				return false;			}			for(int i = line + 1; i < lineCount; i++)			{				if(lineInfo[i].visible && getFoldLevel(i) < initialFoldLevel)				{					end = i - 1;					break;				}			}		}		int delta = 0;		int tmpMapLen = 0;		int[] tmpVirtualMap = new int[end - start + 1];		// we need a different value of initialFoldLevel here!		initialFoldLevel = getFoldLevel(start);		for(int i = start; i <= end; i++)		{			LineInfo info = lineInfo[i];			if(info.visible)			{				// user will be confused if 'expand fold'				// hides lines

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -