📄 offsetmanager.java
字号:
/* * OffsetManager.java - Manages line info, line start offsets, positions * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2001, 2002 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */package org.gjt.sp.jedit.buffer;//{{{ Importsimport javax.swing.text.*;import org.gjt.sp.jedit.syntax.*;import org.gjt.sp.jedit.Buffer;import org.gjt.sp.util.IntegerArray;import org.gjt.sp.util.Log;//}}}/** * A class internal to jEdit's document model. You should not use it * directly. To improve performance, none of the methods in this class * check for out of bounds access, nor are they thread-safe. The * <code>Buffer</code> class, through which these methods must be * called through, implements such protection. * * @author Slava Pestov * @version $Id: OffsetManager.java,v 1.33 2003/02/23 04:05:21 spestov Exp $ * @since jEdit 4.0pre1 */public class OffsetManager{ //{{{ OffsetManager constructor public OffsetManager(Buffer buffer) { this.buffer = buffer; lineInfo = new long[1]; // make first line visible by default lineInfo[0] = 1L | (0xffL << VISIBLE_SHIFT); lineContext = new TokenMarker.LineContext[1]; lineCount = 1; positions = new PosBottomHalf[100]; virtualLineCounts = new int[8]; for(int i = 0; i < 8; i++) virtualLineCounts[i] = 1; gapLine = -1; } //}}} //{{{ getLineCount() method public final int getLineCount() { return lineCount; } //}}} //{{{ getVirtualLineCount() method public final int getVirtualLineCount(int index) { return virtualLineCounts[index]; } //}}} //{{{ setVirtualLineCount() method public final void setVirtualLineCount(int index, int lineCount) { virtualLineCounts[index] = lineCount; } //}}} //{{{ getLineOfOffset() method public int getLineOfOffset(int offset) { int start = 0; int end = lineCount - 1; for(;;) { switch(end - start) { case 0: if(getLineEndOffset(start) <= offset) return start + 1; else return start; case 1: if(getLineEndOffset(start) <= offset) { if(getLineEndOffset(end) <= offset) return end + 1; else return end; } else return start; default: int pivot = (end + start) / 2; int value = getLineEndOffset(pivot); if(value == offset) return pivot + 1; else if(value < offset) start = pivot + 1; else end = pivot - 1; break; } } } //}}} //{{{ getLineEndOffset() method public final int getLineEndOffset(int line) { int end = (int)(lineInfo[line] & END_MASK); if(gapLine != -1 && line >= gapLine) return end + gapWidth; else return end; } //}}} //{{{ isFoldLevelValid() method public final boolean isFoldLevelValid(int line) { if(gapLine != -1 && line >= gapLine) return false; return (lineInfo[line] & FOLD_LEVEL_VALID_MASK) != 0; } //}}} //{{{ getFoldLevel() method public final int getFoldLevel(int line) { return (int)((lineInfo[line] & FOLD_LEVEL_MASK) >> FOLD_LEVEL_SHIFT); } //}}} //{{{ setFoldLevel() method // Also sets 'fold level valid' flag public final void setFoldLevel(int line, int level) { if(gapLine != -1 && line >= gapLine) moveGap(line + 1,0,"setFoldLevel"); lineInfo[line] = ((lineInfo[line] & ~FOLD_LEVEL_MASK) | ((long)level << FOLD_LEVEL_SHIFT) | FOLD_LEVEL_VALID_MASK); } //}}} //{{{ isLineVisible() method public final boolean isLineVisible(int line, int index) { long mask = 1L << (index + VISIBLE_SHIFT); return (lineInfo[line] & mask) != 0; } //}}} //{{{ setLineVisible() method public final void setLineVisible(int line, int index, boolean visible) { long mask = 1L << (index + VISIBLE_SHIFT); if(visible) lineInfo[line] = (lineInfo[line] | mask); else lineInfo[line] = (lineInfo[line] & ~mask); } //}}} /* the next two methods are not used! //{{{ getScreenLineCount() method public final int getScreenLineCount(int line) { return (int)((lineInfo[line] & SCREEN_LINES_MASK) >> SCREEN_LINES_SHIFT); } //}}} //{{{ setScreenLineCount() method public final void setScreenLineCount(int line, int count) { lineInfo[line] = ((lineInfo[line] & ~SCREEN_LINES_MASK) | ((long)count << SCREEN_LINES_SHIFT)); } //}}} */ //{{{ isLineContextValid() method public final boolean isLineContextValid(int line) { if(gapLine != -1 && line >= gapLine) return false; return (lineInfo[line] & CONTEXT_VALID_MASK) != 0; } //}}} //{{{ getLineContext() method public final TokenMarker.LineContext getLineContext(int line) { return lineContext[line]; } //}}} //{{{ setLineContext() method // Also sets 'context valid' to true public final void setLineContext(int line, TokenMarker.LineContext context) { if(gapLine != -1 && line >= gapLine) moveGap(line + 1,0,"setLineContext"); lineContext[line] = context; lineInfo[line] |= CONTEXT_VALID_MASK; } //}}} //{{{ createPosition() method // note: Buffer.createPosition() grabs a read lock, so the buffer // will not change during this method. however, if two stops call // it, there can be contention issues unless this method is // synchronized. // I could make Buffer.createPosition() grab a write lock, but then // it would be necessary to implement grabbing write locks within // read locks, since HyperSearch for example does everything inside // a read lock. public synchronized Position createPosition(int offset) { PosBottomHalf bh = null; for(int i = 0; i < positionCount; i++) { PosBottomHalf _bh = positions[i]; if(_bh.offset == offset) { bh = _bh; break; } else if(_bh.offset > offset) { bh = new PosBottomHalf(offset); growPositionArray(); System.arraycopy(positions,i,positions,i+1, positionCount - i); positionCount++; positions[i] = bh; break; } } if(bh == null) { bh = new PosBottomHalf(offset); growPositionArray(); positions[positionCount++] = bh; } return new PosTopHalf(bh); } //}}} //{{{ expandFolds() method /** * Like <code>FoldVisibilityManager.expandFolds()</code>, but does * it for all fold visibility managers viewing this buffer. Should * only be called after loading. */ public void expandFolds(int foldLevel) { int newVirtualLineCount = 0; if(foldLevel == 0) { newVirtualLineCount = lineCount; for(int i = 0; i < lineCount; i++) lineInfo[i] |= VISIBLE_MASK; } else { foldLevel = (foldLevel - 1) * buffer.getIndentSize() + 1; /* this ensures that the first line is always visible */ boolean seenVisibleLine = false; for(int i = 0; i < lineCount; i++) { if(!seenVisibleLine || buffer.getFoldLevel(i) < foldLevel) { seenVisibleLine = true; lineInfo[i] |= VISIBLE_MASK; newVirtualLineCount++; } else lineInfo[i] &= ~VISIBLE_MASK; } } for(int i = 0; i < virtualLineCounts.length; i++) { virtualLineCounts[i] = newVirtualLineCount; } } //}}} //{{{ contentInserted() method public void contentInserted(int startLine, int offset, int numLines, int length, IntegerArray endOffsets) { int endLine = startLine + numLines; //{{{ Update line info and line context arrays if(numLines > 0) { moveGap(-1,0,"contentInserted"); lineCount += numLines; if(lineInfo.length <= lineCount) { long[] lineInfoN = new long[(lineCount + 1) * 2]; System.arraycopy(lineInfo,0,lineInfoN,0, lineInfo.length); lineInfo = lineInfoN; TokenMarker.LineContext[] lineContextN = new TokenMarker.LineContext[(lineCount + 1) * 2]; System.arraycopy(lineContext,0,lineContextN,0, lineContext.length); lineContext = lineContextN; } System.arraycopy(lineInfo,startLine,lineInfo, endLine,lineCount - endLine); System.arraycopy(lineContext,startLine,lineContext, endLine,lineCount - endLine); //{{{ Find fold start of this line int foldLevel = buffer.getFoldLevel(startLine); long visible = (0xffL << VISIBLE_SHIFT); if(startLine != 0) { for(int i = startLine; i > 0; i--) { if(/* buffer.isFoldStart(i - 1) && */ buffer.getFoldLevel(i) <= foldLevel) { visible = (lineInfo[i] & VISIBLE_MASK); break; } } } //}}} for(int i = 0; i < numLines; i++) { // need the line end offset to be in place // for following fold level calculations lineInfo[startLine + i] = (offset + endOffsets.get(i) + 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -