1 11 package org.eclipse.swt.custom; 12 13 import org.eclipse.swt.graphics.*; 14 import org.eclipse.swt.internal.Compatibility; 15 import java.util.Vector ; 16 17 class DefaultLineStyler implements LineStyleListener, LineBackgroundListener { 18 StyledTextContent content; 19 StyleRange styles[] = new StyleRange[0]; 20 int styleCount = 0; int lineExpandExp = 1; int lineCount = 0; 23 Color lineBackgrounds[]; 24 25 31 public DefaultLineStyler(StyledTextContent content) { 32 this.content = content; 33 lineCount = content.getLineCount(); 34 lineBackgrounds = new Color[lineCount]; 35 } 36 45 void insertStyle(StyleRange style, int index) { 46 insertStyles(new StyleRange[] {style}, index); 47 } 48 57 void insertStyles(StyleRange[] insertStyles, int index) { 58 int size = styles.length; 59 int insertCount = insertStyles.length; 60 int spaceNeeded = styleCount + insertCount - size; 61 if (spaceNeeded > 0) { 62 StyleRange[] newStyles = new StyleRange[size+spaceNeeded]; 63 System.arraycopy(styles, 0, newStyles, 0, size); 64 styles = newStyles; 65 } 66 System.arraycopy(styles, index, styles, index + insertCount, styleCount - index); 68 System.arraycopy(insertStyles, 0, styles, index, insertCount); 70 styleCount = styleCount + insertCount; 71 } 72 82 boolean insertMergeStyle(StyleRange style, int index) { 83 if (mergeStyleBefore(style, index)) return false; 84 if (mergeStyleAfter(style, index)) return false; 85 insertStyle(style, index); 86 return true; 87 } 88 96 boolean mergeStyleBefore(StyleRange style, int index) { 97 if (index > 0) { 100 StyleRange previous = styles[index-1]; 101 if (style.similarTo(previous)) { 102 int previousEnd = previous.start + previous.length; 105 if ((style.start <= previousEnd) && (style.start >= previous.start)) { 106 int styleEnd = style.start + style.length; 107 if ((index == styleCount) || (styleEnd <= styles[index].start)) { 108 previous.length = style.start + style.length - previous.start; 109 return true; 110 } 111 } 112 } 113 } 114 return false; 115 } 116 124 boolean mergeStyleAfter(StyleRange style, int index) { 125 if (index < styleCount) { 128 StyleRange next = styles[index]; 129 if (style.similarTo(next)) { 130 int styleEnd = style.start + style.length; 133 int nextEnd = next.start + next.length; 134 if ((styleEnd <= nextEnd) && (styleEnd >= next.start)) { 135 if ((index == 0) || (style.start >= styles[index-1].start + styles[index-1].length)) { 136 next.length = next.start + next.length - style.start; 137 next.start = style.start; 138 return true; 139 } 140 } 141 } 142 } 143 return false; 144 } 145 151 void clearStyle(StyleRange clearStyle) { 152 Point pt = getOverlappingStyles(clearStyle.start, clearStyle.length); 153 int clearStyleEnd = clearStyle.start + clearStyle.length - 1; 154 155 if ((pt == null) || (pt.y == 0)) return; 157 158 int count = 0; 162 int deleteStyle = -1; 163 int deleteCount = 0; 164 for (int i=pt.x; count<pt.y; i++) { 165 StyleRange overlap = styles[i]; 166 int overlapEnd = overlap.start + overlap.length - 1; 167 if (overlap.start < clearStyle.start) { 168 if (overlapEnd <= clearStyleEnd) { 169 overlap.length=clearStyle.start - overlap.start; 171 } else { 172 StyleRange endStyle = (StyleRange)overlap.clone(); 175 endStyle.start = clearStyleEnd + 1; 176 endStyle.length = overlapEnd - clearStyleEnd; 177 overlap.length = clearStyle.start - overlap.start; 178 insertStyle(endStyle, i+1); 179 break; 180 } 181 } else { 182 if (overlapEnd <= clearStyleEnd) { 183 if (deleteStyle == -1) { 185 deleteStyle = i; 186 } 187 deleteCount++; 188 } else { 189 overlap.start=clearStyleEnd + 1; 191 overlap.length=overlapEnd - overlap.start + 1; 192 break; 193 } 194 } 195 count++; 196 } 197 deleteStyles(deleteStyle, deleteCount); 198 } 199 206 void expandLinesBy(int numLines) { 207 int size = lineBackgrounds.length; 208 if (size - lineCount >= numLines) { 209 return; 210 } 211 Color[] newLines = new Color[size+Math.max(Compatibility.pow2(lineExpandExp), numLines)]; 212 System.arraycopy(lineBackgrounds, 0, newLines, 0, size); 213 lineBackgrounds = newLines; 214 lineExpandExp++; 215 } 216 222 void deleteStyle(int index) { 223 deleteStyles(index, 1); 224 } 225 232 void deleteStyles(int index, int count) { 233 if ((count == 0) || (index < 0)) return; 234 System.arraycopy(styles, index + count, styles, index, styleCount - (index + count)); 236 for (int i=0; i<count; i++) { 237 styles[styleCount - i - 1] = null; 238 } 239 styleCount = styleCount - count; 240 } 241 247 StyleRange [] getStyleRanges() { 248 StyleRange[] newStyles = new StyleRange[styleCount]; 249 System.arraycopy(styles, 0, newStyles, 0, styleCount); 250 return newStyles; 251 } 252 259 public void lineGetBackground(LineBackgroundEvent event) { 260 int lineIndex = content.getLineAtOffset(event.lineOffset); 261 event.lineBackground = lineBackgrounds[lineIndex]; 262 } 263 270 public void lineGetStyle(LineStyleEvent event) { 271 int lineStart = event.lineOffset; 272 int lineEnd = lineStart + event.lineText.length(); 273 274 int high = searchForStyle(lineStart, lineEnd); 275 StyleRange style = null; 276 Vector lineStyles = new Vector (); 277 278 for (int index = high; index < styleCount; index++) { 286 style = styles[index]; 287 if (style.start > lineEnd) 288 break; 290 int styleEnd = style.start + style.length - 1; 291 if (styleEnd >= lineStart) lineStyles.addElement(style); 292 } 293 event.styles = new StyleRange[lineStyles.size()]; 294 lineStyles.copyInto(event.styles); 295 } 296 302 int searchForStyle(int start, int end) { 303 int high = styleCount; 304 int low = -1; 305 int index = high; 306 while (high - low > 1) { 308 index = (high + low) / 2; 309 StyleRange style = styles[index]; 310 int styleEnd = style.start + style.length - 1; 311 if (start <= style.start || end <= styleEnd || (start > style.start && styleEnd >= start && styleEnd < end)) { 312 high = index; 313 } 314 else { 315 low = index; 316 } 317 } 318 return high; 319 } 320 328 void setLineBackground(int startLine, int count, Color background) { 329 for (int i=startLine; i<startLine + count; i++) { 330 lineBackgrounds[i]=background; 331 } 332 } 333 342 void setStyleRange(StyleRange newStyle) { 343 if (newStyle == null) { 344 styles = new StyleRange[0]; 345 styleCount = 0; 346 return; 347 } 348 if (newStyle.length ==0) return; 349 if (newStyle.isUnstyled()) { 350 clearStyle(newStyle); 351 return; 352 } 353 354 Point pt = getOverlappingStyles(newStyle.start, newStyle.length); 355 int newStyleEnd = newStyle.start + newStyle.length - 1; 356 357 if (pt == null) { 359 insertStyle(newStyle, 0); 360 return; 361 } 362 363 if (pt.y == 0) { 365 insertMergeStyle(newStyle, pt.x); 366 return; 367 } 368 369 boolean added = false; int count = 0; 372 for (int i=pt.x; count<pt.y; i++) { 375 StyleRange overlap = styles[i]; 376 int overlapEnd = overlap.start + overlap.length - 1; 377 if (overlap.start < newStyle.start) { 378 if (overlapEnd <= newStyleEnd) { 379 if (newStyle.similarTo(overlap)) { 381 overlap.length = newStyle.start + newStyle.length - overlap.start; 383 } else { 384 overlap.length=newStyle.start - overlap.start; 385 if (mergeStyleAfter(newStyle, i+1)) break; 388 insertStyle(newStyle, i+1); 391 i++; 392 } 393 added = true; 394 } else { 395 if (newStyle.similarTo(overlap)) break; 398 StyleRange endStyle = (StyleRange)overlap.clone(); 399 endStyle.start = newStyleEnd + 1; 400 endStyle.length = overlapEnd - newStyleEnd; 401 overlap.length = newStyle.start - overlap.start; 402 insertStyle(newStyle, i+1); 403 i++; 404 insertStyle(endStyle, i+1); 405 break; 408 } 409 } else { 410 if (overlapEnd <= newStyleEnd) { 411 if (!added) { 414 styles[i] = newStyle; 415 added = true; 416 } else { 417 deleteStyle(i); 418 i--; 419 } 420 } else { 421 overlap.start=newStyleEnd + 1; 423 overlap.length=overlapEnd - overlap.start + 1; 424 if (!added) { 425 insertMergeStyle(newStyle, i); 426 } 427 break; 430 } 431 } 432 count++; 433 } 434 } 435 442 void replaceStyleRanges(int start, int length, StyleRange[] ranges) { 443 clearStyle(new StyleRange(start, length, null, null)); 444 int high = styleCount; 446 int low = -1; 447 int index = high; 448 while (high - low > 1) { 449 index = (high + low) / 2; 450 StyleRange style = styles[index]; 451 if (start <= style.start) { 452 high = index; 453 } 454 else { 455 low = index; 456 } 457 } 458 insertStyles(ranges, high); 459 } 460 466 void setStyleRanges(StyleRange[] styles) { 467 this.styles = new StyleRange[styles.length]; 468 System.arraycopy(styles, 0, this.styles, 0, styles.length); 469 styleCount = styles.length; 470 } 471 479 public void textChanging(TextChangingEvent event) { 480 int startLine = content.getLineAtOffset(event.start); 481 int startLineOffset = content.getOffsetAtLine(startLine); 482 483 textChanging(event.start, -event.replaceCharCount); 484 textChanging(event.start, event.newCharCount); 485 486 if (event.replaceCharCount == content.getCharCount()) { 487 linesChanging(0, -lineCount); 489 linesChanging(0, content.getLineCount() - event.replaceLineCount + event.newLineCount); 490 return; 491 } 492 493 if (event.start != startLineOffset) { 494 startLine = startLine + 1; 495 } 496 497 linesChanging(startLine, -event.replaceLineCount); 498 linesChanging(startLine, event.newLineCount); 499 } 500 508 void linesChanging(int start, int delta) { 509 if (delta == 0) return; 510 boolean inserting = delta > 0; 511 if (inserting) { 512 expandLinesBy(delta); 514 for (int i = lineCount-1; i >= start; i--) { 515 lineBackgrounds[i + delta]=lineBackgrounds[i]; 516 } 517 for (int i=start; i<start + delta; i++) { 518 lineBackgrounds[i]=null; 519 } 520 } else { 521 for (int i = start - delta; i < lineCount; i++) { 523 lineBackgrounds[i+delta]=lineBackgrounds[i]; 524 } 525 } 526 lineCount += delta; 527 } 528 537 void textChanging(int start, int delta) { 538 if (delta == 0) return; 539 StyleRange style; 540 int end; 543 int deleteStart = -1; 544 int deleteCount = 0; 545 boolean inserting = delta > 0; 546 if (inserting) { 547 end = (start + delta) - 1; 548 } else { 549 end = (start - delta) - 1; 550 } 551 int high = searchForStyle(start, end); 552 int index; 553 for (index = high; index < styleCount; index++) { 555 style = styles[index]; 556 if (inserting) { 557 if (style.start >= start) break; 558 StyleRange beforeStyle = (StyleRange)style.clone(); 561 beforeStyle.length = start - style.start; 562 style.start = start; 563 style.length = style.length - beforeStyle.length; 564 if (beforeStyle.length != 0) insertStyle(beforeStyle, index); 565 index++; 566 break; 567 } else { 568 int styleEnd = style.start + style.length - 1; 569 if (style.start > end) break; 570 if (style.start < start) { 573 if (styleEnd <= end) { 574 style.length = start - style.start; 576 } else { 577 style.length = style.length + delta; 579 index++; 580 break; 581 } 582 } else { 583 if (styleEnd <= end) { 584 if (deleteStart == -1) { 586 deleteStart = index; 587 } 588 deleteCount++; 589 } else { 590 style.start = start; 592 style.length = styleEnd - end; 593 index++; 594 break; 595 } 596 } 597 } 598 } 599 deleteStyles(deleteStart, deleteCount); 600 for (int i = index - deleteCount; i < styleCount; i++) { 602 style = styles[i]; 603 style.start = style.start + delta; 604 } 605 } 606 614 Point getOverlappingStyles(int start, int length) { 615 StyleRange style; 616 if (styleCount == 0) return null; 617 int end = start + length - 1; 620 int high = searchForStyle(start, end); 621 int count = 0; 622 for (int index = high; index < styleCount; index++) { 623 style = styles[index]; 624 int styleEnd = style.start + style.length - 1; 625 if (style.start > end) break; 626 if (styleEnd >= start) count++; 627 } 628 return new Point(high, count); 629 } 630 638 Color getLineBackground(int index) { 639 return lineBackgrounds[index]; 640 } 641 650 StyleRange getStyleRangeAtOffset(int offset) { 651 if (styleCount == 0) return null; 652 Point pt = getOverlappingStyles(offset, 1); 653 if (pt == null || pt.y == 0) return null; 654 StyleRange newStyle = (StyleRange)styles[pt.x].clone(); 655 newStyle.start = offset; 656 newStyle.length = 1; 657 return newStyle; 658 } 659 670 StyleRange[] getStyleRangesFor(int offset, int length) { 671 if (styleCount == 0) return null; 672 Point pt = getOverlappingStyles(offset, length); 673 if (pt == null || pt.y == 0) return null; 674 StyleRange[] ranges = new StyleRange[pt.y]; 675 for (int i=0; i<pt.y; i++) { 676 StyleRange newStyle = styles[pt.x + i]; 677 ranges[i]=newStyle; 678 } 679 return ranges; 680 } 681 void release () { 682 styles = null; 683 } 684 } 685 | Popular Tags |