1 // Scintilla source code edit control 
   3  ** Main code for the edit control. 
   5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> 
   6 // The License.txt file describes the conditions under which this software may be distributed. 
  16 #define INCLUDE_DEPRECATED_FEATURES 
  18 #include "Scintilla.h" 
  20 #include "ContractionState.h" 
  22 #include "CellBuffer.h" 
  24 #include "Indicator.h" 
  26 #include "LineMarker.h" 
  28 #include "ViewStyle.h" 
  33 active(false), on(false), period(500) {} 
  36 ticking(false), ticksToWait(0), tickerID(0) {} 
  38 LineLayout::LineLayout(int maxLineLength_
) : 
  56         widthLine(wrapWidthInfinite
), 
  58         Resize(maxLineLength_
); 
  61 LineLayout::~LineLayout() { 
  65 void LineLayout::Resize(int maxLineLength_
) { 
  66         if (maxLineLength_ 
> maxLineLength
) { 
  68                 chars 
= new char[maxLineLength_ 
+ 1]; 
  69                 styles 
= new char[maxLineLength_ 
+ 1]; 
  70                 indicators 
= new char[maxLineLength_ 
+ 1]; 
  71                 // Extra position allocated as sometimes the Windows 
  72                 // GetTextExtentExPoint API writes an extra element. 
  73                 positions 
= new int[maxLineLength_ 
+ 1 + 1]; 
  74                 maxLineLength 
= maxLineLength_
; 
  78 void LineLayout::Free() { 
  91 void LineLayout::Invalidate(validLevel validity_
) { 
  92         if (validity 
> validity_
) 
  96 void LineLayout::SetLineStart(int line
, int start
) { 
  97         if ((line 
>= lenLineStarts
) && (line 
!= 0)) { 
  98                 int newMaxLines 
= line 
+ 20; 
  99                 int *newLineStarts 
= new int[newMaxLines
]; 
 102                 for (int i 
= 0; i 
< newMaxLines
; i
++) { 
 103                         if (i 
< lenLineStarts
) 
 104                                 newLineStarts
[i
] = lineStarts
[i
]; 
 106                                 newLineStarts
[i
] = 0; 
 109                 lineStarts 
= newLineStarts
; 
 110                 lenLineStarts 
= newMaxLines
; 
 112         lineStarts
[line
] = start
; 
 115 void LineLayout::SetBracesHighlight(Range rangeLine
, Position braces
[], 
 116                                     char bracesMatchStyle
, int xHighlight
) { 
 117         if (rangeLine
.ContainsCharacter(braces
[0])) { 
 118                 int braceOffset 
= braces
[0] - rangeLine
.start
; 
 119                 if (braceOffset 
< numCharsInLine
) { 
 120                         bracePreviousStyles
[0] = styles
[braceOffset
]; 
 121                         styles
[braceOffset
] = bracesMatchStyle
; 
 124         if (rangeLine
.ContainsCharacter(braces
[1])) { 
 125                 int braceOffset 
= braces
[1] - rangeLine
.start
; 
 126                 if (braceOffset 
< numCharsInLine
) { 
 127                         bracePreviousStyles
[1] = styles
[braceOffset
]; 
 128                         styles
[braceOffset
] = bracesMatchStyle
; 
 131         if ((braces
[0] >= rangeLine
.start 
&& braces
[1] <= rangeLine
.end
) || 
 132                 (braces
[1] >= rangeLine
.start 
&& braces
[0] <= rangeLine
.end
)) { 
 133                 xHighlightGuide 
= xHighlight
; 
 137 void LineLayout::RestoreBracesHighlight(Range rangeLine
, Position braces
[]) { 
 138         if (rangeLine
.ContainsCharacter(braces
[0])) { 
 139                 int braceOffset 
= braces
[0] - rangeLine
.start
; 
 140                 if (braceOffset 
< numCharsInLine
) { 
 141                         styles
[braceOffset
] = bracePreviousStyles
[0]; 
 144         if (rangeLine
.ContainsCharacter(braces
[1])) { 
 145                 int braceOffset 
= braces
[1] - rangeLine
.start
; 
 146                 if (braceOffset 
< numCharsInLine
) { 
 147                         styles
[braceOffset
] = bracePreviousStyles
[1]; 
 153 LineLayoutCache::LineLayoutCache() : 
 154         level(0), length(0), size(0), cache(0), 
 155         allInvalidated(false), styleClock(-1) { 
 159 LineLayoutCache::~LineLayoutCache() { 
 163 void LineLayoutCache::Allocate(int length_
) { 
 164         allInvalidated 
= false; 
 168                 size 
= (size 
/ 16 + 1) * 16; 
 171                 cache 
= new LineLayout 
* [size
]; 
 173         for (int i 
= 0; i 
< size
; i
++) 
 177 void LineLayoutCache::AllocateForLevel(int linesOnScreen
, int linesInDoc
) { 
 178         int lengthForLevel 
= 0; 
 179         if (level 
== llcCaret
) { 
 181         } else if (level 
== llcPage
) { 
 182                 lengthForLevel 
= linesOnScreen 
+ 1; 
 183         } else if (level 
== llcDocument
) { 
 184                 lengthForLevel 
= linesInDoc
; 
 186         if (lengthForLevel 
> size
) { 
 188         } else if (lengthForLevel 
< length
) { 
 189                 for (int i 
= lengthForLevel
; i 
< length
; i
++) { 
 195                 Allocate(lengthForLevel
); 
 199 void LineLayoutCache::Deallocate() { 
 200         for (int i 
= 0; i 
< length
; i
++) 
 207 void LineLayoutCache::Invalidate(LineLayout::validLevel validity_
) { 
 208         if (cache 
&& !allInvalidated
) { 
 209                 for (int i 
= 0; i 
< length
; i
++) { 
 211                                 cache
[i
]->Invalidate(validity_
); 
 214                 if (validity_ 
== LineLayout::llInvalid
) { 
 215                         allInvalidated 
= true; 
 220 void LineLayoutCache::SetLevel(int level_
) { 
 221         allInvalidated 
= false; 
 222         if ((level_ 
!= -1) && (level 
!= level_
)) { 
 228 LineLayout 
*LineLayoutCache::Retrieve(int lineNumber
, int lineCaret
, int maxChars
, int styleClock_
, 
 229                                       int linesOnScreen
, int linesInDoc
) { 
 230         AllocateForLevel(linesOnScreen
, linesInDoc
); 
 231         if (styleClock 
!= styleClock_
) { 
 232                 Invalidate(LineLayout::llCheckTextAndStyle
); 
 233                 styleClock 
= styleClock_
; 
 235         allInvalidated 
= false; 
 238         if (((level 
== llcCaret
) || (level 
== llcPage
)) && (lineNumber 
== lineCaret
)) { 
 240         } else if (level 
== llcPage
) { 
 241                 pos 
= lineNumber 
% length
; 
 242         } else if (level 
== llcDocument
) { 
 246                 if (cache 
&& (pos 
< length
)) { 
 248                                 if ((cache
[pos
]->lineNumber 
!= lineNumber
) || 
 249                                         (cache
[pos
]->maxLineLength 
< maxChars
)) { 
 255                                 cache
[pos
] = new LineLayout(maxChars
); 
 258                                 cache
[pos
]->lineNumber 
= lineNumber
; 
 259                                 cache
[pos
]->inCache 
= true; 
 266                 ret 
= new LineLayout(maxChars
); 
 267                 ret
->lineNumber 
= lineNumber
; 
 273 void LineLayoutCache::Dispose(LineLayout 
*ll
) { 
 274         allInvalidated 
= false; 
 287         printMagnification 
= 0; 
 288         printColourMode 
= SC_PRINT_NORMAL
; 
 289         printWrapState 
= eWrapWord
; 
 290         cursorMode 
= SC_CURSORNORMAL
; 
 291         controlCharSymbol 
= 0;  /* Draw the control characters */ 
 294         hideSelection 
= false; 
 295         inOverstrike 
= false; 
 297         mouseDownCaptures 
= true; 
 303         dwellDelay 
= SC_TIME_FOREVER
; 
 304         ticksToDwell 
= SC_TIME_FOREVER
; 
 309         dropWentOutside 
= false; 
 310         posDrag 
= invalidPosition
; 
 311         posDrop 
= invalidPosition
; 
 312         selectionType 
= selChar
; 
 316         originalAnchorPos 
= 0; 
 321         primarySelection 
= true; 
 323         caretXPolicy 
= CARET_SLOP 
| CARET_EVEN
; 
 326         caretYPolicy 
= CARET_EVEN
; 
 333         horizontalScrollBarVisible 
= true; 
 335         verticalScrollBarVisible 
= true; 
 336         endAtLastLine 
= true; 
 338         pixmapLine 
= Surface::Allocate(); 
 339         pixmapSelMargin 
= Surface::Allocate(); 
 340         pixmapSelPattern 
= Surface::Allocate(); 
 341         pixmapIndentGuide 
= Surface::Allocate(); 
 342         pixmapIndentGuideHighlight 
= Surface::Allocate(); 
 355         braces
[0] = invalidPosition
; 
 356         braces
[1] = invalidPosition
; 
 357         bracesMatchStyle 
= STYLE_BRACEBAD
; 
 358         highlightGuideColumn 
= 0; 
 362         paintState 
= notPainting
; 
 364         modEventMask 
= SC_MODEVENTMASKALL
; 
 366         pdoc 
= new Document(); 
 368         pdoc
->AddWatcher(this, 0); 
 370         recordingMacro 
= false; 
 373         wrapState 
= eWrapNone
; 
 374         wrapWidth 
= LineLayout::wrapWidthInfinite
; 
 375         docLineLastWrapped 
= -1; 
 380         llc
.SetLevel(LineLayoutCache::llcCaret
); 
 384         pdoc
->RemoveWatcher(this, 0); 
 389         delete pixmapSelMargin
; 
 390         delete pixmapSelPattern
; 
 391         delete pixmapIndentGuide
; 
 392         delete pixmapIndentGuideHighlight
; 
 395 void Editor::Finalise() { 
 399 void Editor::DropGraphics() { 
 400         pixmapLine
->Release(); 
 401         pixmapSelMargin
->Release(); 
 402         pixmapSelPattern
->Release(); 
 403         pixmapIndentGuide
->Release(); 
 406 void Editor::InvalidateStyleData() { 
 410         llc
.Invalidate(LineLayout::llInvalid
); 
 413 void Editor::InvalidateStyleRedraw() { 
 415         InvalidateStyleData(); 
 419 void Editor::RefreshColourPalette(Palette 
&pal
, bool want
) { 
 420         vs
.RefreshColourPalette(pal
, want
); 
 423 void Editor::RefreshStyleData() { 
 426                 AutoSurface 
surface(this); 
 428                         vs
.Refresh(*surface
); 
 429                         RefreshColourPalette(palette
, true); 
 430                         palette
.Allocate(wMain
); 
 431                         RefreshColourPalette(palette
, false); 
 437 PRectangle 
Editor::GetClientRectangle() { 
 438         return wMain
.GetClientPosition(); 
 441 PRectangle 
Editor::GetTextRectangle() { 
 442         PRectangle rc 
= GetClientRectangle(); 
 443         rc
.left 
+= vs
.fixedColumnWidth
; 
 444         rc
.right 
-= vs
.rightMarginWidth
; 
 448 int Editor::LinesOnScreen() { 
 449         PRectangle rcClient 
= GetClientRectangle(); 
 450         int htClient 
= rcClient
.bottom 
- rcClient
.top
; 
 451         //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1); 
 452         return htClient 
/ vs
.lineHeight
; 
 455 int Editor::LinesToScroll() { 
 456         int retVal 
= LinesOnScreen() - 1; 
 463 int Editor::MaxScrollPos() { 
 464         //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n", 
 465         //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1); 
 466         int retVal 
= cs
.LinesDisplayed(); 
 468                 retVal 
-= LinesOnScreen(); 
 479 static inline bool IsControlCharacter(char ch
) { 
 480         // iscntrl returns true for lots of chars > 127 which are displayable 
 481         return ch 
>= 0 && ch 
< ' '; 
 484 const char *ControlCharacterString(unsigned char ch
) { 
 485         const char *reps
[] = { 
 486                 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", 
 487                 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", 
 488                 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", 
 489                 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" 
 491         if (ch 
< (sizeof(reps
) / sizeof(reps
[0]))) { 
 498 // Convenience class to ensure LineLayout objects are always disposed. 
 499 class AutoLineLayout 
{ 
 500         LineLayoutCache 
&llc
; 
 502         AutoLineLayout 
&operator=(const AutoLineLayout 
&) { return * this; } 
 504         AutoLineLayout(LineLayoutCache 
&llc_
, LineLayout 
*ll_
) : llc(llc_
), ll(ll_
) {} 
 509         LineLayout 
*operator->() const { 
 512         operator LineLayout 
*() const { 
 515         void Set(LineLayout 
*ll_
) { 
 521 Point 
Editor::LocationFromPosition(int pos
) { 
 524         if (pos 
== INVALID_POSITION
) 
 526         int line 
= pdoc
->LineFromPosition(pos
); 
 527         int lineVisible 
= cs
.DisplayFromDoc(line
); 
 528         //Platform::DebugPrintf("line=%d\n", line); 
 529         AutoSurface 
surface(this); 
 530         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
 532                 // -1 because of adding in for visible lines in following loop. 
 533                 pt
.y 
= (lineVisible 
- topLine 
- 1) * vs
.lineHeight
; 
 535                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
 536                 LayoutLine(line
, surface
, vs
, ll
, wrapWidth
); 
 537                 int posInLine 
= pos 
- posLineStart
; 
 538                 // In case of very long line put x at arbitrary large position 
 539                 if (posInLine 
> ll
->maxLineLength
) { 
 540                         pt
.x 
= ll
->positions
[ll
->maxLineLength
] - ll
->positions
[ll
->LineStart(ll
->lines
)]; 
 542                 for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
 543                         if ((posInLine 
>= ll
->LineStart(subLine
)) && (posInLine 
<= ll
->LineStart(subLine 
+ 1))) { 
 544                                 pt
.x 
= ll
->positions
[posInLine
] - ll
->positions
[ll
->LineStart(subLine
)]; 
 546                         if (posInLine 
>= ll
->LineStart(subLine
)) { 
 547                                 pt
.y 
+= vs
.lineHeight
; 
 550                 pt
.x 
+= vs
.fixedColumnWidth 
- xOffset
; 
 555 int Editor::XFromPosition(int pos
) { 
 556         Point pt 
= LocationFromPosition(pos
); 
 557         return pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 560 int Editor::LineFromLocation(Point pt
) { 
 561         return cs
.DocFromDisplay(pt
.y 
/ vs
.lineHeight 
+ topLine
); 
 564 void Editor::SetTopLine(int topLineNew
) { 
 565         topLine 
= topLineNew
; 
 566         posTopLine 
= pdoc
->LineStart(topLine
); 
 569 static inline bool IsEOLChar(char ch
) { 
 570         return (ch 
== '\r') || (ch 
== '\n'); 
 573 int Editor::PositionFromLocation(Point pt
) { 
 575         pt
.x 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 576         int visibleLine 
= pt
.y 
/ vs
.lineHeight 
+ topLine
; 
 577         if (pt
.y 
< 0) { // Division rounds towards 0 
 578                 visibleLine 
= (pt
.y 
- (vs
.lineHeight 
- 1)) / vs
.lineHeight 
+ topLine
; 
 582         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
 583         if (lineDoc 
>= pdoc
->LinesTotal()) 
 584                 return pdoc
->Length(); 
 585         unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 586         int retVal 
= posLineStart
; 
 587         AutoSurface 
surface(this); 
 588         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 590                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 591                 int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
 592                 int subLine 
= visibleLine 
- lineStartSet
; 
 593                 if (subLine 
< ll
->lines
) { 
 594                         int lineStart 
= ll
->LineStart(subLine
); 
 595                         int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 596                         int subLineStart 
= ll
->positions
[lineStart
]; 
 597                         for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 598                                 if (pt
.x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 599                                         IsEOLChar(ll
->chars
[i
])) { 
 600                                         return pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 603                         return lineEnd 
+ posLineStart
; 
 605                 retVal 
= ll
->numCharsInLine 
+ posLineStart
; 
 610 // Like PositionFromLocation but INVALID_POSITION returned when not near any text. 
 611 int Editor::PositionFromLocationClose(Point pt
) { 
 613         PRectangle rcClient 
= GetTextRectangle(); 
 614         if (!rcClient
.Contains(pt
)) 
 615                 return INVALID_POSITION
; 
 616         if (pt
.x 
< vs
.fixedColumnWidth
) 
 617                 return INVALID_POSITION
; 
 619                 return INVALID_POSITION
; 
 620         pt
.x 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 621         int visibleLine 
= pt
.y 
/ vs
.lineHeight 
+ topLine
; 
 622         if (pt
.y 
< 0) { // Division rounds towards 0 
 623                 visibleLine 
= (pt
.y 
- (vs
.lineHeight 
- 1)) / vs
.lineHeight 
+ topLine
; 
 625         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
 627                 return INVALID_POSITION
; 
 628         if (lineDoc 
>= pdoc
->LinesTotal()) 
 629                 return INVALID_POSITION
; 
 630         AutoSurface 
surface(this); 
 631         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 633                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 634                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 635                 int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
 636                 int subLine 
= visibleLine 
- lineStartSet
; 
 637                 if (subLine 
< ll
->lines
) { 
 638                         int lineStart 
= ll
->LineStart(subLine
); 
 639                         int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 640                         int subLineStart 
= ll
->positions
[lineStart
]; 
 641                         for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 642                                 if (pt
.x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 643                                         IsEOLChar(ll
->chars
[i
])) { 
 644                                         return pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 650         return INVALID_POSITION
; 
 654  * Find the document position corresponding to an x coordinate on a particular document line. 
 655  * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. 
 657 int Editor::PositionFromLineX(int lineDoc
, int x
) { 
 659         if (lineDoc 
>= pdoc
->LinesTotal()) 
 660                 return pdoc
->Length(); 
 661         //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); 
 662         AutoSurface 
surface(this); 
 663         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 666                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 667                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 668                 retVal 
= ll
->numCharsInLine 
+ posLineStart
; 
 670                 int lineStart 
= ll
->LineStart(subLine
); 
 671                 int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 672                 int subLineStart 
= ll
->positions
[lineStart
]; 
 673                 for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 674                         if (x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 675                                 IsEOLChar(ll
->chars
[i
])) { 
 676                                 retVal 
= pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 684 // If painting then abandon the painting because a wider redraw is needed. 
 685 // Return true if calling code should stop drawing 
 686 bool Editor::AbandonPaint() { 
 687         if ((paintState 
== painting
) && !paintingAllText
) { 
 688                 paintState 
= paintAbandoned
; 
 690         return paintState 
== paintAbandoned
; 
 693 void Editor::RedrawRect(PRectangle rc
) { 
 694         //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); 
 696         // Clip the redraw rectangle into the client area 
 697         PRectangle rcClient 
= GetClientRectangle(); 
 698         if (rc
.top 
< rcClient
.top
) 
 699                 rc
.top 
= rcClient
.top
; 
 700         if (rc
.bottom 
> rcClient
.bottom
) 
 701                 rc
.bottom 
= rcClient
.bottom
; 
 702         if (rc
.left 
< rcClient
.left
) 
 703                 rc
.left 
= rcClient
.left
; 
 704         if (rc
.right 
> rcClient
.right
) 
 705                 rc
.right 
= rcClient
.right
; 
 707         if ((rc
.bottom 
> rc
.top
) && (rc
.right 
> rc
.left
)) { 
 708                 wMain
.InvalidateRectangle(rc
); 
 712 void Editor::Redraw() { 
 713         //Platform::DebugPrintf("Redraw all\n"); 
 714         PRectangle rcClient 
= GetClientRectangle(); 
 715         wMain
.InvalidateRectangle(rcClient
); 
 716         //wMain.InvalidateAll(); 
 719 void Editor::RedrawSelMargin() { 
 720         if (!AbandonPaint()) { 
 724                         PRectangle rcSelMargin 
= GetClientRectangle(); 
 725                         rcSelMargin
.right 
= vs
.fixedColumnWidth
; 
 726                         wMain
.InvalidateRectangle(rcSelMargin
); 
 731 PRectangle 
Editor::RectangleFromRange(int start
, int end
) { 
 738         int minLine 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(minPos
)); 
 739         int lineDocMax 
= pdoc
->LineFromPosition(maxPos
); 
 740         int maxLine 
= cs
.DisplayFromDoc(lineDocMax
) + cs
.GetHeight(lineDocMax
) - 1; 
 741         PRectangle rcClient 
= GetTextRectangle(); 
 743         rc
.left 
= vs
.fixedColumnWidth
; 
 744         rc
.top 
= (minLine 
- topLine
) * vs
.lineHeight
; 
 747         rc
.right 
= rcClient
.right
; 
 748         rc
.bottom 
= (maxLine 
- topLine 
+ 1) * vs
.lineHeight
; 
 749         // Ensure PRectangle is within 16 bit space 
 750         rc
.top 
= Platform::Clamp(rc
.top
, -32000, 32000); 
 751         rc
.bottom 
= Platform::Clamp(rc
.bottom
, -32000, 32000); 
 756 void Editor::InvalidateRange(int start
, int end
) { 
 757         RedrawRect(RectangleFromRange(start
, end
)); 
 760 int Editor::CurrentPosition() { 
 764 bool Editor::SelectionEmpty() { 
 765         return anchor 
== currentPos
; 
 768 int Editor::SelectionStart(int line
) { 
 769         if ((line 
== -1) || (selType 
== selStream
)) { 
 770                 return Platform::Minimum(currentPos
, anchor
); 
 771         } else { // selType == selRectangle 
 772                 int selStart 
= SelectionStart(); 
 773                 int selEnd 
= SelectionEnd(); 
 774                 int lineStart 
= pdoc
->LineFromPosition(selStart
); 
 775                 int lineEnd 
= pdoc
->LineFromPosition(selEnd
); 
 776                 if (line 
< lineStart 
|| line 
> lineEnd
) { 
 779                         int minX 
= Platform::Minimum(xStartSelect
, xEndSelect
); 
 780                         return PositionFromLineX(line
, minX
); 
 785 int Editor::SelectionEnd(int line
) { 
 786         if ((line 
== -1) || (selType 
== selStream
)) { 
 787                 return Platform::Maximum(currentPos
, anchor
); 
 788         } else { // selType == selRectangle 
 789                 int selStart 
= SelectionStart(); 
 790                 int selEnd 
= SelectionEnd(); 
 791                 int lineStart 
= pdoc
->LineFromPosition(selStart
); 
 792                 int lineEnd 
= pdoc
->LineFromPosition(selEnd
); 
 793                 if (line 
< lineStart 
|| line 
> lineEnd
) { 
 796                         int maxX 
= Platform::Maximum(xStartSelect
, xEndSelect
); 
 797                         // measure line and return character closest to minx 
 798                         return PositionFromLineX(line
, maxX
); 
 803 void Editor::SetSelection(int currentPos_
, int anchor_
) { 
 804         currentPos_ 
= pdoc
->ClampPositionIntoDocument(currentPos_
); 
 805         anchor_ 
= pdoc
->ClampPositionIntoDocument(anchor_
); 
 806         if ((currentPos 
!= currentPos_
) || (anchor 
!= anchor_
)) { 
 807                 int firstAffected 
= anchor
; 
 808                 if (firstAffected 
> currentPos
) 
 809                         firstAffected 
= currentPos
; 
 810                 if (firstAffected 
> anchor_
) 
 811                         firstAffected 
= anchor_
; 
 812                 if (firstAffected 
> currentPos_
) 
 813                         firstAffected 
= currentPos_
; 
 814                 int lastAffected 
= anchor
; 
 815                 if (lastAffected 
< currentPos
) 
 816                         lastAffected 
= currentPos
; 
 817                 if (lastAffected 
< anchor_
) 
 818                         lastAffected 
= anchor_
; 
 819                 if (lastAffected 
< (currentPos_ 
+ 1))   // +1 ensures caret repainted 
 820                         lastAffected 
= (currentPos_ 
+ 1); 
 821                 currentPos 
= currentPos_
; 
 824                 InvalidateRange(firstAffected
, lastAffected
); 
 829 void Editor::SetSelection(int currentPos_
) { 
 830         currentPos_ 
= pdoc
->ClampPositionIntoDocument(currentPos_
); 
 831         if (currentPos 
!= currentPos_
) { 
 832                 int firstAffected 
= anchor
; 
 833                 if (firstAffected 
> currentPos
) 
 834                         firstAffected 
= currentPos
; 
 835                 if (firstAffected 
> currentPos_
) 
 836                         firstAffected 
= currentPos_
; 
 837                 int lastAffected 
= anchor
; 
 838                 if (lastAffected 
< currentPos
) 
 839                         lastAffected 
= currentPos
; 
 840                 if (lastAffected 
< (currentPos_ 
+ 1))   // +1 ensures caret repainted 
 841                         lastAffected 
= (currentPos_ 
+ 1); 
 842                 currentPos 
= currentPos_
; 
 844                 InvalidateRange(firstAffected
, lastAffected
); 
 849 void Editor::SetEmptySelection(int currentPos_
) { 
 851         SetSelection(currentPos_
, currentPos_
); 
 854 bool Editor::RangeContainsProtected(int start
, int end
) const { 
 855         if (vs
.ProtectionActive()) { 
 861                 int mask 
= pdoc
->stylingBitsMask
; 
 862                 for (int pos 
= start
; pos 
< end
; pos
++) { 
 863                         if (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected()) 
 870 bool Editor::SelectionContainsProtected() const { 
 871         // TODO: make support rectangular selection 
 872         return RangeContainsProtected(anchor
, currentPos
); 
 875 int Editor::MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
) { 
 876         // Asks document to find a good position and then moves out of any invisible positions 
 877         pos 
= pdoc
->MovePositionOutsideChar(pos
, moveDir
, checkLineEnd
); 
 878         if (vs
.ProtectionActive()) { 
 879                 int mask 
= pdoc
->stylingBitsMask
; 
 881                         if ((pos 
> 0) && vs
.styles
[pdoc
->StyleAt(pos 
- 1) & mask
].IsProtected()) { 
 882                                 while ((pos 
< pdoc
->Length()) && 
 883                                         (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected())) 
 886                 } else if (moveDir 
< 0) { 
 887                         if (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected()) { 
 889                                         (vs
.styles
[pdoc
->StyleAt(pos 
- 1) & mask
].IsProtected())) 
 897 int Editor::MovePositionTo(int newPos
, bool extend
, bool ensureVisible
) { 
 898         int delta 
= newPos 
- currentPos
; 
 899         newPos 
= pdoc
->ClampPositionIntoDocument(newPos
); 
 900         newPos 
= MovePositionOutsideChar(newPos
, delta
); 
 902                 SetSelection(newPos
); 
 904                 SetEmptySelection(newPos
); 
 906         ShowCaretAtCurrentPosition(); 
 908                 EnsureCaretVisible(); 
 913 int Editor::MovePositionSoVisible(int pos
, int moveDir
) { 
 914         pos 
= pdoc
->ClampPositionIntoDocument(pos
); 
 915         pos 
= MovePositionOutsideChar(pos
, moveDir
); 
 916         int lineDoc 
= pdoc
->LineFromPosition(pos
); 
 917         if (cs
.GetVisible(lineDoc
)) { 
 920                 int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
 922                         // lineDisplay is already line before fold as lines in fold use display line of line after fold 
 923                         lineDisplay 
= Platform::Clamp(lineDisplay
, 0, cs
.LinesDisplayed()); 
 924                         return pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
)); 
 926                         lineDisplay 
= Platform::Clamp(lineDisplay 
- 1, 0, cs
.LinesDisplayed()); 
 927                         return pdoc
->LineEnd(cs
.DocFromDisplay(lineDisplay
)); 
 932 // Choose the x position that the caret will try to stick to as it is moves up and down 
 933 void Editor::SetLastXChosen() { 
 934         Point pt 
= LocationFromPosition(currentPos
); 
 938 void Editor::ScrollTo(int line
, bool moveThumb
) { 
 939         int topLineNew 
= Platform::Clamp(line
, 0, MaxScrollPos()); 
 940         if (topLineNew 
!= topLine
) { 
 941                 // Try to optimise small scrolls 
 942                 int linesToMove 
= topLine 
- topLineNew
; 
 943                 SetTopLine(topLineNew
); 
 944                 ShowCaretAtCurrentPosition(); 
 945                 // Perform redraw rather than scroll if many lines would be redrawn anyway. 
 946                 if (abs(linesToMove
) <= 10) { 
 947                         ScrollText(linesToMove
); 
 952                         SetVerticalScrollPos(); 
 957 void Editor::ScrollText(int /* linesToMove */) { 
 958         //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove); 
 962 void Editor::HorizontalScrollTo(int xPos
) { 
 963         //Platform::DebugPrintf("HorizontalScroll %d\n", xPos); 
 966         if ((wrapState 
== eWrapNone
) && (xOffset 
!= xPos
)) { 
 968                 SetHorizontalScrollPos(); 
 969                 RedrawRect(GetClientRectangle()); 
 973 void Editor::MoveCaretInsideView(bool ensureVisible
) { 
 974         PRectangle rcClient 
= GetTextRectangle(); 
 975         Point pt 
= LocationFromPosition(currentPos
); 
 976         if (pt
.y 
< rcClient
.top
) { 
 977                 MovePositionTo(PositionFromLocation( 
 978                                    Point(lastXChosen
, rcClient
.top
)), 
 979                                false, ensureVisible
); 
 980         } else if ((pt
.y 
+ vs
.lineHeight 
- 1) > rcClient
.bottom
) { 
 981                 int yOfLastLineFullyDisplayed 
= rcClient
.top 
+ (LinesOnScreen() - 1) * vs
.lineHeight
; 
 982                 MovePositionTo(PositionFromLocation( 
 983                                    Point(lastXChosen
, rcClient
.top 
+ yOfLastLineFullyDisplayed
)), 
 984                                false, ensureVisible
); 
 988 int Editor::DisplayFromPosition(int pos
) { 
 989         int lineDoc 
= pdoc
->LineFromPosition(pos
); 
 990         int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
 991         AutoSurface 
surface(this); 
 992         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 994                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 995                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 996                 int posInLine 
= pos 
- posLineStart
; 
 997                 lineDisplay
--; // To make up for first increment ahead. 
 998                 for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
 999                         if (posInLine 
>= ll
->LineStart(subLine
)) { 
1008  * Ensure the caret is reasonably visible in context. 
1010 Caret policy in SciTE 
1012 If slop is set, we can define a slop value. 
1013 This value defines an unwanted zone (UZ) where the caret is... unwanted. 
1014 This zone is defined as a number of pixels near the vertical margins, 
1015 and as a number of lines near the horizontal margins. 
1016 By keeping the caret away from the edges, it is seen within its context, 
1017 so it is likely that the identifier that the caret is on can be completely seen, 
1018 and that the current line is seen with some of the lines following it which are 
1019 often dependent on that line. 
1021 If strict is set, the policy is enforced... strictly. 
1022 The caret is centred on the display if slop is not set, 
1023 and cannot go in the UZ if slop is set. 
1025 If jumps is set, the display is moved more energetically 
1026 so the caret can move in the same direction longer before the policy is applied again. 
1027 '3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin. 
1029 If even is not set, instead of having symmetrical UZs, 
1030 the left and bottom UZs are extended up to right and top UZs respectively. 
1031 This way, we favour the displaying of useful information: the begining of lines, 
1032 where most code reside, and the lines after the caret, eg. the body of a function. 
1035 slop | strict | jumps | even | Caret can go to the margin                 | When reaching limit (caret going out of 
1036      |        |       |      |                                            | visibility or going into the UZ) display is... 
1037 -----+--------+-------+------+--------------------------------------------+-------------------------------------------------------------- 
1038   0  |   0    |   0   |   0  | Yes                                        | moved to put caret on top/on right 
1039   0  |   0    |   0   |   1  | Yes                                        | moved by one position 
1040   0  |   0    |   1   |   0  | Yes                                        | moved to put caret on top/on right 
1041   0  |   0    |   1   |   1  | Yes                                        | centred on the caret 
1042   0  |   1    |   -   |   0  | Caret is always on top/on right of display | - 
1043   0  |   1    |   -   |   1  | No, caret is always centred                | - 
1044   1  |   0    |   0   |   0  | Yes                                        | moved to put caret out of the asymmetrical UZ 
1045   1  |   0    |   0   |   1  | Yes                                        | moved to put caret out of the UZ 
1046   1  |   0    |   1   |   0  | Yes                                        | moved to put caret at 3UZ of the top or right margin 
1047   1  |   0    |   1   |   1  | Yes                                        | moved to put caret at 3UZ of the margin 
1048   1  |   1    |   -   |   0  | Caret is always at UZ of top/right margin  | - 
1049   1  |   1    |   0   |   1  | No, kept out of UZ                         | moved by one position 
1050   1  |   1    |   1   |   1  | No, kept out of UZ                         | moved to put caret at 3UZ of the margin 
1052 void Editor::EnsureCaretVisible(bool useMargin
, bool vert
, bool horiz
) { 
1053         //Platform::DebugPrintf("EnsureCaretVisible %d %s\n", xOffset, useMargin ? " margin" : " "); 
1054         PRectangle rcClient 
= GetTextRectangle(); 
1055         //int rcClientFullWidth = rcClient.Width(); 
1056         int posCaret 
= currentPos
; 
1060         Point pt 
= LocationFromPosition(posCaret
); 
1061         Point ptBottomCaret 
= pt
; 
1062         ptBottomCaret
.y 
+= vs
.lineHeight 
- 1; 
1063         int lineCaret 
= DisplayFromPosition(posCaret
); 
1064         bool bSlop
, bStrict
, bJump
, bEven
; 
1066         // Vertical positioning 
1067         if (vert 
&& (pt
.y 
< rcClient
.top 
|| ptBottomCaret
.y 
> rcClient
.bottom 
|| (caretYPolicy 
& CARET_STRICT
) != 0)) { 
1068                 int linesOnScreen 
= LinesOnScreen(); 
1069                 int halfScreen 
= Platform::Maximum(linesOnScreen 
- 1, 2) / 2; 
1070                 int newTopLine 
= topLine
; 
1071                 bSlop 
= (caretYPolicy 
& CARET_SLOP
) != 0; 
1072                 bStrict 
= (caretYPolicy 
& CARET_STRICT
) != 0; 
1073                 bJump 
= (caretYPolicy 
& CARET_JUMPS
) != 0; 
1074                 bEven 
= (caretYPolicy 
& CARET_EVEN
) != 0; 
1076                 // It should be possible to scroll the window to show the caret, 
1077                 // but this fails to remove the caret on GTK+ 
1078                 if (bSlop
) {    // A margin is defined 
1081                                 int yMarginT
, yMarginB
; 
1083                                         // In drag mode, avoid moves 
1084                                         // otherwise, a double click will select several lines. 
1085                                         yMarginT 
= yMarginB 
= 0; 
1087                                         // yMarginT must equal to caretYSlop, with a minimum of 1 and 
1088                                         // a maximum of slightly less than half the heigth of the text area. 
1089                                         yMarginT 
= Platform::Clamp(caretYSlop
, 1, halfScreen
); 
1091                                                 yMarginB 
= yMarginT
; 
1093                                                 yMarginB 
= linesOnScreen 
- yMarginT 
- 1; 
1099                                                 yMoveT 
= Platform::Clamp(caretYSlop 
* 3, 1, halfScreen
); 
1103                                         yMoveB 
= linesOnScreen 
- yMoveT 
- 1; 
1105                                 if (lineCaret 
< topLine 
+ yMarginT
) { 
1106                                         // Caret goes too high 
1107                                         newTopLine 
= lineCaret 
- yMoveT
; 
1108                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1 - yMarginB
) { 
1109                                         // Caret goes too low 
1110                                         newTopLine 
= lineCaret 
- linesOnScreen 
+ 1 + yMoveB
; 
1112                         } else {        // Not strict 
1113                                 yMoveT 
= bJump 
? caretYSlop 
* 3 : caretYSlop
; 
1114                                 yMoveT 
= Platform::Clamp(yMoveT
, 1, halfScreen
); 
1118                                         yMoveB 
= linesOnScreen 
- yMoveT 
- 1; 
1120                                 if (lineCaret 
< topLine
) { 
1121                                         // Caret goes too high 
1122                                         newTopLine 
= lineCaret 
- yMoveT
; 
1123                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1) { 
1124                                         // Caret goes too low 
1125                                         newTopLine 
= lineCaret 
- linesOnScreen 
+ 1 + yMoveB
; 
1129                         if (!bStrict 
&& !bJump
) { 
1131                                 if (lineCaret 
< topLine
) { 
1132                                         // Caret goes too high 
1133                                         newTopLine 
= lineCaret
; 
1134                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1) { 
1135                                         // Caret goes too low 
1137                                                 newTopLine 
= lineCaret 
- linesOnScreen 
+ 1; 
1139                                                 newTopLine 
= lineCaret
; 
1142                         } else {        // Strict or going out of display 
1144                                         // Always center caret 
1145                                         newTopLine 
= lineCaret 
- halfScreen
; 
1147                                         // Always put caret on top of display 
1148                                         newTopLine 
= lineCaret
; 
1152                 newTopLine 
= Platform::Clamp(newTopLine
, 0, MaxScrollPos()); 
1153                 if (newTopLine 
!= topLine
) { 
1155                         SetTopLine(newTopLine
); 
1156                         SetVerticalScrollPos(); 
1160         // Horizontal positioning 
1161         if (horiz 
&& (wrapState 
== eWrapNone
)) { 
1162                 int halfScreen 
= Platform::Maximum(rcClient
.Width() - 4, 4) / 2; 
1163                 int xOffsetNew 
= xOffset
; 
1164                 bSlop 
= (caretXPolicy 
& CARET_SLOP
) != 0; 
1165                 bStrict 
= (caretXPolicy 
& CARET_STRICT
) != 0; 
1166                 bJump 
= (caretXPolicy 
& CARET_JUMPS
) != 0; 
1167                 bEven 
= (caretXPolicy 
& CARET_EVEN
) != 0; 
1169                 if (bSlop
) {    // A margin is defined 
1172                                 int xMarginL
, xMarginR
; 
1174                                         // In drag mode, avoid moves unless very near of the margin 
1175                                         // otherwise, a simple click will select text. 
1176                                         xMarginL 
= xMarginR 
= 2; 
1178                                         // xMargin must equal to caretXSlop, with a minimum of 2 and 
1179                                         // a maximum of slightly less than half the width of the text area. 
1180                                         xMarginR 
= Platform::Clamp(caretXSlop
, 2, halfScreen
); 
1182                                                 xMarginL 
= xMarginR
; 
1184                                                 xMarginL 
= rcClient
.Width() - xMarginR 
- 4; 
1187                                 if (bJump 
&& bEven
) { 
1188                                         // Jump is used only in even mode 
1189                                         xMoveL 
= xMoveR 
= Platform::Clamp(caretXSlop 
* 3, 1, halfScreen
); 
1191                                         xMoveL 
= xMoveR 
= 0;    // Not used, avoid a warning 
1193                                 if (pt
.x 
< rcClient
.left 
+ xMarginL
) { 
1194                                         // Caret is on the left of the display 
1195                                         if (bJump 
&& bEven
) { 
1196                                                 xOffsetNew 
-= xMoveL
; 
1198                                                 // Move just enough to allow to display the caret 
1199                                                 xOffsetNew 
-= (rcClient
.left 
+ xMarginL
) - pt
.x
; 
1201                                 } else if (pt
.x 
>= rcClient
.right 
- xMarginR
) { 
1202                                         // Caret is on the right of the display 
1203                                         if (bJump 
&& bEven
) { 
1204                                                 xOffsetNew 
+= xMoveR
; 
1206                                                 // Move just enough to allow to display the caret 
1207                                                 xOffsetNew 
+= pt
.x 
- (rcClient
.right 
- xMarginR
) + 1; 
1210                         } else {        // Not strict 
1211                                 xMoveR 
= bJump 
? caretXSlop 
* 3 : caretXSlop
; 
1212                                 xMoveR 
= Platform::Clamp(xMoveR
, 1, halfScreen
); 
1216                                         xMoveL 
= rcClient
.Width() - xMoveR 
- 4; 
1218                                 if (pt
.x 
< rcClient
.left
) { 
1219                                         // Caret is on the left of the display 
1220                                         xOffsetNew 
-= xMoveL
; 
1221                                 } else if (pt
.x 
>= rcClient
.right
) { 
1222                                         // Caret is on the right of the display 
1223                                         xOffsetNew 
+= xMoveR
; 
1228                                 (bJump 
&& (pt
.x 
< rcClient
.left 
|| pt
.x 
>= rcClient
.right
))) { 
1229                                 // Strict or going out of display 
1232                                         xOffsetNew 
+= pt
.x 
- rcClient
.left 
- halfScreen
; 
1234                                         // Put caret on right 
1235                                         xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1238                                 // Move just enough to allow to display the caret 
1239                                 if (pt
.x 
< rcClient
.left
) { 
1240                                         // Caret is on the left of the display 
1242                                                 xOffsetNew 
-= rcClient
.left 
- pt
.x
; 
1244                                                 xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1246                                 } else if (pt
.x 
>= rcClient
.right
) { 
1247                                         // Caret is on the right of the display 
1248                                         xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1252                 // In case of a jump (find result) largely out of display, adjust the offset to display the caret 
1253                 if (pt
.x 
+ xOffset 
< rcClient
.left 
+ xOffsetNew
) { 
1254                         xOffsetNew 
= pt
.x 
+ xOffset 
- rcClient
.left
; 
1255                 } else if (pt
.x 
+ xOffset 
>= rcClient
.right 
+ xOffsetNew
) { 
1256                         xOffsetNew 
= pt
.x 
+ xOffset 
- rcClient
.right 
+ 1; 
1258                 if (xOffsetNew 
< 0) { 
1261                 if (xOffset 
!= xOffsetNew
) { 
1262                         xOffset 
= xOffsetNew
; 
1263                         if (xOffsetNew 
> 0) { 
1264                                 PRectangle rcText 
= GetTextRectangle(); 
1265                                 if (horizontalScrollBarVisible 
== true && 
1266                                         rcText
.Width() + xOffset 
> scrollWidth
) { 
1267                                         scrollWidth 
= xOffset 
+ rcText
.Width(); 
1271                         SetHorizontalScrollPos(); 
1277 void Editor::ShowCaretAtCurrentPosition() { 
1279                 caret
.active 
= true; 
1283                 caret
.active 
= false; 
1289 void Editor::DropCaret() { 
1290         caret
.active 
= false; 
1294 void Editor::InvalidateCaret() { 
1296                 InvalidateRange(posDrag
, posDrag 
+ 1); 
1298                 InvalidateRange(currentPos
, currentPos 
+ 1); 
1301 void Editor::NeedWrapping(int docLineStartWrapping
) { 
1302         if (docLineLastWrapped 
> (docLineStartWrapping 
- 1)) { 
1303                 docLineLastWrapped 
= docLineStartWrapping 
- 1; 
1304                 if (docLineLastWrapped 
< -1) 
1305                         docLineLastWrapped 
= -1; 
1306                 llc
.Invalidate(LineLayout::llPositions
); 
1310 // Check if wrapping needed and perform any needed wrapping. 
1311 // Return true if wrapping occurred. 
1312 bool Editor::WrapLines() { 
1313         int goodTopLine 
= topLine
; 
1314         bool wrapOccurred 
= false; 
1315         if (docLineLastWrapped 
< pdoc
->LinesTotal()) { 
1316                 if (wrapState 
== eWrapNone
) { 
1317                         if (wrapWidth 
!= LineLayout::wrapWidthInfinite
) { 
1318                                 wrapWidth 
= LineLayout::wrapWidthInfinite
; 
1319                                 for (int lineDoc 
= 0; lineDoc 
< pdoc
->LinesTotal(); lineDoc
++) { 
1320                                         cs
.SetHeight(lineDoc
, 1); 
1322                                 wrapOccurred 
= true; 
1324                         docLineLastWrapped 
= 0x7ffffff; 
1327                         int lineDocTop 
= cs
.DocFromDisplay(topLine
); 
1328                         int subLineTop 
= topLine 
- cs
.DisplayFromDoc(lineDocTop
); 
1329                         PRectangle rcTextArea 
= GetClientRectangle(); 
1330                         rcTextArea
.left 
= vs
.fixedColumnWidth
; 
1331                         rcTextArea
.right 
-= vs
.rightMarginWidth
; 
1332                         wrapWidth 
= rcTextArea
.Width(); 
1333                         // Ensure all of the document is styled. 
1334                         pdoc
->EnsureStyledTo(pdoc
->Length()); 
1335                         AutoSurface 
surface(this); 
1337                                 int lastLineToWrap 
= pdoc
->LinesTotal(); 
1338                                 while (docLineLastWrapped 
<= lastLineToWrap
) { 
1339                                         docLineLastWrapped
++; 
1340                                         AutoLineLayout 
ll(llc
, RetrieveLineLayout(docLineLastWrapped
)); 
1341                                         int linesWrapped 
= 1; 
1343                                                 LayoutLine(docLineLastWrapped
, surface
, vs
, ll
, wrapWidth
); 
1344                                                 linesWrapped 
= ll
->lines
; 
1346                                         if (cs
.SetHeight(docLineLastWrapped
, linesWrapped
)) { 
1347                                                 wrapOccurred 
= true; 
1351                         goodTopLine 
= cs
.DisplayFromDoc(lineDocTop
); 
1352                         if (subLineTop 
< cs
.GetHeight(lineDocTop
)) 
1353                                 goodTopLine 
+= subLineTop
; 
1355                                 goodTopLine 
+= cs
.GetHeight(lineDocTop
); 
1356                         //double durWrap = et.Duration(true); 
1357                         //Platform::DebugPrintf("Wrap:%9.6g \n", durWrap); 
1362                 SetTopLine(Platform::Clamp(goodTopLine
, 0, MaxScrollPos())); 
1363                 SetVerticalScrollPos(); 
1365         return wrapOccurred
; 
1368 void Editor::LinesJoin() { 
1369         if (!RangeContainsProtected(targetStart
, targetEnd
)) { 
1370                 pdoc
->BeginUndoAction(); 
1371                 bool prevNonWS 
= true; 
1372                 for (int pos 
= targetStart
; pos 
< targetEnd
; pos
++) { 
1373                         if (IsEOLChar(pdoc
->CharAt(pos
))) { 
1374                                 targetEnd 
-= pdoc
->LenChar(pos
); 
1377                                         // Ensure at least one space separating previous lines 
1378                                         pdoc
->InsertChar(pos
, ' '); 
1381                                 prevNonWS 
= pdoc
->CharAt(pos
) != ' '; 
1384                 pdoc
->EndUndoAction(); 
1388 const char *StringFromEOLMode(int eolMode
) { 
1389         if (eolMode 
== SC_EOL_CRLF
) { 
1391         } else if (eolMode 
== SC_EOL_CR
) { 
1398 void Editor::LinesSplit(int pixelWidth
) { 
1399         if (!RangeContainsProtected(targetStart
, targetEnd
)) { 
1400                 if (pixelWidth 
== 0) { 
1401                         PRectangle rcText 
= GetTextRectangle(); 
1402                         pixelWidth 
= rcText
.Width(); 
1404                 int lineStart 
= pdoc
->LineFromPosition(targetStart
); 
1405                 int lineEnd 
= pdoc
->LineFromPosition(targetEnd
); 
1406                 const char *eol 
= StringFromEOLMode(pdoc
->eolMode
); 
1407                 pdoc
->BeginUndoAction(); 
1408                 for (int line 
= lineStart
; line 
<= lineEnd
; line
++) { 
1409                         AutoSurface 
surface(this); 
1410                         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
1411                         if (surface 
&& ll
) { 
1412                                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
1413                                 LayoutLine(line
, surface
, vs
, ll
, pixelWidth
); 
1414                                 for (int subLine 
= 1; subLine 
< ll
->lines
; subLine
++) { 
1415                                         pdoc
->InsertString(posLineStart 
+ (subLine 
- 1) * strlen(eol
) + 
1416                                                 ll
->LineStart(subLine
), eol
); 
1417                                         targetEnd 
+= static_cast<int>(strlen(eol
)); 
1421                 pdoc
->EndUndoAction(); 
1425 int Editor::SubstituteMarkerIfEmpty(int markerCheck
, int markerDefault
) { 
1426         if (vs
.markers
[markerCheck
].markType 
== SC_MARK_EMPTY
) 
1427                 return markerDefault
; 
1431 // Avoid 64 bit compiler warnings. 
1432 // Scintilla does not support text buffers larger than 2**31 
1433 static int istrlen(const char *s
) { 
1434         return static_cast<int>(strlen(s
)); 
1437 void Editor::PaintSelMargin(Surface 
*surfWindow
, PRectangle 
&rc
) { 
1438         if (vs
.fixedColumnWidth 
== 0) 
1441         PRectangle rcMargin 
= GetClientRectangle(); 
1442         rcMargin
.right 
= vs
.fixedColumnWidth
; 
1444         if (!rc
.Intersects(rcMargin
)) 
1449                 surface 
= pixmapSelMargin
; 
1451                 surface 
= surfWindow
; 
1454         PRectangle rcSelMargin 
= rcMargin
; 
1455         rcSelMargin
.right 
= rcMargin
.left
; 
1457         for (int margin 
= 0; margin 
< vs
.margins
; margin
++) { 
1458                 if (vs
.ms
[margin
].width 
> 0) { 
1460                         rcSelMargin
.left 
= rcSelMargin
.right
; 
1461                         rcSelMargin
.right 
= rcSelMargin
.left 
+ vs
.ms
[margin
].width
; 
1463                         if (vs
.ms
[margin
].symbol
) { 
1464                                 /* alternate scheme: 
1465                                 if (vs.ms[margin].mask & SC_MASK_FOLDERS) 
1466                                         surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
1468                                         // Required because of special way brush is created for selection margin 
1469                                         surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
1471                                 if (vs
.ms
[margin
].mask 
& SC_MASK_FOLDERS
) 
1472                                         // Required because of special way brush is created for selection margin 
1473                                         surface
->FillRectangle(rcSelMargin
, *pixmapSelPattern
); 
1475                                         surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1477                                 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1480                         int visibleLine 
= topLine
; 
1483                         // Work out whether the top line is whitespace located after a 
1484                         // lessening of fold level which implies a 'fold tail' but which should not 
1485                         // be displayed until the last of a sequence of whitespace. 
1486                         bool needWhiteClosure 
= false; 
1487                         int level 
= pdoc
->GetLevel(cs
.DocFromDisplay(topLine
)); 
1488                         if (level 
& SC_FOLDLEVELWHITEFLAG
) { 
1489                                 int lineBack 
= cs
.DocFromDisplay(topLine
); 
1490                                 int levelPrev 
= level
; 
1491                                 while ((lineBack 
> 0) && (levelPrev 
& SC_FOLDLEVELWHITEFLAG
)) { 
1493                                         levelPrev 
= pdoc
->GetLevel(lineBack
); 
1495                                 if (!(levelPrev 
& SC_FOLDLEVELHEADERFLAG
)) { 
1496                                         if ((level 
& SC_FOLDLEVELNUMBERMASK
) < (levelPrev 
& SC_FOLDLEVELNUMBERMASK
)) 
1497                                                 needWhiteClosure 
= true; 
1501                         // Old code does not know about new markers needed to distinguish all cases 
1502                         int folderOpenMid 
= SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID
, 
1503                                             SC_MARKNUM_FOLDEROPEN
); 
1504                         int folderEnd 
= SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND
, 
1507                         while ((visibleLine 
< cs
.LinesDisplayed()) && yposScreen 
< rcMargin
.bottom
) { 
1509                                 PLATFORM_ASSERT(visibleLine 
< cs
.LinesDisplayed()); 
1511                                 int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
1512                                 PLATFORM_ASSERT(cs
.GetVisible(lineDoc
)); 
1513                                 bool firstSubLine 
= visibleLine 
== cs
.DisplayFromDoc(lineDoc
); 
1515                                 // Decide which fold indicator should be displayed 
1516                                 level 
= pdoc
->GetLevel(lineDoc
); 
1517                                 int levelNext 
= pdoc
->GetLevel(lineDoc 
+ 1); 
1518                                 int marks 
= pdoc
->GetMark(lineDoc
); 
1521                                 int levelNum 
= level 
& SC_FOLDLEVELNUMBERMASK
; 
1522                                 int levelNextNum 
= levelNext 
& SC_FOLDLEVELNUMBERMASK
; 
1523                                 if (level 
& SC_FOLDLEVELHEADERFLAG
) { 
1525                                                 if (cs
.GetExpanded(lineDoc
)) { 
1526                                                         if (levelNum 
== SC_FOLDLEVELBASE
) 
1527                                                                 marks 
|= 1 << SC_MARKNUM_FOLDEROPEN
; 
1529                                                                 marks 
|= 1 << folderOpenMid
; 
1531                                                         if (levelNum 
== SC_FOLDLEVELBASE
) 
1532                                                                 marks 
|= 1 << SC_MARKNUM_FOLDER
; 
1534                                                                 marks 
|= 1 << folderEnd
; 
1537                                                 marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1539                                         needWhiteClosure 
= false; 
1540                                 } else if (level 
& SC_FOLDLEVELWHITEFLAG
) { 
1541                                         if (needWhiteClosure
) { 
1542                                                 if (levelNext 
& SC_FOLDLEVELWHITEFLAG
) { 
1543                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1544                                                 } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1545                                                         marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1546                                                         needWhiteClosure 
= false; 
1548                                                         marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1549                                                         needWhiteClosure 
= false; 
1551                                         } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1552                                                 if (levelNextNum 
< levelNum
) { 
1553                                                         if (levelNextNum 
> SC_FOLDLEVELBASE
) { 
1554                                                                 marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1556                                                                 marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1559                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1562                                 } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1563                                         if (levelNextNum 
< levelNum
) { 
1564                                                 needWhiteClosure 
= false; 
1565                                                 if (levelNext 
& SC_FOLDLEVELWHITEFLAG
) { 
1566                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1567                                                         needWhiteClosure 
= true; 
1568                                                 } else if (levelNextNum 
> SC_FOLDLEVELBASE
) { 
1569                                                         marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1571                                                         marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1574                                                 marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1578                                 marks 
&= vs
.ms
[margin
].mask
; 
1579                                 PRectangle rcMarker 
= rcSelMargin
; 
1580                                 rcMarker
.top 
= yposScreen
; 
1581                                 rcMarker
.bottom 
= yposScreen 
+ vs
.lineHeight
; 
1582                                 if (!vs
.ms
[margin
].symbol
) { 
1586                                                 sprintf(number
, "%d", lineDoc 
+ 1); 
1587                                         if (foldFlags 
& SC_FOLDFLAG_LEVELNUMBERS
) { 
1588                                                 int lev 
= pdoc
->GetLevel(lineDoc
); 
1589                                                 sprintf(number
, "%c%c %03X %03X", 
1590                                                         (lev 
& SC_FOLDLEVELHEADERFLAG
) ? 'H' : '_', 
1591                                                         (lev 
& SC_FOLDLEVELWHITEFLAG
) ? 'W' : '_', 
1592                                                         lev 
& SC_FOLDLEVELNUMBERMASK
, 
1596                                         PRectangle rcNumber 
= rcMarker
; 
1598                                         int width 
= surface
->WidthText(vs
.styles
[STYLE_LINENUMBER
].font
, number
, istrlen(number
)); 
1599                                         int xpos 
= rcNumber
.right 
- width 
- 3; 
1600                                         rcNumber
.left 
= xpos
; 
1601                                         surface
->DrawTextNoClip(rcNumber
, vs
.styles
[STYLE_LINENUMBER
].font
, 
1602                                                                 rcNumber
.top 
+ vs
.maxAscent
, number
, istrlen(number
), 
1603                                                                 vs
.styles
[STYLE_LINENUMBER
].fore
.allocated
, 
1604                                                                 vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1608                                         for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
1610                                                         vs
.markers
[markBit
].Draw(surface
, rcMarker
, vs
.styles
[STYLE_LINENUMBER
].font
); 
1617                                 yposScreen 
+= vs
.lineHeight
; 
1622         PRectangle rcBlankMargin 
= rcMargin
; 
1623         rcBlankMargin
.left 
= rcSelMargin
.right
; 
1624         surface
->FillRectangle(rcBlankMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
1627                 surfWindow
->Copy(rcMargin
, Point(), *pixmapSelMargin
); 
1631 void DrawTabArrow(Surface 
*surface
, PRectangle rcTab
, int ymid
) { 
1632         int ydiff 
= (rcTab
.bottom 
- rcTab
.top
) / 2; 
1633         int xhead 
= rcTab
.right 
- 1 - ydiff
; 
1634         if (xhead 
<= rcTab
.left
) { 
1635                 ydiff 
-= rcTab
.left 
- xhead 
- 1; 
1636                 xhead 
= rcTab
.left 
- 1; 
1638         if ((rcTab
.left 
+ 2) < (rcTab
.right 
- 1)) 
1639                 surface
->MoveTo(rcTab
.left 
+ 2, ymid
); 
1641                 surface
->MoveTo(rcTab
.right 
- 1, ymid
); 
1642         surface
->LineTo(rcTab
.right 
- 1, ymid
); 
1643         surface
->LineTo(xhead
, ymid 
- ydiff
); 
1644         surface
->MoveTo(rcTab
.right 
- 1, ymid
); 
1645         surface
->LineTo(xhead
, ymid 
+ ydiff
); 
1648 static bool IsSpaceOrTab(char ch
) { 
1649         return ch 
== ' ' || ch 
== '\t'; 
1652 LineLayout 
*Editor::RetrieveLineLayout(int lineNumber
) { 
1653         int posLineStart 
= pdoc
->LineStart(lineNumber
); 
1654         int posLineEnd 
= pdoc
->LineStart(lineNumber 
+ 1); 
1655         int lineCaret 
= pdoc
->LineFromPosition(currentPos
); 
1656         return llc
.Retrieve(lineNumber
, lineCaret
, 
1657                             posLineEnd 
- posLineStart
, pdoc
->GetStyleClock(), 
1658                             LinesOnScreen() + 1, pdoc
->LinesTotal()); 
1662  * Fill in the LineLayout data for the given line. 
1663  * Copy the given @a line and its styles from the document into local arrays. 
1664  * Also determine the x position at which each character starts. 
1666 void Editor::LayoutLine(int line
, Surface 
*surface
, ViewStyle 
&vstyle
, LineLayout 
*ll
, int width
) { 
1669         int posLineStart 
= pdoc
->LineStart(line
); 
1670         int posLineEnd 
= pdoc
->LineStart(line 
+ 1); 
1671         // If the line is very long, limit the treatment to a length that should fit in the viewport 
1672         if (posLineEnd 
> (posLineStart 
+ ll
->maxLineLength
)) { 
1673                 posLineEnd 
= posLineStart 
+ ll
->maxLineLength
; 
1675         if (ll
->validity 
== LineLayout::llCheckTextAndStyle
) { 
1677                 for (int cid 
= posLineStart
; cid 
< posLineEnd
; cid
++) { 
1678                         char chDoc 
= pdoc
->CharAt(cid
); 
1679                         if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1683                 if (lineLength 
== ll
->numCharsInLine
) { 
1684                         int numCharsInLine 
= 0; 
1685                         // See if chars, styles, indicators, are all the same 
1686                         bool allSame 
= true; 
1688                         int styleMask 
= pdoc
->stylingBitsMask
; 
1689                         // Check base line layout 
1690                         for (int charInDoc 
= posLineStart
; allSame 
&& (charInDoc 
< posLineEnd
); charInDoc
++) { 
1691                                 char chDoc 
= pdoc
->CharAt(charInDoc
); 
1692                                 styleByte 
= pdoc
->StyleAt(charInDoc
); 
1693                                 if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc 
!= '\r'))) { 
1694                                         allSame 
= allSame 
&& 
1695                                                   (ll
->styles
[numCharsInLine
] == static_cast<char>(styleByte 
& styleMask
)); 
1696                                         allSame 
= allSame 
&& 
1697                                                   (ll
->indicators
[numCharsInLine
] == static_cast<char>(styleByte 
& ~styleMask
)); 
1698                                         if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseUpper
) 
1699                                                 allSame 
= allSame 
&& 
1700                                                           (ll
->chars
[numCharsInLine
] == static_cast<char>(toupper(chDoc
))); 
1701                                         else if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseLower
) 
1702                                                 allSame 
= allSame 
&& 
1703                                                           (ll
->chars
[numCharsInLine
] == static_cast<char>(tolower(chDoc
))); 
1705                                                 allSame 
= allSame 
&& 
1706                                                           (ll
->chars
[numCharsInLine
] == chDoc
); 
1711                                 ll
->validity 
= LineLayout::llPositions
; 
1713                                 ll
->validity 
= LineLayout::llInvalid
; 
1716                         ll
->validity 
= LineLayout::llInvalid
; 
1719         if (ll
->validity 
== LineLayout::llInvalid
) { 
1720                 ll
->widthLine 
= LineLayout::wrapWidthInfinite
; 
1722                 int numCharsInLine 
= 0; 
1723                 if (vstyle
.edgeState 
== EDGE_BACKGROUND
) { 
1724                         ll
->edgeColumn 
= pdoc
->FindColumn(line
, theEdge
); 
1725                         if (ll
->edgeColumn 
>= posLineStart
) { 
1726                                 ll
->edgeColumn 
-= posLineStart
; 
1729                         ll
->edgeColumn 
= -1; 
1733                 int styleMask 
= pdoc
->stylingBitsMask
; 
1734                 // Fill base line layout 
1735                 for (int charInDoc 
= posLineStart
; charInDoc 
< posLineEnd
; charInDoc
++) { 
1736                         char chDoc 
= pdoc
->CharAt(charInDoc
); 
1737                         styleByte 
= pdoc
->StyleAt(charInDoc
); 
1738                         if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1739                                 ll
->chars
[numCharsInLine
] = chDoc
; 
1740                                 ll
->styles
[numCharsInLine
] = static_cast<char>(styleByte 
& styleMask
); 
1741                                 ll
->indicators
[numCharsInLine
] = static_cast<char>(styleByte 
& ~styleMask
); 
1742                                 if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseUpper
) 
1743                                         ll
->chars
[numCharsInLine
] = static_cast<char>(toupper(chDoc
)); 
1744                                 else if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseLower
) 
1745                                         ll
->chars
[numCharsInLine
] = static_cast<char>(tolower(chDoc
)); 
1749                 ll
->xHighlightGuide 
= 0; 
1750                 // Extra element at the end of the line to hold end x position and act as 
1751                 ll
->chars
[numCharsInLine
] = 0;   // Also triggers processing in the loops as this is a control character 
1752                 ll
->styles
[numCharsInLine
] = styleByte
; // For eolFilled 
1753                 ll
->indicators
[numCharsInLine
] = 0; 
1755                 // Layout the line, determining the position of each character, 
1756                 // with an extra element at the end for the end of the line. 
1757                 int startseg 
= 0;       // Start of the current segment, in char. number 
1758                 int startsegx 
= 0;      // Start of the current segment, in pixels 
1759                 ll
->positions
[0] = 0; 
1760                 unsigned int tabWidth 
= vstyle
.spaceWidth 
* pdoc
->tabInChars
; 
1761                 bool lastSegItalics 
= false; 
1762                 Font 
&ctrlCharsFont 
= vstyle
.styles
[STYLE_CONTROLCHAR
].font
; 
1764                 bool isControlNext 
= IsControlCharacter(ll
->chars
[0]); 
1765                 for (int charInLine 
= 0; charInLine 
< numCharsInLine
; charInLine
++) { 
1766                         bool isControl 
= isControlNext
; 
1767                         isControlNext 
= IsControlCharacter(ll
->chars
[charInLine 
+ 1]); 
1768                         if ((ll
->styles
[charInLine
] != ll
->styles
[charInLine 
+ 1]) || 
1769                                 isControl 
|| isControlNext
) { 
1770                                 ll
->positions
[startseg
] = 0; 
1771                                 if (vstyle
.styles
[ll
->styles
[charInLine
]].visible
) { 
1773                                                 if (ll
->chars
[charInLine
] == '\t') { 
1774                                                         ll
->positions
[charInLine 
+ 1] = ((((startsegx 
+ 2) / 
1775                                                                                            tabWidth
) + 1) * tabWidth
) - startsegx
; 
1776                                                 } else if (controlCharSymbol 
< 32) { 
1777                                                         const char *ctrlChar 
= ControlCharacterString(ll
->chars
[charInLine
]); 
1778                                                         // +3 For a blank on front and rounded edge each side: 
1779                                                         ll
->positions
[charInLine 
+ 1] = surface
->WidthText(ctrlCharsFont
, ctrlChar
, istrlen(ctrlChar
)) + 3; 
1781                                                         char cc
[2] = { static_cast<char>(controlCharSymbol
), '\0' }; 
1782                                                         surface
->MeasureWidths(ctrlCharsFont
, cc
, 1, 
1783                                                                                ll
->positions 
+ startseg 
+ 1); 
1785                                                 lastSegItalics 
= false; 
1786                                         } else {        // Regular character 
1787                                                 int lenSeg 
= charInLine 
- startseg 
+ 1; 
1788                                                 if ((lenSeg 
== 1) && (' ' == ll
->chars
[startseg
])) { 
1789                                                         lastSegItalics 
= false; 
1790                                                         // Over half the segments are single characters and of these about half are space characters. 
1791                                                         ll
->positions
[charInLine 
+ 1] = vstyle
.styles
[ll
->styles
[charInLine
]].spaceWidth
; 
1793                                                         lastSegItalics 
= vstyle
.styles
[ll
->styles
[charInLine
]].italic
; 
1794                                                         surface
->MeasureWidths(vstyle
.styles
[ll
->styles
[charInLine
]].font
, ll
->chars 
+ startseg
, 
1795                                                                                lenSeg
, ll
->positions 
+ startseg 
+ 1); 
1798                                 } else {    // invisible 
1799                                         for (int posToZero 
= startseg
; posToZero 
<= (charInLine 
+ 1); posToZero
++) { 
1800                                                 ll
->positions
[posToZero
] = 0; 
1803                                 for (int posToIncrease 
= startseg
; posToIncrease 
<= (charInLine 
+ 1); posToIncrease
++) { 
1804                                         ll
->positions
[posToIncrease
] += startsegx
; 
1806                                 startsegx 
= ll
->positions
[charInLine 
+ 1]; 
1807                                 startseg 
= charInLine 
+ 1; 
1810                 // Small hack to make lines that end with italics not cut off the edge of the last character 
1811                 if ((startseg 
> 0) && lastSegItalics
) { 
1812                         ll
->positions
[startseg
] += 2; 
1814                 ll
->numCharsInLine 
= numCharsInLine
; 
1815                 ll
->validity 
= LineLayout::llPositions
; 
1817         // Hard to cope when too narrow, so just assume there is space 
1821         if ((ll
->validity 
== LineLayout::llPositions
) || (ll
->widthLine 
!= width
)) { 
1822                 ll
->widthLine 
= width
; 
1823                 if (width 
== LineLayout::wrapWidthInfinite
) { 
1825                 } else if (width 
> ll
->positions
[ll
->numCharsInLine
]) { 
1826                         // Simple common case where line does not need wrapping. 
1830                         // Calculate line start positions based upon width. 
1831                         // For now this is simplistic - wraps on byte rather than character and 
1832                         // in the middle of words. Should search for spaces or style changes. 
1833                         int lastGoodBreak 
= 0; 
1834                         int lastLineStart 
= 0; 
1835                         int startOffset 
= 0; 
1837                         while (p 
< ll
->numCharsInLine
) { 
1838                                 if ((ll
->positions
[p 
+ 1] - startOffset
) >= width
) { 
1839                                         if (lastGoodBreak 
== lastLineStart
) { 
1840                                                 // Try moving to start of last character 
1842                                                         lastGoodBreak 
= pdoc
->MovePositionOutsideChar(p 
+ posLineStart
, -1) 
1845                                                 if (lastGoodBreak 
== lastLineStart
) { 
1846                                                         // Ensure at least one character on line. 
1847                                                         lastGoodBreak 
= pdoc
->MovePositionOutsideChar(lastGoodBreak 
+ posLineStart 
+ 1, 1) 
1851                                         lastLineStart 
= lastGoodBreak
; 
1853                                         ll
->SetLineStart(ll
->lines
, lastGoodBreak
); 
1854                                         startOffset 
= ll
->positions
[lastGoodBreak
]; 
1855                                         p 
= lastGoodBreak 
+ 1; 
1859                                         if (ll
->styles
[p
] != ll
->styles
[p 
- 1]) { 
1861                                         } else if (IsSpaceOrTab(ll
->chars
[p 
- 1]) && !IsSpaceOrTab(ll
->chars
[p
])) { 
1869                 ll
->validity 
= LineLayout::llLines
; 
1873 ColourAllocated 
Editor::TextBackground(ViewStyle 
&vsDraw
, bool overrideBackground
, 
1874                                        ColourAllocated background
, bool inSelection
, bool inHotspot
, int styleMain
, int i
, LineLayout 
*ll
) { 
1876                 if (vsDraw
.selbackset
) { 
1877                         if (primarySelection
) 
1878                                 return vsDraw
.selbackground
.allocated
; 
1880                                 return vsDraw
.selbackground2
.allocated
; 
1883                 if ((vsDraw
.edgeState 
== EDGE_BACKGROUND
) && 
1884                         (i 
>= ll
->edgeColumn
) && 
1885                         !IsEOLChar(ll
->chars
[i
])) 
1886                         return vsDraw
.edgecolour
.allocated
; 
1888                         return vsDraw
.hotspotBackground
.allocated
; 
1889                 if (overrideBackground
) 
1892         return vsDraw
.styles
[styleMain
].back
.allocated
; 
1895 void Editor::DrawIndentGuide(Surface 
*surface
, int lineVisible
, int lineHeight
, int start
, PRectangle rcSegment
, bool highlight
) { 
1896         Point 
from(0, ((lineVisible 
& 1) && (lineHeight 
& 1)) ? 1 : 0); 
1897         PRectangle 
rcCopyArea(start 
+ 1, rcSegment
.top
, start 
+ 2, rcSegment
.bottom
); 
1898         surface
->Copy(rcCopyArea
, from
, 
1899                       highlight 
? *pixmapIndentGuideHighlight 
: *pixmapIndentGuide
); 
1902 void Editor::DrawEOL(Surface 
*surface
, ViewStyle 
&vsDraw
, PRectangle rcLine
, LineLayout 
*ll
, 
1903                      int line
, int lineEnd
, int xStart
, int subLine
, int subLineStart
, 
1904                      bool overrideBackground
, ColourAllocated background
) { 
1906         int styleMask 
= pdoc
->stylingBitsMask
; 
1907         PRectangle rcSegment 
= rcLine
; 
1909         // Fill in a PRectangle representing the end of line characters 
1910         int xEol 
= ll
->positions
[lineEnd
] - subLineStart
; 
1911         rcSegment
.left 
= xEol 
+ xStart
; 
1912         rcSegment
.right 
= xEol 
+ vsDraw
.aveCharWidth 
+ xStart
; 
1913         int posLineEnd 
= pdoc
->LineStart(line 
+ 1); 
1914         bool eolInSelection 
= (subLine 
== (ll
->lines 
- 1)) && 
1915                               (posLineEnd 
> ll
->selStart
) && (posLineEnd 
<= ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
1916         if (eolInSelection 
&& vsDraw
.selbackset 
&& (line 
< pdoc
->LinesTotal() - 1)) { 
1917                 if (primarySelection
) 
1918                         surface
->FillRectangle(rcSegment
, vsDraw
.selbackground
.allocated
); 
1920                         surface
->FillRectangle(rcSegment
, vsDraw
.selbackground2
.allocated
); 
1921         } else if (overrideBackground
) { 
1922                 surface
->FillRectangle(rcSegment
, background
); 
1924                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].back
.allocated
); 
1927         rcSegment
.left 
= xEol 
+ vsDraw
.aveCharWidth 
+ xStart
; 
1928         rcSegment
.right 
= rcLine
.right
; 
1929         if (overrideBackground
) { 
1930                 surface
->FillRectangle(rcSegment
, background
); 
1931         } else if (vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].eolFilled
) { 
1932                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].back
.allocated
); 
1934                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[STYLE_DEFAULT
].back
.allocated
); 
1938 void Editor::DrawLine(Surface 
*surface
, ViewStyle 
&vsDraw
, int line
, int lineVisible
, int xStart
, 
1939                       PRectangle rcLine
, LineLayout 
*ll
, int subLine
) { 
1941         PRectangle rcSegment 
= rcLine
; 
1943         // Using one font for all control characters so it can be controlled independently to ensure 
1944         // the box goes around the characters tightly. Seems to be no way to work out what height 
1945         // is taken by an individual character - internal leading gives varying results. 
1946         Font 
&ctrlCharsFont 
= vsDraw
.styles
[STYLE_CONTROLCHAR
].font
; 
1948         // See if something overrides the line background color:  Either if caret is on the line 
1949         // and background color is set for that, or if a marker is defined that forces its background 
1950         // color onto the line, or if a marker is defined but has no selection margin in which to 
1951         // display itself.  These are checked in order with the earlier taking precedence.  When 
1952         // multiple markers cause background override, the color for the highest numbered one is used. 
1953         bool overrideBackground 
= false; 
1954         ColourAllocated background
; 
1955         if (caret
.active 
&& vsDraw
.showCaretLineBackground 
&& ll
->containsCaret
) { 
1956                 overrideBackground 
= true; 
1957                 background 
= vsDraw
.caretLineBackground
.allocated
; 
1959         if (!overrideBackground
) { 
1960                 int marks 
= pdoc
->GetMark(line
); 
1961                 for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
1962                         if ((marks 
& 1) && vsDraw
.markers
[markBit
].markType 
== SC_MARK_BACKGROUND
) { 
1963                                 background 
= vsDraw
.markers
[markBit
].back
.allocated
; 
1964                                 overrideBackground 
= true; 
1969         if (!overrideBackground
) { 
1970                 if (vsDraw
.maskInLine
) { 
1971                         int marks 
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
; 
1973                                 overrideBackground 
= true; 
1974                                 for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
1976                                                 background 
= vsDraw
.markers
[markBit
].back
.allocated
; 
1984         bool drawWhitespaceBackground 
= (vsDraw
.viewWhitespace 
!= wsInvisible
) && 
1985                                         (!overrideBackground
) && (vsDraw
.whitespaceBackgroundSet
); 
1987         bool inIndentation 
= subLine 
== 0;      // Do not handle indentation except on first subline. 
1988         int indentWidth 
= pdoc
->indentInChars 
* vsDraw
.spaceWidth
; 
1989         if (indentWidth 
== 0) 
1990                 indentWidth 
= pdoc
->tabInChars 
* vsDraw
.spaceWidth
; 
1992         int posLineStart 
= pdoc
->LineStart(line
); 
1994         int startseg 
= ll
->LineStart(subLine
); 
1995         int subLineStart 
= ll
->positions
[startseg
]; 
1998         if (subLine 
< ll
->lines
) { 
1999                 lineStart 
= ll
->LineStart(subLine
); 
2000                 lineEnd 
= ll
->LineStart(subLine 
+ 1); 
2004         // Background drawing loop 
2005         for (i 
= lineStart
; twoPhaseDraw 
&& (i 
< lineEnd
); i
++) { 
2007                 int iDoc 
= i 
+ posLineStart
; 
2008                 // If there is the end of a style run for any reason 
2009                 if ((ll
->styles
[i
] != ll
->styles
[i 
+ 1]) || 
2010                         i 
== (lineEnd 
- 1) || 
2011                         IsControlCharacter(ll
->chars
[i
]) || IsControlCharacter(ll
->chars
[i 
+ 1]) || 
2012                         ((ll
->selStart 
!= ll
->selEnd
) && ((iDoc 
+ 1 == ll
->selStart
) || (iDoc 
+ 1 == ll
->selEnd
))) || 
2013                         (i 
== (ll
->edgeColumn 
- 1))) { 
2014                         rcSegment
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2015                         rcSegment
.right 
= ll
->positions
[i 
+ 1] + xStart 
- subLineStart
; 
2016                         // Only try to draw if really visible - enhances performance by not calling environment to 
2017                         // draw strings that are completely past the right side of the window. 
2018                         if ((rcSegment
.left 
<= rcLine
.right
) && (rcSegment
.right 
>= rcLine
.left
)) { 
2019                                 int styleMain 
= ll
->styles
[i
]; 
2020                                 bool inSelection 
= (iDoc 
>= ll
->selStart
) && (iDoc 
< ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2021                                 bool inHotspot 
= (ll
->hsStart 
!= -1) && (iDoc 
>= ll
->hsStart
) && (iDoc 
< ll
->hsEnd
); 
2022                                 ColourAllocated textBack 
= TextBackground(vsDraw
, overrideBackground
, background
, inSelection
, inHotspot
, styleMain
, i
, ll
); 
2023                                 if (ll
->chars
[i
] == '\t') { 
2025                                         if (drawWhitespaceBackground 
&& 
2026                                                 (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) 
2027                                                 textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2028                                         surface
->FillRectangle(rcSegment
, textBack
); 
2029                                 } else if (IsControlCharacter(ll
->chars
[i
])) { 
2030                                         // Control character display 
2031                                         inIndentation 
= false; 
2032                                         surface
->FillRectangle(rcSegment
, textBack
); 
2034                                         // Normal text display 
2035                                         surface
->FillRectangle(rcSegment
, textBack
); 
2036                                         if (vsDraw
.viewWhitespace 
!= wsInvisible 
|| 
2037                                                 (inIndentation 
&& vsDraw
.viewIndentationGuides
)) { 
2038                                                 for (int cpos 
= 0; cpos 
<= i 
- startseg
; cpos
++) { 
2039                                                         if (ll
->chars
[cpos 
+ startseg
] == ' ') { 
2040                                                                 if (drawWhitespaceBackground 
&& 
2041                                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) { 
2042                                                                         PRectangle 
rcSpace(ll
->positions
[cpos 
+ startseg
] + xStart
, rcSegment
.top
, 
2043                                                                                            ll
->positions
[cpos 
+ startseg 
+ 1] + xStart
, rcSegment
.bottom
); 
2044                                                                         surface
->FillRectangle(rcSpace
, vsDraw
.whitespaceBackground
.allocated
); 
2047                                                                 inIndentation 
= false; 
2058                 DrawEOL(surface
, vsDraw
, rcLine
, ll
, line
, lineEnd
, 
2059                         xStart
, subLine
, subLineStart
, overrideBackground
, background
); 
2062         inIndentation 
= subLine 
== 0;   // Do not handle indentation except on first subline. 
2063         startseg 
= ll
->LineStart(subLine
); 
2064         // Foreground drawing loop 
2065         for (i 
= lineStart
; i 
< lineEnd
; i
++) { 
2067                 int iDoc 
= i 
+ posLineStart
; 
2068                 // If there is the end of a style run for any reason 
2069                 if ((ll
->styles
[i
] != ll
->styles
[i 
+ 1]) || 
2070                         i 
== (lineEnd 
- 1) || 
2071                         IsControlCharacter(ll
->chars
[i
]) || IsControlCharacter(ll
->chars
[i 
+ 1]) || 
2072                         ((ll
->selStart 
!= ll
->selEnd
) && ((iDoc 
+ 1 == ll
->selStart
) || (iDoc 
+ 1 == ll
->selEnd
))) || 
2073                         (i 
== (ll
->edgeColumn 
- 1))) { 
2074                         rcSegment
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2075                         rcSegment
.right 
= ll
->positions
[i 
+ 1] + xStart 
- subLineStart
; 
2076                         // Only try to draw if really visible - enhances performance by not calling environment to 
2077                         // draw strings that are completely past the right side of the window. 
2078                         if ((rcSegment
.left 
<= rcLine
.right
) && (rcSegment
.right 
>= rcLine
.left
)) { 
2079                                 int styleMain 
= ll
->styles
[i
]; 
2080                                 ColourAllocated textFore 
= vsDraw
.styles
[styleMain
].fore
.allocated
; 
2081                                 Font 
&textFont 
= vsDraw
.styles
[styleMain
].font
; 
2082                                 //hotspot foreground 
2083                                 if (ll
->hsStart 
!= -1 && iDoc 
>= ll
->hsStart 
&& iDoc 
< hsEnd
) { 
2084                                         if (vsDraw
.hotspotForegroundSet
) 
2085                                                 textFore 
= vsDraw
.hotspotForeground
.allocated
; 
2087                                 bool inSelection 
= (iDoc 
>= ll
->selStart
) && (iDoc 
< ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2088                                 if (inSelection 
&& (vsDraw
.selforeset
)) { 
2089                                         textFore 
= vsDraw
.selforeground
.allocated
; 
2091                                 bool inHotspot 
= (ll
->hsStart 
!= -1) && (iDoc 
>= ll
->hsStart
) && (iDoc 
< ll
->hsEnd
); 
2092                                 ColourAllocated textBack 
= TextBackground(vsDraw
, overrideBackground
, background
, inSelection
, inHotspot
, styleMain
, i
, ll
); 
2093                                 if (ll
->chars
[i
] == '\t') { 
2095                                         if (!twoPhaseDraw
) { 
2096                                                 if (drawWhitespaceBackground 
&& 
2097                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) 
2098                                                         textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2099                                                 surface
->FillRectangle(rcSegment
, textBack
); 
2101                                         if ((vsDraw
.viewWhitespace 
!= wsInvisible
) || ((inIndentation 
&& vsDraw
.viewIndentationGuides
))) { 
2102                                                 if (vsDraw
.whitespaceForegroundSet
) 
2103                                                         textFore 
= vsDraw
.whitespaceForeground
.allocated
; 
2104                                                 surface
->PenColour(textFore
); 
2106                                         if (inIndentation 
&& vsDraw
.viewIndentationGuides
) { 
2107                                                 for (int xIG 
= ll
->positions
[i
] / indentWidth 
* indentWidth
; xIG 
< ll
->positions
[i 
+ 1]; xIG 
+= indentWidth
) { 
2108                                                         if (xIG 
>= ll
->positions
[i
] && xIG 
> 0) { 
2109                                                                 DrawIndentGuide(surface
, lineVisible
, vsDraw
.lineHeight
, xIG 
+ xStart
, rcSegment
, 
2110                                                                                 (ll
->xHighlightGuide 
== xIG
)); 
2114                                         if (vsDraw
.viewWhitespace 
!= wsInvisible
) { 
2115                                                 if (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
) { 
2116                                                         PRectangle 
rcTab(rcSegment
.left 
+ 1, rcSegment
.top 
+ 4, 
2117                                                                          rcSegment
.right 
- 1, rcSegment
.bottom 
- vsDraw
.maxDescent
); 
2118                                                         DrawTabArrow(surface
, rcTab
, rcSegment
.top 
+ vsDraw
.lineHeight 
/ 2); 
2121                                 } else if (IsControlCharacter(ll
->chars
[i
])) { 
2122                                         // Control character display 
2123                                         inIndentation 
= false; 
2124                                         if (controlCharSymbol 
< 32) { 
2125                                                 // Draw the character 
2126                                                 const char *ctrlChar 
= ControlCharacterString(ll
->chars
[i
]); 
2127                                                 if (!twoPhaseDraw
) { 
2128                                                         surface
->FillRectangle(rcSegment
, textBack
); 
2130                                                 int normalCharHeight 
= surface
->Ascent(ctrlCharsFont
) - 
2131                                                                        surface
->InternalLeading(ctrlCharsFont
); 
2132                                                 PRectangle rcCChar 
= rcSegment
; 
2133                                                 rcCChar
.left 
= rcCChar
.left 
+ 1; 
2134                                                 rcCChar
.top 
= rcSegment
.top 
+ vsDraw
.maxAscent 
- normalCharHeight
; 
2135                                                 rcCChar
.bottom 
= rcSegment
.top 
+ vsDraw
.maxAscent 
+ 1; 
2136                                                 PRectangle rcCentral 
= rcCChar
; 
2139                                                 surface
->FillRectangle(rcCentral
, textFore
); 
2140                                                 PRectangle rcChar 
= rcCChar
; 
2143                                                 surface
->DrawTextClipped(rcChar
, ctrlCharsFont
, 
2144                                                                          rcSegment
.top 
+ vsDraw
.maxAscent
, ctrlChar
, istrlen(ctrlChar
), 
2145                                                                          textBack
, textFore
); 
2147                                                 char cc
[2] = { static_cast<char>(controlCharSymbol
), '\0' }; 
2148                                                 surface
->DrawTextNoClip(rcSegment
, ctrlCharsFont
, 
2149                                                                         rcSegment
.top 
+ vsDraw
.maxAscent
, 
2150                                                                         cc
, 1, textBack
, textFore
); 
2153                                         // Normal text display 
2154                                         if (vsDraw
.styles
[styleMain
].visible
) { 
2156                                                         surface
->DrawTextTransparent(rcSegment
, textFont
, 
2157                                                                                      rcSegment
.top 
+ vsDraw
.maxAscent
, ll
->chars 
+ startseg
, 
2158                                                                                      i 
- startseg 
+ 1, textFore
); 
2160                                                         surface
->DrawTextNoClip(rcSegment
, textFont
, 
2161                                                                                 rcSegment
.top 
+ vsDraw
.maxAscent
, ll
->chars 
+ startseg
, 
2162                                                                                 i 
- startseg 
+ 1, textFore
, textBack
); 
2165                                         if (vsDraw
.viewWhitespace 
!= wsInvisible 
|| 
2166                                                 (inIndentation 
&& vsDraw
.viewIndentationGuides
)) { 
2167                                                 for (int cpos 
= 0; cpos 
<= i 
- startseg
; cpos
++) { 
2168                                                         if (ll
->chars
[cpos 
+ startseg
] == ' ') { 
2169                                                                 if (vsDraw
.viewWhitespace 
!= wsInvisible
) { 
2170                                                                         if (vsDraw
.whitespaceForegroundSet
) 
2171                                                                                 textFore 
= vsDraw
.whitespaceForeground
.allocated
; 
2172                                                                         if (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
) { 
2173                                                                                 int xmid 
= (ll
->positions
[cpos 
+ startseg
] + ll
->positions
[cpos 
+ startseg 
+ 1]) / 2; 
2174                                                                                 if (!twoPhaseDraw 
&& drawWhitespaceBackground 
&& 
2175                                                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) { 
2176                                                                                         textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2177                                                                                         PRectangle 
rcSpace(ll
->positions
[cpos 
+ startseg
] + xStart
, rcSegment
.top
, ll
->positions
[cpos 
+ startseg 
+ 1] + xStart
, rcSegment
.bottom
); 
2178                                                                                         surface
->FillRectangle(rcSpace
, textBack
); 
2180                                                                                 PRectangle 
rcDot(xmid 
+ xStart 
- subLineStart
, rcSegment
.top 
+ vsDraw
.lineHeight 
/ 2, 0, 0); 
2181                                                                                 rcDot
.right 
= rcDot
.left 
+ 1; 
2182                                                                                 rcDot
.bottom 
= rcDot
.top 
+ 1; 
2183                                                                                 surface
->FillRectangle(rcDot
, textFore
); 
2186                                                                 if (inIndentation 
&& vsDraw
.viewIndentationGuides
) { 
2187                                                                         int startSpace 
= ll
->positions
[cpos 
+ startseg
]; 
2188                                                                         if (startSpace 
> 0 && (startSpace 
% indentWidth 
== 0)) { 
2189                                                                                 DrawIndentGuide(surface
, lineVisible
, vsDraw
.lineHeight
, startSpace 
+ xStart
, rcSegment
, 
2190                                                                                                 (ll
->xHighlightGuide 
== ll
->positions
[cpos 
+ startseg
])); 
2194                                                                 inIndentation 
= false; 
2199                                 if (ll
->hsStart 
!= -1 && vsDraw
.hotspotUnderline 
&& iDoc 
>= ll
->hsStart 
&& iDoc 
< ll
->hsEnd 
) { 
2200                                         PRectangle rcUL 
= rcSegment
; 
2201                                         rcUL
.top 
= rcUL
.top 
+ vsDraw
.maxAscent 
+ 1; 
2202                                         rcUL
.bottom 
= rcUL
.top 
+ 1; 
2203                                         if (vsDraw
.hotspotForegroundSet
) 
2204                                                 surface
->FillRectangle(rcUL
, vsDraw
.hotspotForeground
.allocated
); 
2206                                                 surface
->FillRectangle(rcUL
, textFore
); 
2207                                 } else if (vsDraw
.styles
[styleMain
].underline
) { 
2208                                         PRectangle rcUL 
= rcSegment
; 
2209                                         rcUL
.top 
= rcUL
.top 
+ vsDraw
.maxAscent 
+ 1; 
2210                                         rcUL
.bottom 
= rcUL
.top 
+ 1; 
2211                                         surface
->FillRectangle(rcUL
, textFore
); 
2219         int indStart
[INDIC_MAX 
+ 1] = {0}; 
2220         for (int indica 
= 0; indica 
<= INDIC_MAX
; indica
++) 
2221                 indStart
[indica
] = 0; 
2223         for (int indicPos 
= 0; indicPos 
< ll
->numCharsInLine
; indicPos
++) { 
2224                 if (ll
->indicators
[indicPos
] != ll
->indicators
[indicPos 
+ 1]) { 
2225                         int mask 
= 1 << pdoc
->stylingBits
; 
2226                         for (int indicnum 
= 0; mask 
< 0x100; indicnum
++) { 
2227                                 if ((ll
->indicators
[indicPos 
+ 1] & mask
) && !(ll
->indicators
[indicPos
] & mask
)) { 
2228                                         indStart
[indicnum
] = ll
->positions
[indicPos 
+ 1]; 
2230                                 if (!(ll
->indicators
[indicPos 
+ 1] & mask
) && (ll
->indicators
[indicPos
] & mask
)) { 
2232                                             indStart
[indicnum
] + xStart
, 
2233                                             rcLine
.top 
+ vsDraw
.maxAscent
, 
2234                                             ll
->positions
[indicPos 
+ 1] + xStart
, 
2235                                             rcLine
.top 
+ vsDraw
.maxAscent 
+ 3); 
2236                                         vsDraw
.indicators
[indicnum
].Draw(surface
, rcIndic
); 
2242         // End of the drawing of the current line 
2244         if (!twoPhaseDraw
) { 
2245                 DrawEOL(surface
, vsDraw
, rcLine
, ll
, line
, lineEnd
, 
2246                         xStart
, subLine
, subLineStart
, overrideBackground
, background
); 
2249         if (vsDraw
.edgeState 
== EDGE_LINE
) { 
2250                 int edgeX 
= theEdge 
* vsDraw
.spaceWidth
; 
2251                 rcSegment
.left 
= edgeX 
+ xStart
; 
2252                 rcSegment
.right 
= rcSegment
.left 
+ 1; 
2253                 surface
->FillRectangle(rcSegment
, vsDraw
.edgecolour
.allocated
); 
2257 void Editor::RefreshPixMaps(Surface 
*surfaceWindow
) { 
2258         if (!pixmapSelPattern
->Initialised()) { 
2259                 const int patternSize 
= 8; 
2260                 pixmapSelPattern
->InitPixMap(patternSize
, patternSize
, surfaceWindow
, wMain
.GetID()); 
2261                 // This complex procedure is to reproduce the checkerboard dithered pattern used by windows 
2262                 // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half 
2263                 // way between the chrome colour and the chrome highlight colour making a nice transition 
2264                 // between the window chrome and the content area. And it works in low colour depths. 
2265                 PRectangle 
rcPattern(0, 0, patternSize
, patternSize
); 
2267                 // Initialize default colours based on the chrome colour scheme.  Typically the highlight is white. 
2268                 ColourAllocated colourFMFill 
= vs
.selbar
.allocated
; 
2269                 ColourAllocated colourFMStripes 
= vs
.selbarlight
.allocated
; 
2271                 if (!(vs
.selbarlight
.desired 
== ColourDesired(0xff, 0xff, 0xff))) { 
2272                         // User has chosen an unusual chrome colour scheme so just use the highlight edge colour. 
2273                         // (Typically, the highlight colour is white.) 
2274                         colourFMFill 
= vs
.selbarlight
.allocated
; 
2277                 if (vs
.foldmarginColourSet
) { 
2278                         // override default fold margin colour 
2279                         colourFMFill 
= vs
.foldmarginColour
.allocated
; 
2281                 if (vs
.foldmarginHighlightColourSet
) { 
2282                         // override default fold margin highlight colour 
2283                         colourFMStripes 
= vs
.foldmarginHighlightColour
.allocated
; 
2286                 pixmapSelPattern
->FillRectangle(rcPattern
, colourFMFill
); 
2287                 pixmapSelPattern
->PenColour(colourFMStripes
); 
2288                 for (int stripe 
= 0; stripe 
< patternSize
; stripe
++) { 
2289                         // Alternating 1 pixel stripes is same as checkerboard. 
2290                         pixmapSelPattern
->MoveTo(0, stripe 
* 2); 
2291                         pixmapSelPattern
->LineTo(patternSize
, stripe 
* 2 - patternSize
); 
2295         if (!pixmapIndentGuide
->Initialised()) { 
2296                 // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line 
2297                 pixmapIndentGuide
->InitPixMap(1, vs
.lineHeight 
+ 1, surfaceWindow
, wMain
.GetID()); 
2298                 pixmapIndentGuideHighlight
->InitPixMap(1, vs
.lineHeight 
+ 1, surfaceWindow
, wMain
.GetID()); 
2299                 PRectangle 
rcIG(0, 0, 1, vs
.lineHeight
); 
2300                 pixmapIndentGuide
->FillRectangle(rcIG
, vs
.styles
[STYLE_INDENTGUIDE
].back
.allocated
); 
2301                 pixmapIndentGuide
->PenColour(vs
.styles
[STYLE_INDENTGUIDE
].fore
.allocated
); 
2302                 pixmapIndentGuideHighlight
->FillRectangle(rcIG
, vs
.styles
[STYLE_BRACELIGHT
].back
.allocated
); 
2303                 pixmapIndentGuideHighlight
->PenColour(vs
.styles
[STYLE_BRACELIGHT
].fore
.allocated
); 
2304                 for (int stripe 
= 1; stripe 
< vs
.lineHeight 
+ 1; stripe 
+= 2) { 
2305                         pixmapIndentGuide
->MoveTo(0, stripe
); 
2306                         pixmapIndentGuide
->LineTo(2, stripe
); 
2307                         pixmapIndentGuideHighlight
->MoveTo(0, stripe
); 
2308                         pixmapIndentGuideHighlight
->LineTo(2, stripe
); 
2313                 if (!pixmapLine
->Initialised()) { 
2314                         PRectangle rcClient 
= GetClientRectangle(); 
2315                         pixmapLine
->InitPixMap(rcClient
.Width(), rcClient
.Height(), 
2316                                                surfaceWindow
, wMain
.GetID()); 
2317                         pixmapSelMargin
->InitPixMap(vs
.fixedColumnWidth
, 
2318                                                     rcClient
.Height(), surfaceWindow
, wMain
.GetID()); 
2323 void Editor::Paint(Surface 
*surfaceWindow
, PRectangle rcArea
) { 
2324         //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n", 
2325         //      paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); 
2329         RefreshPixMaps(surfaceWindow
); 
2331         PRectangle rcClient 
= GetClientRectangle(); 
2332         //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n", 
2333         //      rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); 
2335         surfaceWindow
->SetPalette(&palette
, true); 
2336         pixmapLine
->SetPalette(&palette
, !hasFocus
); 
2338         int screenLinePaintFirst 
= rcArea
.top 
/ vs
.lineHeight
; 
2339         // The area to be painted plus one extra line is styled. 
2340         // The extra line is to determine when a style change, such as starting a comment flows on to other lines. 
2341         int lineStyleLast 
= topLine 
+ (rcArea
.bottom 
- 1) / vs
.lineHeight 
+ 1; 
2342         //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast); 
2343         int endPosPaint 
= pdoc
->Length(); 
2344         if (lineStyleLast 
< cs
.LinesDisplayed()) 
2345                 endPosPaint 
= pdoc
->LineStart(cs
.DocFromDisplay(lineStyleLast 
+ 1)); 
2347         int xStart 
= vs
.fixedColumnWidth 
- xOffset
; 
2350                 ypos 
+= screenLinePaintFirst 
* vs
.lineHeight
; 
2351         int yposScreen 
= screenLinePaintFirst 
* vs
.lineHeight
; 
2353         // Ensure we are styled as far as we are painting. 
2354         pdoc
->EnsureStyledTo(endPosPaint
); 
2355         bool paintAbandonedByStyling 
= paintState 
== paintAbandoned
; 
2358                 needUpdateUI 
= false; 
2361         PaintSelMargin(surfaceWindow
, rcArea
); 
2364                 // The wrapping process has changed the height of some lines so abandon this 
2365                 // paint for a complete repaint. 
2366                 if (AbandonPaint()) { 
2369                 RefreshPixMaps(surfaceWindow
);  // In case pixmaps invalidated by scrollbar change 
2371         PLATFORM_ASSERT(pixmapSelPattern
->Initialised()); 
2373         PRectangle rcRightMargin 
= rcClient
; 
2374         rcRightMargin
.left 
= rcRightMargin
.right 
- vs
.rightMarginWidth
; 
2375         if (rcArea
.Intersects(rcRightMargin
)) { 
2376                 surfaceWindow
->FillRectangle(rcRightMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2379         if (paintState 
== paintAbandoned
) { 
2380                 // Either styling or NotifyUpdateUI noticed that painting is needed 
2381                 // outside the current painting rectangle 
2382                 //Platform::DebugPrintf("Abandoning paint\n"); 
2383                 if (wrapState 
!= eWrapNone
) { 
2384                         if (paintAbandonedByStyling
) { 
2385                                 // Styling has spilled over a line end, such as occurs by starting a multiline 
2386                                 // comment. The width of subsequent text may have changed, so rewrap. 
2387                                 NeedWrapping(cs
.DocFromDisplay(topLine
)); 
2392         //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); 
2395         if (rcArea
.right 
> vs
.fixedColumnWidth
) { 
2397                 Surface 
*surface 
= surfaceWindow
; 
2399                         surface 
= pixmapLine
; 
2400                         PLATFORM_ASSERT(pixmapLine
->Initialised()); 
2402                 surface
->SetUnicodeMode(IsUnicodeMode()); 
2403                 surface
->SetDBCSMode(CodePage()); 
2405                 int visibleLine 
= topLine 
+ screenLinePaintFirst
; 
2407                 int posCaret 
= currentPos
; 
2410                 int lineCaret 
= pdoc
->LineFromPosition(posCaret
); 
2412                 // Remove selection margin from drawing area so text will not be drawn 
2413                 // on it in unbuffered mode. 
2414                 PRectangle rcTextArea 
= rcClient
; 
2415                 rcTextArea
.left 
= vs
.fixedColumnWidth
; 
2416                 rcTextArea
.right 
-= vs
.rightMarginWidth
; 
2417                 surfaceWindow
->SetClip(rcTextArea
); 
2419                 // Loop on visible lines 
2420                 //double durLayout = 0.0; 
2421                 //double durPaint = 0.0; 
2422                 //double durCopy = 0.0; 
2423                 //ElapsedTime etWhole; 
2424                 int lineDocPrevious 
= -1;       // Used to avoid laying out one document line multiple times 
2425                 AutoLineLayout 
ll(llc
, 0); 
2426                 while (visibleLine 
< cs
.LinesDisplayed() && yposScreen 
< rcArea
.bottom
) { 
2428                         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
2429                         // Only visible lines should be handled by the code within the loop 
2430                         PLATFORM_ASSERT(cs
.GetVisible(lineDoc
)); 
2431                         int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
2432                         int subLine 
= visibleLine 
- lineStartSet
; 
2434                         // Copy this line and its styles from the document into local arrays 
2435                         // and determine the x position at which each character starts. 
2437                         if (lineDoc 
!= lineDocPrevious
) { 
2438                                 ll
.Set(RetrieveLineLayout(lineDoc
)); 
2439                                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
2440                                 lineDocPrevious 
= lineDoc
; 
2442                         //durLayout += et.Duration(true); 
2445                                 ll
->selStart 
= SelectionStart(lineDoc
); 
2446                                 ll
->selEnd 
= SelectionEnd(lineDoc
); 
2447                                 ll
->containsCaret 
= lineDoc 
== lineCaret
; 
2448                                 if (hideSelection
) { 
2451                                         ll
->containsCaret 
= false; 
2454                                 GetHotSpotRange(ll
->hsStart
, ll
->hsEnd
); 
2456                                 PRectangle rcLine 
= rcClient
; 
2458                                 rcLine
.bottom 
= ypos 
+ vs
.lineHeight
; 
2460                                 Range 
rangeLine(pdoc
->LineStart(lineDoc
), pdoc
->LineStart(lineDoc 
+ 1)); 
2461                                 // Highlight the current braces if any 
2462                                 ll
->SetBracesHighlight(rangeLine
, braces
, static_cast<char>(bracesMatchStyle
), 
2463                                                        highlightGuideColumn 
* vs
.spaceWidth
); 
2466                                 DrawLine(surface
, vs
, lineDoc
, visibleLine
, xStart
, rcLine
, ll
, subLine
); 
2467                                 //durPaint += et.Duration(true); 
2469                                 // Restore the precvious styles for the brace highlights in case layout is in cache. 
2470                                 ll
->RestoreBracesHighlight(rangeLine
, braces
); 
2472                                 bool expanded 
= cs
.GetExpanded(lineDoc
); 
2473                                 if ((foldFlags 
& SC_FOLDFLAG_BOX
) == 0) { 
2474                                         // Paint the line above the fold 
2475                                         if ((expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEBEFORE_EXPANDED
)) 
2477                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEBEFORE_CONTRACTED
))) { 
2478                                                 if (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELHEADERFLAG
) { 
2479                                                         PRectangle rcFoldLine 
= rcLine
; 
2480                                                         rcFoldLine
.bottom 
= rcFoldLine
.top 
+ 1; 
2481                                                         surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2484                                         // Paint the line below the fold 
2485                                         if ((expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_EXPANDED
)) 
2487                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_CONTRACTED
))) { 
2488                                                 if (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELHEADERFLAG
) { 
2489                                                         PRectangle rcFoldLine 
= rcLine
; 
2490                                                         rcFoldLine
.top 
= rcFoldLine
.bottom 
- 1; 
2491                                                         surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2495                                         int FoldLevelCurr 
= (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELNUMBERMASK
) - SC_FOLDLEVELBASE
; 
2496                                         int FoldLevelPrev 
= (pdoc
->GetLevel(lineDoc 
- 1) & SC_FOLDLEVELNUMBERMASK
) - SC_FOLDLEVELBASE
; 
2497                                         int FoldLevelFlags 
= (pdoc
->GetLevel(lineDoc
) & ~SC_FOLDLEVELNUMBERMASK
) & ~(0xFFF0000); 
2498                                         int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
2499                                         // Draw line above fold 
2500                                         if ((FoldLevelPrev 
< FoldLevelCurr
) 
2502                                                 (FoldLevelFlags 
& SC_FOLDLEVELBOXHEADERFLAG
 
2504                                                  (pdoc
->GetLevel(lineDoc 
- 1) & SC_FOLDLEVELBOXFOOTERFLAG
) == 0)) { 
2505                                                 PRectangle rcFoldLine 
= rcLine
; 
2506                                                 rcFoldLine
.bottom 
= rcFoldLine
.top 
+ 1; 
2507                                                 rcFoldLine
.left 
+= xStart 
+ FoldLevelCurr 
* vs
.spaceWidth 
* indentationStep 
- 1; 
2508                                                 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2511                                         // Line below the fold (or below a contracted fold) 
2512                                         if (FoldLevelFlags 
& SC_FOLDLEVELBOXFOOTERFLAG
 
2514                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_CONTRACTED
))) { 
2515                                                 PRectangle rcFoldLine 
= rcLine
; 
2516                                                 rcFoldLine
.top 
= rcFoldLine
.bottom 
- 1; 
2517                                                 rcFoldLine
.left 
+= xStart 
+ (FoldLevelCurr
) * vs
.spaceWidth 
* indentationStep 
- 1; 
2518                                                 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2521                                         PRectangle rcBoxLine 
= rcLine
; 
2522                                         // Draw vertical line for every fold level 
2523                                         for (int i 
= 0; i 
<= FoldLevelCurr
; i
++) { 
2524                                                 rcBoxLine
.left 
= xStart 
+ i 
* vs
.spaceWidth 
* indentationStep 
- 1; 
2525                                                 rcBoxLine
.right 
= rcBoxLine
.left 
+ 1; 
2526                                                 surface
->FillRectangle(rcBoxLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2531                                 if (lineDoc 
== lineCaret
) { 
2532                                         int offset 
= Platform::Minimum(posCaret 
- rangeLine
.start
, ll
->maxLineLength
); 
2533                                         if ((offset 
>= ll
->LineStart(subLine
)) && 
2534                                                 ((offset 
< ll
->LineStart(subLine 
+ 1)) || offset 
== ll
->numCharsInLine
)) { 
2535                                                 int xposCaret 
= ll
->positions
[offset
] - ll
->positions
[ll
->LineStart(subLine
)] + xStart
; 
2536                                                 int widthOverstrikeCaret
; 
2537                                                 if (posCaret 
== pdoc
->Length()) {   // At end of document 
2538                                                         widthOverstrikeCaret 
= vs
.aveCharWidth
; 
2539                                                 } else if ((posCaret 
- rangeLine
.start
) >= ll
->numCharsInLine
) {        // At end of line 
2540                                                         widthOverstrikeCaret 
= vs
.aveCharWidth
; 
2542                                                         widthOverstrikeCaret 
= ll
->positions
[offset 
+ 1] - ll
->positions
[offset
]; 
2544                                                 if (widthOverstrikeCaret 
< 3)   // Make sure its visible 
2545                                                         widthOverstrikeCaret 
= 3; 
2546                                                 if (((caret
.active 
&& caret
.on
) || (posDrag 
>= 0)) && xposCaret 
>= 0) { 
2547                                                         PRectangle rcCaret 
= rcLine
; 
2548                                                         int caretWidthOffset 
= 0; 
2549                                                         if ((offset 
> 0) && (vs
.caretWidth 
> 1)) 
2550                                                                 caretWidthOffset 
= 1;   // Move back so overlaps both character cells. 
2552                                                                 rcCaret
.left 
= xposCaret 
- caretWidthOffset
; 
2553                                                                 rcCaret
.right 
= rcCaret
.left 
+ vs
.caretWidth
; 
2556                                                                         rcCaret
.top 
= rcCaret
.bottom 
- 2; 
2557                                                                         rcCaret
.left 
= xposCaret 
+ 1; 
2558                                                                         rcCaret
.right 
= rcCaret
.left 
+ widthOverstrikeCaret 
- 1; 
2560                                                                         rcCaret
.left 
= xposCaret 
- caretWidthOffset
; 
2561                                                                         rcCaret
.right 
= rcCaret
.left 
+ vs
.caretWidth
; 
2564                                                         surface
->FillRectangle(rcCaret
, vs
.caretcolour
.allocated
); 
2570                                         Point 
from(vs
.fixedColumnWidth
, 0); 
2571                                         PRectangle 
rcCopyArea(vs
.fixedColumnWidth
, yposScreen
, 
2572                                                               rcClient
.right
, yposScreen 
+ vs
.lineHeight
); 
2573                                         surfaceWindow
->Copy(rcCopyArea
, from
, *pixmapLine
); 
2575                                 //durCopy += et.Duration(true); 
2578                         if (!bufferedDraw
) { 
2579                                 ypos 
+= vs
.lineHeight
; 
2582                         yposScreen 
+= vs
.lineHeight
; 
2586                 //if (durPaint < 0.00000001) 
2587                 //      durPaint = 0.00000001; 
2589                 // Right column limit indicator 
2590                 PRectangle rcBeyondEOF 
= rcClient
; 
2591                 rcBeyondEOF
.left 
= vs
.fixedColumnWidth
; 
2592                 rcBeyondEOF
.right 
= rcBeyondEOF
.right
; 
2593                 rcBeyondEOF
.top 
= (cs
.LinesDisplayed() - topLine
) * vs
.lineHeight
; 
2594                 if (rcBeyondEOF
.top 
< rcBeyondEOF
.bottom
) { 
2595                         surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2596                         if (vs
.edgeState 
== EDGE_LINE
) { 
2597                                 int edgeX 
= theEdge 
* vs
.spaceWidth
; 
2598                                 rcBeyondEOF
.left 
= edgeX 
+ xStart
; 
2599                                 rcBeyondEOF
.right 
= rcBeyondEOF
.left 
+ 1; 
2600                                 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.edgecolour
.allocated
); 
2603                 //Platform::DebugPrintf( 
2604                 //"Layout:%9.6g    Paint:%9.6g    Ratio:%9.6g   Copy:%9.6g   Total:%9.6g\n", 
2605                 //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); 
2610 // Space (3 space characters) between line numbers and text when printing. 
2611 #define lineNumberPrintSpace "   " 
2613 ColourDesired 
InvertedLight(ColourDesired orig
) { 
2614         unsigned int r 
= orig
.GetRed(); 
2615         unsigned int g 
= orig
.GetGreen(); 
2616         unsigned int b 
= orig
.GetBlue(); 
2617         unsigned int l 
= (r 
+ g 
+ b
) / 3;       // There is a better calculation for this that matches human eye 
2618         unsigned int il 
= 0xff - l
; 
2620                 return ColourDesired(0xff, 0xff, 0xff); 
2624         return ColourDesired(Platform::Minimum(r
, 0xff), Platform::Minimum(g
, 0xff), Platform::Minimum(b
, 0xff)); 
2627 // This is mostly copied from the Paint method but with some things omitted 
2628 // such as the margin markers, line numbers, selection and caret 
2629 // Should be merged back into a combined Draw method. 
2630 long Editor::FormatRange(bool draw
, RangeToFormat 
*pfr
) { 
2634         AutoSurface 
surface(pfr
->hdc
, this); 
2637         AutoSurface 
surfaceMeasure(pfr
->hdcTarget
, this); 
2638         if (!surfaceMeasure
) { 
2642         ViewStyle 
vsPrint(vs
); 
2644         // Modify the view style for printing as do not normally want any of the transient features to be printed 
2645         // Printing supports only the line number margin. 
2646         int lineNumberIndex 
= -1; 
2647         for (int margin 
= 0; margin 
< ViewStyle::margins
; margin
++) { 
2648                 if ((!vsPrint
.ms
[margin
].symbol
) && (vsPrint
.ms
[margin
].width 
> 0)) { 
2649                         lineNumberIndex 
= margin
; 
2651                         vsPrint
.ms
[margin
].width 
= 0; 
2654         vsPrint
.showMarkedLines 
= false; 
2655         vsPrint
.fixedColumnWidth 
= 0; 
2656         vsPrint
.zoomLevel 
= printMagnification
; 
2657         vsPrint
.viewIndentationGuides 
= false; 
2658         // Don't show the selection when printing 
2659         vsPrint
.selbackset 
= false; 
2660         vsPrint
.selforeset 
= false; 
2661         vsPrint
.whitespaceBackgroundSet 
= false; 
2662         vsPrint
.whitespaceForegroundSet 
= false; 
2663         vsPrint
.showCaretLineBackground 
= false; 
2665         // Set colours for printing according to users settings 
2666         for (int sty 
= 0;sty 
<= STYLE_MAX
;sty
++) { 
2667                 if (printColourMode 
== SC_PRINT_INVERTLIGHT
) { 
2668                         vsPrint
.styles
[sty
].fore
.desired 
= InvertedLight(vsPrint
.styles
[sty
].fore
.desired
); 
2669                         vsPrint
.styles
[sty
].back
.desired 
= InvertedLight(vsPrint
.styles
[sty
].back
.desired
); 
2670                 } else if (printColourMode 
== SC_PRINT_BLACKONWHITE
) { 
2671                         vsPrint
.styles
[sty
].fore
.desired 
= ColourDesired(0, 0, 0); 
2672                         vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2673                 } else if (printColourMode 
== SC_PRINT_COLOURONWHITE
) { 
2674                         vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2675                 } else if (printColourMode 
== SC_PRINT_COLOURONWHITEDEFAULTBG
) { 
2676                         if (sty 
<= STYLE_DEFAULT
) { 
2677                                 vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2681         // White background for the line numbers 
2682         vsPrint
.styles
[STYLE_LINENUMBER
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2684         vsPrint
.Refresh(*surfaceMeasure
); 
2685         // Ensure colours are set up 
2686         vsPrint
.RefreshColourPalette(palette
, true); 
2687         vsPrint
.RefreshColourPalette(palette
, false); 
2688         // Determining width must hapen after fonts have been realised in Refresh 
2689         int lineNumberWidth 
= 0; 
2690         if (lineNumberIndex 
>= 0) { 
2691                 lineNumberWidth 
= surfaceMeasure
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
, 
2692                                   "99999" lineNumberPrintSpace
, 5 + istrlen(lineNumberPrintSpace
)); 
2693                 vsPrint
.ms
[lineNumberIndex
].width 
= lineNumberWidth
; 
2696         int linePrintStart 
= pdoc
->LineFromPosition(pfr
->chrg
.cpMin
); 
2697         int linePrintLast 
= linePrintStart 
+ (pfr
->rc
.bottom 
- pfr
->rc
.top
) / vsPrint
.lineHeight 
- 1; 
2698         if (linePrintLast 
< linePrintStart
) 
2699                 linePrintLast 
= linePrintStart
; 
2700         int linePrintMax 
= pdoc
->LineFromPosition(pfr
->chrg
.cpMax
); 
2701         if (linePrintLast 
> linePrintMax
) 
2702                 linePrintLast 
= linePrintMax
; 
2703         //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", 
2704         //      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight, 
2705         //      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font)); 
2706         int endPosPrint 
= pdoc
->Length(); 
2707         if (linePrintLast 
< pdoc
->LinesTotal()) 
2708                 endPosPrint 
= pdoc
->LineStart(linePrintLast 
+ 1); 
2710         // Ensure we are styled to where we are formatting. 
2711         pdoc
->EnsureStyledTo(endPosPrint
); 
2713         int xStart 
= vsPrint
.fixedColumnWidth 
+ pfr
->rc
.left 
+ lineNumberWidth
; 
2714         int ypos 
= pfr
->rc
.top
; 
2716         int lineDoc 
= linePrintStart
; 
2718         int nPrintPos 
= pfr
->chrg
.cpMin
; 
2719         int visibleLine 
= 0; 
2720         int widthPrint 
= pfr
->rc
.Width() - lineNumberWidth
; 
2721         if (printWrapState 
== eWrapNone
) 
2722                 widthPrint 
= LineLayout::wrapWidthInfinite
; 
2724         while (lineDoc 
<= linePrintLast 
&& ypos 
< pfr
->rc
.bottom
) { 
2726                 // When printing, the hdc and hdcTarget may be the same, so 
2727                 // changing the state of surfaceMeasure may change the underlying 
2728                 // state of surface. Therefore, any cached state is discarded before 
2729                 // using each surface. 
2730                 surfaceMeasure
->FlushCachedState(); 
2732                 // Copy this line and its styles from the document into local arrays 
2733                 // and determine the x position at which each character starts. 
2734                 LineLayout 
ll(8000); 
2735                 LayoutLine(lineDoc
, surfaceMeasure
, vsPrint
, &ll
, widthPrint
); 
2739                 ll
.containsCaret 
= false; 
2742                 rcLine
.left 
= pfr
->rc
.left 
+ lineNumberWidth
; 
2744                 rcLine
.right 
= pfr
->rc
.right 
- 1; 
2745                 rcLine
.bottom 
= ypos 
+ vsPrint
.lineHeight
; 
2747                 // When document line is wrapped over multiple display lines, find where 
2748                 // to start printing from to ensure a particular position is on the first 
2749                 // line of the page. 
2750                 if (visibleLine 
== 0) { 
2751                         int startWithinLine 
= nPrintPos 
- pdoc
->LineStart(lineDoc
); 
2752                         for (int iwl 
= 0; iwl 
< ll
.lines 
- 1; iwl
++) { 
2753                                 if (ll
.LineStart(iwl
) <= startWithinLine 
&& ll
.LineStart(iwl 
+ 1) >= startWithinLine
) { 
2758                         if (ll
.lines 
> 1 && startWithinLine 
>= ll
.LineStart(ll
.lines 
- 1)) { 
2759                                 visibleLine 
= -(ll
.lines 
- 1); 
2763                 if (draw 
&& lineNumberWidth 
&& 
2764                         (ypos 
+ vsPrint
.lineHeight 
<= pfr
->rc
.bottom
) && 
2765                         (visibleLine 
>= 0)) { 
2767                         sprintf(number
, "%d" lineNumberPrintSpace
, lineDoc 
+ 1); 
2768                         PRectangle rcNumber 
= rcLine
; 
2769                         rcNumber
.right 
= rcNumber
.left 
+ lineNumberWidth
; 
2771                         rcNumber
.left 
-= surfaceMeasure
->WidthText( 
2772                                              vsPrint
.styles
[STYLE_LINENUMBER
].font
, number
, istrlen(number
)); 
2773                         surface
->FlushCachedState(); 
2774                         surface
->DrawTextNoClip(rcNumber
, vsPrint
.styles
[STYLE_LINENUMBER
].font
, 
2775                                                 ypos 
+ vsPrint
.maxAscent
, number
, istrlen(number
), 
2776                                                 vsPrint
.styles
[STYLE_LINENUMBER
].fore
.allocated
, 
2777                                                 vsPrint
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
2781                 surface
->FlushCachedState(); 
2783                 for (int iwl 
= 0; iwl 
< ll
.lines
; iwl
++) { 
2784                         if (ypos 
+ vsPrint
.lineHeight 
<= pfr
->rc
.bottom
) { 
2785                                 if (visibleLine 
>= 0) { 
2788                                                 rcLine
.bottom 
= ypos 
+ vsPrint
.lineHeight
; 
2789                                                 DrawLine(surface
, vsPrint
, lineDoc
, visibleLine
, xStart
, rcLine
, &ll
, iwl
); 
2791                                         ypos 
+= vsPrint
.lineHeight
; 
2794                                 if (iwl 
== ll
.lines 
- 1) 
2795                                         nPrintPos 
= pdoc
->LineStart(lineDoc 
+ 1); 
2797                                         nPrintPos 
+= ll
.LineStart(iwl 
+ 1) - ll
.LineStart(iwl
); 
2807 int Editor::TextWidth(int style
, const char *text
) { 
2809         AutoSurface 
surface(this); 
2811                 return surface
->WidthText(vs
.styles
[style
].font
, text
, istrlen(text
)); 
2817 // Empty method is overridden on GTK+ to show / hide scrollbars 
2818 void Editor::ReconfigureScrollBars() {} 
2820 void Editor::SetScrollBars() { 
2823         int nMax 
= MaxScrollPos(); 
2824         int nPage 
= LinesOnScreen(); 
2825         bool modified 
= ModifyScrollBars(nMax 
+ nPage 
- 1, nPage
); 
2827         // TODO: ensure always showing as many lines as possible 
2828         // May not be, if, for example, window made larger 
2829         if (topLine 
> MaxScrollPos()) { 
2830                 SetTopLine(Platform::Clamp(topLine
, 0, MaxScrollPos())); 
2831                 SetVerticalScrollPos(); 
2835                 if (!AbandonPaint()) 
2838         //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage); 
2841 void Editor::ChangeSize() { 
2844         if (wrapState 
!= eWrapNone
) { 
2845                 PRectangle rcTextArea 
= GetClientRectangle(); 
2846                 rcTextArea
.left 
= vs
.fixedColumnWidth
; 
2847                 rcTextArea
.right 
-= vs
.rightMarginWidth
; 
2848                 if (wrapWidth 
!= rcTextArea
.Width()) { 
2855 void Editor::AddChar(char ch
) { 
2862 void Editor::AddCharUTF(char *s
, unsigned int len
, bool treatAsDBCS
) { 
2863         bool wasSelection 
= currentPos 
!= anchor
; 
2865         if (inOverstrike 
&& !wasSelection 
&& !RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
2866                 if (currentPos 
< (pdoc
->Length())) { 
2867                         if (!IsEOLChar(pdoc
->CharAt(currentPos
))) { 
2868                                 pdoc
->DelChar(currentPos
); 
2872         if (pdoc
->InsertString(currentPos
, s
, len
)) { 
2873                 SetEmptySelection(currentPos 
+ len
); 
2875         EnsureCaretVisible(); 
2876         // Avoid blinking during rapid typing: 
2877         ShowCaretAtCurrentPosition(); 
2881                 NotifyChar((static_cast<unsigned char>(s
[0]) << 8) | 
2882                            static_cast<unsigned char>(s
[1])); 
2884                 int byte 
= static_cast<unsigned char>(s
[0]); 
2885                 if ((byte 
< 0xC0) || (1 == len
)) { 
2886                         // Handles UTF-8 characters between 0x01 and 0x7F and single byte 
2887                         // characters when not in UTF-8 mode. 
2888                         // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid 
2889                         // characters representing themselves. 
2891                         // Unroll 1 to 3 byte UTF-8 sequences.  See reference data at: 
2892                         // http://www.cl.cam.ac.uk/~mgk25/unicode.html 
2893                         // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 
2895                                 int byte2 
= static_cast<unsigned char>(s
[1]); 
2896                                 if ((byte2 
& 0xC0) == 0x80) { 
2897                                         // Two-byte-character lead-byte followed by a trail-byte. 
2898                                         byte 
= (((byte 
& 0x1F) << 6) | (byte2 
& 0x3F)); 
2900                                 // A two-byte-character lead-byte not followed by trail-byte 
2901                                 // represents itself. 
2902                         } else if (byte 
< 0xF0) { 
2903                                 int byte2 
= static_cast<unsigned char>(s
[1]); 
2904                                 int byte3 
= static_cast<unsigned char>(s
[2]); 
2905                                 if (((byte2 
& 0xC0) == 0x80) && ((byte3 
& 0xC0) == 0x80)) { 
2906                                         // Three-byte-character lead byte followed by two trail bytes. 
2907                                         byte 
= (((byte 
& 0x0F) << 12) | ((byte2 
& 0x3F) << 6) | 
2910                                 // A three-byte-character lead-byte not followed by two trail-bytes 
2911                                 // represents itself. 
2918 void Editor::ClearSelection() { 
2919         if (!SelectionContainsProtected()) { 
2920                 if (selType 
== selRectangle
) { 
2921                         pdoc
->BeginUndoAction(); 
2922                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
2923                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
2924                         int startPos 
= SelectionStart(); 
2925                         for (int line 
= lineEnd
; line 
>= lineStart
; line
--) { 
2926                                 startPos 
= SelectionStart(line
); 
2927                                 unsigned int chars 
= SelectionEnd(line
) - startPos
; 
2929                                         pdoc
->DeleteChars(startPos
, chars
); 
2932                         SetEmptySelection(startPos
); 
2933                         pdoc
->EndUndoAction(); 
2934                         selType 
= selStream
; 
2936                         int startPos 
= SelectionStart(); 
2937                         unsigned int chars 
= SelectionEnd() - startPos
; 
2938                         SetEmptySelection(startPos
); 
2940                                 pdoc
->BeginUndoAction(); 
2941                                 pdoc
->DeleteChars(startPos
, chars
); 
2942                                 pdoc
->EndUndoAction(); 
2948 void Editor::ClearAll() { 
2949         pdoc
->BeginUndoAction(); 
2950         if (0 != pdoc
->Length()) { 
2951                 pdoc
->DeleteChars(0, pdoc
->Length()); 
2953         if (!pdoc
->IsReadOnly()) { 
2956         pdoc
->EndUndoAction(); 
2960         SetVerticalScrollPos(); 
2963 void Editor::ClearDocumentStyle() { 
2964         pdoc
->StartStyling(0, '\377'); 
2965         pdoc
->SetStyleFor(pdoc
->Length(), 0); 
2967         pdoc
->ClearLevels(); 
2970 void Editor::Cut() { 
2971         if (!pdoc
->IsReadOnly() && !SelectionContainsProtected()) { 
2977 void Editor::PasteRectangular(int pos
, const char *ptr
, int len
) { 
2978         if (pdoc
->IsReadOnly() || SelectionContainsProtected()) { 
2982         int xInsert 
= XFromPosition(currentPos
); 
2983         int line 
= pdoc
->LineFromPosition(currentPos
); 
2984         bool prevCr 
= false; 
2985         pdoc
->BeginUndoAction(); 
2986         for (int i 
= 0; i 
< len
; i
++) { 
2987                 if (IsEOLChar(ptr
[i
])) { 
2988                         if ((ptr
[i
] == '\r') || (!prevCr
)) 
2990                         if (line 
>= pdoc
->LinesTotal()) { 
2991                                 if (pdoc
->eolMode 
!= SC_EOL_LF
) 
2992                                         pdoc
->InsertChar(pdoc
->Length(), '\r'); 
2993                                 if (pdoc
->eolMode 
!= SC_EOL_CR
) 
2994                                         pdoc
->InsertChar(pdoc
->Length(), '\n'); 
2996                         // Pad the end of lines with spaces if required 
2997                         currentPos 
= PositionFromLineX(line
, xInsert
); 
2998                         if ((XFromPosition(currentPos
) < xInsert
) && (i 
+ 1 < len
)) { 
2999                                 for (int i 
= 0; i 
< xInsert 
- XFromPosition(currentPos
); i
++) { 
3000                                         pdoc
->InsertChar(currentPos
, ' '); 
3004                         prevCr 
= ptr
[i
] == '\r'; 
3006                         pdoc
->InsertString(currentPos
, ptr 
+ i
, 1); 
3011         pdoc
->EndUndoAction(); 
3012         SetEmptySelection(pos
); 
3015 bool Editor::CanPaste() { 
3016         return !pdoc
->IsReadOnly() && !SelectionContainsProtected(); 
3019 void Editor::Clear() { 
3020         if (currentPos 
== anchor
) { 
3021                 if (!RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3027         SetEmptySelection(currentPos
); 
3030 void Editor::SelectAll() { 
3031         SetSelection(0, pdoc
->Length()); 
3035 void Editor::Undo() { 
3036         if (pdoc
->CanUndo()) { 
3038                 int newPos 
= pdoc
->Undo(); 
3039                 SetEmptySelection(newPos
); 
3040                 EnsureCaretVisible(); 
3044 void Editor::Redo() { 
3045         if (pdoc
->CanRedo()) { 
3046                 int newPos 
= pdoc
->Redo(); 
3047                 SetEmptySelection(newPos
); 
3048                 EnsureCaretVisible(); 
3052 void Editor::DelChar() { 
3053         if (!RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3054                 pdoc
->DelChar(currentPos
); 
3056         // Avoid blinking during rapid typing: 
3057         ShowCaretAtCurrentPosition(); 
3060 void Editor::DelCharBack(bool allowLineStartDeletion
) { 
3061         if (currentPos 
== anchor
) { 
3062                 if (!RangeContainsProtected(currentPos 
- 1, currentPos
)) { 
3063                         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
3064                         if (allowLineStartDeletion 
|| (pdoc
->LineStart(lineCurrentPos
) != currentPos
)) { 
3065                                 if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetLineIndentation(lineCurrentPos
) && 
3066                                         pdoc
->GetColumn(currentPos
) > 0 && pdoc
->backspaceUnindents
) { 
3067                                         pdoc
->BeginUndoAction(); 
3068                                         int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
3069                                         int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
3070                                         if (indentation 
% indentationStep 
== 0) { 
3071                                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- indentationStep
); 
3073                                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- (indentation 
% indentationStep
)); 
3075                                         SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
3076                                         pdoc
->EndUndoAction(); 
3078                                         pdoc
->DelCharBack(currentPos
); 
3084                 SetEmptySelection(currentPos
); 
3086         // Avoid blinking during rapid typing: 
3087         ShowCaretAtCurrentPosition(); 
3090 void Editor::NotifyFocus(bool) {} 
3092 void Editor::NotifyStyleToNeeded(int endStyleNeeded
) { 
3094         scn
.nmhdr
.code 
= SCN_STYLENEEDED
; 
3095         scn
.position 
= endStyleNeeded
; 
3099 void Editor::NotifyStyleNeeded(Document
*, void *, int endStyleNeeded
) { 
3100         NotifyStyleToNeeded(endStyleNeeded
); 
3103 void Editor::NotifyChar(int ch
) { 
3105         scn
.nmhdr
.code 
= SCN_CHARADDED
; 
3108         if (recordingMacro
) { 
3110                 txt
[0] = static_cast<char>(ch
); 
3112                 NotifyMacroRecord(SCI_REPLACESEL
, 0, reinterpret_cast<sptr_t
>(txt
)); 
3116 void Editor::NotifySavePoint(bool isSavePoint
) { 
3119                 scn
.nmhdr
.code 
= SCN_SAVEPOINTREACHED
; 
3121                 scn
.nmhdr
.code 
= SCN_SAVEPOINTLEFT
; 
3126 void Editor::NotifyModifyAttempt() { 
3128         scn
.nmhdr
.code 
= SCN_MODIFYATTEMPTRO
; 
3132 void Editor::NotifyDoubleClick(Point
, bool) { 
3134         scn
.nmhdr
.code 
= SCN_DOUBLECLICK
; 
3138 void Editor::NotifyHotSpotDoubleClicked(int position
, bool shift
, bool ctrl
, bool alt
) { 
3140         scn
.nmhdr
.code 
= SCN_HOTSPOTDOUBLECLICK
; 
3141         scn
.position 
= position
; 
3142         scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3143                         (alt 
? SCI_ALT 
: 0); 
3147 void Editor::NotifyHotSpotClicked(int position
, bool shift
, bool ctrl
, bool alt
) { 
3149         scn
.nmhdr
.code 
= SCN_HOTSPOTCLICK
; 
3150         scn
.position 
= position
; 
3151         scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3152                         (alt 
? SCI_ALT 
: 0); 
3156 void Editor::NotifyUpdateUI() { 
3158         scn
.nmhdr
.code 
= SCN_UPDATEUI
; 
3162 void Editor::NotifyPainted() { 
3164         scn
.nmhdr
.code 
= SCN_PAINTED
; 
3168 bool Editor::NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
) { 
3169         int marginClicked 
= -1; 
3171         for (int margin 
= 0; margin 
< ViewStyle::margins
; margin
++) { 
3172                 if ((pt
.x 
> x
) && (pt
.x 
< x 
+ vs
.ms
[margin
].width
)) 
3173                         marginClicked 
= margin
; 
3174                 x 
+= vs
.ms
[margin
].width
; 
3176         if ((marginClicked 
>= 0) && vs
.ms
[marginClicked
].sensitive
) { 
3178                 scn
.nmhdr
.code 
= SCN_MARGINCLICK
; 
3179                 scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3180                                 (alt 
? SCI_ALT 
: 0); 
3181                 scn
.position 
= pdoc
->LineStart(LineFromLocation(pt
)); 
3182                 scn
.margin 
= marginClicked
; 
3190 void Editor::NotifyNeedShown(int pos
, int len
) { 
3192         scn
.nmhdr
.code 
= SCN_NEEDSHOWN
; 
3198 void Editor::NotifyDwelling(Point pt
, bool state
) { 
3200         scn
.nmhdr
.code 
= state 
? SCN_DWELLSTART 
: SCN_DWELLEND
; 
3201         scn
.position 
= PositionFromLocationClose(pt
); 
3207 void Editor::NotifyZoom() { 
3209         scn
.nmhdr
.code 
= SCN_ZOOM
; 
3213 // Notifications from document 
3214 void Editor::NotifyModifyAttempt(Document
*, void *) { 
3215         //Platform::DebugPrintf("** Modify Attempt\n"); 
3216         NotifyModifyAttempt(); 
3219 void Editor::NotifyMove(int position
) { 
3221         scn
.nmhdr
.code 
= SCN_POSCHANGED
; 
3222         scn
.position 
= position
; 
3226 void Editor::NotifySavePoint(Document
*, void *, bool atSavePoint
) { 
3227         //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off"); 
3228         NotifySavePoint(atSavePoint
); 
3231 void Editor::CheckModificationForWrap(DocModification mh
) { 
3232         if ((mh
.modificationType 
& SC_MOD_INSERTTEXT
) || 
3233                 (mh
.modificationType 
& SC_MOD_DELETETEXT
)) { 
3234                 llc
.Invalidate(LineLayout::llCheckTextAndStyle
); 
3235                 if (wrapState 
!= eWrapNone
) { 
3236                         int lineDoc 
= pdoc
->LineFromPosition(mh
.position
); 
3237                         if (mh
.linesAdded 
== 0) { 
3238                                 AutoSurface 
surface(this); 
3239                                 AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
3240                                 if (surface 
&& ll
) { 
3241                                         LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
3242                                         if (cs
.GetHeight(lineDoc
) != ll
->lines
) { 
3243                                                 NeedWrapping(lineDoc 
- 1); 
3247                                         NeedWrapping(lineDoc
); 
3250                                 NeedWrapping(lineDoc
); 
3256 // Move a position so it is still after the same character as before the insertion. 
3257 static inline int MovePositionForInsertion(int position
, int startInsertion
, int length
) { 
3258         if (position 
> startInsertion
) { 
3259                 return position 
+ length
; 
3264 // Move a position so it is still after the same character as before the deletion if that 
3265 // character is still present else after the previous surviving character. 
3266 static inline int MovePositionForDeletion(int position
, int startDeletion
, int length
) { 
3267         if (position 
> startDeletion
) { 
3268                 int endDeletion 
= startDeletion 
+ length
; 
3269                 if (position 
> endDeletion
) { 
3270                         return position 
- length
; 
3272                         return startDeletion
; 
3279 void Editor::NotifyModified(Document
*, DocModification mh
, void *) { 
3280         needUpdateUI 
= true; 
3281         if (paintState 
== painting
) { 
3282                 CheckForChangeOutsidePaint(Range(mh
.position
, mh
.position 
+ mh
.length
)); 
3284         CheckModificationForWrap(mh
); 
3285         if (mh
.modificationType 
& SC_MOD_CHANGESTYLE
) { 
3286                 if (paintState 
== notPainting
) { 
3287                         if (mh
.position 
< pdoc
->LineStart(topLine
)) { 
3288                                 // Styling performed before this view 
3291                                 InvalidateRange(mh
.position
, mh
.position 
+ mh
.length
); 
3295                 // Move selection and brace highlights 
3296                 if (mh
.modificationType 
& SC_MOD_INSERTTEXT
) { 
3297                         currentPos 
= MovePositionForInsertion(currentPos
, mh
.position
, mh
.length
); 
3298                         anchor 
= MovePositionForInsertion(anchor
, mh
.position
, mh
.length
); 
3299                         braces
[0] = MovePositionForInsertion(braces
[0], mh
.position
, mh
.length
); 
3300                         braces
[1] = MovePositionForInsertion(braces
[1], mh
.position
, mh
.length
); 
3301                 } else if (mh
.modificationType 
& SC_MOD_DELETETEXT
) { 
3302                         currentPos 
= MovePositionForDeletion(currentPos
, mh
.position
, mh
.length
); 
3303                         anchor 
= MovePositionForDeletion(anchor
, mh
.position
, mh
.length
); 
3304                         braces
[0] = MovePositionForDeletion(braces
[0], mh
.position
, mh
.length
); 
3305                         braces
[1] = MovePositionForDeletion(braces
[1], mh
.position
, mh
.length
); 
3307                 if (cs
.LinesDisplayed() < cs
.LinesInDoc()) { 
3308                         // Some lines are hidden so may need shown. 
3309                         // TODO: check if the modified area is hidden. 
3310                         if (mh
.modificationType 
& SC_MOD_BEFOREINSERT
) { 
3311                                 NotifyNeedShown(mh
.position
, mh
.length
); 
3312                         } else if (mh
.modificationType 
& SC_MOD_BEFOREDELETE
) { 
3313                                 NotifyNeedShown(mh
.position
, mh
.length
); 
3316                 if (mh
.linesAdded 
!= 0) { 
3317                         // Update contraction state for inserted and removed lines 
3318                         // lineOfPos should be calculated in context of state before modification, shouldn't it 
3319                         int lineOfPos 
= pdoc
->LineFromPosition(mh
.position
); 
3320                         if (mh
.linesAdded 
> 0) { 
3321                                 cs
.InsertLines(lineOfPos
, mh
.linesAdded
); 
3323                                 cs
.DeleteLines(lineOfPos
, -mh
.linesAdded
); 
3325                         // Avoid scrolling of display if change before current display 
3326                         if (mh
.position 
< posTopLine
) { 
3327                                 int newTop 
= Platform::Clamp(topLine 
+ mh
.linesAdded
, 0, MaxScrollPos()); 
3328                                 if (newTop 
!= topLine
) { 
3330                                         SetVerticalScrollPos(); 
3334                         //Platform::DebugPrintf("** %x Doc Changed\n", this); 
3335                         // TODO: could invalidate from mh.startModification to end of screen 
3336                         //InvalidateRange(mh.position, mh.position + mh.length); 
3337                         if (paintState 
== notPainting
) { 
3341                         //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this, 
3342                         //      mh.position, mh.position + mh.length); 
3343                         if (paintState 
== notPainting
) { 
3344                                 InvalidateRange(mh
.position
, mh
.position 
+ mh
.length
); 
3349         if (mh
.linesAdded 
!= 0) { 
3353         if (mh
.modificationType 
& SC_MOD_CHANGEMARKER
) { 
3354                 if (paintState 
== notPainting
) { 
3359         // If client wants to see this modification 
3360         if (mh
.modificationType 
& modEventMask
) { 
3361                 if ((mh
.modificationType 
& SC_MOD_CHANGESTYLE
) == 0) { 
3362                         // Real modification made to text of document. 
3363                         NotifyChange(); // Send EN_CHANGE 
3367                 scn
.nmhdr
.code 
= SCN_MODIFIED
; 
3368                 scn
.position 
= mh
.position
; 
3369                 scn
.modificationType 
= mh
.modificationType
; 
3371                 scn
.length 
= mh
.length
; 
3372                 scn
.linesAdded 
= mh
.linesAdded
; 
3374                 scn
.foldLevelNow 
= mh
.foldLevelNow
; 
3375                 scn
.foldLevelPrev 
= mh
.foldLevelPrev
; 
3380 void Editor::NotifyDeleted(Document 
*, void *) { 
3384 void Editor::NotifyMacroRecord(unsigned int iMessage
, unsigned long wParam
, long lParam
) { 
3386         // Enumerates all macroable messages 
3392         case SCI_REPLACESEL
: 
3394         case SCI_INSERTTEXT
: 
3395         case SCI_APPENDTEXT
: 
3400         case SCI_SEARCHANCHOR
: 
3401         case SCI_SEARCHNEXT
: 
3402         case SCI_SEARCHPREV
: 
3404         case SCI_LINEDOWNEXTEND
: 
3406         case SCI_PARADOWNEXTEND
: 
3408         case SCI_LINEUPEXTEND
: 
3410         case SCI_PARAUPEXTEND
: 
3412         case SCI_CHARLEFTEXTEND
: 
3414         case SCI_CHARRIGHTEXTEND
: 
3416         case SCI_WORDLEFTEXTEND
: 
3418         case SCI_WORDRIGHTEXTEND
: 
3419         case SCI_WORDPARTLEFT
: 
3420         case SCI_WORDPARTLEFTEXTEND
: 
3421         case SCI_WORDPARTRIGHT
: 
3422         case SCI_WORDPARTRIGHTEXTEND
: 
3424         case SCI_HOMEEXTEND
: 
3426         case SCI_LINEENDEXTEND
: 
3428         case SCI_HOMEWRAPEXTEND
: 
3429         case SCI_LINEENDWRAP
: 
3430         case SCI_LINEENDWRAPEXTEND
: 
3431         case SCI_DOCUMENTSTART
: 
3432         case SCI_DOCUMENTSTARTEXTEND
: 
3433         case SCI_DOCUMENTEND
: 
3434         case SCI_DOCUMENTENDEXTEND
: 
3436         case SCI_PAGEUPEXTEND
: 
3438         case SCI_PAGEDOWNEXTEND
: 
3439         case SCI_EDITTOGGLEOVERTYPE
: 
3441         case SCI_DELETEBACK
: 
3446         case SCI_VCHOMEEXTEND
: 
3447         case SCI_VCHOMEWRAP
: 
3448         case SCI_VCHOMEWRAPEXTEND
: 
3449         case SCI_DELWORDLEFT
: 
3450         case SCI_DELWORDRIGHT
: 
3451         case SCI_DELLINELEFT
: 
3452         case SCI_DELLINERIGHT
: 
3455         case SCI_LINEDELETE
: 
3456         case SCI_LINETRANSPOSE
: 
3457         case SCI_LINEDUPLICATE
: 
3460         case SCI_LINESCROLLDOWN
: 
3461         case SCI_LINESCROLLUP
: 
3462         case SCI_DELETEBACKNOTLINE
: 
3463         case SCI_HOMEDISPLAY
: 
3464         case SCI_HOMEDISPLAYEXTEND
: 
3465         case SCI_LINEENDDISPLAY
: 
3466         case SCI_LINEENDDISPLAYEXTEND
: 
3469                 // Filter out all others like display changes.  Also, newlines are redundant 
3470                 // with char insert messages. 
3473                 //              printf("Filtered out %ld of macro recording\n", iMessage); 
3477         // Send notification 
3479         scn
.nmhdr
.code 
= SCN_MACRORECORD
; 
3480         scn
.message 
= iMessage
; 
3481         scn
.wParam 
= wParam
; 
3482         scn
.lParam 
= lParam
; 
3486 // Force scroll and keep position relative to top of window 
3487 void Editor::PageMove(int direction
, bool extend
) { 
3488         Point pt 
= LocationFromPosition(currentPos
); 
3489         int topLineNew 
= Platform::Clamp( 
3490                              topLine 
+ direction 
* LinesToScroll(), 0, MaxScrollPos()); 
3491         int newPos 
= PositionFromLocation( 
3492                          Point(lastXChosen
, pt
.y 
+ direction 
* (vs
.lineHeight 
* LinesToScroll()))); 
3493         if (topLineNew 
!= topLine
) { 
3494                 SetTopLine(topLineNew
); 
3495                 MovePositionTo(newPos
, extend
); 
3497                 SetVerticalScrollPos(); 
3499                 MovePositionTo(newPos
, extend
); 
3503 void Editor::ChangeCaseOfSelection(bool makeUpperCase
) { 
3504         pdoc
->BeginUndoAction(); 
3505         int startCurrent 
= currentPos
; 
3506         int startAnchor 
= anchor
; 
3507         if (selType 
== selRectangle
) { 
3508                 int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
3509                 int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
3510                 for (int line 
= lineEnd
; line 
>= lineStart
; line
--) { 
3512                             Range(SelectionStart(line
), SelectionEnd(line
)), 
3515                 // Would be nicer to keep the rectangular selection but this is complex 
3516                 selType 
= selStream
; 
3517                 SetSelection(startCurrent
, startCurrent
); 
3519                 pdoc
->ChangeCase(Range(SelectionStart(), SelectionEnd()), 
3521                 SetSelection(startCurrent
, startAnchor
); 
3523         pdoc
->EndUndoAction(); 
3526 void Editor::LineTranspose() { 
3527         int line 
= pdoc
->LineFromPosition(currentPos
); 
3529                 int startPrev 
= pdoc
->LineStart(line 
- 1); 
3530                 int endPrev 
= pdoc
->LineEnd(line 
- 1); 
3531                 int start 
= pdoc
->LineStart(line
); 
3532                 int end 
= pdoc
->LineEnd(line
); 
3533                 int startNext 
= pdoc
->LineStart(line 
+ 1); 
3534                 if (end 
< pdoc
->Length()) { 
3536                         char *thisLine 
= CopyRange(start
, end
); 
3537                         pdoc
->DeleteChars(start
, end 
- start
); 
3538                         if (pdoc
->InsertString(startPrev
, thisLine
, end 
- start
)) { 
3539                                 MovePositionTo(startPrev 
+ end 
- start
); 
3543                         // Last line so line has no line end 
3544                         char *thisLine 
= CopyRange(start
, end
); 
3545                         char *prevEnd 
= CopyRange(endPrev
, start
); 
3546                         pdoc
->DeleteChars(endPrev
, end 
- endPrev
); 
3547                         pdoc
->InsertString(startPrev
, thisLine
, end 
- start
); 
3548                         if (pdoc
->InsertString(startPrev 
+ end 
- start
, prevEnd
, start 
- endPrev
)) { 
3549                                 MovePositionTo(startPrev 
+ end 
- endPrev
); 
3558 void Editor::LineDuplicate() { 
3559         int line 
= pdoc
->LineFromPosition(currentPos
); 
3560         int start 
= pdoc
->LineStart(line
); 
3561         int end 
= pdoc
->LineEnd(line
); 
3562         char *thisLine 
= CopyRange(start
, end
); 
3563         const char *eol 
= StringFromEOLMode(pdoc
->eolMode
); 
3564         pdoc
->InsertString(end
, eol
); 
3565         pdoc
->InsertString(end 
+ istrlen(eol
), thisLine
, end 
- start
); 
3569 void Editor::CancelModes() {} 
3571 void Editor::NewLine() { 
3573         const char *eol 
= "\n"; 
3574         if (pdoc
->eolMode 
== SC_EOL_CRLF
) { 
3576         } else if (pdoc
->eolMode 
== SC_EOL_CR
) { 
3578         } // else SC_EOL_LF -> "\n" already set 
3579         if (pdoc
->InsertString(currentPos
, eol
)) { 
3580                 SetEmptySelection(currentPos 
+ istrlen(eol
)); 
3587         EnsureCaretVisible(); 
3590 void Editor::CursorUpOrDown(int direction
, bool extend
) { 
3591         Point pt 
= LocationFromPosition(currentPos
); 
3592         int posNew 
= PositionFromLocation( 
3593                          Point(lastXChosen
, pt
.y 
+ direction 
* vs
.lineHeight
)); 
3594         if (direction 
< 0) { 
3595                 // Line wrapping may lead to a location on the same line, so 
3596                 // seek back if that is the case. 
3597                 // There is an equivalent case when moving down which skips 
3598                 // over a line but as that does not trap the user it is fine. 
3599                 Point ptNew 
= LocationFromPosition(posNew
); 
3600                 while ((posNew 
> 0) && (pt
.y 
== ptNew
.y
)) { 
3602                         ptNew 
= LocationFromPosition(posNew
); 
3605         MovePositionTo(posNew
, extend
); 
3608 int Editor::StartEndDisplayLine(int pos
, bool start
) { 
3610         int line 
= pdoc
->LineFromPosition(pos
); 
3611         AutoSurface 
surface(this); 
3612         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
3613         int posRet 
= INVALID_POSITION
; 
3614         if (surface 
&& ll
) { 
3615                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
3616                 LayoutLine(line
, surface
, vs
, ll
, wrapWidth
); 
3617                 int posInLine 
= pos 
- posLineStart
; 
3618                 if (posInLine 
<= ll
->maxLineLength
) { 
3619                         for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
3620                                 if ((posInLine 
>= ll
->LineStart(subLine
)) && (posInLine 
<= ll
->LineStart(subLine 
+ 1))) { 
3622                                                 posRet 
= ll
->LineStart(subLine
) + posLineStart
; 
3624                                                 if (subLine 
== ll
->lines 
- 1) 
3625                                                         posRet 
= ll
->LineStart(subLine 
+ 1) + posLineStart
; 
3627                                                         posRet 
= ll
->LineStart(subLine 
+ 1) + posLineStart 
- 1; 
3633         if (posRet 
== INVALID_POSITION
) { 
3640 int Editor::KeyCommand(unsigned int iMessage
) { 
3645         case SCI_LINEDOWNEXTEND
: 
3646                 CursorUpOrDown(1, true); 
3649                 MovePositionTo(pdoc
->ParaDown(currentPos
)); 
3651         case SCI_PARADOWNEXTEND
: 
3652                 MovePositionTo(pdoc
->ParaDown(currentPos
), true); 
3654         case SCI_LINESCROLLDOWN
: 
3655                 ScrollTo(topLine 
+ 1); 
3656                 MoveCaretInsideView(false); 
3661         case SCI_LINEUPEXTEND
: 
3662                 CursorUpOrDown(-1, true); 
3665                 MovePositionTo(pdoc
->ParaUp(currentPos
)); 
3667         case SCI_PARAUPEXTEND
: 
3668                 MovePositionTo(pdoc
->ParaUp(currentPos
), true); 
3670         case SCI_LINESCROLLUP
: 
3671                 ScrollTo(topLine 
- 1); 
3672                 MoveCaretInsideView(false); 
3675                 if (SelectionEmpty()) { 
3676                         MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1)); 
3678                         MovePositionTo(SelectionStart()); 
3682         case SCI_CHARLEFTEXTEND
: 
3683                 MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1), true); 
3687                 if (SelectionEmpty()) { 
3688                         MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1)); 
3690                         MovePositionTo(SelectionEnd()); 
3694         case SCI_CHARRIGHTEXTEND
: 
3695                 MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1), true); 
3699                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1)); 
3702         case SCI_WORDLEFTEXTEND
: 
3703                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1), true); 
3707                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1)); 
3710         case SCI_WORDRIGHTEXTEND
: 
3711                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1), true); 
3715                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
))); 
3718         case SCI_HOMEEXTEND
: 
3719                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), true); 
3723                 MovePositionTo(pdoc
->LineEndPosition(currentPos
)); 
3726         case SCI_LINEENDEXTEND
: 
3727                 MovePositionTo(pdoc
->LineEndPosition(currentPos
), true); 
3730         case SCI_HOMEWRAP
: { 
3731                         int homePos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
3732                         if (currentPos 
<= homePos
) 
3733                                 homePos 
= pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)); 
3734                         MovePositionTo(homePos
); 
3738         case SCI_HOMEWRAPEXTEND
: { 
3739                         int homePos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
3740                         if (currentPos 
<= homePos
) 
3741                                 homePos 
= pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)); 
3742                         MovePositionTo(homePos
, true); 
3746         case SCI_LINEENDWRAP
: { 
3747                         int endPos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, false), 1); 
3748                         if (currentPos 
>= endPos
) 
3749                                 endPos 
= pdoc
->LineEndPosition(currentPos
); 
3750                         MovePositionTo(endPos
); 
3754         case SCI_LINEENDWRAPEXTEND
: { 
3755                         int endPos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, false), 1); 
3756                         if (currentPos 
>= endPos
) 
3757                                 endPos 
= pdoc
->LineEndPosition(currentPos
); 
3758                         MovePositionTo(endPos
, true); 
3762         case SCI_DOCUMENTSTART
: 
3766         case SCI_DOCUMENTSTARTEXTEND
: 
3767                 MovePositionTo(0, true); 
3770         case SCI_DOCUMENTEND
: 
3771                 MovePositionTo(pdoc
->Length()); 
3774         case SCI_DOCUMENTENDEXTEND
: 
3775                 MovePositionTo(pdoc
->Length(), true); 
3781         case SCI_PAGEUPEXTEND
: 
3787         case SCI_PAGEDOWNEXTEND
: 
3790         case SCI_EDITTOGGLEOVERTYPE
: 
3791                 inOverstrike 
= !inOverstrike
; 
3793                 ShowCaretAtCurrentPosition(); 
3796         case SCI_CANCEL
:                // Cancel any modes - handled in subclass 
3797                 // Also unselect text 
3800         case SCI_DELETEBACK
: 
3803                 EnsureCaretVisible(); 
3805         case SCI_DELETEBACKNOTLINE
: 
3808                 EnsureCaretVisible(); 
3813                 EnsureCaretVisible(); 
3818                 EnsureCaretVisible(); 
3827                 MovePositionTo(pdoc
->VCHomePosition(currentPos
)); 
3830         case SCI_VCHOMEEXTEND
: 
3831                 MovePositionTo(pdoc
->VCHomePosition(currentPos
), true); 
3834         case SCI_VCHOMEWRAP
: { 
3835                         int homePos 
= pdoc
->VCHomePosition(currentPos
); 
3836                         int viewLineStart 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
3837                         if ((viewLineStart 
< currentPos
) && (viewLineStart 
> homePos
)) 
3838                                 homePos 
= viewLineStart
; 
3840                         MovePositionTo(homePos
); 
3844         case SCI_VCHOMEWRAPEXTEND
: { 
3845                         int homePos 
= pdoc
->VCHomePosition(currentPos
); 
3846                         int viewLineStart 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
3847                         if ((viewLineStart 
< currentPos
) && (viewLineStart 
> homePos
)) 
3848                                 homePos 
= viewLineStart
; 
3850                         MovePositionTo(homePos
, true); 
3855                 if (vs
.zoomLevel 
< 20) { 
3857                         InvalidateStyleRedraw(); 
3862                 if (vs
.zoomLevel 
> -10) { 
3864                         InvalidateStyleRedraw(); 
3868         case SCI_DELWORDLEFT
: { 
3869                         int startWord 
= pdoc
->NextWordStart(currentPos
, -1); 
3870                         pdoc
->DeleteChars(startWord
, currentPos 
- startWord
); 
3874         case SCI_DELWORDRIGHT
: { 
3875                         int endWord 
= pdoc
->NextWordStart(currentPos
, 1); 
3876                         pdoc
->DeleteChars(currentPos
, endWord 
- currentPos
); 
3879         case SCI_DELLINELEFT
: { 
3880                         int line 
= pdoc
->LineFromPosition(currentPos
); 
3881                         int start 
= pdoc
->LineStart(line
); 
3882                         pdoc
->DeleteChars(start
, currentPos 
- start
); 
3886         case SCI_DELLINERIGHT
: { 
3887                         int line 
= pdoc
->LineFromPosition(currentPos
); 
3888                         int end 
= pdoc
->LineEnd(line
); 
3889                         pdoc
->DeleteChars(currentPos
, end 
- currentPos
); 
3892         case SCI_LINECOPY
: { 
3893                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
3894                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
3895                         CopyRangeToClipboard(pdoc
->LineStart(lineStart
), 
3896                                 pdoc
->LineStart(lineEnd 
+ 1)); 
3900                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
3901                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
3902                         int start 
= pdoc
->LineStart(lineStart
); 
3903                         int end 
= pdoc
->LineStart(lineEnd 
+ 1); 
3904                         SetSelection(start
, end
); 
3909         case SCI_LINEDELETE
: { 
3910                         int line 
= pdoc
->LineFromPosition(currentPos
); 
3911                         int start 
= pdoc
->LineStart(line
); 
3912                         int end 
= pdoc
->LineStart(line 
+ 1); 
3913                         pdoc
->DeleteChars(start
, end 
- start
); 
3916         case SCI_LINETRANSPOSE
: 
3919         case SCI_LINEDUPLICATE
: 
3923                 ChangeCaseOfSelection(false); 
3926                 ChangeCaseOfSelection(true); 
3928         case SCI_WORDPARTLEFT
: 
3929                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartLeft(currentPos
), -1)); 
3932         case SCI_WORDPARTLEFTEXTEND
: 
3933                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartLeft(currentPos
), -1), true); 
3936         case SCI_WORDPARTRIGHT
: 
3937                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartRight(currentPos
), 1)); 
3940         case SCI_WORDPARTRIGHTEXTEND
: 
3941                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartRight(currentPos
), 1), true); 
3944         case SCI_HOMEDISPLAY
: 
3945                 MovePositionTo(MovePositionSoVisible( 
3946                                    StartEndDisplayLine(currentPos
, true), -1)); 
3949         case SCI_HOMEDISPLAYEXTEND
: 
3950                 MovePositionTo(MovePositionSoVisible( 
3951                                    StartEndDisplayLine(currentPos
, true), -1), true); 
3954         case SCI_LINEENDDISPLAY
: 
3955                 MovePositionTo(MovePositionSoVisible( 
3956                                    StartEndDisplayLine(currentPos
, false), 1)); 
3959         case SCI_LINEENDDISPLAYEXTEND
: 
3960                 MovePositionTo(MovePositionSoVisible( 
3961                                    StartEndDisplayLine(currentPos
, false), 1), true); 
3968 int Editor::KeyDefault(int, int) { 
3972 int Editor::KeyDown(int key
, bool shift
, bool ctrl
, bool alt
, bool *consumed
) { 
3974         int modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3975                         (alt 
? SCI_ALT 
: 0); 
3976         int msg 
= kmap
.Find(key
, modifiers
); 
3980                 return WndProc(msg
, 0, 0); 
3984                 return KeyDefault(key
, modifiers
); 
3988 void Editor::SetWhitespaceVisible(int view
) { 
3989         vs
.viewWhitespace 
= static_cast<WhiteSpaceVisibility
>(view
); 
3992 int Editor::GetWhitespaceVisible() { 
3993         return vs
.viewWhitespace
; 
3996 void Editor::Indent(bool forwards
) { 
3997         //Platform::DebugPrintf("INdent %d\n", forwards); 
3998         int lineOfAnchor 
= pdoc
->LineFromPosition(anchor
); 
3999         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
4000         if (lineOfAnchor 
== lineCurrentPos
) { 
4002                         pdoc
->BeginUndoAction(); 
4004                         if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetColumn(pdoc
->GetLineIndentPosition(lineCurrentPos
)) && 
4006                                 int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
4007                                 int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
4008                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
+ indentationStep
); 
4009                                 SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
4011                                 if (pdoc
->useTabs
) { 
4012                                         pdoc
->InsertChar(currentPos
, '\t'); 
4013                                         SetEmptySelection(currentPos 
+ 1); 
4015                                         int numSpaces 
= (pdoc
->tabInChars
) - 
4016                                                         (pdoc
->GetColumn(currentPos
) % (pdoc
->tabInChars
)); 
4018                                                 numSpaces 
= pdoc
->tabInChars
; 
4019                                         for (int i 
= 0; i 
< numSpaces
; i
++) { 
4020                                                 pdoc
->InsertChar(currentPos 
+ i
, ' '); 
4022                                         SetEmptySelection(currentPos 
+ numSpaces
); 
4025                         pdoc
->EndUndoAction(); 
4027                         if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetLineIndentation(lineCurrentPos
) && 
4029                                 pdoc
->BeginUndoAction(); 
4030                                 int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
4031                                 int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
4032                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- indentationStep
); 
4033                                 SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
4034                                 pdoc
->EndUndoAction(); 
4036                                 int newColumn 
= ((pdoc
->GetColumn(currentPos
) - 1) / pdoc
->tabInChars
) * 
4040                                 int newPos 
= currentPos
; 
4041                                 while (pdoc
->GetColumn(newPos
) > newColumn
) 
4043                                 SetEmptySelection(newPos
); 
4047                 int anchorPosOnLine 
= anchor 
- pdoc
->LineStart(lineOfAnchor
); 
4048                 int currentPosPosOnLine 
= currentPos 
- pdoc
->LineStart(lineCurrentPos
); 
4049                 // Multiple lines selected so indent / dedent 
4050                 int lineTopSel 
= Platform::Minimum(lineOfAnchor
, lineCurrentPos
); 
4051                 int lineBottomSel 
= Platform::Maximum(lineOfAnchor
, lineCurrentPos
); 
4052                 if (pdoc
->LineStart(lineBottomSel
) == anchor 
|| pdoc
->LineStart(lineBottomSel
) == currentPos
) 
4053                         lineBottomSel
--;        // If not selecting any characters on a line, do not indent 
4054                 pdoc
->BeginUndoAction(); 
4055                 pdoc
->Indent(forwards
, lineBottomSel
, lineTopSel
); 
4056                 pdoc
->EndUndoAction(); 
4057                 if (lineOfAnchor 
< lineCurrentPos
) { 
4058                         if (currentPosPosOnLine 
== 0) 
4059                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
)); 
4061                                 SetSelection(pdoc
->LineStart(lineCurrentPos 
+ 1), pdoc
->LineStart(lineOfAnchor
)); 
4063                         if (anchorPosOnLine 
== 0) 
4064                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
)); 
4066                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor 
+ 1)); 
4072  * Search of a text in the document, in the given range. 
4073  * @return The position of the found text, -1 if not found. 
4075 long Editor::FindText( 
4076     uptr_t wParam
,              ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, 
4077     ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. 
4078     sptr_t lParam
) {                    ///< @c TextToFind structure: The text to search for in the given range. 
4080         TextToFind 
*ft 
= reinterpret_cast<TextToFind 
*>(lParam
); 
4081         int lengthFound 
= istrlen(ft
->lpstrText
); 
4082         int pos 
= pdoc
->FindText(ft
->chrg
.cpMin
, ft
->chrg
.cpMax
, ft
->lpstrText
, 
4083                                  (wParam 
& SCFIND_MATCHCASE
) != 0, 
4084                                  (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4085                                  (wParam 
& SCFIND_WORDSTART
) != 0, 
4086                                  (wParam 
& SCFIND_REGEXP
) != 0, 
4087                                  (wParam 
& SCFIND_POSIX
) != 0, 
4090                 ft
->chrgText
.cpMin 
= pos
; 
4091                 ft
->chrgText
.cpMax 
= pos 
+ lengthFound
; 
4097  * Relocatable search support : Searches relative to current selection 
4098  * point and sets the selection to the found text range with 
4102  * Anchor following searches at current selection start: This allows 
4103  * multiple incremental interactive searches to be macro recorded 
4104  * while still setting the selection to found text so the find/select 
4105  * operation is self-contained. 
4107 void Editor::SearchAnchor() { 
4108         searchAnchor 
= SelectionStart(); 
4112  * Find text from current search anchor: Must call @c SearchAnchor first. 
4113  * Used for next text and previous text requests. 
4114  * @return The position of the found text, -1 if not found. 
4116 long Editor::SearchText( 
4117     unsigned int iMessage
,              ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV. 
4118     uptr_t wParam
,              ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, 
4119     ///< @c SCFIND_WORDSTART or @c SCFIND_REGEXP. 
4120     sptr_t lParam
) {                    ///< The text to search for. 
4122         const char *txt 
= reinterpret_cast<char *>(lParam
); 
4124         int lengthFound 
= istrlen(txt
); 
4125         if (iMessage 
== SCI_SEARCHNEXT
) { 
4126                 pos 
= pdoc
->FindText(searchAnchor
, pdoc
->Length(), txt
, 
4127                                      (wParam 
& SCFIND_MATCHCASE
) != 0, 
4128                                      (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4129                                      (wParam 
& SCFIND_WORDSTART
) != 0, 
4130                                      (wParam 
& SCFIND_REGEXP
) != 0, 
4131                                      (wParam 
& SCFIND_POSIX
) != 0, 
4134                 pos 
= pdoc
->FindText(searchAnchor
, 0, txt
, 
4135                                      (wParam 
& SCFIND_MATCHCASE
) != 0, 
4136                                      (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4137                                      (wParam 
& SCFIND_WORDSTART
) != 0, 
4138                                      (wParam 
& SCFIND_REGEXP
) != 0, 
4139                                      (wParam 
& SCFIND_POSIX
) != 0, 
4144                 SetSelection(pos
, pos 
+ lengthFound
); 
4151  * Search for text in the target range of the document. 
4152  * @return The position of the found text, -1 if not found. 
4154 long Editor::SearchInTarget(const char *text
, int length
) { 
4155         int lengthFound 
= length
; 
4156         int pos 
= pdoc
->FindText(targetStart
, targetEnd
, text
, 
4157                                  (searchFlags 
& SCFIND_MATCHCASE
) != 0, 
4158                                  (searchFlags 
& SCFIND_WHOLEWORD
) != 0, 
4159                                  (searchFlags 
& SCFIND_WORDSTART
) != 0, 
4160                                  (searchFlags 
& SCFIND_REGEXP
) != 0, 
4161                                  (searchFlags 
& SCFIND_POSIX
) != 0, 
4165                 targetEnd 
= pos 
+ lengthFound
; 
4170 void Editor::GoToLine(int lineNo
) { 
4171         if (lineNo 
> pdoc
->LinesTotal()) 
4172                 lineNo 
= pdoc
->LinesTotal(); 
4175         SetEmptySelection(pdoc
->LineStart(lineNo
)); 
4176         ShowCaretAtCurrentPosition(); 
4177         EnsureCaretVisible(); 
4180 static bool Close(Point pt1
, Point pt2
) { 
4181         if (abs(pt1
.x 
- pt2
.x
) > 3) 
4183         if (abs(pt1
.y 
- pt2
.y
) > 3) 
4188 char *Editor::CopyRange(int start
, int end
) { 
4191                 int len 
= end 
- start
; 
4192                 text 
= new char[len 
+ 1]; 
4194                         for (int i 
= 0; i 
< len
; i
++) { 
4195                                 text
[i
] = pdoc
->CharAt(start 
+ i
); 
4203 void Editor::CopySelectionFromRange(SelectionText 
*ss
, int start
, int end
) { 
4204         ss
->Set(CopyRange(start
, end
), end 
- start 
+ 1, false); 
4207 void Editor::CopySelectionRange(SelectionText 
*ss
) { 
4208         if (selType 
== selRectangle
) { 
4211                 int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
4212                 int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
4214                 for (line 
= lineStart
; line 
<= lineEnd
; line
++) { 
4215                         size 
+= SelectionEnd(line
) - SelectionStart(line
) + 1; 
4216                         if (pdoc
->eolMode 
== SC_EOL_CRLF
) 
4220                         text 
= new char[size 
+ 1]; 
4223                                 for (line 
= lineStart
; line 
<= lineEnd
; line
++) { 
4224                                         for (int i 
= SelectionStart(line
);i 
< SelectionEnd(line
);i
++) { 
4225                                                 text
[j
++] = pdoc
->CharAt(i
); 
4227                                         if (pdoc
->eolMode 
!= SC_EOL_LF
) 
4229                                         if (pdoc
->eolMode 
!= SC_EOL_CR
) 
4235                 ss
->Set(text
, size 
+ 1, true); 
4237                 CopySelectionFromRange(ss
, SelectionStart(), SelectionEnd()); 
4241 void Editor::CopyRangeToClipboard(int start
, int end
) { 
4242         start 
= pdoc
->ClampPositionIntoDocument(start
); 
4243         end 
= pdoc
->ClampPositionIntoDocument(end
); 
4244         SelectionText selectedText
; 
4245         selectedText
.Set(CopyRange(start
, end
), end 
- start 
+ 1); 
4246         CopyToClipboard(selectedText
); 
4249 void Editor::CopyText(int length
, const char *text
) { 
4250         SelectionText selectedText
; 
4251         selectedText
.Copy(text
, length
); 
4252         CopyToClipboard(selectedText
); 
4255 void Editor::SetDragPosition(int newPos
) { 
4257                 newPos 
= MovePositionOutsideChar(newPos
, 1); 
4260         if (posDrag 
!= newPos
) { 
4269 void Editor::DisplayCursor(Window::Cursor c
) { 
4270         if (cursorMode 
== SC_CURSORNORMAL
) 
4273                 wMain
.SetCursor(static_cast<Window::Cursor
>(cursorMode
)); 
4276 void Editor::StartDrag() { 
4277         // Always handled by subclasses 
4278         //SetMouseCapture(true); 
4279         //DisplayCursor(Window::cursorArrow); 
4282 void Editor::DropAt(int position
, const char *value
, bool moving
, bool rectangular
) { 
4283         //Platform::DebugPrintf("DropAt %d\n", inDragDrop); 
4285                 dropWentOutside 
= false; 
4287         int positionWasInSelection 
= PositionInSelection(position
); 
4289         bool positionOnEdgeOfSelection 
= 
4290             (position 
== SelectionStart()) || (position 
== SelectionEnd()); 
4292         if ((!inDragDrop
) || !(0 == positionWasInSelection
) || 
4293                 (positionOnEdgeOfSelection 
&& !moving
)) { 
4295                 int selStart 
= SelectionStart(); 
4296                 int selEnd 
= SelectionEnd(); 
4298                 pdoc
->BeginUndoAction(); 
4300                 int positionAfterDeletion 
= position
; 
4301                 if (inDragDrop 
&& moving
) { 
4302                         // Remove dragged out text 
4304                                 int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
4305                                 int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
4306                                 for (int line 
= lineStart
; line 
<= lineEnd
; line
++) { 
4307                                         int startPos 
= SelectionStart(line
); 
4308                                         int endPos 
= SelectionEnd(line
); 
4309                                         if (position 
>= startPos
) { 
4310                                                 if (position 
> endPos
) { 
4311                                                         positionAfterDeletion 
-= endPos 
- startPos
; 
4313                                                         positionAfterDeletion 
-= position 
- startPos
; 
4318                                 if (position 
> selStart
) { 
4319                                         positionAfterDeletion 
-= selEnd 
- selStart
; 
4324                 position 
= positionAfterDeletion
; 
4327                         PasteRectangular(position
, value
, istrlen(value
)); 
4328                         pdoc
->EndUndoAction(); 
4329                         // Should try to select new rectangle but it may not be a rectangle now so just select the drop position 
4330                         SetSelection(position
, position
); 
4332                         position 
= MovePositionOutsideChar(position
, currentPos 
- position
); 
4333                         if (pdoc
->InsertString(position
, value
)) { 
4334                                 SetSelection(position 
+ istrlen(value
), position
); 
4336                         pdoc
->EndUndoAction(); 
4338         } else if (inDragDrop
) { 
4339                 SetSelection(position
, position
); 
4343 static int BeforeInOrAfter(int val
, int minim
, int maxim
) { 
4346         else if (val 
> maxim
) 
4352 int Editor::PositionInSelection(int pos
) { 
4353         pos 
= MovePositionOutsideChar(pos
, currentPos 
- pos
); 
4354         if (selType 
== selRectangle
) { 
4355                 if (pos 
< SelectionStart()) 
4357                 if (pos 
> SelectionEnd()) 
4359                 int linePos 
= pdoc
->LineFromPosition(pos
); 
4360                 return BeforeInOrAfter(pos
, SelectionStart(linePos
), SelectionEnd(linePos
)); 
4362                 if (currentPos 
> anchor
) { 
4363                         return BeforeInOrAfter(pos
, anchor
, currentPos
); 
4364                 } else if (currentPos 
< anchor
) { 
4365                         return BeforeInOrAfter(pos
, currentPos
, anchor
); 
4371 bool Editor::PointInSelection(Point pt
) { 
4372         // TODO: fix up for rectangular selection 
4373         int pos 
= PositionFromLocation(pt
); 
4374         if (0 == PositionInSelection(pos
)) { 
4375                 if (pos 
== SelectionStart()) { 
4376                         // see if just before selection 
4377                         Point locStart 
= LocationFromPosition(pos
); 
4378                         if (pt
.x 
< locStart
.x
) 
4381                 if (pos 
== SelectionEnd()) { 
4382                         // see if just after selection 
4383                         Point locEnd 
= LocationFromPosition(pos
); 
4384                         if (pt
.x 
> locEnd
.x
) 
4392 bool Editor::PointInSelMargin(Point pt
) { 
4393         // Really means: "Point in a margin" 
4394         if (vs
.fixedColumnWidth 
> 0) {  // There is a margin 
4395                 PRectangle rcSelMargin 
= GetClientRectangle(); 
4396                 rcSelMargin
.right 
= vs
.fixedColumnWidth 
- vs
.leftMarginWidth
; 
4397                 return rcSelMargin
.Contains(pt
); 
4403 void Editor::LineSelection(int lineCurrent_
, int lineAnchor_
) { 
4404         if (lineAnchor_ 
< lineCurrent_
) { 
4405                 SetSelection(pdoc
->LineStart(lineCurrent_ 
+ 1), 
4406                              pdoc
->LineStart(lineAnchor_
)); 
4407         } else if (lineAnchor_ 
> lineCurrent_
) { 
4408                 SetSelection(pdoc
->LineStart(lineCurrent_
), 
4409                              pdoc
->LineStart(lineAnchor_ 
+ 1)); 
4410         } else { // Same line, select it 
4411                 SetSelection(pdoc
->LineStart(lineAnchor_ 
+ 1), 
4412                              pdoc
->LineStart(lineAnchor_
)); 
4416 void Editor::DwellEnd(bool mouseMoved
) { 
4418                 ticksToDwell 
= dwellDelay
; 
4420                 ticksToDwell 
= SC_TIME_FOREVER
; 
4421         if (dwelling 
&& (dwellDelay 
< SC_TIME_FOREVER
)) { 
4423                 NotifyDwelling(ptMouseLast
, dwelling
); 
4427 void Editor::ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
) { 
4428         //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt); 
4430         int newPos 
= PositionFromLocation(pt
); 
4431         newPos 
= MovePositionOutsideChar(newPos
, currentPos 
- newPos
); 
4434         bool processed 
= NotifyMarginClick(pt
, shift
, ctrl
, alt
); 
4438         bool inSelMargin 
= PointInSelMargin(pt
); 
4439         if (shift 
& !inSelMargin
) { 
4440                 SetSelection(newPos
); 
4442         if (((curTime 
- lastClickTime
) < Platform::DoubleClickTime()) && Close(pt
, lastClick
)) { 
4443                 //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); 
4444                 SetMouseCapture(true); 
4445                 SetEmptySelection(newPos
); 
4446                 bool doubleClick 
= false; 
4447                 // Stop mouse button bounce changing selection type 
4448                 if (!Platform::MouseButtonBounce() || curTime 
!= lastClickTime
) { 
4449                         if (selectionType 
== selChar
) { 
4450                                 selectionType 
= selWord
; 
4452                         } else if (selectionType 
== selWord
) { 
4453                                 selectionType 
= selLine
; 
4455                                 selectionType 
= selChar
; 
4456                                 originalAnchorPos 
= currentPos
; 
4460                 if (selectionType 
== selWord
) { 
4461                         if (currentPos 
>= originalAnchorPos
) {  // Moved forward 
4462                                 SetSelection(pdoc
->ExtendWordSelect(currentPos
, 1), 
4463                                              pdoc
->ExtendWordSelect(originalAnchorPos
, -1)); 
4464                         } else {        // Moved backward 
4465                                 SetSelection(pdoc
->ExtendWordSelect(currentPos
, -1), 
4466                                              pdoc
->ExtendWordSelect(originalAnchorPos
, 1)); 
4468                 } else if (selectionType 
== selLine
) { 
4469                         lineAnchor 
= LineFromLocation(pt
); 
4470                         SetSelection(pdoc
->LineStart(lineAnchor 
+ 1), pdoc
->LineStart(lineAnchor
)); 
4471                         //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos); 
4473                         SetEmptySelection(currentPos
); 
4475                 //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos); 
4477                         NotifyDoubleClick(pt
, shift
); 
4478                         if (PositionIsHotspot(newPos
)) 
4479                                 NotifyHotSpotDoubleClicked(newPos
, shift
, ctrl
, alt
); 
4481         } else {        // Single click 
4483                         selType 
= selStream
; 
4486                                 lastClickTime 
= curTime
; 
4490                                 lineAnchor 
= LineFromLocation(pt
); 
4491                                 // Single click in margin: select whole line 
4492                                 LineSelection(lineAnchor
, lineAnchor
); 
4493                                 SetSelection(pdoc
->LineStart(lineAnchor 
+ 1), 
4494                                              pdoc
->LineStart(lineAnchor
)); 
4496                                 // Single shift+click in margin: select from line anchor to clicked line 
4497                                 if (anchor 
> currentPos
) 
4498                                         lineAnchor 
= pdoc
->LineFromPosition(anchor 
- 1); 
4500                                         lineAnchor 
= pdoc
->LineFromPosition(anchor
); 
4501                                 int lineStart 
= LineFromLocation(pt
); 
4502                                 LineSelection(lineStart
, lineAnchor
); 
4503                                 //lineAnchor = lineStart; // Keep the same anchor for ButtonMove 
4506                         SetDragPosition(invalidPosition
); 
4507                         SetMouseCapture(true); 
4508                         selectionType 
= selLine
; 
4510                         if (PositionIsHotspot(newPos
)) { 
4511                                 NotifyHotSpotClicked(newPos
, shift
, ctrl
, alt
); 
4514                                 inDragDrop 
= PointInSelection(pt
); 
4517                                 SetMouseCapture(false); 
4518                                 SetDragPosition(newPos
); 
4519                                 CopySelectionRange(&drag
); 
4522                                 xStartSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4523                                 xEndSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4524                                 SetDragPosition(invalidPosition
); 
4525                                 SetMouseCapture(true); 
4527                                         SetEmptySelection(newPos
); 
4528                                 selType 
= alt 
? selRectangle 
: selStream
; 
4529                                 selectionType 
= selChar
; 
4530                                 originalAnchorPos 
= currentPos
; 
4534         lastClickTime 
= curTime
; 
4536         ShowCaretAtCurrentPosition(); 
4539 bool Editor::PositionIsHotspot(int position
) { 
4540         return vs
.styles
[pdoc
->StyleAt(position
)].hotspot
; 
4543 bool Editor::PointIsHotspot(Point pt
) { 
4544         int pos 
= PositionFromLocation(pt
); 
4545         return PositionIsHotspot(pos
); 
4548 void Editor::SetHotSpotRange(Point 
*pt
) { 
4550                 int pos 
= PositionFromLocation(*pt
); 
4552                 // If we don't limit this to word characters then the 
4553                 // range can encompass more than the run range and then 
4554                 // the underline will not be drawn properly. 
4555                 int hsStart_ 
= pdoc
->ExtendStyleRange(pos
, -1); 
4556                 int hsEnd_ 
= pdoc
->ExtendStyleRange(pos
, 1); 
4558                 // Only invalidate the range if the hotspot range has changed... 
4559                 if (hsStart_ 
!= hsStart 
|| hsEnd_ 
!= hsEnd
) { 
4560                         if (hsStart 
!= -1) { 
4561                                 InvalidateRange(hsStart
, hsEnd
); 
4565                         InvalidateRange(hsStart
, hsEnd
); 
4568                 if (hsStart 
!= -1) { 
4569                         int hsStart_ 
= hsStart
; 
4573                         InvalidateRange(hsStart_
, hsEnd_
); 
4581 void Editor::GetHotSpotRange(int& hsStart_
, int& hsEnd_
) { 
4586 void Editor::ButtonMove(Point pt
) { 
4587         if ((ptMouseLast
.x 
!= pt
.x
) || (ptMouseLast
.y 
!= pt
.y
)) { 
4591         //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); 
4592         if (HaveMouseCapture()) { 
4594                 // Slow down autoscrolling/selection 
4595                 autoScrollTimer
.ticksToWait 
-= timer
.tickSize
; 
4596                 if (autoScrollTimer
.ticksToWait 
> 0) 
4598                 autoScrollTimer
.ticksToWait 
= autoScrollDelay
; 
4601                 xEndSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4602                 int movePos 
= PositionFromLocation(pt
); 
4603                 movePos 
= MovePositionOutsideChar(movePos
, currentPos 
- movePos
); 
4605                         SetDragPosition(movePos
); 
4607                         if (selectionType 
== selChar
) { 
4608                                 SetSelection(movePos
); 
4609                         } else if (selectionType 
== selWord
) { 
4610                                 // Continue selecting by word 
4611                                 if (movePos 
>= originalAnchorPos
) {     // Moved forward 
4612                                         SetSelection(pdoc
->ExtendWordSelect(movePos
, 1), 
4613                                                      pdoc
->ExtendWordSelect(originalAnchorPos
, -1)); 
4614                                 } else {        // Moved backward 
4615                                         SetSelection(pdoc
->ExtendWordSelect(movePos
, -1), 
4616                                                      pdoc
->ExtendWordSelect(originalAnchorPos
, 1)); 
4619                                 // Continue selecting by line 
4620                                 int lineMove 
= LineFromLocation(pt
); 
4621                                 LineSelection(lineMove
, lineAnchor
); 
4626                 PRectangle rcClient 
= GetClientRectangle(); 
4627                 if (pt
.y 
> rcClient
.bottom
) { 
4628                         int lineMove 
= cs
.DisplayFromDoc(LineFromLocation(pt
)); 
4630                                 lineMove 
= cs
.DisplayFromDoc(pdoc
->LinesTotal() - 1); 
4632                         ScrollTo(lineMove 
- LinesOnScreen() + 5); 
4634                 } else if (pt
.y 
< rcClient
.top
) { 
4635                         int lineMove 
= cs
.DisplayFromDoc(LineFromLocation(pt
)); 
4636                         ScrollTo(lineMove 
- 5); 
4639                 EnsureCaretVisible(false, false, true); 
4641                 if (hsStart 
!= -1 && !PositionIsHotspot(movePos
)) 
4642                         SetHotSpotRange(NULL
); 
4645                 if (vs
.fixedColumnWidth 
> 0) {  // There is a margin 
4646                         if (PointInSelMargin(pt
)) { 
4647                                 DisplayCursor(Window::cursorReverseArrow
); 
4648                                 return;         // No need to test for selection 
4651                 // Display regular (drag) cursor over selection 
4652                 if (PointInSelection(pt
)) { 
4653                         DisplayCursor(Window::cursorArrow
); 
4654                 } else if (PointIsHotspot(pt
)) { 
4655                         DisplayCursor(Window::cursorHand
); 
4656                         SetHotSpotRange(&pt
); 
4658                         DisplayCursor(Window::cursorText
); 
4659                         SetHotSpotRange(NULL
); 
4665 void Editor::ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
) { 
4666         //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture()); 
4667         if (HaveMouseCapture()) { 
4668                 if (PointInSelMargin(pt
)) { 
4669                         DisplayCursor(Window::cursorReverseArrow
); 
4671                         DisplayCursor(Window::cursorText
); 
4672                         SetHotSpotRange(NULL
); 
4674                 xEndSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4676                 SetMouseCapture(false); 
4677                 int newPos 
= PositionFromLocation(pt
); 
4678                 newPos 
= MovePositionOutsideChar(newPos
, currentPos 
- newPos
); 
4680                         int selStart 
= SelectionStart(); 
4681                         int selEnd 
= SelectionEnd(); 
4682                         if (selStart 
< selEnd
) { 
4685                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
4686                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
4688                                         } else if (newPos 
< selStart
) { 
4689                                                 pdoc
->DeleteChars(selStart
, drag
.len
); 
4690                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
4691                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
4693                                         } else if (newPos 
> selEnd
) { 
4694                                                 pdoc
->DeleteChars(selStart
, drag
.len
); 
4696                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
4697                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
4700                                                 SetEmptySelection(newPos
); 
4704                                 selectionType 
= selChar
; 
4707                         if (selectionType 
== selChar
) { 
4708                                 SetSelection(newPos
); 
4711                 lastClickTime 
= curTime
; 
4714                 if (selType 
== selStream
) { 
4718                 EnsureCaretVisible(false); 
4722 // Called frequently to perform background UI including 
4723 // caret blinking and automatic scrolling. 
4724 void Editor::Tick() { 
4725         if (HaveMouseCapture()) { 
4727                 ButtonMove(ptMouseLast
); 
4729         if (caret
.period 
> 0) { 
4730                 timer
.ticksToWait 
-= timer
.tickSize
; 
4731                 if (timer
.ticksToWait 
<= 0) { 
4732                         caret
.on 
= !caret
.on
; 
4733                         timer
.ticksToWait 
= caret
.period
; 
4737         if ((dwellDelay 
< SC_TIME_FOREVER
) && 
4738                 (ticksToDwell 
> 0) && 
4739                 (!HaveMouseCapture())) { 
4740                 ticksToDwell 
-= timer
.tickSize
; 
4741                 if (ticksToDwell 
<= 0) { 
4743                         NotifyDwelling(ptMouseLast
, dwelling
); 
4748 void Editor::SetFocusState(bool focusState
) { 
4749         hasFocus 
= focusState
; 
4750         NotifyFocus(hasFocus
); 
4752                 ShowCaretAtCurrentPosition(); 
4759 static bool IsIn(int a
, int minimum
, int maximum
) { 
4760         return (a 
>= minimum
) && (a 
<= maximum
); 
4763 static bool IsOverlap(int mina
, int maxa
, int minb
, int maxb
) { 
4765             IsIn(mina
, minb
, maxb
) || 
4766             IsIn(maxa
, minb
, maxb
) || 
4767             IsIn(minb
, mina
, maxa
) || 
4768             IsIn(maxb
, mina
, maxa
); 
4771 void Editor::CheckForChangeOutsidePaint(Range r
) { 
4772         if (paintState 
== painting 
&& !paintingAllText
) { 
4773                 //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end); 
4777                 PRectangle rcText 
= GetTextRectangle(); 
4778                 // Determine number of lines displayed including a possible partially displayed last line 
4779                 int linesDisplayed 
= (rcText
.bottom 
- rcText
.top 
- 1) / vs
.lineHeight 
+ 1; 
4780                 int bottomLine 
= topLine 
+ linesDisplayed 
- 1; 
4782                 int lineRangeStart 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.start
)); 
4783                 int lineRangeEnd 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.end
)); 
4784                 if (!IsOverlap(topLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) { 
4785                         //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n", 
4786                         //              lineRangeStart, lineRangeEnd, topLine, bottomLine); 
4790                 // Assert rcPaint contained within or equal to rcText 
4791                 if (rcPaint
.top 
> rcText
.top
) { 
4792                         // does range intersect rcText.top .. rcPaint.top 
4793                         int paintTopLine 
= ((rcPaint
.top 
- rcText
.top 
- 1) / vs
.lineHeight
) + topLine
; 
4794                         // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle 
4795                         if (IsOverlap(topLine
, paintTopLine
, lineRangeStart
, lineRangeEnd
)) { 
4796                                 //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n", 
4797                                 //      lineRangeStart, lineRangeEnd, topLine, paintTopLine); 
4802                 if (rcPaint
.bottom 
< rcText
.bottom
) { 
4803                         // does range intersect rcPaint.bottom .. rcText.bottom 
4804                         int paintBottomLine 
= ((rcPaint
.bottom 
- rcText
.top 
- 1) / vs
.lineHeight 
+ 1) + topLine
; 
4805                         // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle 
4806                         if (IsOverlap(paintBottomLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) { 
4807                                 //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n", 
4808                                 //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine); 
4816 char BraceOpposite(char ch
) { 
4839 // TODO: should be able to extend styled region to find matching brace 
4840 // TODO: may need to make DBCS safe 
4841 // so should be moved into Document 
4842 int Editor::BraceMatch(int position
, int /*maxReStyle*/) { 
4843         char chBrace 
= pdoc
->CharAt(position
); 
4844         char chSeek 
= BraceOpposite(chBrace
); 
4847         char styBrace 
= static_cast<char>( 
4848                             pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
); 
4850         if (chBrace 
== '(' || chBrace 
== '[' || chBrace 
== '{' || chBrace 
== '<') 
4853         position 
= position 
+ direction
; 
4854         while ((position 
>= 0) && (position 
< pdoc
->Length())) { 
4855                 char chAtPos 
= pdoc
->CharAt(position
); 
4856                 char styAtPos 
= static_cast<char>(pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
); 
4857                 if ((position 
> pdoc
->GetEndStyled()) || (styAtPos 
== styBrace
)) { 
4858                         if (chAtPos 
== chBrace
) 
4860                         if (chAtPos 
== chSeek
) 
4865                 position 
= position 
+ direction
; 
4870 void Editor::SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
) { 
4871         if ((pos0 
!= braces
[0]) || (pos1 
!= braces
[1]) || (matchStyle 
!= bracesMatchStyle
)) { 
4872                 if ((braces
[0] != pos0
) || (matchStyle 
!= bracesMatchStyle
)) { 
4873                         CheckForChangeOutsidePaint(Range(braces
[0])); 
4874                         CheckForChangeOutsidePaint(Range(pos0
)); 
4877                 if ((braces
[1] != pos1
) || (matchStyle 
!= bracesMatchStyle
)) { 
4878                         CheckForChangeOutsidePaint(Range(braces
[1])); 
4879                         CheckForChangeOutsidePaint(Range(pos1
)); 
4882                 bracesMatchStyle 
= matchStyle
; 
4883                 if (paintState 
== notPainting
) { 
4889 void Editor::SetDocPointer(Document 
*document
) { 
4890         //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document); 
4891         pdoc
->RemoveWatcher(this, 0); 
4893         if (document 
== NULL
) { 
4894                 pdoc 
= new Document(); 
4900         // Ensure all positions within document 
4906         // Reset the contraction state to fully shown. 
4908         cs
.InsertLines(0, pdoc
->LinesTotal() - 1); 
4912         pdoc
->AddWatcher(this, 0); 
4917 // Recursively expand a fold, making lines visible except where they have an unexpanded parent 
4918 void Editor::Expand(int &line
, bool doExpand
) { 
4919         int lineMaxSubord 
= pdoc
->GetLastChild(line
); 
4921         while (line 
<= lineMaxSubord
) { 
4923                         cs
.SetVisible(line
, line
, true); 
4924                 int level 
= pdoc
->GetLevel(line
); 
4925                 if (level 
& SC_FOLDLEVELHEADERFLAG
) { 
4926                         if (doExpand 
&& cs
.GetExpanded(line
)) { 
4929                                 Expand(line
, false); 
4937 void Editor::ToggleContraction(int line
) { 
4938         if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) { 
4939                 if (cs
.GetExpanded(line
)) { 
4940                         int lineMaxSubord 
= pdoc
->GetLastChild(line
); 
4941                         cs
.SetExpanded(line
, 0); 
4942                         if (lineMaxSubord 
> line
) { 
4943                                 cs
.SetVisible(line 
+ 1, lineMaxSubord
, false); 
4948                         cs
.SetExpanded(line
, 1); 
4956 // Recurse up from this line to find any folds that prevent this line from being visible 
4957 // and unfold them all-> 
4958 void Editor::EnsureLineVisible(int lineDoc
, bool enforcePolicy
) { 
4960         // In case in need of wrapping to ensure DisplayFromDoc works. 
4963         if (!cs
.GetVisible(lineDoc
)) { 
4964                 int lineParent 
= pdoc
->GetFoldParent(lineDoc
); 
4965                 if (lineParent 
>= 0) { 
4966                         if (lineDoc 
!= lineParent
) 
4967                                 EnsureLineVisible(lineParent
, enforcePolicy
); 
4968                         if (!cs
.GetExpanded(lineParent
)) { 
4969                                 cs
.SetExpanded(lineParent
, 1); 
4970                                 Expand(lineParent
, true); 
4976         if (enforcePolicy
) { 
4977                 int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
4978                 if (visiblePolicy 
& VISIBLE_SLOP
) { 
4979                         if ((topLine 
> lineDisplay
) || ((visiblePolicy 
& VISIBLE_STRICT
) && (topLine 
+ visibleSlop 
> lineDisplay
))) { 
4980                                 SetTopLine(Platform::Clamp(lineDisplay 
- visibleSlop
, 0, MaxScrollPos())); 
4981                                 SetVerticalScrollPos(); 
4983                         } else if ((lineDisplay 
> topLine 
+ LinesOnScreen() - 1) || 
4984                                    ((visiblePolicy 
& VISIBLE_STRICT
) && (lineDisplay 
> topLine 
+ LinesOnScreen() - 1 - visibleSlop
))) { 
4985                                 SetTopLine(Platform::Clamp(lineDisplay 
- LinesOnScreen() + 1 + visibleSlop
, 0, MaxScrollPos())); 
4986                                 SetVerticalScrollPos(); 
4990                         if ((topLine 
> lineDisplay
) || (lineDisplay 
> topLine 
+ LinesOnScreen() - 1) || (visiblePolicy 
& VISIBLE_STRICT
)) { 
4991                                 SetTopLine(Platform::Clamp(lineDisplay 
- LinesOnScreen() / 2 + 1, 0, MaxScrollPos())); 
4992                                 SetVerticalScrollPos(); 
4999 int Editor::ReplaceTarget(bool replacePatterns
, const char *text
, int length
) { 
5000         pdoc
->BeginUndoAction(); 
5002                 length 
= istrlen(text
); 
5003         if (replacePatterns
) { 
5004                 text 
= pdoc
->SubstituteByPosition(text
, &length
); 
5008         if (targetStart 
!= targetEnd
) 
5009                 pdoc
->DeleteChars(targetStart
, targetEnd 
- targetStart
); 
5010         targetEnd 
= targetStart
; 
5011         pdoc
->InsertString(targetStart
, text
, length
); 
5012         targetEnd 
= targetStart 
+ length
; 
5013         pdoc
->EndUndoAction(); 
5017 bool Editor::IsUnicodeMode() const { 
5018         return pdoc 
&& (SC_CP_UTF8 
== pdoc
->dbcsCodePage
); 
5021 int Editor::CodePage() const { 
5023                 return pdoc
->dbcsCodePage
; 
5028 static bool ValidMargin(unsigned long wParam
) { 
5029         return wParam 
< ViewStyle::margins
; 
5032 static char *CharPtrFromSPtr(sptr_t lParam
) { 
5033         return reinterpret_cast<char *>(lParam
); 
5036 sptr_t 
Editor::WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) { 
5037         //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam); 
5039         // Optional macro recording hook 
5041                 NotifyMacroRecord(iMessage
, wParam
, lParam
); 
5050                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5051                         unsigned int iChar 
= 0; 
5052                         for (; iChar 
< wParam 
- 1; iChar
++) 
5053                                 ptr
[iChar
] = pdoc
->CharAt(iChar
); 
5061                         pdoc
->DeleteChars(0, pdoc
->Length()); 
5062                         SetEmptySelection(0); 
5063                         pdoc
->InsertString(0, CharPtrFromSPtr(lParam
)); 
5067         case SCI_GETTEXTLENGTH
: 
5068                 return pdoc
->Length(); 
5080                 CopyRangeToClipboard(wParam
, lParam
); 
5084                 CopyText(wParam
, CharPtrFromSPtr(lParam
)); 
5090                 EnsureCaretVisible(); 
5096                 EnsureCaretVisible(); 
5105                 return pdoc
->CanUndo() ? 1 : 0; 
5107         case SCI_EMPTYUNDOBUFFER
: 
5108                 pdoc
->DeleteUndoHistory(); 
5111         case SCI_GETFIRSTVISIBLELINE
: 
5114         case SCI_GETLINE
: {     // Risk of overwriting the end of the buffer 
5118                         int lineStart 
= pdoc
->LineStart(wParam
); 
5119                         int lineEnd 
= pdoc
->LineStart(wParam 
+ 1); 
5120                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5122                         for (int iChar 
= lineStart
; iChar 
< lineEnd
; iChar
++) { 
5123                                 ptr
[iPlace
++] = pdoc
->CharAt(iChar
); 
5128         case SCI_GETLINECOUNT
: 
5129                 if (pdoc
->LinesTotal() == 0) 
5132                         return pdoc
->LinesTotal(); 
5135                 return !pdoc
->IsSavePoint(); 
5138                         int nStart 
= static_cast<int>(wParam
); 
5139                         int nEnd 
= static_cast<int>(lParam
); 
5141                                 nEnd 
= pdoc
->Length(); 
5143                                 nStart 
= nEnd
;  // Remove selection 
5144                         selType 
= selStream
; 
5145                         SetSelection(nEnd
, nStart
); 
5146                         EnsureCaretVisible(); 
5150         case SCI_GETSELTEXT
: { 
5153                         SelectionText selectedText
; 
5154                         CopySelectionRange(&selectedText
); 
5155                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5157                         if (selectedText
.len
) { 
5158                                 for (; iChar 
< selectedText
.len
; iChar
++) 
5159                                         ptr
[iChar
] = selectedText
.s
[iChar
]; 
5167         case SCI_LINEFROMPOSITION
: 
5168                 if (static_cast<int>(wParam
) < 0) 
5170                 return pdoc
->LineFromPosition(wParam
); 
5172         case SCI_POSITIONFROMLINE
: 
5173                 if (static_cast<int>(wParam
) < 0) 
5174                         wParam 
= pdoc
->LineFromPosition(SelectionStart()); 
5176                         return 0;       // Even if there is no text, there is a first line that starts at 0 
5177                 if (static_cast<int>(wParam
) > pdoc
->LinesTotal()) 
5179                 //if (wParam > pdoc->LineFromPosition(pdoc->Length()))  // Useful test, anyway... 
5181                 return pdoc
->LineStart(wParam
); 
5183                 // Replacement of the old Scintilla interpretation of EM_LINELENGTH 
5184         case SCI_LINELENGTH
: 
5185                 if ((static_cast<int>(wParam
) < 0) || 
5186                         (static_cast<int>(wParam
) > pdoc
->LineFromPosition(pdoc
->Length()))) 
5188                 return pdoc
->LineStart(wParam 
+ 1) - pdoc
->LineStart(wParam
); 
5190         case SCI_REPLACESEL
: { 
5193                         pdoc
->BeginUndoAction(); 
5195                         char *replacement 
= CharPtrFromSPtr(lParam
); 
5196                         pdoc
->InsertString(currentPos
, replacement
); 
5197                         pdoc
->EndUndoAction(); 
5198                         SetEmptySelection(currentPos 
+ istrlen(replacement
)); 
5199                         EnsureCaretVisible(); 
5203         case SCI_SETTARGETSTART
: 
5204                 targetStart 
= wParam
; 
5207         case SCI_GETTARGETSTART
: 
5210         case SCI_SETTARGETEND
: 
5214         case SCI_GETTARGETEND
: 
5217         case SCI_TARGETFROMSELECTION
: 
5218                 if (currentPos 
< anchor
) { 
5219                         targetStart 
= currentPos
; 
5222                         targetStart 
= anchor
; 
5223                         targetEnd 
= currentPos
; 
5227         case SCI_REPLACETARGET
: 
5228                 PLATFORM_ASSERT(lParam
); 
5229                 return ReplaceTarget(false, CharPtrFromSPtr(lParam
), wParam
); 
5231         case SCI_REPLACETARGETRE
: 
5232                 PLATFORM_ASSERT(lParam
); 
5233                 return ReplaceTarget(true, CharPtrFromSPtr(lParam
), wParam
); 
5235         case SCI_SEARCHINTARGET
: 
5236                 PLATFORM_ASSERT(lParam
); 
5237                 return SearchInTarget(CharPtrFromSPtr(lParam
), wParam
); 
5239         case SCI_SETSEARCHFLAGS
: 
5240                 searchFlags 
= wParam
; 
5243         case SCI_GETSEARCHFLAGS
: 
5246         case SCI_POSITIONBEFORE
: 
5247                 return pdoc
->MovePositionOutsideChar(wParam
-1, -1, true); 
5249         case SCI_POSITIONAFTER
: 
5250                 return pdoc
->MovePositionOutsideChar(wParam
+1, 1, true); 
5252         case SCI_LINESCROLL
: 
5253                 ScrollTo(topLine 
+ lParam
); 
5254                 HorizontalScrollTo(xOffset 
+ wParam 
* vs
.spaceWidth
); 
5257         case SCI_SETXOFFSET
: 
5259                 SetHorizontalScrollPos(); 
5263         case SCI_GETXOFFSET
: 
5266         case SCI_CHOOSECARETX
: 
5270         case SCI_SCROLLCARET
: 
5271                 EnsureCaretVisible(); 
5274         case SCI_SETREADONLY
: 
5275                 pdoc
->SetReadOnly(wParam 
!= 0); 
5278         case SCI_GETREADONLY
: 
5279                 return pdoc
->IsReadOnly(); 
5284         case SCI_POINTXFROMPOSITION
: 
5288                         Point pt 
= LocationFromPosition(lParam
); 
5292         case SCI_POINTYFROMPOSITION
: 
5296                         Point pt 
= LocationFromPosition(lParam
); 
5301                 return FindText(wParam
, lParam
); 
5303         case SCI_GETTEXTRANGE
: { 
5306                         TextRange 
*tr 
= reinterpret_cast<TextRange 
*>(lParam
); 
5307                         int cpMax 
= tr
->chrg
.cpMax
; 
5309                                 cpMax 
= pdoc
->Length(); 
5310                         int len 
= cpMax 
- tr
->chrg
.cpMin
;       // No -1 as cpMin and cpMax are referring to inter character positions 
5311                         pdoc
->GetCharRange(tr
->lpstrText
, tr
->chrg
.cpMin
, len
); 
5312                         // Spec says copied text is terminated with a NUL 
5313                         tr
->lpstrText
[len
] = '\0'; 
5314                         return len
;     // Not including NUL 
5317         case SCI_HIDESELECTION
: 
5318                 hideSelection 
= wParam 
!= 0; 
5322         case SCI_FORMATRANGE
: 
5323                 return FormatRange(wParam 
!= 0, reinterpret_cast<RangeToFormat 
*>(lParam
)); 
5325         case SCI_GETMARGINLEFT
: 
5326                 return vs
.leftMarginWidth
; 
5328         case SCI_GETMARGINRIGHT
: 
5329                 return vs
.rightMarginWidth
; 
5331         case SCI_SETMARGINLEFT
: 
5332                 vs
.leftMarginWidth 
= lParam
; 
5333                 InvalidateStyleRedraw(); 
5336         case SCI_SETMARGINRIGHT
: 
5337                 vs
.rightMarginWidth 
= lParam
; 
5338                 InvalidateStyleRedraw(); 
5341                 // Control specific mesages 
5346                         pdoc
->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam
), wParam
); 
5347                         SetEmptySelection(currentPos 
+ wParam
); 
5351         case SCI_ADDSTYLEDTEXT
: { 
5354                         pdoc
->InsertStyledString(CurrentPosition() * 2, CharPtrFromSPtr(lParam
), wParam
); 
5355                         SetEmptySelection(currentPos 
+ wParam 
/ 2); 
5359         case SCI_INSERTTEXT
: { 
5362                         int insertPos 
= wParam
; 
5363                         if (static_cast<short>(wParam
) == -1) 
5364                                 insertPos 
= CurrentPosition(); 
5365                         int newCurrent 
= CurrentPosition(); 
5366                         char *sz 
= CharPtrFromSPtr(lParam
); 
5367                         pdoc
->InsertString(insertPos
, sz
); 
5368                         if (newCurrent 
> insertPos
) 
5369                                 newCurrent 
+= istrlen(sz
); 
5370                         SetEmptySelection(newCurrent
); 
5374         case SCI_APPENDTEXT
: 
5375                 pdoc
->InsertString(pdoc
->Length(), CharPtrFromSPtr(lParam
), wParam
); 
5382         case SCI_CLEARDOCUMENTSTYLE
: 
5383                 ClearDocumentStyle(); 
5386         case SCI_SETUNDOCOLLECTION
: 
5387                 pdoc
->SetUndoCollection(wParam 
!= 0); 
5390         case SCI_GETUNDOCOLLECTION
: 
5391                 return pdoc
->IsCollectingUndo(); 
5393         case SCI_BEGINUNDOACTION
: 
5394                 pdoc
->BeginUndoAction(); 
5397         case SCI_ENDUNDOACTION
: 
5398                 pdoc
->EndUndoAction(); 
5401         case SCI_GETCARETPERIOD
: 
5402                 return caret
.period
; 
5404         case SCI_SETCARETPERIOD
: 
5405                 caret
.period 
= wParam
; 
5408         case SCI_SETWORDCHARS
: { 
5411                         pdoc
->SetWordChars(reinterpret_cast<unsigned char *>(lParam
)); 
5416                 return pdoc
->Length(); 
5419                 return pdoc
->CharAt(wParam
); 
5421         case SCI_SETCURRENTPOS
: 
5422                 SetSelection(wParam
, anchor
); 
5425         case SCI_GETCURRENTPOS
: 
5429                 SetSelection(currentPos
, wParam
); 
5435         case SCI_SETSELECTIONSTART
: 
5436                 SetSelection(Platform::Maximum(currentPos
, wParam
), wParam
); 
5439         case SCI_GETSELECTIONSTART
: 
5440                 return Platform::Minimum(anchor
, currentPos
); 
5442         case SCI_SETSELECTIONEND
: 
5443                 SetSelection(wParam
, Platform::Minimum(anchor
, wParam
)); 
5446         case SCI_GETSELECTIONEND
: 
5447                 return Platform::Maximum(anchor
, currentPos
); 
5449         case SCI_SETPRINTMAGNIFICATION
: 
5450                 printMagnification 
= wParam
; 
5453         case SCI_GETPRINTMAGNIFICATION
: 
5454                 return printMagnification
; 
5456         case SCI_SETPRINTCOLOURMODE
: 
5457                 printColourMode 
= wParam
; 
5460         case SCI_GETPRINTCOLOURMODE
: 
5461                 return printColourMode
; 
5463         case SCI_SETPRINTWRAPMODE
: 
5464                 printWrapState 
= (wParam 
== SC_WRAP_WORD
) ? eWrapWord 
: eWrapNone
; 
5467         case SCI_GETPRINTWRAPMODE
: 
5468                 return printWrapState
; 
5470         case SCI_GETSTYLEAT
: 
5471                 if (static_cast<short>(wParam
) >= pdoc
->Length()) 
5474                         return pdoc
->StyleAt(wParam
); 
5484         case SCI_SETSAVEPOINT
: 
5485                 pdoc
->SetSavePoint(); 
5488         case SCI_GETSTYLEDTEXT
: { 
5491                         TextRange 
*tr 
= reinterpret_cast<TextRange 
*>(lParam
); 
5493                         for (int iChar 
= tr
->chrg
.cpMin
; iChar 
< tr
->chrg
.cpMax
; iChar
++) { 
5494                                 tr
->lpstrText
[iPlace
++] = pdoc
->CharAt(iChar
); 
5495                                 tr
->lpstrText
[iPlace
++] = pdoc
->StyleAt(iChar
); 
5497                         tr
->lpstrText
[iPlace
] = '\0'; 
5498                         tr
->lpstrText
[iPlace 
+ 1] = '\0'; 
5503                 return pdoc
->CanRedo() ? 1 : 0; 
5505         case SCI_MARKERLINEFROMHANDLE
: 
5506                 return pdoc
->LineFromHandle(wParam
); 
5508         case SCI_MARKERDELETEHANDLE
: 
5509                 pdoc
->DeleteMarkFromHandle(wParam
); 
5513                 return vs
.viewWhitespace
; 
5516                 vs
.viewWhitespace 
= static_cast<WhiteSpaceVisibility
>(wParam
); 
5520         case SCI_POSITIONFROMPOINT
: 
5521                 return PositionFromLocation(Point(wParam
, lParam
)); 
5523         case SCI_POSITIONFROMPOINTCLOSE
: 
5524                 return PositionFromLocationClose(Point(wParam
, lParam
)); 
5531                 SetEmptySelection(wParam
); 
5532                 EnsureCaretVisible(); 
5536         case SCI_GETCURLINE
: { 
5540                         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
5541                         int lineStart 
= pdoc
->LineStart(lineCurrentPos
); 
5542                         unsigned int lineEnd 
= pdoc
->LineStart(lineCurrentPos 
+ 1); 
5543                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5544                         unsigned int iPlace 
= 0; 
5545                         for (unsigned int iChar 
= lineStart
; iChar 
< lineEnd 
&& iPlace 
< wParam 
- 1; iChar
++) { 
5546                                 ptr
[iPlace
++] = pdoc
->CharAt(iChar
); 
5549                         return currentPos 
- lineStart
; 
5552         case SCI_GETENDSTYLED
: 
5553                 return pdoc
->GetEndStyled(); 
5555         case SCI_GETEOLMODE
: 
5556                 return pdoc
->eolMode
; 
5558         case SCI_SETEOLMODE
: 
5559                 pdoc
->eolMode 
= wParam
; 
5562         case SCI_STARTSTYLING
: 
5563                 pdoc
->StartStyling(wParam
, static_cast<char>(lParam
)); 
5566         case SCI_SETSTYLING
: 
5567                 pdoc
->SetStyleFor(wParam
, static_cast<char>(lParam
)); 
5570         case SCI_SETSTYLINGEX
:             // Specify a complete styling buffer 
5573                 pdoc
->SetStyles(wParam
, CharPtrFromSPtr(lParam
)); 
5576         case SCI_SETBUFFEREDDRAW
: 
5577                 bufferedDraw 
= wParam 
!= 0; 
5580         case SCI_GETBUFFEREDDRAW
: 
5581                 return bufferedDraw
; 
5583         case SCI_GETTWOPHASEDRAW
: 
5584                 return twoPhaseDraw
; 
5586         case SCI_SETTWOPHASEDRAW
: 
5587                 twoPhaseDraw 
= wParam 
!= 0; 
5588                 InvalidateStyleRedraw(); 
5591         case SCI_SETTABWIDTH
: 
5593                         pdoc
->tabInChars 
= wParam
; 
5594                 InvalidateStyleRedraw(); 
5597         case SCI_GETTABWIDTH
: 
5598                 return pdoc
->tabInChars
; 
5601                 pdoc
->indentInChars 
= wParam
; 
5602                 InvalidateStyleRedraw(); 
5606                 return pdoc
->indentInChars
; 
5608         case SCI_SETUSETABS
: 
5609                 pdoc
->useTabs 
= wParam 
!= 0; 
5610                 InvalidateStyleRedraw(); 
5613         case SCI_GETUSETABS
: 
5614                 return pdoc
->useTabs
; 
5616         case SCI_SETLINEINDENTATION
: 
5617                 pdoc
->SetLineIndentation(wParam
, lParam
); 
5620         case SCI_GETLINEINDENTATION
: 
5621                 return pdoc
->GetLineIndentation(wParam
); 
5623         case SCI_GETLINEINDENTPOSITION
: 
5624                 return pdoc
->GetLineIndentPosition(wParam
); 
5626         case SCI_SETTABINDENTS
: 
5627                 pdoc
->tabIndents 
= wParam 
!= 0; 
5630         case SCI_GETTABINDENTS
: 
5631                 return pdoc
->tabIndents
; 
5633         case SCI_SETBACKSPACEUNINDENTS
: 
5634                 pdoc
->backspaceUnindents 
= wParam 
!= 0; 
5637         case SCI_GETBACKSPACEUNINDENTS
: 
5638                 return pdoc
->backspaceUnindents
; 
5640         case SCI_SETMOUSEDWELLTIME
: 
5641                 dwellDelay 
= wParam
; 
5642                 ticksToDwell 
= dwellDelay
; 
5645         case SCI_GETMOUSEDWELLTIME
: 
5648         case SCI_WORDSTARTPOSITION
: 
5649                 return pdoc
->ExtendWordSelect(wParam
, -1, lParam 
!= 0); 
5651         case SCI_WORDENDPOSITION
: 
5652                 return pdoc
->ExtendWordSelect(wParam
, 1, lParam 
!= 0); 
5654         case SCI_SETWRAPMODE
: 
5655                 wrapState 
= (wParam 
== SC_WRAP_WORD
) ? eWrapWord 
: eWrapNone
; 
5657                 InvalidateStyleRedraw(); 
5658                 ReconfigureScrollBars(); 
5661         case SCI_GETWRAPMODE
: 
5664         case SCI_SETLAYOUTCACHE
: 
5665                 llc
.SetLevel(wParam
); 
5668         case SCI_GETLAYOUTCACHE
: 
5669                 return llc
.GetLevel(); 
5671         case SCI_SETSCROLLWIDTH
: 
5672                 PLATFORM_ASSERT(wParam 
> 0); 
5673                 if ((wParam 
> 0) && (wParam 
!= static_cast<unsigned int >(scrollWidth
))) { 
5674                         scrollWidth 
= wParam
; 
5679         case SCI_GETSCROLLWIDTH
: 
5686         case SCI_LINESSPLIT
: 
5691                 PLATFORM_ASSERT(wParam 
<= STYLE_MAX
); 
5692                 PLATFORM_ASSERT(lParam
); 
5693                 return TextWidth(wParam
, CharPtrFromSPtr(lParam
)); 
5695         case SCI_TEXTHEIGHT
: 
5696                 return vs
.lineHeight
; 
5698         case SCI_SETENDATLASTLINE
: 
5699                 PLATFORM_ASSERT((wParam 
== 0) || (wParam 
== 1)); 
5700                 if (endAtLastLine 
!= (wParam 
!= 0)) { 
5701                         endAtLastLine 
= wParam 
!= 0; 
5706         case SCI_GETENDATLASTLINE
: 
5707                 return endAtLastLine
; 
5710                 return pdoc
->GetColumn(wParam
); 
5712         case SCI_SETHSCROLLBAR 
: 
5713                 if (horizontalScrollBarVisible 
!= (wParam 
!= 0)) { 
5714                         horizontalScrollBarVisible 
= wParam 
!= 0; 
5716                         ReconfigureScrollBars(); 
5720         case SCI_GETHSCROLLBAR
: 
5721                 return horizontalScrollBarVisible
; 
5723         case SCI_SETVSCROLLBAR
: 
5724                 if (verticalScrollBarVisible 
!= (wParam 
!= 0)) { 
5725                         verticalScrollBarVisible 
= wParam 
!= 0; 
5727                         ReconfigureScrollBars(); 
5731         case SCI_GETVSCROLLBAR
: 
5732                 return verticalScrollBarVisible
; 
5734         case SCI_SETINDENTATIONGUIDES
: 
5735                 vs
.viewIndentationGuides 
= wParam 
!= 0; 
5739         case SCI_GETINDENTATIONGUIDES
: 
5740                 return vs
.viewIndentationGuides
; 
5742         case SCI_SETHIGHLIGHTGUIDE
: 
5743                 if ((highlightGuideColumn 
!= static_cast<int>(wParam
)) || (wParam 
> 0)) { 
5744                         highlightGuideColumn 
= wParam
; 
5749         case SCI_GETHIGHLIGHTGUIDE
: 
5750                 return highlightGuideColumn
; 
5752         case SCI_GETLINEENDPOSITION
: 
5753                 return pdoc
->LineEnd(wParam
); 
5755         case SCI_SETCODEPAGE
: 
5756                 pdoc
->dbcsCodePage 
= wParam
; 
5757                 InvalidateStyleRedraw(); 
5760         case SCI_GETCODEPAGE
: 
5761                 return pdoc
->dbcsCodePage
; 
5763         case SCI_SETUSEPALETTE
: 
5764                 palette
.allowRealization 
= wParam 
!= 0; 
5765                 InvalidateStyleRedraw(); 
5768         case SCI_GETUSEPALETTE
: 
5769                 return palette
.allowRealization
; 
5771                 // Marker definition and setting 
5772         case SCI_MARKERDEFINE
: 
5773                 if (wParam 
<= MARKER_MAX
) 
5774                         vs
.markers
[wParam
].markType 
= lParam
; 
5775                 InvalidateStyleData(); 
5778         case SCI_MARKERSETFORE
: 
5779                 if (wParam 
<= MARKER_MAX
) 
5780                         vs
.markers
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
5781                 InvalidateStyleData(); 
5784         case SCI_MARKERSETBACK
: 
5785                 if (wParam 
<= MARKER_MAX
) 
5786                         vs
.markers
[wParam
].back
.desired 
= ColourDesired(lParam
); 
5787                 InvalidateStyleData(); 
5790         case SCI_MARKERADD
: { 
5791                         int markerID 
= pdoc
->AddMark(wParam
, lParam
); 
5795         case SCI_MARKERDELETE
: 
5796                 pdoc
->DeleteMark(wParam
, lParam
); 
5799         case SCI_MARKERDELETEALL
: 
5800                 pdoc
->DeleteAllMarks(static_cast<int>(wParam
)); 
5804                 return pdoc
->GetMark(wParam
); 
5806         case SCI_MARKERNEXT
: { 
5807                         int lt 
= pdoc
->LinesTotal(); 
5808                         for (int iLine 
= wParam
; iLine 
< lt
; iLine
++) { 
5809                                 if ((pdoc
->GetMark(iLine
) & lParam
) != 0) 
5815         case SCI_MARKERPREVIOUS
: { 
5816                         for (int iLine 
= wParam
; iLine 
>= 0; iLine
--) { 
5817                                 if ((pdoc
->GetMark(iLine
) & lParam
) != 0) 
5823         case SCI_MARKERDEFINEPIXMAP
: 
5824                 if (wParam 
<= MARKER_MAX
) { 
5825                         vs
.markers
[wParam
].SetXPM(CharPtrFromSPtr(lParam
)); 
5827                 InvalidateStyleData(); 
5831         case SCI_SETMARGINTYPEN
: 
5832                 if (ValidMargin(wParam
)) { 
5833                         vs
.ms
[wParam
].symbol 
= (lParam 
== SC_MARGIN_SYMBOL
); 
5834                         InvalidateStyleRedraw(); 
5838         case SCI_GETMARGINTYPEN
: 
5839                 if (ValidMargin(wParam
)) 
5840                         return vs
.ms
[wParam
].symbol 
? SC_MARGIN_SYMBOL 
: SC_MARGIN_NUMBER
; 
5844         case SCI_SETMARGINWIDTHN
: 
5845                 if (ValidMargin(wParam
)) { 
5846                         vs
.ms
[wParam
].width 
= lParam
; 
5847                         InvalidateStyleRedraw(); 
5851         case SCI_GETMARGINWIDTHN
: 
5852                 if (ValidMargin(wParam
)) 
5853                         return vs
.ms
[wParam
].width
; 
5857         case SCI_SETMARGINMASKN
: 
5858                 if (ValidMargin(wParam
)) { 
5859                         vs
.ms
[wParam
].mask 
= lParam
; 
5860                         InvalidateStyleRedraw(); 
5864         case SCI_GETMARGINMASKN
: 
5865                 if (ValidMargin(wParam
)) 
5866                         return vs
.ms
[wParam
].mask
; 
5870         case SCI_SETMARGINSENSITIVEN
: 
5871                 if (ValidMargin(wParam
)) { 
5872                         vs
.ms
[wParam
].sensitive 
= lParam 
!= 0; 
5873                         InvalidateStyleRedraw(); 
5877         case SCI_GETMARGINSENSITIVEN
: 
5878                 if (ValidMargin(wParam
)) 
5879                         return vs
.ms
[wParam
].sensitive 
? 1 : 0; 
5883         case SCI_STYLECLEARALL
: 
5885                 InvalidateStyleRedraw(); 
5888         case SCI_STYLESETFORE
: 
5889                 if (wParam 
<= STYLE_MAX
) { 
5890                         vs
.styles
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
5891                         InvalidateStyleRedraw(); 
5894         case SCI_STYLESETBACK
: 
5895                 if (wParam 
<= STYLE_MAX
) { 
5896                         vs
.styles
[wParam
].back
.desired 
= ColourDesired(lParam
); 
5897                         InvalidateStyleRedraw(); 
5900         case SCI_STYLESETBOLD
: 
5901                 if (wParam 
<= STYLE_MAX
) { 
5902                         vs
.styles
[wParam
].bold 
= lParam 
!= 0; 
5903                         InvalidateStyleRedraw(); 
5906         case SCI_STYLESETITALIC
: 
5907                 if (wParam 
<= STYLE_MAX
) { 
5908                         vs
.styles
[wParam
].italic 
= lParam 
!= 0; 
5909                         InvalidateStyleRedraw(); 
5912         case SCI_STYLESETEOLFILLED
: 
5913                 if (wParam 
<= STYLE_MAX
) { 
5914                         vs
.styles
[wParam
].eolFilled 
= lParam 
!= 0; 
5915                         InvalidateStyleRedraw(); 
5918         case SCI_STYLESETSIZE
: 
5919                 if (wParam 
<= STYLE_MAX
) { 
5920                         vs
.styles
[wParam
].size 
= lParam
; 
5921                         InvalidateStyleRedraw(); 
5924         case SCI_STYLESETFONT
: 
5927                 if (wParam 
<= STYLE_MAX
) { 
5928                         vs
.SetStyleFontName(wParam
, CharPtrFromSPtr(lParam
)); 
5929                         InvalidateStyleRedraw(); 
5932         case SCI_STYLESETUNDERLINE
: 
5933                 if (wParam 
<= STYLE_MAX
) { 
5934                         vs
.styles
[wParam
].underline 
= lParam 
!= 0; 
5935                         InvalidateStyleRedraw(); 
5938         case SCI_STYLESETCASE
: 
5939                 if (wParam 
<= STYLE_MAX
) { 
5940                         vs
.styles
[wParam
].caseForce 
= static_cast<Style::ecaseForced
>(lParam
); 
5941                         InvalidateStyleRedraw(); 
5944         case SCI_STYLESETCHARACTERSET
: 
5945                 if (wParam 
<= STYLE_MAX
) { 
5946                         vs
.styles
[wParam
].characterSet 
= lParam
; 
5947                         InvalidateStyleRedraw(); 
5950         case SCI_STYLESETVISIBLE
: 
5951                 if (wParam 
<= STYLE_MAX
) { 
5952                         vs
.styles
[wParam
].visible 
= lParam 
!= 0; 
5953                         InvalidateStyleRedraw(); 
5956         case SCI_STYLESETCHANGEABLE
: 
5957                 if (wParam 
<= STYLE_MAX
) { 
5958                         vs
.styles
[wParam
].changeable 
= lParam 
!= 0; 
5959                         InvalidateStyleRedraw(); 
5962         case SCI_STYLESETHOTSPOT
: 
5963                 if (wParam 
<= STYLE_MAX
) { 
5964                         vs
.styles
[wParam
].hotspot 
= lParam 
!= 0; 
5965                         InvalidateStyleRedraw(); 
5969         case SCI_STYLERESETDEFAULT
: 
5970                 vs
.ResetDefaultStyle(); 
5971                 InvalidateStyleRedraw(); 
5973         case SCI_SETSTYLEBITS
: 
5974                 pdoc
->SetStylingBits(wParam
); 
5977         case SCI_GETSTYLEBITS
: 
5978                 return pdoc
->stylingBits
; 
5980         case SCI_SETLINESTATE
: 
5981                 return pdoc
->SetLineState(wParam
, lParam
); 
5983         case SCI_GETLINESTATE
: 
5984                 return pdoc
->GetLineState(wParam
); 
5986         case SCI_GETMAXLINESTATE
: 
5987                 return pdoc
->GetMaxLineState(); 
5989         case SCI_GETCARETLINEVISIBLE
: 
5990                 return vs
.showCaretLineBackground
; 
5991         case SCI_SETCARETLINEVISIBLE
: 
5992                 vs
.showCaretLineBackground 
= wParam 
!= 0; 
5993                 InvalidateStyleRedraw(); 
5995         case SCI_GETCARETLINEBACK
: 
5996                 return vs
.caretLineBackground
.desired
.AsLong(); 
5997         case SCI_SETCARETLINEBACK
: 
5998                 vs
.caretLineBackground
.desired 
= wParam
; 
5999                 InvalidateStyleRedraw(); 
6004         case SCI_VISIBLEFROMDOCLINE
: 
6005                 return cs
.DisplayFromDoc(wParam
); 
6007         case SCI_DOCLINEFROMVISIBLE
: 
6008                 return cs
.DocFromDisplay(wParam
); 
6010         case SCI_SETFOLDLEVEL
: { 
6011                         int prev 
= pdoc
->SetLevel(wParam
, lParam
); 
6017         case SCI_GETFOLDLEVEL
: 
6018                 return pdoc
->GetLevel(wParam
); 
6020         case SCI_GETLASTCHILD
: 
6021                 return pdoc
->GetLastChild(wParam
, lParam
); 
6023         case SCI_GETFOLDPARENT
: 
6024                 return pdoc
->GetFoldParent(wParam
); 
6027                 cs
.SetVisible(wParam
, lParam
, true); 
6033                 cs
.SetVisible(wParam
, lParam
, false); 
6038         case SCI_GETLINEVISIBLE
: 
6039                 return cs
.GetVisible(wParam
); 
6041         case SCI_SETFOLDEXPANDED
: 
6042                 if (cs
.SetExpanded(wParam
, lParam 
!= 0)) { 
6047         case SCI_GETFOLDEXPANDED
: 
6048                 return cs
.GetExpanded(wParam
); 
6050         case SCI_SETFOLDFLAGS
: 
6055         case SCI_TOGGLEFOLD
: 
6056                 ToggleContraction(wParam
); 
6059         case SCI_ENSUREVISIBLE
: 
6060                 EnsureLineVisible(wParam
, false); 
6063         case SCI_ENSUREVISIBLEENFORCEPOLICY
: 
6064                 EnsureLineVisible(wParam
, true); 
6067         case SCI_SEARCHANCHOR
: 
6071         case SCI_SEARCHNEXT
: 
6072         case SCI_SEARCHPREV
: 
6073                 return SearchText(iMessage
, wParam
, lParam
); 
6075 #ifdef INCLUDE_DEPRECATED_FEATURES 
6076         case SCI_SETCARETPOLICY
:        // Deprecated 
6077                 caretXPolicy 
= caretYPolicy 
= wParam
; 
6078                 caretXSlop 
= caretYSlop 
= lParam
; 
6082         case SCI_SETXCARETPOLICY
: 
6083                 caretXPolicy 
= wParam
; 
6084                 caretXSlop 
= lParam
; 
6087         case SCI_SETYCARETPOLICY
: 
6088                 caretYPolicy 
= wParam
; 
6089                 caretYSlop 
= lParam
; 
6092         case SCI_SETVISIBLEPOLICY
: 
6093                 visiblePolicy 
= wParam
; 
6094                 visibleSlop 
= lParam
; 
6097         case SCI_LINESONSCREEN
: 
6098                 return LinesOnScreen(); 
6100         case SCI_SETSELFORE
: 
6101                 vs
.selforeset 
= wParam 
!= 0; 
6102                 vs
.selforeground
.desired 
= ColourDesired(lParam
); 
6103                 InvalidateStyleRedraw(); 
6106         case SCI_SETSELBACK
: 
6107                 vs
.selbackset 
= wParam 
!= 0; 
6108                 vs
.selbackground
.desired 
= ColourDesired(lParam
); 
6109                 InvalidateStyleRedraw(); 
6112         case SCI_SETWHITESPACEFORE
: 
6113                 vs
.whitespaceForegroundSet 
= wParam 
!= 0; 
6114                 vs
.whitespaceForeground
.desired 
= ColourDesired(lParam
); 
6115                 InvalidateStyleRedraw(); 
6118         case SCI_SETWHITESPACEBACK
: 
6119                 vs
.whitespaceBackgroundSet 
= wParam 
!= 0; 
6120                 vs
.whitespaceBackground
.desired 
= ColourDesired(lParam
); 
6121                 InvalidateStyleRedraw(); 
6124         case SCI_SETCARETFORE
: 
6125                 vs
.caretcolour
.desired 
= ColourDesired(wParam
); 
6126                 InvalidateStyleRedraw(); 
6129         case SCI_GETCARETFORE
: 
6130                 return vs
.caretcolour
.desired
.AsLong(); 
6132         case SCI_SETCARETWIDTH
: 
6135                 else if (wParam 
>= 3) 
6138                         vs
.caretWidth 
= wParam
; 
6139                 InvalidateStyleRedraw(); 
6142         case SCI_GETCARETWIDTH
: 
6143                 return vs
.caretWidth
; 
6145         case SCI_ASSIGNCMDKEY
: 
6146                 kmap
.AssignCmdKey(Platform::LowShortFromLong(wParam
), 
6147                                   Platform::HighShortFromLong(wParam
), lParam
); 
6150         case SCI_CLEARCMDKEY
: 
6151                 kmap
.AssignCmdKey(Platform::LowShortFromLong(wParam
), 
6152                                   Platform::HighShortFromLong(wParam
), SCI_NULL
); 
6155         case SCI_CLEARALLCMDKEYS
: 
6159         case SCI_INDICSETSTYLE
: 
6160                 if (wParam 
<= INDIC_MAX
) { 
6161                         vs
.indicators
[wParam
].style 
= lParam
; 
6162                         InvalidateStyleRedraw(); 
6166         case SCI_INDICGETSTYLE
: 
6167                 return (wParam 
<= INDIC_MAX
) ? vs
.indicators
[wParam
].style 
: 0; 
6169         case SCI_INDICSETFORE
: 
6170                 if (wParam 
<= INDIC_MAX
) { 
6171                         vs
.indicators
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6172                         InvalidateStyleRedraw(); 
6176         case SCI_INDICGETFORE
: 
6177                 return (wParam 
<= INDIC_MAX
) ? vs
.indicators
[wParam
].fore
.desired
.AsLong() : 0; 
6180         case SCI_LINEDOWNEXTEND
: 
6182         case SCI_PARADOWNEXTEND
: 
6184         case SCI_LINEUPEXTEND
: 
6186         case SCI_PARAUPEXTEND
: 
6188         case SCI_CHARLEFTEXTEND
: 
6190         case SCI_CHARRIGHTEXTEND
: 
6192         case SCI_WORDLEFTEXTEND
: 
6194         case SCI_WORDRIGHTEXTEND
: 
6196         case SCI_HOMEEXTEND
: 
6198         case SCI_LINEENDEXTEND
: 
6200         case SCI_HOMEWRAPEXTEND
: 
6201         case SCI_LINEENDWRAP
: 
6202         case SCI_LINEENDWRAPEXTEND
: 
6203         case SCI_DOCUMENTSTART
: 
6204         case SCI_DOCUMENTSTARTEXTEND
: 
6205         case SCI_DOCUMENTEND
: 
6206         case SCI_DOCUMENTENDEXTEND
: 
6208         case SCI_PAGEUPEXTEND
: 
6210         case SCI_PAGEDOWNEXTEND
: 
6211         case SCI_EDITTOGGLEOVERTYPE
: 
6213         case SCI_DELETEBACK
: 
6219         case SCI_VCHOMEEXTEND
: 
6220         case SCI_VCHOMEWRAP
: 
6221         case SCI_VCHOMEWRAPEXTEND
: 
6224         case SCI_DELWORDLEFT
: 
6225         case SCI_DELWORDRIGHT
: 
6226         case SCI_DELLINELEFT
: 
6227         case SCI_DELLINERIGHT
: 
6230         case SCI_LINEDELETE
: 
6231         case SCI_LINETRANSPOSE
: 
6232         case SCI_LINEDUPLICATE
: 
6235         case SCI_LINESCROLLDOWN
: 
6236         case SCI_LINESCROLLUP
: 
6237         case SCI_WORDPARTLEFT
: 
6238         case SCI_WORDPARTLEFTEXTEND
: 
6239         case SCI_WORDPARTRIGHT
: 
6240         case SCI_WORDPARTRIGHTEXTEND
: 
6241         case SCI_DELETEBACKNOTLINE
: 
6242         case SCI_HOMEDISPLAY
: 
6243         case SCI_HOMEDISPLAYEXTEND
: 
6244         case SCI_LINEENDDISPLAY
: 
6245         case SCI_LINEENDDISPLAYEXTEND
: 
6246                 return KeyCommand(iMessage
); 
6248         case SCI_BRACEHIGHLIGHT
: 
6249                 SetBraceHighlight(static_cast<int>(wParam
), lParam
, STYLE_BRACELIGHT
); 
6252         case SCI_BRACEBADLIGHT
: 
6253                 SetBraceHighlight(static_cast<int>(wParam
), -1, STYLE_BRACEBAD
); 
6256         case SCI_BRACEMATCH
: 
6257                 // wParam is position of char to find brace for, 
6258                 // lParam is maximum amount of text to restyle to find it 
6259                 return BraceMatch(wParam
, lParam
); 
6261         case SCI_GETVIEWEOL
: 
6264         case SCI_SETVIEWEOL
: 
6265                 vs
.viewEOL 
= wParam 
!= 0; 
6266                 InvalidateStyleRedraw(); 
6270                 vs
.zoomLevel 
= wParam
; 
6271                 InvalidateStyleRedraw(); 
6276                 return vs
.zoomLevel
; 
6278         case SCI_GETEDGECOLUMN
: 
6281         case SCI_SETEDGECOLUMN
: 
6283                 InvalidateStyleRedraw(); 
6286         case SCI_GETEDGEMODE
: 
6287                 return vs
.edgeState
; 
6289         case SCI_SETEDGEMODE
: 
6290                 vs
.edgeState 
= wParam
; 
6291                 InvalidateStyleRedraw(); 
6294         case SCI_GETEDGECOLOUR
: 
6295                 return vs
.edgecolour
.desired
.AsLong(); 
6297         case SCI_SETEDGECOLOUR
: 
6298                 vs
.edgecolour
.desired 
= ColourDesired(wParam
); 
6299                 InvalidateStyleRedraw(); 
6302         case SCI_GETDOCPOINTER
: 
6303                 return reinterpret_cast<sptr_t
>(pdoc
); 
6305         case SCI_SETDOCPOINTER
: 
6307                 SetDocPointer(reinterpret_cast<Document 
*>(lParam
)); 
6310         case SCI_CREATEDOCUMENT
: { 
6311                         Document 
*doc 
= new Document(); 
6315                         return reinterpret_cast<sptr_t
>(doc
); 
6318         case SCI_ADDREFDOCUMENT
: 
6319                 (reinterpret_cast<Document 
*>(lParam
))->AddRef(); 
6322         case SCI_RELEASEDOCUMENT
: 
6323                 (reinterpret_cast<Document 
*>(lParam
))->Release(); 
6326         case SCI_SETMODEVENTMASK
: 
6327                 modEventMask 
= wParam
; 
6330         case SCI_GETMODEVENTMASK
: 
6331                 return modEventMask
; 
6333         case SCI_CONVERTEOLS
: 
6334                 pdoc
->ConvertLineEnds(wParam
); 
6335                 SetSelection(currentPos
, anchor
);       // Ensure selection inside document 
6338         case SCI_SELECTIONISRECTANGLE
: 
6339                 return (selType 
== selRectangle
) ? 1 : 0; 
6341         case SCI_SETOVERTYPE
: 
6342                 inOverstrike 
= wParam 
!= 0; 
6345         case SCI_GETOVERTYPE
: 
6346                 return inOverstrike 
? 1 : 0; 
6349                 SetFocusState(wParam 
!= 0); 
6356                 errorStatus 
= wParam
; 
6362         case SCI_SETMOUSEDOWNCAPTURES
: 
6363                 mouseDownCaptures 
= wParam 
!= 0; 
6366         case SCI_GETMOUSEDOWNCAPTURES
: 
6367                 return mouseDownCaptures
; 
6370                 cursorMode 
= wParam
; 
6371                 DisplayCursor(Window::cursorText
); 
6377         case SCI_SETCONTROLCHARSYMBOL
: 
6378                 controlCharSymbol 
= wParam
; 
6381         case SCI_GETCONTROLCHARSYMBOL
: 
6382                 return controlCharSymbol
; 
6384         case SCI_STARTRECORD
: 
6385                 recordingMacro 
= true; 
6388         case SCI_STOPRECORD
: 
6389                 recordingMacro 
= false; 
6392         case SCI_MOVECARETINSIDEVIEW
: 
6393                 MoveCaretInsideView(); 
6396         case SCI_SETFOLDMARGINCOLOUR
: 
6397                 vs
.foldmarginColourSet 
= wParam 
!= 0; 
6398                 vs
.foldmarginColour
.desired 
= ColourDesired(lParam
); 
6399                 InvalidateStyleRedraw(); 
6402         case SCI_SETFOLDMARGINHICOLOUR
: 
6403                 vs
.foldmarginHighlightColourSet 
= wParam 
!= 0; 
6404                 vs
.foldmarginHighlightColour
.desired 
= ColourDesired(lParam
); 
6405                 InvalidateStyleRedraw(); 
6408         case SCI_SETHOTSPOTACTIVEFORE
: 
6409                 vs
.hotspotForegroundSet 
= wParam 
!= 0; 
6410                 vs
.hotspotForeground
.desired 
= ColourDesired(lParam
); 
6411                 InvalidateStyleRedraw(); 
6414         case SCI_SETHOTSPOTACTIVEBACK
: 
6415                 vs
.hotspotBackgroundSet 
= wParam 
!= 0; 
6416                 vs
.hotspotBackground
.desired 
= ColourDesired(lParam
); 
6417                 InvalidateStyleRedraw(); 
6420         case SCI_SETHOTSPOTACTIVEUNDERLINE
: 
6421                 vs
.hotspotUnderline 
= wParam 
!= 0; 
6422                 InvalidateStyleRedraw(); 
6426                 return DefWndProc(iMessage
, wParam
, lParam
); 
6428         //Platform::DebugPrintf("end wnd proc\n");