1 19 20 package org.netbeans.editor; 21 22 import javax.swing.text.BadLocationException ; 23 import javax.swing.text.Document ; 24 import javax.swing.text.Position ; 25 26 32 33 public class MarkBlockChain { 34 35 36 protected MarkBlock chain; 37 38 39 protected MarkBlock currentBlock; 40 41 42 protected BaseDocument doc; 43 44 45 public MarkBlockChain(BaseDocument doc) { 46 this.doc = doc; 47 } 48 49 public final MarkBlock getChain() { 50 return chain; 51 } 52 53 60 public int compareBlock(int startPos, int endPos) { 61 if (currentBlock == null) { 62 currentBlock = chain; 63 if (currentBlock == null) { 64 return MarkBlock.INVALID; 65 } 66 } 67 68 int rel; boolean afterPrev = false; boolean beforeNext = false; boolean cont = false; MarkBlock contBlk = null; 73 int contRel = 0; 74 while (true) { 75 rel = currentBlock.compare(startPos, endPos); 76 if ((rel & MarkBlock.OVERLAP) != 0) { 77 return rel; 78 } 79 80 if ((rel & MarkBlock.AFTER) != 0) { if (beforeNext) { 82 if (!cont || (rel & MarkBlock.CONTINUE) != 0) { 83 return rel; 84 } else { currentBlock = contBlk; 86 return contRel; 87 } 88 } else { if (currentBlock.next != null) { 90 afterPrev = true; 91 cont = ((rel & MarkBlock.CONTINUE) != 0); 92 if (cont) { 93 contRel = rel; 94 contBlk = currentBlock; 95 } 96 currentBlock = currentBlock.next; 97 } else { return rel; 99 } 100 } 101 } else { if (afterPrev) { 103 if (!cont || (rel & MarkBlock.EXTEND) != 0) { 104 return rel; 105 } else { 106 currentBlock = contBlk; 107 return contRel; 108 } 109 } else { if (currentBlock.prev != null) { 111 beforeNext = true; 112 cont = ((rel & MarkBlock.CONTINUE) != 0); 113 if (cont) { 114 contRel = rel; 115 contBlk = currentBlock; 116 } 117 currentBlock = currentBlock.prev; 118 } else { return rel; 120 } 121 } 122 } 123 } 124 } 125 126 public void removeEmptyBlocks() { 127 try { 128 MarkBlock blk = chain; 129 while (blk != null) { 130 if (blk.startMark.getOffset() == blk.endMark.getOffset()) { blk = checkedRemove(blk); } else { 133 blk = blk.next; 134 } 135 } 136 } catch (InvalidMarkException e) { 137 Utilities.annotateLoggable(e); 138 } 139 } 140 141 protected MarkBlock createBlock(int startPos, int endPos) 142 throws BadLocationException { 143 return new MarkBlock(doc, createBlockStartMark(), createBlockEndMark(), 144 startPos, endPos); 145 } 146 147 protected Mark createBlockStartMark() { 148 return new Mark(); 149 } 150 151 protected Mark createBlockEndMark() { 152 return new Mark(); 153 } 154 155 private void removeCurrentIfEmpty() { 156 try { 157 while (currentBlock != null) { 158 if (currentBlock.startMark.getOffset() >= currentBlock.endMark.getOffset()) { 160 checkedRemove(currentBlock); 161 currentBlock = chain; 162 } else { break; 164 } 165 } 166 } catch (InvalidMarkException e) { 167 Utilities.annotateLoggable(e); 168 } 169 } 170 171 172 175 public void addBlock(int startPos, int endPos, boolean concat) { 176 if (startPos == endPos) { 177 return; 178 } 179 removeCurrentIfEmpty(); 180 try { 181 int rel = compareBlock(startPos, endPos) & MarkBlock.IGNORE_EMPTY; 182 if ((rel & MarkBlock.BEFORE) != 0) { if (concat && rel == MarkBlock.CONTINUE_BEGIN) { currentBlock.startMark.move(doc, startPos); 185 } else { boolean first = (currentBlock == chain); 187 MarkBlock blk = currentBlock.insertChain(createBlock(startPos, endPos)); 188 if (first) { 189 chain = blk; 190 } 191 } 192 } else if ((rel & MarkBlock.AFTER) != 0) { if (concat && rel == MarkBlock.CONTINUE_END) { 194 currentBlock.endMark.move(doc, endPos); 195 } else { currentBlock.addChain(createBlock(startPos, endPos)); 197 } 198 } else { if (currentBlock == null) { chain = createBlock(startPos, endPos); 201 } else { currentBlock.extendStart(startPos); 204 currentBlock.extendEnd(endPos); 205 MarkBlock blk = chain; 207 while (blk != null) { 208 if (blk != currentBlock) { if (currentBlock.extend(blk, concat)) { MarkBlock tempCurBlk = currentBlock; 211 blk = checkedRemove(blk); currentBlock = tempCurBlk; 213 } else { blk = blk.next; 215 } 216 } else { 217 blk = blk.next; 218 } 219 } 220 } 221 } 222 } catch (InvalidMarkException e) { 223 Utilities.annotateLoggable(e); 224 } catch (BadLocationException e) { 225 Utilities.annotateLoggable(e); 226 } 227 } 228 229 230 public void removeBlock(int startPos, int endPos) { 231 if (startPos == endPos) { 232 return; 233 } 234 try { 235 int rel; 236 while (((rel = compareBlock(startPos, endPos)) & MarkBlock.OVERLAP) != 0) { 237 if ((rel & MarkBlock.THIS_EMPTY) != 0) { checkedRemove(currentBlock); 239 } else { 240 switch (currentBlock.shrink(startPos, endPos)) { 241 case MarkBlock.INNER: int endMarkPos = currentBlock.endMark.getOffset(); 243 currentBlock.endMark.move(doc, startPos); 244 currentBlock.addChain(createBlock(endPos, endMarkPos)); 245 return; 246 case MarkBlock.INSIDE_BEGIN: 247 case MarkBlock.OVERLAP_BEGIN: 248 currentBlock.startMark.move(doc, endPos); 249 return; 250 case MarkBlock.INSIDE_END: 251 case MarkBlock.OVERLAP_END: 252 currentBlock.endMark.move(doc, startPos); 253 return; 254 default: checkedRemove(currentBlock); 256 break; 257 } 258 } 259 } 260 } catch (BadLocationException e) { 261 Utilities.annotateLoggable(e); 262 } catch (InvalidMarkException e) { 263 Utilities.annotateLoggable(e); 264 } 265 } 266 267 270 protected MarkBlock checkedRemove(MarkBlock blk) { 271 boolean first = (blk == chain); 272 blk = blk.removeChain(); 273 if (first) { 274 chain = blk; 275 } 276 currentBlock = null; return blk; 278 } 279 280 public int adjustToBlockEnd(int pos) { 281 int rel = compareBlock(pos, pos) & MarkBlock.IGNORE_EMPTY; 282 if (rel == MarkBlock.INSIDE_BEGIN || rel == MarkBlock.INNER) { pos = currentBlock.getEndOffset(); 284 } 285 return pos; 286 } 287 288 290 public int adjustToNextBlockStart(int pos) { 291 int rel = compareBlock(pos, pos) & MarkBlock.IGNORE_EMPTY; 293 if ((rel & MarkBlock.BEFORE) != 0) { 294 pos = currentBlock.getStartOffset(); 295 } else { if (currentBlock != null) { 297 MarkBlock nextBlk = currentBlock.getNext(); 298 if (nextBlk != null) { 299 pos = nextBlk.getStartOffset(); 300 } else { pos = -1; 302 } 303 } else { pos = -1; 305 } 306 } 307 return pos; 308 } 309 310 public static class LayerChain extends MarkBlockChain { 311 312 private String layerName; 313 314 public LayerChain(BaseDocument doc, String layerName) { 315 super(doc); 316 this.layerName = layerName; 317 } 318 319 public final String getLayerName() { 320 return layerName; 321 } 322 323 protected Mark createBlockStartMark() { 324 MarkFactory.DrawMark startMark = new MarkFactory.DrawMark(layerName, null); 325 startMark.activateLayer = true; 326 return startMark; 327 } 328 329 protected Mark createBlockEndMark() { 330 MarkFactory.DrawMark endMark = new MarkFactory.DrawMark(layerName, null, Position.Bias.Backward); 331 return endMark; 332 } 333 334 } 335 336 public String toString() { 337 return "MarkBlockChain: currentBlock=" + currentBlock + "\nblock chain: " + (chain != null ? ("\n" + chain.toStringChain()) : " Empty"); } 340 341 } 342 | Popular Tags |