📄 buffer.java
字号:
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 + -