1 // Scintilla source code edit control 
   3  ** Main code for the edit control. 
   5 // Copyright 1998-2004 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) {} 
  39 state(false), idlerID(0) {} 
  41 LineLayout::LineLayout(int maxLineLength_
) : 
  61         widthLine(wrapWidthInfinite
), 
  63         Resize(maxLineLength_
); 
  66 LineLayout::~LineLayout() { 
  70 void LineLayout::Resize(int maxLineLength_
) { 
  71         if (maxLineLength_ 
> maxLineLength
) { 
  73                 chars 
= new char[maxLineLength_ 
+ 1]; 
  74                 styles 
= new unsigned char[maxLineLength_ 
+ 1]; 
  75                 indicators 
= new char[maxLineLength_ 
+ 1]; 
  76                 // Extra position allocated as sometimes the Windows 
  77                 // GetTextExtentExPoint API writes an extra element. 
  78                 positions 
= new int[maxLineLength_ 
+ 1 + 1]; 
  79                 maxLineLength 
= maxLineLength_
; 
  83 void LineLayout::Free() { 
  96 void LineLayout::Invalidate(validLevel validity_
) { 
  97         if (validity 
> validity_
) 
 101 void LineLayout::SetLineStart(int line
, int start
) { 
 102         if ((line 
>= lenLineStarts
) && (line 
!= 0)) { 
 103                 int newMaxLines 
= line 
+ 20; 
 104                 int *newLineStarts 
= new int[newMaxLines
]; 
 107                 for (int i 
= 0; i 
< newMaxLines
; i
++) { 
 108                         if (i 
< lenLineStarts
) 
 109                                 newLineStarts
[i
] = lineStarts
[i
]; 
 111                                 newLineStarts
[i
] = 0; 
 114                 lineStarts 
= newLineStarts
; 
 115                 lenLineStarts 
= newMaxLines
; 
 117         lineStarts
[line
] = start
; 
 120 void LineLayout::SetBracesHighlight(Range rangeLine
, Position braces
[], 
 121                                     char bracesMatchStyle
, int xHighlight
) { 
 122         if (rangeLine
.ContainsCharacter(braces
[0])) { 
 123                 int braceOffset 
= braces
[0] - rangeLine
.start
; 
 124                 if (braceOffset 
< numCharsInLine
) { 
 125                         bracePreviousStyles
[0] = styles
[braceOffset
]; 
 126                         styles
[braceOffset
] = bracesMatchStyle
; 
 129         if (rangeLine
.ContainsCharacter(braces
[1])) { 
 130                 int braceOffset 
= braces
[1] - rangeLine
.start
; 
 131                 if (braceOffset 
< numCharsInLine
) { 
 132                         bracePreviousStyles
[1] = styles
[braceOffset
]; 
 133                         styles
[braceOffset
] = bracesMatchStyle
; 
 136         if ((braces
[0] >= rangeLine
.start 
&& braces
[1] <= rangeLine
.end
) || 
 137                 (braces
[1] >= rangeLine
.start 
&& braces
[0] <= rangeLine
.end
)) { 
 138                 xHighlightGuide 
= xHighlight
; 
 142 void LineLayout::RestoreBracesHighlight(Range rangeLine
, Position braces
[]) { 
 143         if (rangeLine
.ContainsCharacter(braces
[0])) { 
 144                 int braceOffset 
= braces
[0] - rangeLine
.start
; 
 145                 if (braceOffset 
< numCharsInLine
) { 
 146                         styles
[braceOffset
] = bracePreviousStyles
[0]; 
 149         if (rangeLine
.ContainsCharacter(braces
[1])) { 
 150                 int braceOffset 
= braces
[1] - rangeLine
.start
; 
 151                 if (braceOffset 
< numCharsInLine
) { 
 152                         styles
[braceOffset
] = bracePreviousStyles
[1]; 
 158 LineLayoutCache::LineLayoutCache() : 
 159         level(0), length(0), size(0), cache(0), 
 160         allInvalidated(false), styleClock(-1) { 
 164 LineLayoutCache::~LineLayoutCache() { 
 168 void LineLayoutCache::Allocate(int length_
) { 
 169         allInvalidated 
= false; 
 173                 size 
= (size 
/ 16 + 1) * 16; 
 176                 cache 
= new LineLayout 
* [size
]; 
 178         for (int i 
= 0; i 
< size
; i
++) 
 182 void LineLayoutCache::AllocateForLevel(int linesOnScreen
, int linesInDoc
) { 
 183         int lengthForLevel 
= 0; 
 184         if (level 
== llcCaret
) { 
 186         } else if (level 
== llcPage
) { 
 187                 lengthForLevel 
= linesOnScreen 
+ 1; 
 188         } else if (level 
== llcDocument
) { 
 189                 lengthForLevel 
= linesInDoc
; 
 191         if (lengthForLevel 
> size
) { 
 193         } else if (lengthForLevel 
< length
) { 
 194                 for (int i 
= lengthForLevel
; i 
< length
; i
++) { 
 200                 Allocate(lengthForLevel
); 
 204 void LineLayoutCache::Deallocate() { 
 205         for (int i 
= 0; i 
< length
; i
++) 
 212 void LineLayoutCache::Invalidate(LineLayout::validLevel validity_
) { 
 213         if (cache 
&& !allInvalidated
) { 
 214                 for (int i 
= 0; i 
< length
; i
++) { 
 216                                 cache
[i
]->Invalidate(validity_
); 
 219                 if (validity_ 
== LineLayout::llInvalid
) { 
 220                         allInvalidated 
= true; 
 225 void LineLayoutCache::SetLevel(int level_
) { 
 226         allInvalidated 
= false; 
 227         if ((level_ 
!= -1) && (level 
!= level_
)) { 
 233 LineLayout 
*LineLayoutCache::Retrieve(int lineNumber
, int lineCaret
, int maxChars
, int styleClock_
, 
 234                                       int linesOnScreen
, int linesInDoc
) { 
 235         AllocateForLevel(linesOnScreen
, linesInDoc
); 
 236         if (styleClock 
!= styleClock_
) { 
 237                 Invalidate(LineLayout::llCheckTextAndStyle
); 
 238                 styleClock 
= styleClock_
; 
 240         allInvalidated 
= false; 
 243         if (level 
== llcCaret
) { 
 245         } else if (level 
== llcPage
) { 
 246                 if (lineNumber 
== lineCaret
) { 
 249                         pos 
= lineNumber 
% length
; 
 251         } else if (level 
== llcDocument
) { 
 255                 if (cache 
&& (pos 
< length
)) { 
 257                                 if ((cache
[pos
]->lineNumber 
!= lineNumber
) || 
 258                                         (cache
[pos
]->maxLineLength 
< maxChars
)) { 
 264                                 cache
[pos
] = new LineLayout(maxChars
); 
 267                                 cache
[pos
]->lineNumber 
= lineNumber
; 
 268                                 cache
[pos
]->inCache 
= true; 
 275                 ret 
= new LineLayout(maxChars
); 
 276                 ret
->lineNumber 
= lineNumber
; 
 282 void LineLayoutCache::Dispose(LineLayout 
*ll
) { 
 283         allInvalidated 
= false; 
 296         printMagnification 
= 0; 
 297         printColourMode 
= SC_PRINT_NORMAL
; 
 298         printWrapState 
= eWrapWord
; 
 299         cursorMode 
= SC_CURSORNORMAL
; 
 300         controlCharSymbol 
= 0;  /* Draw the control characters */ 
 303         hideSelection 
= false; 
 304         inOverstrike 
= false; 
 306         mouseDownCaptures 
= true; 
 312         dwellDelay 
= SC_TIME_FOREVER
; 
 313         ticksToDwell 
= SC_TIME_FOREVER
; 
 318         dropWentOutside 
= false; 
 319         posDrag 
= invalidPosition
; 
 320         posDrop 
= invalidPosition
; 
 321         selectionType 
= selChar
; 
 325         originalAnchorPos 
= 0; 
 328         moveExtendsSelection 
= false; 
 331         primarySelection 
= true; 
 333         caretXPolicy 
= CARET_SLOP 
| CARET_EVEN
; 
 336         caretYPolicy 
= CARET_EVEN
; 
 343         horizontalScrollBarVisible 
= true; 
 345         verticalScrollBarVisible 
= true; 
 346         endAtLastLine 
= true; 
 348         pixmapLine 
= Surface::Allocate(); 
 349         pixmapSelMargin 
= Surface::Allocate(); 
 350         pixmapSelPattern 
= Surface::Allocate(); 
 351         pixmapIndentGuide 
= Surface::Allocate(); 
 352         pixmapIndentGuideHighlight 
= Surface::Allocate(); 
 367         braces
[0] = invalidPosition
; 
 368         braces
[1] = invalidPosition
; 
 369         bracesMatchStyle 
= STYLE_BRACEBAD
; 
 370         highlightGuideColumn 
= 0; 
 374         paintState 
= notPainting
; 
 376         modEventMask 
= SC_MODEVENTMASKALL
; 
 378         pdoc 
= new Document(); 
 380         pdoc
->AddWatcher(this, 0); 
 382         recordingMacro 
= false; 
 385         wrapState 
= eWrapNone
; 
 386         wrapWidth 
= LineLayout::wrapWidthInfinite
; 
 387         docLineLastWrapped 
= -1; 
 388         docLastLineToWrap 
= -1; 
 389         backgroundWrapEnabled 
= true; 
 391         wrapVisualFlagsLocation 
= 0; 
 392         wrapVisualStartIndent 
= 0; 
 393         actualWrapVisualStartIndent 
= 0; 
 398         llc
.SetLevel(LineLayoutCache::llcCaret
); 
 402         pdoc
->RemoveWatcher(this, 0); 
 407         delete pixmapSelMargin
; 
 408         delete pixmapSelPattern
; 
 409         delete pixmapIndentGuide
; 
 410         delete pixmapIndentGuideHighlight
; 
 413 void Editor::Finalise() { 
 418 void Editor::DropGraphics() { 
 419         pixmapLine
->Release(); 
 420         pixmapSelMargin
->Release(); 
 421         pixmapSelPattern
->Release(); 
 422         pixmapIndentGuide
->Release(); 
 425 void Editor::InvalidateStyleData() { 
 429         llc
.Invalidate(LineLayout::llInvalid
); 
 430         if (selType 
== selRectangle
) { 
 431                 xStartSelect 
= XFromPosition(anchor
); 
 432                 xEndSelect 
= XFromPosition(currentPos
); 
 436 void Editor::InvalidateStyleRedraw() { 
 438         InvalidateStyleData(); 
 442 void Editor::RefreshColourPalette(Palette 
&pal
, bool want
) { 
 443         vs
.RefreshColourPalette(pal
, want
); 
 446 void Editor::RefreshStyleData() { 
 449                 AutoSurface 
surface(this); 
 451                         vs
.Refresh(*surface
); 
 452                         RefreshColourPalette(palette
, true); 
 453                         palette
.Allocate(wMain
); 
 454                         RefreshColourPalette(palette
, false); 
 460 PRectangle 
Editor::GetClientRectangle() { 
 461         return wMain
.GetClientPosition(); 
 464 PRectangle 
Editor::GetTextRectangle() { 
 465         PRectangle rc 
= GetClientRectangle(); 
 466         rc
.left 
+= vs
.fixedColumnWidth
; 
 467         rc
.right 
-= vs
.rightMarginWidth
; 
 471 int Editor::LinesOnScreen() { 
 472         PRectangle rcClient 
= GetClientRectangle(); 
 473         int htClient 
= rcClient
.bottom 
- rcClient
.top
; 
 474         //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1); 
 475         return htClient 
/ vs
.lineHeight
; 
 478 int Editor::LinesToScroll() { 
 479         int retVal 
= LinesOnScreen() - 1; 
 486 int Editor::MaxScrollPos() { 
 487         //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n", 
 488         //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1); 
 489         int retVal 
= cs
.LinesDisplayed(); 
 491                 retVal 
-= LinesOnScreen(); 
 502 static inline bool IsControlCharacter(int ch
) { 
 503         // iscntrl returns true for lots of chars > 127 which are displayable 
 504         return ch 
>= 0 && ch 
< ' '; 
 507 const char *ControlCharacterString(unsigned char ch
) { 
 508         const char *reps
[] = { 
 509                 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", 
 510                 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", 
 511                 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", 
 512                 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" 
 514         if (ch 
< (sizeof(reps
) / sizeof(reps
[0]))) { 
 522  * Convenience class to ensure LineLayout objects are always disposed. 
 524 class AutoLineLayout 
{ 
 525         LineLayoutCache 
&llc
; 
 527         AutoLineLayout 
&operator=(const AutoLineLayout 
&) { return * this; } 
 529         AutoLineLayout(LineLayoutCache 
&llc_
, LineLayout 
*ll_
) : llc(llc_
), ll(ll_
) {} 
 534         LineLayout 
*operator->() const { 
 537         operator LineLayout 
*() const { 
 540         void Set(LineLayout 
*ll_
) { 
 547  * Allows to iterate through the lines of a selection. 
 548  * Althought it can be called for a stream selection, in most cases 
 549  * it is inefficient and it should be used only for 
 550  * a rectangular or a line selection. 
 552 class SelectionLineIterator 
{ 
 555         int line
;       ///< Current line within the iteration. 
 556         bool forward
;   ///< True if iterating by increasing line number, false otherwise. 
 557         int selStart
, selEnd
;   ///< Positions of the start and end of the selection relative to the start of the document. 
 558         int minX
, maxX
; ///< Left and right of selection rectangle. 
 561         int lineStart
, lineEnd
; ///< Line numbers, first and last lines of the selection. 
 562         int startPos
, endPos
;   ///< Positions of the beginning and end of the selection on the current line. 
 572         SelectionLineIterator(Editor 
*ed_
, bool forward_ 
= true) : line(0), startPos(0), endPos(0) { 
 575                 selStart 
= ed
->SelectionStart(); 
 576                 selEnd 
= ed
->SelectionEnd(); 
 577                 lineStart 
= ed
->pdoc
->LineFromPosition(selStart
); 
 578                 lineEnd 
= ed
->pdoc
->LineFromPosition(selEnd
); 
 580                 minX 
= Platform::Minimum(ed
->xStartSelect
, ed
->xEndSelect
); 
 581                 // Right of rectangle 
 582                 maxX 
= Platform::Maximum(ed
->xStartSelect
, ed
->xEndSelect
); 
 585         ~SelectionLineIterator() {} 
 587         void SetAt(int line
) { 
 588                 if (line 
< lineStart 
|| line 
> lineEnd
) { 
 589                         startPos 
= endPos 
= INVALID_POSITION
; 
 591                         if (ed
->selType 
== ed
->selRectangle
) { 
 592                                 // Measure line and return character closest to minX 
 593                                 startPos 
= ed
->PositionFromLineX(line
, minX
); 
 594                                 // Measure line and return character closest to maxX 
 595                                 endPos 
= ed
->PositionFromLineX(line
, maxX
); 
 596                         } else if (ed
->selType 
== ed
->selLines
) { 
 597                                 startPos 
= ed
->pdoc
->LineStart(line
); 
 598                                 endPos 
= ed
->pdoc
->LineStart(line 
+ 1); 
 599                         } else {        // Stream selection, here only for completion 
 600                                 if (line 
== lineStart
) { 
 603                                         startPos 
= ed
->pdoc
->LineStart(line
); 
 605                                 if (line 
== lineEnd
) { 
 608                                         endPos 
= ed
->pdoc
->LineStart(line 
+ 1); 
 620                 return startPos 
!= INVALID_POSITION
; 
 624 Point 
Editor::LocationFromPosition(int pos
) { 
 627         if (pos 
== INVALID_POSITION
) 
 629         int line 
= pdoc
->LineFromPosition(pos
); 
 630         int lineVisible 
= cs
.DisplayFromDoc(line
); 
 631         //Platform::DebugPrintf("line=%d\n", line); 
 632         AutoSurface 
surface(this); 
 633         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
 635                 // -1 because of adding in for visible lines in following loop. 
 636                 pt
.y 
= (lineVisible 
- topLine 
- 1) * vs
.lineHeight
; 
 638                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
 639                 LayoutLine(line
, surface
, vs
, ll
, wrapWidth
); 
 640                 int posInLine 
= pos 
- posLineStart
; 
 641                 // In case of very long line put x at arbitrary large position 
 642                 if (posInLine 
> ll
->maxLineLength
) { 
 643                         pt
.x 
= ll
->positions
[ll
->maxLineLength
] - ll
->positions
[ll
->LineStart(ll
->lines
)]; 
 646                 for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
 647                         if ((posInLine 
>= ll
->LineStart(subLine
)) && (posInLine 
<= ll
->LineStart(subLine 
+ 1))) { 
 648                                 pt
.x 
= ll
->positions
[posInLine
] - ll
->positions
[ll
->LineStart(subLine
)]; 
 649                                 if (actualWrapVisualStartIndent 
!= 0) { 
 650                                         int lineStart 
= ll
->LineStart(subLine
); 
 651                                         if (lineStart 
!= 0)     // Wrapped 
 652                                                 pt
.x 
+= actualWrapVisualStartIndent 
* vs
.aveCharWidth
; 
 655                         if (posInLine 
>= ll
->LineStart(subLine
)) { 
 656                                 pt
.y 
+= vs
.lineHeight
; 
 659                 pt
.x 
+= vs
.fixedColumnWidth 
- xOffset
; 
 664 int Editor::XFromPosition(int pos
) { 
 665         Point pt 
= LocationFromPosition(pos
); 
 666         return pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 669 int Editor::LineFromLocation(Point pt
) { 
 670         return cs
.DocFromDisplay(pt
.y 
/ vs
.lineHeight 
+ topLine
); 
 673 void Editor::SetTopLine(int topLineNew
) { 
 674         topLine 
= topLineNew
; 
 675         posTopLine 
= pdoc
->LineStart(cs
.DocFromDisplay(topLine
)); 
 678 static inline bool IsEOLChar(char ch
) { 
 679         return (ch 
== '\r') || (ch 
== '\n'); 
 682 int Editor::PositionFromLocation(Point pt
) { 
 684         pt
.x 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 685         int visibleLine 
= pt
.y 
/ vs
.lineHeight 
+ topLine
; 
 686         if (pt
.y 
< 0) { // Division rounds towards 0 
 687                 visibleLine 
= (pt
.y 
- (vs
.lineHeight 
- 1)) / vs
.lineHeight 
+ topLine
; 
 691         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
 692         if (lineDoc 
>= pdoc
->LinesTotal()) 
 693                 return pdoc
->Length(); 
 694         unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 695         int retVal 
= posLineStart
; 
 696         AutoSurface 
surface(this); 
 697         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 699                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 700                 int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
 701                 int subLine 
= visibleLine 
- lineStartSet
; 
 702                 if (subLine 
< ll
->lines
) { 
 703                         int lineStart 
= ll
->LineStart(subLine
); 
 704                         int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 705                         int subLineStart 
= ll
->positions
[lineStart
]; 
 707                         if (actualWrapVisualStartIndent 
!= 0) { 
 708                                 if (lineStart 
!= 0)     // Wrapped 
 709                                         pt
.x 
-= actualWrapVisualStartIndent 
* vs
.aveCharWidth
; 
 711                         for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 712                                 if (pt
.x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 713                                         IsEOLChar(ll
->chars
[i
])) { 
 714                                         return pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 717                         return lineEnd 
+ posLineStart
; 
 719                 retVal 
= ll
->numCharsInLine 
+ posLineStart
; 
 724 // Like PositionFromLocation but INVALID_POSITION returned when not near any text. 
 725 int Editor::PositionFromLocationClose(Point pt
) { 
 727         PRectangle rcClient 
= GetTextRectangle(); 
 728         if (!rcClient
.Contains(pt
)) 
 729                 return INVALID_POSITION
; 
 730         if (pt
.x 
< vs
.fixedColumnWidth
) 
 731                 return INVALID_POSITION
; 
 733                 return INVALID_POSITION
; 
 734         pt
.x 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 735         int visibleLine 
= pt
.y 
/ vs
.lineHeight 
+ topLine
; 
 736         if (pt
.y 
< 0) { // Division rounds towards 0 
 737                 visibleLine 
= (pt
.y 
- (vs
.lineHeight 
- 1)) / vs
.lineHeight 
+ topLine
; 
 739         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
 741                 return INVALID_POSITION
; 
 742         if (lineDoc 
>= pdoc
->LinesTotal()) 
 743                 return INVALID_POSITION
; 
 744         AutoSurface 
surface(this); 
 745         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 747                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 748                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 749                 int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
 750                 int subLine 
= visibleLine 
- lineStartSet
; 
 751                 if (subLine 
< ll
->lines
) { 
 752                         int lineStart 
= ll
->LineStart(subLine
); 
 753                         int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 754                         int subLineStart 
= ll
->positions
[lineStart
]; 
 756                         if (actualWrapVisualStartIndent 
!= 0) { 
 757                                 if (lineStart 
!= 0)     // Wrapped 
 758                                         pt
.x 
-= actualWrapVisualStartIndent 
* vs
.aveCharWidth
; 
 760                         for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 761                                 if (pt
.x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 762                                         IsEOLChar(ll
->chars
[i
])) { 
 763                                         return pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 769         return INVALID_POSITION
; 
 773  * Find the document position corresponding to an x coordinate on a particular document line. 
 774  * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. 
 776 int Editor::PositionFromLineX(int lineDoc
, int x
) { 
 778         if (lineDoc 
>= pdoc
->LinesTotal()) 
 779                 return pdoc
->Length(); 
 780         //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); 
 781         AutoSurface 
surface(this); 
 782         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 785                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 786                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 787                 retVal 
= ll
->numCharsInLine 
+ posLineStart
; 
 789                 int lineStart 
= ll
->LineStart(subLine
); 
 790                 int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 791                 int subLineStart 
= ll
->positions
[lineStart
]; 
 793                 if (actualWrapVisualStartIndent 
!= 0) { 
 794                         if (lineStart 
!= 0)     // Wrapped 
 795                                 x 
-= actualWrapVisualStartIndent 
* vs
.aveCharWidth
; 
 797                 for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 798                         if (x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 799                                 IsEOLChar(ll
->chars
[i
])) { 
 800                                 retVal 
= pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 809  * If painting then abandon the painting because a wider redraw is needed. 
 810  * @return true if calling code should stop drawing. 
 812 bool Editor::AbandonPaint() { 
 813         if ((paintState 
== painting
) && !paintingAllText
) { 
 814                 paintState 
= paintAbandoned
; 
 816         return paintState 
== paintAbandoned
; 
 819 void Editor::RedrawRect(PRectangle rc
) { 
 820         //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); 
 822         // Clip the redraw rectangle into the client area 
 823         PRectangle rcClient 
= GetClientRectangle(); 
 824         if (rc
.top 
< rcClient
.top
) 
 825                 rc
.top 
= rcClient
.top
; 
 826         if (rc
.bottom 
> rcClient
.bottom
) 
 827                 rc
.bottom 
= rcClient
.bottom
; 
 828         if (rc
.left 
< rcClient
.left
) 
 829                 rc
.left 
= rcClient
.left
; 
 830         if (rc
.right 
> rcClient
.right
) 
 831                 rc
.right 
= rcClient
.right
; 
 833         if ((rc
.bottom 
> rc
.top
) && (rc
.right 
> rc
.left
)) { 
 834                 wMain
.InvalidateRectangle(rc
); 
 838 void Editor::Redraw() { 
 839         //Platform::DebugPrintf("Redraw all\n"); 
 840         PRectangle rcClient 
= GetClientRectangle(); 
 841         wMain
.InvalidateRectangle(rcClient
); 
 842         //wMain.InvalidateAll(); 
 845 void Editor::RedrawSelMargin() { 
 846         if (!AbandonPaint()) { 
 850                         PRectangle rcSelMargin 
= GetClientRectangle(); 
 851                         rcSelMargin
.right 
= vs
.fixedColumnWidth
; 
 852                         wMain
.InvalidateRectangle(rcSelMargin
); 
 857 PRectangle 
Editor::RectangleFromRange(int start
, int end
) { 
 864         int minLine 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(minPos
)); 
 865         int lineDocMax 
= pdoc
->LineFromPosition(maxPos
); 
 866         int maxLine 
= cs
.DisplayFromDoc(lineDocMax
) + cs
.GetHeight(lineDocMax
) - 1; 
 867         PRectangle rcClient 
= GetTextRectangle(); 
 869         rc
.left 
= vs
.fixedColumnWidth
; 
 870         rc
.top 
= (minLine 
- topLine
) * vs
.lineHeight
; 
 873         rc
.right 
= rcClient
.right
; 
 874         rc
.bottom 
= (maxLine 
- topLine 
+ 1) * vs
.lineHeight
; 
 875         // Ensure PRectangle is within 16 bit space 
 876         rc
.top 
= Platform::Clamp(rc
.top
, -32000, 32000); 
 877         rc
.bottom 
= Platform::Clamp(rc
.bottom
, -32000, 32000); 
 882 void Editor::InvalidateRange(int start
, int end
) { 
 883         RedrawRect(RectangleFromRange(start
, end
)); 
 886 int Editor::CurrentPosition() { 
 890 bool Editor::SelectionEmpty() { 
 891         return anchor 
== currentPos
; 
 894 int Editor::SelectionStart() { 
 895         return Platform::Minimum(currentPos
, anchor
); 
 898 int Editor::SelectionEnd() { 
 899         return Platform::Maximum(currentPos
, anchor
); 
 902 void Editor::InvalidateSelection(int currentPos_
, int anchor_
) { 
 903         int firstAffected 
= anchor
; 
 904         if (firstAffected 
> currentPos
) 
 905                 firstAffected 
= currentPos
; 
 906         if (firstAffected 
> anchor_
) 
 907                 firstAffected 
= anchor_
; 
 908         if (firstAffected 
> currentPos_
) 
 909                 firstAffected 
= currentPos_
; 
 910         int lastAffected 
= anchor
; 
 911         if (lastAffected 
< currentPos
) 
 912                 lastAffected 
= currentPos
; 
 913         if (lastAffected 
< anchor_
) 
 914                 lastAffected 
= anchor_
; 
 915         if (lastAffected 
< (currentPos_ 
+ 1))   // +1 ensures caret repainted 
 916                 lastAffected 
= (currentPos_ 
+ 1); 
 918         InvalidateRange(firstAffected
, lastAffected
); 
 921 void Editor::SetSelection(int currentPos_
, int anchor_
) { 
 922         currentPos_ 
= pdoc
->ClampPositionIntoDocument(currentPos_
); 
 923         anchor_ 
= pdoc
->ClampPositionIntoDocument(anchor_
); 
 924         if ((currentPos 
!= currentPos_
) || (anchor 
!= anchor_
)) { 
 925                 InvalidateSelection(currentPos_
, anchor_
); 
 926                 currentPos 
= currentPos_
; 
 929         if (selType 
== selRectangle
) { 
 930                 xStartSelect 
= XFromPosition(anchor
); 
 931                 xEndSelect 
= XFromPosition(currentPos
); 
 936 void Editor::SetSelection(int currentPos_
) { 
 937         currentPos_ 
= pdoc
->ClampPositionIntoDocument(currentPos_
); 
 938         if (currentPos 
!= currentPos_
) { 
 939                 InvalidateSelection(currentPos_
, currentPos_
); 
 940                 currentPos 
= currentPos_
; 
 942         if (selType 
== selRectangle
) { 
 943                 xStartSelect 
= XFromPosition(anchor
); 
 944                 xEndSelect 
= XFromPosition(currentPos
); 
 949 void Editor::SetEmptySelection(int currentPos_
) { 
 951         moveExtendsSelection 
= false; 
 952         SetSelection(currentPos_
, currentPos_
); 
 955 bool Editor::RangeContainsProtected(int start
, int end
) const { 
 956         if (vs
.ProtectionActive()) { 
 962                 int mask 
= pdoc
->stylingBitsMask
; 
 963                 for (int pos 
= start
; pos 
< end
; pos
++) { 
 964                         if (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected()) 
 971 bool Editor::SelectionContainsProtected() { 
 972         // DONE, but untested...: make support rectangular selection 
 974         if (selType 
== selStream
) { 
 975                 scp 
= RangeContainsProtected(anchor
, currentPos
); 
 977                 SelectionLineIterator 
lineIterator(this); 
 978                 while (lineIterator
.Iterate()) { 
 979                         if (RangeContainsProtected(lineIterator
.startPos
, lineIterator
.endPos
)) { 
 989  * Asks document to find a good position and then moves out of any invisible positions. 
 991 int Editor::MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
) { 
 992         pos 
= pdoc
->MovePositionOutsideChar(pos
, moveDir
, checkLineEnd
); 
 993         if (vs
.ProtectionActive()) { 
 994                 int mask 
= pdoc
->stylingBitsMask
; 
 996                         if ((pos 
> 0) && vs
.styles
[pdoc
->StyleAt(pos 
- 1) & mask
].IsProtected()) { 
 997                                 while ((pos 
< pdoc
->Length()) && 
 998                                         (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected())) 
1001                 } else if (moveDir 
< 0) { 
1002                         if (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected()) { 
1004                                         (vs
.styles
[pdoc
->StyleAt(pos 
- 1) & mask
].IsProtected())) 
1012 int Editor::MovePositionTo(int newPos
, selTypes sel
, bool ensureVisible
) { 
1013         int delta 
= newPos 
- currentPos
; 
1014         newPos 
= pdoc
->ClampPositionIntoDocument(newPos
); 
1015         newPos 
= MovePositionOutsideChar(newPos
, delta
); 
1019         if (sel 
!= noSel 
|| moveExtendsSelection
) { 
1020                 SetSelection(newPos
); 
1022                 SetEmptySelection(newPos
); 
1024         ShowCaretAtCurrentPosition(); 
1025         if (ensureVisible
) { 
1026                 EnsureCaretVisible(); 
1032 int Editor::MovePositionSoVisible(int pos
, int moveDir
) { 
1033         pos 
= pdoc
->ClampPositionIntoDocument(pos
); 
1034         pos 
= MovePositionOutsideChar(pos
, moveDir
); 
1035         int lineDoc 
= pdoc
->LineFromPosition(pos
); 
1036         if (cs
.GetVisible(lineDoc
)) { 
1039                 int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
1041                         // lineDisplay is already line before fold as lines in fold use display line of line after fold 
1042                         lineDisplay 
= Platform::Clamp(lineDisplay
, 0, cs
.LinesDisplayed()); 
1043                         return pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
)); 
1045                         lineDisplay 
= Platform::Clamp(lineDisplay 
- 1, 0, cs
.LinesDisplayed()); 
1046                         return pdoc
->LineEnd(cs
.DocFromDisplay(lineDisplay
)); 
1052  * Choose the x position that the caret will try to stick to 
1053  * as it moves up and down. 
1055 void Editor::SetLastXChosen() { 
1056         Point pt 
= LocationFromPosition(currentPos
); 
1060 void Editor::ScrollTo(int line
, bool moveThumb
) { 
1061         int topLineNew 
= Platform::Clamp(line
, 0, MaxScrollPos()); 
1062         if (topLineNew 
!= topLine
) { 
1063                 // Try to optimise small scrolls 
1064                 int linesToMove 
= topLine 
- topLineNew
; 
1065                 SetTopLine(topLineNew
); 
1066                 ShowCaretAtCurrentPosition(); 
1067                 // Perform redraw rather than scroll if many lines would be redrawn anyway. 
1068                 if (abs(linesToMove
) <= 10) { 
1069                         ScrollText(linesToMove
); 
1074                         SetVerticalScrollPos(); 
1079 void Editor::ScrollText(int /* linesToMove */) { 
1080         //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove); 
1084 void Editor::HorizontalScrollTo(int xPos
) { 
1085         //Platform::DebugPrintf("HorizontalScroll %d\n", xPos); 
1088         if ((wrapState 
== eWrapNone
) && (xOffset 
!= xPos
)) { 
1090                 SetHorizontalScrollPos(); 
1091                 RedrawRect(GetClientRectangle()); 
1095 void Editor::MoveCaretInsideView(bool ensureVisible
) { 
1096         PRectangle rcClient 
= GetTextRectangle(); 
1097         Point pt 
= LocationFromPosition(currentPos
); 
1098         if (pt
.y 
< rcClient
.top
) { 
1099                 MovePositionTo(PositionFromLocation( 
1100                                    Point(lastXChosen
, rcClient
.top
)), 
1101                                noSel
, ensureVisible
); 
1102         } else if ((pt
.y 
+ vs
.lineHeight 
- 1) > rcClient
.bottom
) { 
1103                 int yOfLastLineFullyDisplayed 
= rcClient
.top 
+ (LinesOnScreen() - 1) * vs
.lineHeight
; 
1104                 MovePositionTo(PositionFromLocation( 
1105                                    Point(lastXChosen
, rcClient
.top 
+ yOfLastLineFullyDisplayed
)), 
1106                                noSel
, ensureVisible
); 
1110 int Editor::DisplayFromPosition(int pos
) { 
1111         int lineDoc 
= pdoc
->LineFromPosition(pos
); 
1112         int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
1113         AutoSurface 
surface(this); 
1114         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
1115         if (surface 
&& ll
) { 
1116                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
1117                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
1118                 int posInLine 
= pos 
- posLineStart
; 
1119                 lineDisplay
--; // To make up for first increment ahead. 
1120                 for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
1121                         if (posInLine 
>= ll
->LineStart(subLine
)) { 
1130  * Ensure the caret is reasonably visible in context. 
1132 Caret policy in SciTE 
1134 If slop is set, we can define a slop value. 
1135 This value defines an unwanted zone (UZ) where the caret is... unwanted. 
1136 This zone is defined as a number of pixels near the vertical margins, 
1137 and as a number of lines near the horizontal margins. 
1138 By keeping the caret away from the edges, it is seen within its context, 
1139 so it is likely that the identifier that the caret is on can be completely seen, 
1140 and that the current line is seen with some of the lines following it which are 
1141 often dependent on that line. 
1143 If strict is set, the policy is enforced... strictly. 
1144 The caret is centred on the display if slop is not set, 
1145 and cannot go in the UZ if slop is set. 
1147 If jumps is set, the display is moved more energetically 
1148 so the caret can move in the same direction longer before the policy is applied again. 
1149 '3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin. 
1151 If even is not set, instead of having symmetrical UZs, 
1152 the left and bottom UZs are extended up to right and top UZs respectively. 
1153 This way, we favour the displaying of useful information: the begining of lines, 
1154 where most code reside, and the lines after the caret, eg. the body of a function. 
1157 slop | strict | jumps | even | Caret can go to the margin                 | When reaching limitÝ(caret going out of 
1158      |        |       |      |                                            | visibility or going into the UZ) display is... 
1159 -----+--------+-------+------+--------------------------------------------+-------------------------------------------------------------- 
1160   0  |   0    |   0   |   0  | Yes                                        | moved to put caret on top/on right 
1161   0  |   0    |   0   |   1  | Yes                                        | moved by one position 
1162   0  |   0    |   1   |   0  | Yes                                        | moved to put caret on top/on right 
1163   0  |   0    |   1   |   1  | Yes                                        | centred on the caret 
1164   0  |   1    |   -   |   0  | Caret is always on top/on right of display | - 
1165   0  |   1    |   -   |   1  | No, caret is always centred                | - 
1166   1  |   0    |   0   |   0  | Yes                                        | moved to put caret out of the asymmetrical UZ 
1167   1  |   0    |   0   |   1  | Yes                                        | moved to put caret out of the UZ 
1168   1  |   0    |   1   |   0  | Yes                                        | moved to put caret at 3UZ of the top or right margin 
1169   1  |   0    |   1   |   1  | Yes                                        | moved to put caret at 3UZ of the margin 
1170   1  |   1    |   -   |   0  | Caret is always at UZ of top/right margin  | - 
1171   1  |   1    |   0   |   1  | No, kept out of UZ                         | moved by one position 
1172   1  |   1    |   1   |   1  | No, kept out of UZ                         | moved to put caret at 3UZ of the margin 
1174 void Editor::EnsureCaretVisible(bool useMargin
, bool vert
, bool horiz
) { 
1175         //Platform::DebugPrintf("EnsureCaretVisible %d %s\n", xOffset, useMargin ? " margin" : " "); 
1176         PRectangle rcClient 
= GetTextRectangle(); 
1177         //int rcClientFullWidth = rcClient.Width(); 
1178         int posCaret 
= currentPos
; 
1182         Point pt 
= LocationFromPosition(posCaret
); 
1183         Point ptBottomCaret 
= pt
; 
1184         ptBottomCaret
.y 
+= vs
.lineHeight 
- 1; 
1185         int lineCaret 
= DisplayFromPosition(posCaret
); 
1186         bool bSlop
, bStrict
, bJump
, bEven
; 
1188         // Vertical positioning 
1189         if (vert 
&& (pt
.y 
< rcClient
.top 
|| ptBottomCaret
.y 
> rcClient
.bottom 
|| (caretYPolicy 
& CARET_STRICT
) != 0)) { 
1190                 int linesOnScreen 
= LinesOnScreen(); 
1191                 int halfScreen 
= Platform::Maximum(linesOnScreen 
- 1, 2) / 2; 
1192                 int newTopLine 
= topLine
; 
1193                 bSlop 
= (caretYPolicy 
& CARET_SLOP
) != 0; 
1194                 bStrict 
= (caretYPolicy 
& CARET_STRICT
) != 0; 
1195                 bJump 
= (caretYPolicy 
& CARET_JUMPS
) != 0; 
1196                 bEven 
= (caretYPolicy 
& CARET_EVEN
) != 0; 
1198                 // It should be possible to scroll the window to show the caret, 
1199                 // but this fails to remove the caret on GTK+ 
1200                 if (bSlop
) {    // A margin is defined 
1203                                 int yMarginT
, yMarginB
; 
1205                                         // In drag mode, avoid moves 
1206                                         // otherwise, a double click will select several lines. 
1207                                         yMarginT 
= yMarginB 
= 0; 
1209                                         // yMarginT must equal to caretYSlop, with a minimum of 1 and 
1210                                         // a maximum of slightly less than half the heigth of the text area. 
1211                                         yMarginT 
= Platform::Clamp(caretYSlop
, 1, halfScreen
); 
1213                                                 yMarginB 
= yMarginT
; 
1215                                                 yMarginB 
= linesOnScreen 
- yMarginT 
- 1; 
1221                                                 yMoveT 
= Platform::Clamp(caretYSlop 
* 3, 1, halfScreen
); 
1225                                         yMoveB 
= linesOnScreen 
- yMoveT 
- 1; 
1227                                 if (lineCaret 
< topLine 
+ yMarginT
) { 
1228                                         // Caret goes too high 
1229                                         newTopLine 
= lineCaret 
- yMoveT
; 
1230                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1 - yMarginB
) { 
1231                                         // Caret goes too low 
1232                                         newTopLine 
= lineCaret 
- linesOnScreen 
+ 1 + yMoveB
; 
1234                         } else {        // Not strict 
1235                                 yMoveT 
= bJump 
? caretYSlop 
* 3 : caretYSlop
; 
1236                                 yMoveT 
= Platform::Clamp(yMoveT
, 1, halfScreen
); 
1240                                         yMoveB 
= linesOnScreen 
- yMoveT 
- 1; 
1242                                 if (lineCaret 
< topLine
) { 
1243                                         // Caret goes too high 
1244                                         newTopLine 
= lineCaret 
- yMoveT
; 
1245                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1) { 
1246                                         // Caret goes too low 
1247                                         newTopLine 
= lineCaret 
- linesOnScreen 
+ 1 + yMoveB
; 
1251                         if (!bStrict 
&& !bJump
) { 
1253                                 if (lineCaret 
< topLine
) { 
1254                                         // Caret goes too high 
1255                                         newTopLine 
= lineCaret
; 
1256                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1) { 
1257                                         // Caret goes too low 
1259                                                 newTopLine 
= lineCaret 
- linesOnScreen 
+ 1; 
1261                                                 newTopLine 
= lineCaret
; 
1264                         } else {        // Strict or going out of display 
1266                                         // Always center caret 
1267                                         newTopLine 
= lineCaret 
- halfScreen
; 
1269                                         // Always put caret on top of display 
1270                                         newTopLine 
= lineCaret
; 
1274                 newTopLine 
= Platform::Clamp(newTopLine
, 0, MaxScrollPos()); 
1275                 if (newTopLine 
!= topLine
) { 
1277                         SetTopLine(newTopLine
); 
1278                         SetVerticalScrollPos(); 
1282         // Horizontal positioning 
1283         if (horiz 
&& (wrapState 
== eWrapNone
)) { 
1284                 int halfScreen 
= Platform::Maximum(rcClient
.Width() - 4, 4) / 2; 
1285                 int xOffsetNew 
= xOffset
; 
1286                 bSlop 
= (caretXPolicy 
& CARET_SLOP
) != 0; 
1287                 bStrict 
= (caretXPolicy 
& CARET_STRICT
) != 0; 
1288                 bJump 
= (caretXPolicy 
& CARET_JUMPS
) != 0; 
1289                 bEven 
= (caretXPolicy 
& CARET_EVEN
) != 0; 
1291                 if (bSlop
) {    // A margin is defined 
1294                                 int xMarginL
, xMarginR
; 
1296                                         // In drag mode, avoid moves unless very near of the margin 
1297                                         // otherwise, a simple click will select text. 
1298                                         xMarginL 
= xMarginR 
= 2; 
1300                                         // xMargin must equal to caretXSlop, with a minimum of 2 and 
1301                                         // a maximum of slightly less than half the width of the text area. 
1302                                         xMarginR 
= Platform::Clamp(caretXSlop
, 2, halfScreen
); 
1304                                                 xMarginL 
= xMarginR
; 
1306                                                 xMarginL 
= rcClient
.Width() - xMarginR 
- 4; 
1309                                 if (bJump 
&& bEven
) { 
1310                                         // Jump is used only in even mode 
1311                                         xMoveL 
= xMoveR 
= Platform::Clamp(caretXSlop 
* 3, 1, halfScreen
); 
1313                                         xMoveL 
= xMoveR 
= 0;    // Not used, avoid a warning 
1315                                 if (pt
.x 
< rcClient
.left 
+ xMarginL
) { 
1316                                         // Caret is on the left of the display 
1317                                         if (bJump 
&& bEven
) { 
1318                                                 xOffsetNew 
-= xMoveL
; 
1320                                                 // Move just enough to allow to display the caret 
1321                                                 xOffsetNew 
-= (rcClient
.left 
+ xMarginL
) - pt
.x
; 
1323                                 } else if (pt
.x 
>= rcClient
.right 
- xMarginR
) { 
1324                                         // Caret is on the right of the display 
1325                                         if (bJump 
&& bEven
) { 
1326                                                 xOffsetNew 
+= xMoveR
; 
1328                                                 // Move just enough to allow to display the caret 
1329                                                 xOffsetNew 
+= pt
.x 
- (rcClient
.right 
- xMarginR
) + 1; 
1332                         } else {        // Not strict 
1333                                 xMoveR 
= bJump 
? caretXSlop 
* 3 : caretXSlop
; 
1334                                 xMoveR 
= Platform::Clamp(xMoveR
, 1, halfScreen
); 
1338                                         xMoveL 
= rcClient
.Width() - xMoveR 
- 4; 
1340                                 if (pt
.x 
< rcClient
.left
) { 
1341                                         // Caret is on the left of the display 
1342                                         xOffsetNew 
-= xMoveL
; 
1343                                 } else if (pt
.x 
>= rcClient
.right
) { 
1344                                         // Caret is on the right of the display 
1345                                         xOffsetNew 
+= xMoveR
; 
1350                                 (bJump 
&& (pt
.x 
< rcClient
.left 
|| pt
.x 
>= rcClient
.right
))) { 
1351                                 // Strict or going out of display 
1354                                         xOffsetNew 
+= pt
.x 
- rcClient
.left 
- halfScreen
; 
1356                                         // Put caret on right 
1357                                         xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1360                                 // Move just enough to allow to display the caret 
1361                                 if (pt
.x 
< rcClient
.left
) { 
1362                                         // Caret is on the left of the display 
1364                                                 xOffsetNew 
-= rcClient
.left 
- pt
.x
; 
1366                                                 xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1368                                 } else if (pt
.x 
>= rcClient
.right
) { 
1369                                         // Caret is on the right of the display 
1370                                         xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1374                 // In case of a jump (find result) largely out of display, adjust the offset to display the caret 
1375                 if (pt
.x 
+ xOffset 
< rcClient
.left 
+ xOffsetNew
) { 
1376                         xOffsetNew 
= pt
.x 
+ xOffset 
- rcClient
.left
; 
1377                 } else if (pt
.x 
+ xOffset 
>= rcClient
.right 
+ xOffsetNew
) { 
1378                         xOffsetNew 
= pt
.x 
+ xOffset 
- rcClient
.right 
+ 1; 
1380                 if (xOffsetNew 
< 0) { 
1383                 if (xOffset 
!= xOffsetNew
) { 
1384                         xOffset 
= xOffsetNew
; 
1385                         if (xOffsetNew 
> 0) { 
1386                                 PRectangle rcText 
= GetTextRectangle(); 
1387                                 if (horizontalScrollBarVisible 
== true && 
1388                                         rcText
.Width() + xOffset 
> scrollWidth
) { 
1389                                         scrollWidth 
= xOffset 
+ rcText
.Width(); 
1393                         SetHorizontalScrollPos(); 
1397         UpdateSystemCaret(); 
1400 void Editor::ShowCaretAtCurrentPosition() { 
1402                 caret
.active 
= true; 
1406                 caret
.active 
= false; 
1412 void Editor::DropCaret() { 
1413         caret
.active 
= false; 
1417 void Editor::InvalidateCaret() { 
1419                 InvalidateRange(posDrag
, posDrag 
+ 1); 
1421                 InvalidateRange(currentPos
, currentPos 
+ 1); 
1422         UpdateSystemCaret(); 
1425 void Editor::UpdateSystemCaret() { 
1428 void Editor::NeedWrapping(int docLineStartWrapping
, int docLineEndWrapping
) { 
1429         docLineStartWrapping 
= Platform::Minimum(docLineStartWrapping
, pdoc
->LinesTotal()-1); 
1430         docLineEndWrapping 
= Platform::Minimum(docLineEndWrapping
, pdoc
->LinesTotal()-1); 
1431         bool noWrap 
= (docLastLineToWrap 
== docLineLastWrapped
); 
1432         if (docLineLastWrapped 
> (docLineStartWrapping 
- 1)) { 
1433                 docLineLastWrapped 
= docLineStartWrapping 
- 1; 
1434                 if (docLineLastWrapped 
< -1) 
1435                         docLineLastWrapped 
= -1; 
1436                 llc
.Invalidate(LineLayout::llPositions
); 
1439                 docLastLineToWrap 
= docLineEndWrapping
; 
1440         } else if (docLastLineToWrap 
< docLineEndWrapping
) { 
1441                 docLastLineToWrap 
= docLineEndWrapping 
+ 1; 
1443         if (docLastLineToWrap 
< -1) 
1444                 docLastLineToWrap 
= -1; 
1445         if (docLastLineToWrap 
>= pdoc
->LinesTotal()) 
1446                 docLastLineToWrap 
= pdoc
->LinesTotal()-1; 
1447         // Wrap lines during idle. 
1448         if ((wrapState 
!= eWrapNone
) && 
1449                 backgroundWrapEnabled 
&& 
1450                 (docLastLineToWrap 
!= docLineLastWrapped
)) { 
1455 // Check if wrapping needed and perform any needed wrapping. 
1456 // fullwrap: if true, all lines which need wrapping will be done, 
1457 //           in this single call. 
1458 // priorityWrapLineStart: If greater than zero, all lines starting from 
1459 //           here to 100 lines past will be wrapped (even if there are 
1460 //           more lines under wrapping process in idle). 
1461 // If it is neither fullwrap, nor priorityWrap, then 100 lines will be 
1462 // wrapped, if there are any wrapping going on in idle. (Generally this 
1463 // condition is called only from idler). 
1464 // Return true if wrapping occurred. 
1465 bool Editor::WrapLines(bool fullWrap
, int priorityWrapLineStart
) { 
1466         // If there are any pending wraps, do them during idle if possible. 
1467         if (wrapState 
!= eWrapNone
) { 
1468                 if (docLineLastWrapped 
< docLastLineToWrap
) { 
1469                         if (!(backgroundWrapEnabled 
&& SetIdle(true))) { 
1470                                 // Background wrapping is disabled, or idle processing 
1471                                 // not supported.  A full wrap is required. 
1475                 if (!fullWrap 
&& priorityWrapLineStart 
>= 0 && 
1476                         // .. and if the paint window is outside pending wraps 
1477                         (((priorityWrapLineStart 
+ 100) < docLineLastWrapped
) || 
1478                          (priorityWrapLineStart 
> docLastLineToWrap
))) { 
1479                         // No priority wrap pending 
1483         int goodTopLine 
= topLine
; 
1484         bool wrapOccurred 
= false; 
1485         if (docLineLastWrapped 
< pdoc
->LinesTotal()) { 
1486                 if (wrapState 
== eWrapNone
) { 
1487                         if (wrapWidth 
!= LineLayout::wrapWidthInfinite
) { 
1488                                 wrapWidth 
= LineLayout::wrapWidthInfinite
; 
1489                                 for (int lineDoc 
= 0; lineDoc 
< pdoc
->LinesTotal(); lineDoc
++) { 
1490                                         cs
.SetHeight(lineDoc
, 1); 
1492                                 wrapOccurred 
= true; 
1494                         docLineLastWrapped 
= 0x7ffffff; 
1497                         int lineDocTop 
= cs
.DocFromDisplay(topLine
); 
1498                         int subLineTop 
= topLine 
- cs
.DisplayFromDoc(lineDocTop
); 
1499                         PRectangle rcTextArea 
= GetClientRectangle(); 
1500                         rcTextArea
.left 
= vs
.fixedColumnWidth
; 
1501                         rcTextArea
.right 
-= vs
.rightMarginWidth
; 
1502                         wrapWidth 
= rcTextArea
.Width(); 
1503                         // Ensure all of the document is styled. 
1504                         pdoc
->EnsureStyledTo(pdoc
->Length()); 
1506                         AutoSurface 
surface(this); 
1508                                 bool priorityWrap 
= false; 
1509                                 int lastLineToWrap 
= docLastLineToWrap
; 
1510                                 int firstLineToWrap 
= docLineLastWrapped
; 
1512                                         if (priorityWrapLineStart 
>= 0) { 
1513                                                 // This is a priority wrap. 
1514                                                 firstLineToWrap 
= priorityWrapLineStart
; 
1515                                                 lastLineToWrap 
= firstLineToWrap 
+ 100; 
1516                                                 priorityWrap 
= true; 
1518                                                 // This is idle wrap. 
1519                                                 lastLineToWrap 
= docLineLastWrapped 
+ 100; 
1521                                         if (lastLineToWrap 
>= docLastLineToWrap
) 
1522                                                 lastLineToWrap 
= docLastLineToWrap
; 
1523                                 } // else do a fullWrap. 
1525                                 // printf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, firstLineToWrap, lastLineToWrap); 
1526                                 // printf("Pending wraps: %d to %d\n", docLineLastWrapped, docLastLineToWrap); 
1527                                 while (firstLineToWrap 
< lastLineToWrap
) { 
1530                                                 docLineLastWrapped
++; 
1531                                         if (firstLineToWrap 
< pdoc
->LinesTotal()) { 
1532                                         AutoLineLayout 
ll(llc
, RetrieveLineLayout(firstLineToWrap
)); 
1533                                         int linesWrapped 
= 1; 
1535                                                 LayoutLine(firstLineToWrap
, surface
, vs
, ll
, wrapWidth
); 
1536                                                 linesWrapped 
= ll
->lines
; 
1538                                         if (cs
.SetHeight(firstLineToWrap
, linesWrapped
)) { 
1539                                                 wrapOccurred 
= true; 
1543                                 // If wrapping is done, bring it to resting position 
1544                                 if (docLineLastWrapped 
> docLastLineToWrap
) { 
1545                                         docLineLastWrapped 
= -1; 
1546                                         docLastLineToWrap 
= -1; 
1549                         goodTopLine 
= cs
.DisplayFromDoc(lineDocTop
); 
1550                         if (subLineTop 
< cs
.GetHeight(lineDocTop
)) 
1551                                 goodTopLine 
+= subLineTop
; 
1553                                 goodTopLine 
+= cs
.GetHeight(lineDocTop
); 
1554                         //double durWrap = et.Duration(true); 
1555                         //Platform::DebugPrintf("Wrap:%9.6g \n", durWrap); 
1560                 SetTopLine(Platform::Clamp(goodTopLine
, 0, MaxScrollPos())); 
1561                 SetVerticalScrollPos(); 
1563         return wrapOccurred
; 
1566 void Editor::LinesJoin() { 
1567         if (!RangeContainsProtected(targetStart
, targetEnd
)) { 
1568                 pdoc
->BeginUndoAction(); 
1569                 bool prevNonWS 
= true; 
1570                 for (int pos 
= targetStart
; pos 
< targetEnd
; pos
++) { 
1571                         if (IsEOLChar(pdoc
->CharAt(pos
))) { 
1572                                 targetEnd 
-= pdoc
->LenChar(pos
); 
1575                                         // Ensure at least one space separating previous lines 
1576                                         pdoc
->InsertChar(pos
, ' '); 
1579                                 prevNonWS 
= pdoc
->CharAt(pos
) != ' '; 
1582                 pdoc
->EndUndoAction(); 
1586 const char *StringFromEOLMode(int eolMode
) { 
1587         if (eolMode 
== SC_EOL_CRLF
) { 
1589         } else if (eolMode 
== SC_EOL_CR
) { 
1596 void Editor::LinesSplit(int pixelWidth
) { 
1597         if (!RangeContainsProtected(targetStart
, targetEnd
)) { 
1598                 if (pixelWidth 
== 0) { 
1599                         PRectangle rcText 
= GetTextRectangle(); 
1600                         pixelWidth 
= rcText
.Width(); 
1602                 int lineStart 
= pdoc
->LineFromPosition(targetStart
); 
1603                 int lineEnd 
= pdoc
->LineFromPosition(targetEnd
); 
1604                 const char *eol 
= StringFromEOLMode(pdoc
->eolMode
); 
1605                 pdoc
->BeginUndoAction(); 
1606                 for (int line 
= lineStart
; line 
<= lineEnd
; line
++) { 
1607                         AutoSurface 
surface(this); 
1608                         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
1609                         if (surface 
&& ll
) { 
1610                                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
1611                                 LayoutLine(line
, surface
, vs
, ll
, pixelWidth
); 
1612                                 for (int subLine 
= 1; subLine 
< ll
->lines
; subLine
++) { 
1613                                         pdoc
->InsertString(posLineStart 
+ (subLine 
- 1) * strlen(eol
) + 
1614                                                 ll
->LineStart(subLine
), eol
); 
1615                                         targetEnd 
+= static_cast<int>(strlen(eol
)); 
1619                 pdoc
->EndUndoAction(); 
1623 int Editor::SubstituteMarkerIfEmpty(int markerCheck
, int markerDefault
) { 
1624         if (vs
.markers
[markerCheck
].markType 
== SC_MARK_EMPTY
) 
1625                 return markerDefault
; 
1629 // Avoid 64 bit compiler warnings. 
1630 // Scintilla does not support text buffers larger than 2**31 
1631 static int istrlen(const char *s
) { 
1632         return static_cast<int>(strlen(s
)); 
1635 void Editor::PaintSelMargin(Surface 
*surfWindow
, PRectangle 
&rc
) { 
1636         if (vs
.fixedColumnWidth 
== 0) 
1639         PRectangle rcMargin 
= GetClientRectangle(); 
1640         rcMargin
.right 
= vs
.fixedColumnWidth
; 
1642         if (!rc
.Intersects(rcMargin
)) 
1647                 surface 
= pixmapSelMargin
; 
1649                 surface 
= surfWindow
; 
1652         PRectangle rcSelMargin 
= rcMargin
; 
1653         rcSelMargin
.right 
= rcMargin
.left
; 
1655         for (int margin 
= 0; margin 
< vs
.margins
; margin
++) { 
1656                 if (vs
.ms
[margin
].width 
> 0) { 
1658                         rcSelMargin
.left 
= rcSelMargin
.right
; 
1659                         rcSelMargin
.right 
= rcSelMargin
.left 
+ vs
.ms
[margin
].width
; 
1661                         if (vs
.ms
[margin
].symbol
) { 
1662                                 /* alternate scheme: 
1663                                 if (vs.ms[margin].mask & SC_MASK_FOLDERS) 
1664                                         surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
1666                                         // Required because of special way brush is created for selection margin 
1667                                         surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
1669                                 if (vs
.ms
[margin
].mask 
& SC_MASK_FOLDERS
) 
1670                                         // Required because of special way brush is created for selection margin 
1671                                         surface
->FillRectangle(rcSelMargin
, *pixmapSelPattern
); 
1673                                         surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1675                                 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1678                         int visibleLine 
= topLine
; 
1681                         // Work out whether the top line is whitespace located after a 
1682                         // lessening of fold level which implies a 'fold tail' but which should not 
1683                         // be displayed until the last of a sequence of whitespace. 
1684                         bool needWhiteClosure 
= false; 
1685                         int level 
= pdoc
->GetLevel(cs
.DocFromDisplay(topLine
)); 
1686                         if (level 
& SC_FOLDLEVELWHITEFLAG
) { 
1687                                 int lineBack 
= cs
.DocFromDisplay(topLine
); 
1688                                 int levelPrev 
= level
; 
1689                                 while ((lineBack 
> 0) && (levelPrev 
& SC_FOLDLEVELWHITEFLAG
)) { 
1691                                         levelPrev 
= pdoc
->GetLevel(lineBack
); 
1693                                 if (!(levelPrev 
& SC_FOLDLEVELHEADERFLAG
)) { 
1694                                         if ((level 
& SC_FOLDLEVELNUMBERMASK
) < (levelPrev 
& SC_FOLDLEVELNUMBERMASK
)) 
1695                                                 needWhiteClosure 
= true; 
1699                         // Old code does not know about new markers needed to distinguish all cases 
1700                         int folderOpenMid 
= SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID
, 
1701                                             SC_MARKNUM_FOLDEROPEN
); 
1702                         int folderEnd 
= SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND
, 
1705                         while ((visibleLine 
< cs
.LinesDisplayed()) && yposScreen 
< rcMargin
.bottom
) { 
1707                                 PLATFORM_ASSERT(visibleLine 
< cs
.LinesDisplayed()); 
1709                                 int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
1710                                 PLATFORM_ASSERT(cs
.GetVisible(lineDoc
)); 
1711                                 bool firstSubLine 
= visibleLine 
== cs
.DisplayFromDoc(lineDoc
); 
1713                                 // Decide which fold indicator should be displayed 
1714                                 level 
= pdoc
->GetLevel(lineDoc
); 
1715                                 int levelNext 
= pdoc
->GetLevel(lineDoc 
+ 1); 
1716                                 int marks 
= pdoc
->GetMark(lineDoc
); 
1719                                 int levelNum 
= level 
& SC_FOLDLEVELNUMBERMASK
; 
1720                                 int levelNextNum 
= levelNext 
& SC_FOLDLEVELNUMBERMASK
; 
1721                                 if (level 
& SC_FOLDLEVELHEADERFLAG
) { 
1723                                                 if (cs
.GetExpanded(lineDoc
)) { 
1724                                                         if (levelNum 
== SC_FOLDLEVELBASE
) 
1725                                                                 marks 
|= 1 << SC_MARKNUM_FOLDEROPEN
; 
1727                                                                 marks 
|= 1 << folderOpenMid
; 
1729                                                         if (levelNum 
== SC_FOLDLEVELBASE
) 
1730                                                                 marks 
|= 1 << SC_MARKNUM_FOLDER
; 
1732                                                                 marks 
|= 1 << folderEnd
; 
1735                                                 marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1737                                         needWhiteClosure 
= false; 
1738                                 } else if (level 
& SC_FOLDLEVELWHITEFLAG
) { 
1739                                         if (needWhiteClosure
) { 
1740                                                 if (levelNext 
& SC_FOLDLEVELWHITEFLAG
) { 
1741                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1742                                                 } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1743                                                         marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1744                                                         needWhiteClosure 
= false; 
1746                                                         marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1747                                                         needWhiteClosure 
= false; 
1749                                         } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1750                                                 if (levelNextNum 
< levelNum
) { 
1751                                                         if (levelNextNum 
> SC_FOLDLEVELBASE
) { 
1752                                                                 marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1754                                                                 marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1757                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1760                                 } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1761                                         if (levelNextNum 
< levelNum
) { 
1762                                                 needWhiteClosure 
= false; 
1763                                                 if (levelNext 
& SC_FOLDLEVELWHITEFLAG
) { 
1764                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1765                                                         needWhiteClosure 
= true; 
1766                                                 } else if (levelNextNum 
> SC_FOLDLEVELBASE
) { 
1767                                                         marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1769                                                         marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1772                                                 marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1776                                 marks 
&= vs
.ms
[margin
].mask
; 
1777                                 PRectangle rcMarker 
= rcSelMargin
; 
1778                                 rcMarker
.top 
= yposScreen
; 
1779                                 rcMarker
.bottom 
= yposScreen 
+ vs
.lineHeight
; 
1780                                 if (!vs
.ms
[margin
].symbol
) { 
1784                                                 sprintf(number
, "%d", lineDoc 
+ 1); 
1785                                         if (foldFlags 
& SC_FOLDFLAG_LEVELNUMBERS
) { 
1786                                                 int lev 
= pdoc
->GetLevel(lineDoc
); 
1787                                                 sprintf(number
, "%c%c %03X %03X", 
1788                                                         (lev 
& SC_FOLDLEVELHEADERFLAG
) ? 'H' : '_', 
1789                                                         (lev 
& SC_FOLDLEVELWHITEFLAG
) ? 'W' : '_', 
1790                                                         lev 
& SC_FOLDLEVELNUMBERMASK
, 
1794                                         PRectangle rcNumber 
= rcMarker
; 
1796                                         int width 
= surface
->WidthText(vs
.styles
[STYLE_LINENUMBER
].font
, number
, istrlen(number
)); 
1797                                         int xpos 
= rcNumber
.right 
- width 
- 3; 
1798                                         rcNumber
.left 
= xpos
; 
1799                                         surface
->DrawTextNoClip(rcNumber
, vs
.styles
[STYLE_LINENUMBER
].font
, 
1800                                                                 rcNumber
.top 
+ vs
.maxAscent
, number
, istrlen(number
), 
1801                                                                 vs
.styles
[STYLE_LINENUMBER
].fore
.allocated
, 
1802                                                                 vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1806                                         for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
1808                                                         vs
.markers
[markBit
].Draw(surface
, rcMarker
, vs
.styles
[STYLE_LINENUMBER
].font
); 
1815                                 yposScreen 
+= vs
.lineHeight
; 
1820         PRectangle rcBlankMargin 
= rcMargin
; 
1821         rcBlankMargin
.left 
= rcSelMargin
.right
; 
1822         surface
->FillRectangle(rcBlankMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
1825                 surfWindow
->Copy(rcMargin
, Point(), *pixmapSelMargin
); 
1829 void DrawTabArrow(Surface 
*surface
, PRectangle rcTab
, int ymid
) { 
1830         int ydiff 
= (rcTab
.bottom 
- rcTab
.top
) / 2; 
1831         int xhead 
= rcTab
.right 
- 1 - ydiff
; 
1832         if (xhead 
<= rcTab
.left
) { 
1833                 ydiff 
-= rcTab
.left 
- xhead 
- 1; 
1834                 xhead 
= rcTab
.left 
- 1; 
1836         if ((rcTab
.left 
+ 2) < (rcTab
.right 
- 1)) 
1837                 surface
->MoveTo(rcTab
.left 
+ 2, ymid
); 
1839                 surface
->MoveTo(rcTab
.right 
- 1, ymid
); 
1840         surface
->LineTo(rcTab
.right 
- 1, ymid
); 
1841         surface
->LineTo(xhead
, ymid 
- ydiff
); 
1842         surface
->MoveTo(rcTab
.right 
- 1, ymid
); 
1843         surface
->LineTo(xhead
, ymid 
+ ydiff
); 
1846 static bool IsSpaceOrTab(char ch
) { 
1847         return ch 
== ' ' || ch 
== '\t'; 
1850 LineLayout 
*Editor::RetrieveLineLayout(int lineNumber
) { 
1851         int posLineStart 
= pdoc
->LineStart(lineNumber
); 
1852         int posLineEnd 
= pdoc
->LineStart(lineNumber 
+ 1); 
1853         int lineCaret 
= pdoc
->LineFromPosition(currentPos
); 
1854         return llc
.Retrieve(lineNumber
, lineCaret
, 
1855                             posLineEnd 
- posLineStart
, pdoc
->GetStyleClock(), 
1856                             LinesOnScreen() + 1, pdoc
->LinesTotal()); 
1860  * Fill in the LineLayout data for the given line. 
1861  * Copy the given @a line and its styles from the document into local arrays. 
1862  * Also determine the x position at which each character starts. 
1864 void Editor::LayoutLine(int line
, Surface 
*surface
, ViewStyle 
&vstyle
, LineLayout 
*ll
, int width
) { 
1867         PLATFORM_ASSERT(line 
< pdoc
->LinesTotal()); 
1868         int posLineStart 
= pdoc
->LineStart(line
); 
1869         int posLineEnd 
= pdoc
->LineStart(line 
+ 1); 
1870         // If the line is very long, limit the treatment to a length that should fit in the viewport 
1871         if (posLineEnd 
> (posLineStart 
+ ll
->maxLineLength
)) { 
1872                 posLineEnd 
= posLineStart 
+ ll
->maxLineLength
; 
1874         if (ll
->validity 
== LineLayout::llCheckTextAndStyle
) { 
1876                 for (int cid 
= posLineStart
; cid 
< posLineEnd
; cid
++) { 
1877                         char chDoc 
= pdoc
->CharAt(cid
); 
1878                         if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1882                 if (lineLength 
== ll
->numCharsInLine
) { 
1883                         int numCharsInLine 
= 0; 
1884                         // See if chars, styles, indicators, are all the same 
1885                         bool allSame 
= true; 
1886                         const int styleMask 
= pdoc
->stylingBitsMask
; 
1887                         // Check base line layout 
1888                         for (int charInDoc 
= posLineStart
; allSame 
&& (charInDoc 
< posLineEnd
); charInDoc
++) { 
1889                                 char chDoc 
= pdoc
->CharAt(charInDoc
); 
1890                                 if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1891                                         char styleByte 
= pdoc
->StyleAt(charInDoc
); 
1892                                         allSame 
= allSame 
&& 
1893                                                   (ll
->styles
[numCharsInLine
] == static_cast<char>(styleByte 
& styleMask
)); 
1894                                         allSame 
= allSame 
&& 
1895                                                   (ll
->indicators
[numCharsInLine
] == static_cast<char>(styleByte 
& ~styleMask
)); 
1896                                         if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseUpper
) 
1897                                                 allSame 
= allSame 
&& 
1898                                                           (ll
->chars
[numCharsInLine
] == static_cast<char>(toupper(chDoc
))); 
1899                                         else if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseLower
) 
1900                                                 allSame 
= allSame 
&& 
1901                                                           (ll
->chars
[numCharsInLine
] == static_cast<char>(tolower(chDoc
))); 
1903                                                 allSame 
= allSame 
&& 
1904                                                           (ll
->chars
[numCharsInLine
] == chDoc
); 
1909                                 ll
->validity 
= LineLayout::llPositions
; 
1911                                 ll
->validity 
= LineLayout::llInvalid
; 
1914                         ll
->validity 
= LineLayout::llInvalid
; 
1917         if (ll
->validity 
== LineLayout::llInvalid
) { 
1918                 ll
->widthLine 
= LineLayout::wrapWidthInfinite
; 
1920                 int numCharsInLine 
= 0; 
1921                 if (vstyle
.edgeState 
== EDGE_BACKGROUND
) { 
1922                         ll
->edgeColumn 
= pdoc
->FindColumn(line
, theEdge
); 
1923                         if (ll
->edgeColumn 
>= posLineStart
) { 
1924                                 ll
->edgeColumn 
-= posLineStart
; 
1927                         ll
->edgeColumn 
= -1; 
1931                 int styleMask 
= pdoc
->stylingBitsMask
; 
1932                 // Fill base line layout 
1933                 for (int charInDoc 
= posLineStart
; charInDoc 
< posLineEnd
; charInDoc
++) { 
1934                         char chDoc 
= pdoc
->CharAt(charInDoc
); 
1935                         styleByte 
= pdoc
->StyleAt(charInDoc
); 
1936                         if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1937                                 ll
->chars
[numCharsInLine
] = chDoc
; 
1938                                 ll
->styles
[numCharsInLine
] = static_cast<char>(styleByte 
& styleMask
); 
1939                                 ll
->indicators
[numCharsInLine
] = static_cast<char>(styleByte 
& ~styleMask
); 
1940                                 if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseUpper
) 
1941                                         ll
->chars
[numCharsInLine
] = static_cast<char>(toupper(chDoc
)); 
1942                                 else if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseLower
) 
1943                                         ll
->chars
[numCharsInLine
] = static_cast<char>(tolower(chDoc
)); 
1947                 ll
->xHighlightGuide 
= 0; 
1948                 // Extra element at the end of the line to hold end x position and act as 
1949                 ll
->chars
[numCharsInLine
] = 0;   // Also triggers processing in the loops as this is a control character 
1950                 ll
->styles
[numCharsInLine
] = styleByte
; // For eolFilled 
1951                 ll
->indicators
[numCharsInLine
] = 0; 
1953                 // Layout the line, determining the position of each character, 
1954                 // with an extra element at the end for the end of the line. 
1955                 int startseg 
= 0;       // Start of the current segment, in char. number 
1956                 int startsegx 
= 0;      // Start of the current segment, in pixels 
1957                 ll
->positions
[0] = 0; 
1958                 unsigned int tabWidth 
= vstyle
.spaceWidth 
* pdoc
->tabInChars
; 
1959                 bool lastSegItalics 
= false; 
1960                 Font 
&ctrlCharsFont 
= vstyle
.styles
[STYLE_CONTROLCHAR
].font
; 
1962                 bool isControlNext 
= IsControlCharacter(ll
->chars
[0]); 
1963                 for (int charInLine 
= 0; charInLine 
< numCharsInLine
; charInLine
++) { 
1964                         bool isControl 
= isControlNext
; 
1965                         isControlNext 
= IsControlCharacter(ll
->chars
[charInLine 
+ 1]); 
1966                         if ((ll
->styles
[charInLine
] != ll
->styles
[charInLine 
+ 1]) || 
1967                                 isControl 
|| isControlNext
) { 
1968                                 ll
->positions
[startseg
] = 0; 
1969                                 if (vstyle
.styles
[ll
->styles
[charInLine
]].visible
) { 
1971                                                 if (ll
->chars
[charInLine
] == '\t') { 
1972                                                         ll
->positions
[charInLine 
+ 1] = ((((startsegx 
+ 2) / 
1973                                                                                            tabWidth
) + 1) * tabWidth
) - startsegx
; 
1974                                                 } else if (controlCharSymbol 
< 32) { 
1975                                                         const char *ctrlChar 
= ControlCharacterString(ll
->chars
[charInLine
]); 
1976                                                         // +3 For a blank on front and rounded edge each side: 
1977                                                         ll
->positions
[charInLine 
+ 1] = surface
->WidthText(ctrlCharsFont
, ctrlChar
, istrlen(ctrlChar
)) + 3; 
1979                                                         char cc
[2] = { static_cast<char>(controlCharSymbol
), '\0' }; 
1980                                                         surface
->MeasureWidths(ctrlCharsFont
, cc
, 1, 
1981                                                                                ll
->positions 
+ startseg 
+ 1); 
1983                                                 lastSegItalics 
= false; 
1984                                         } else {        // Regular character 
1985                                                 int lenSeg 
= charInLine 
- startseg 
+ 1; 
1986                                                 if ((lenSeg 
== 1) && (' ' == ll
->chars
[startseg
])) { 
1987                                                         lastSegItalics 
= false; 
1988                                                         // Over half the segments are single characters and of these about half are space characters. 
1989                                                         ll
->positions
[charInLine 
+ 1] = vstyle
.styles
[ll
->styles
[charInLine
]].spaceWidth
; 
1991                                                         lastSegItalics 
= vstyle
.styles
[ll
->styles
[charInLine
]].italic
; 
1992                                                         surface
->MeasureWidths(vstyle
.styles
[ll
->styles
[charInLine
]].font
, ll
->chars 
+ startseg
, 
1993                                                                                lenSeg
, ll
->positions 
+ startseg 
+ 1); 
1996                                 } else {    // invisible 
1997                                         for (int posToZero 
= startseg
; posToZero 
<= (charInLine 
+ 1); posToZero
++) { 
1998                                                 ll
->positions
[posToZero
] = 0; 
2001                                 for (int posToIncrease 
= startseg
; posToIncrease 
<= (charInLine 
+ 1); posToIncrease
++) { 
2002                                         ll
->positions
[posToIncrease
] += startsegx
; 
2004                                 startsegx 
= ll
->positions
[charInLine 
+ 1]; 
2005                                 startseg 
= charInLine 
+ 1; 
2008                 // Small hack to make lines that end with italics not cut off the edge of the last character 
2009                 if ((startseg 
> 0) && lastSegItalics
) { 
2010                         ll
->positions
[startseg
] += 2; 
2012                 ll
->numCharsInLine 
= numCharsInLine
; 
2013                 ll
->validity 
= LineLayout::llPositions
; 
2015         // Hard to cope when too narrow, so just assume there is space 
2019         if ((ll
->validity 
== LineLayout::llPositions
) || (ll
->widthLine 
!= width
)) { 
2020                 ll
->widthLine 
= width
; 
2021                 if (width 
== LineLayout::wrapWidthInfinite
) { 
2023                 } else if (width 
> ll
->positions
[ll
->numCharsInLine
]) { 
2024                         // Simple common case where line does not need wrapping. 
2027                         if (wrapVisualFlags 
& SC_WRAPVISUALFLAG_END
) { 
2028                                 width 
-= vstyle
.aveCharWidth
; // take into account the space for end wrap mark 
2031                         // Calculate line start positions based upon width. 
2032                         // For now this is simplistic - wraps on byte rather than character and 
2033                         // in the middle of words. Should search for spaces or style changes. 
2034                         int lastGoodBreak 
= 0; 
2035                         int lastLineStart 
= 0; 
2036                         int startOffset 
= 0; 
2038                         while (p 
< ll
->numCharsInLine
) { 
2039                                 if ((ll
->positions
[p 
+ 1] - startOffset
) >= width
) { 
2040                                         if (lastGoodBreak 
== lastLineStart
) { 
2041                                                 // Try moving to start of last character 
2043                                                         lastGoodBreak 
= pdoc
->MovePositionOutsideChar(p 
+ posLineStart
, -1) 
2046                                                 if (lastGoodBreak 
== lastLineStart
) { 
2047                                                         // Ensure at least one character on line. 
2048                                                         lastGoodBreak 
= pdoc
->MovePositionOutsideChar(lastGoodBreak 
+ posLineStart 
+ 1, 1) 
2052                                         lastLineStart 
= lastGoodBreak
; 
2054                                         ll
->SetLineStart(ll
->lines
, lastGoodBreak
); 
2055                                         startOffset 
= ll
->positions
[lastGoodBreak
]; 
2056                                         // take into account the space for start wrap mark and indent 
2057                                         startOffset 
-= actualWrapVisualStartIndent 
* vstyle
.aveCharWidth
; 
2058                                         p 
= lastGoodBreak 
+ 1; 
2062                                         if (ll
->styles
[p
] != ll
->styles
[p 
- 1]) { 
2064                                         } else if (IsSpaceOrTab(ll
->chars
[p 
- 1]) && !IsSpaceOrTab(ll
->chars
[p
])) { 
2072                 ll
->validity 
= LineLayout::llLines
; 
2076 ColourAllocated 
Editor::TextBackground(ViewStyle 
&vsDraw
, bool overrideBackground
, 
2077                                        ColourAllocated background
, bool inSelection
, bool inHotspot
, int styleMain
, int i
, LineLayout 
*ll
) { 
2079                 if (vsDraw
.selbackset
) { 
2080                         if (primarySelection
) 
2081                                 return vsDraw
.selbackground
.allocated
; 
2083                                 return vsDraw
.selbackground2
.allocated
; 
2086                 if ((vsDraw
.edgeState 
== EDGE_BACKGROUND
) && 
2087                         (i 
>= ll
->edgeColumn
) && 
2088                         !IsEOLChar(ll
->chars
[i
])) 
2089                         return vsDraw
.edgecolour
.allocated
; 
2090                 if (inHotspot 
&& vsDraw
.hotspotBackgroundSet
) 
2091                         return vsDraw
.hotspotBackground
.allocated
; 
2092                 if (overrideBackground
) 
2095         return vsDraw
.styles
[styleMain
].back
.allocated
; 
2098 void Editor::DrawIndentGuide(Surface 
*surface
, int lineVisible
, int lineHeight
, int start
, PRectangle rcSegment
, bool highlight
) { 
2099         Point 
from(0, ((lineVisible 
& 1) && (lineHeight 
& 1)) ? 1 : 0); 
2100         PRectangle 
rcCopyArea(start 
+ 1, rcSegment
.top
, start 
+ 2, rcSegment
.bottom
); 
2101         surface
->Copy(rcCopyArea
, from
, 
2102                       highlight 
? *pixmapIndentGuideHighlight 
: *pixmapIndentGuide
); 
2105 void Editor::DrawWrapMarker(Surface 
*surface
, PRectangle rcPlace
, 
2106                             bool isEndMarker
, ColourAllocated wrapColour
) { 
2107         surface
->PenColour(wrapColour
); 
2109         enum { xa 
= 1 }; // gap before start 
2110         int w 
= rcPlace
.right 
- rcPlace
.left 
- xa 
- 1; 
2112         bool xStraight 
= isEndMarker
;  // x-mirrored symbol for start marker 
2113         bool yStraight 
= true; 
2114         //bool yStraight= isEndMarker; // comment in for start marker y-mirrowed 
2116         int x0 
= xStraight 
? rcPlace
.left 
: rcPlace
.right 
- 1; 
2117         int y0 
= yStraight 
? rcPlace
.top 
: rcPlace
.bottom 
- 1; 
2119         int dy 
= (rcPlace
.bottom 
- rcPlace
.top
) / 5; 
2120         int y 
= (rcPlace
.bottom 
- rcPlace
.top
) / 2 + dy
; 
2128                 void MoveTo(int xRelative
, int yRelative
) { 
2129                     surface
->MoveTo(xBase 
+ xDir 
* xRelative
, yBase 
+ yDir 
* yRelative
); 
2131                 void LineTo(int xRelative
, int yRelative
) { 
2132                     surface
->LineTo(xBase 
+ xDir 
* xRelative
, yBase 
+ yDir 
* yRelative
); 
2135         Relative rel 
= {surface
, x0
, xStraight
?1:-1, y0
, yStraight
?1:-1}; 
2139         rel
.LineTo(xa 
+ 2*w 
/ 3, y 
- dy
); 
2141         rel
.LineTo(xa 
+ 2*w 
/ 3, y 
+ dy
); 
2145         rel
.LineTo(xa 
+ w
, y
); 
2146         rel
.LineTo(xa 
+ w
, y 
- 2 * dy
); 
2147         rel
.LineTo(xa 
- 1,   // on windows lineto is exclusive endpoint, perhaps GTK not... 
2151 void Editor::DrawEOL(Surface 
*surface
, ViewStyle 
&vsDraw
, PRectangle rcLine
, LineLayout 
*ll
, 
2152                      int line
, int lineEnd
, int xStart
, int subLine
, int subLineStart
, 
2153                      bool overrideBackground
, ColourAllocated background
, 
2154                      bool drawWrapMarkEnd
, ColourAllocated wrapColour
) { 
2156         int styleMask 
= pdoc
->stylingBitsMask
; 
2157         PRectangle rcSegment 
= rcLine
; 
2159         // Fill in a PRectangle representing the end of line characters 
2160         int xEol 
= ll
->positions
[lineEnd
] - subLineStart
; 
2161         rcSegment
.left 
= xEol 
+ xStart
; 
2162         rcSegment
.right 
= xEol 
+ vsDraw
.aveCharWidth 
+ xStart
; 
2163         int posLineEnd 
= pdoc
->LineStart(line 
+ 1); 
2164         bool eolInSelection 
= (subLine 
== (ll
->lines 
- 1)) && 
2165                               (posLineEnd 
> ll
->selStart
) && (posLineEnd 
<= ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2167         if (eolInSelection 
&& vsDraw
.selbackset 
&& (line 
< pdoc
->LinesTotal() - 1)) { 
2168                 if (primarySelection
) 
2169                         surface
->FillRectangle(rcSegment
, vsDraw
.selbackground
.allocated
); 
2171                         surface
->FillRectangle(rcSegment
, vsDraw
.selbackground2
.allocated
); 
2172         } else if (overrideBackground
) { 
2173                 surface
->FillRectangle(rcSegment
, background
); 
2175                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].back
.allocated
); 
2178         rcSegment
.left 
= xEol 
+ vsDraw
.aveCharWidth 
+ xStart
; 
2179         rcSegment
.right 
= rcLine
.right
; 
2180         if (overrideBackground
) { 
2181                 surface
->FillRectangle(rcSegment
, background
); 
2182         } else if (vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].eolFilled
) { 
2183                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].back
.allocated
); 
2185                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2188         if (drawWrapMarkEnd
) { 
2189                 PRectangle rcPlace 
= rcSegment
; 
2191                 if (wrapVisualFlagsLocation 
& SC_WRAPVISUALFLAGLOC_END_BY_TEXT
) { 
2192                         rcPlace
.left 
= xEol 
+ xStart
; 
2193                         rcPlace
.right 
= rcPlace
.left 
+ vsDraw
.aveCharWidth
; 
2195                         // draw left of the right text margin, to avoid clipping by the current clip rect 
2196                         rcPlace
.right 
= rcLine
.right 
- vs
.rightMarginWidth
; 
2197                         rcPlace
.left 
= rcPlace
.right 
- vsDraw
.aveCharWidth
; 
2199                 DrawWrapMarker(surface
, rcPlace
, true, wrapColour
); 
2203 void Editor::DrawLine(Surface 
*surface
, ViewStyle 
&vsDraw
, int line
, int lineVisible
, int xStart
, 
2204                       PRectangle rcLine
, LineLayout 
*ll
, int subLine
) { 
2206         PRectangle rcSegment 
= rcLine
; 
2208         // Using one font for all control characters so it can be controlled independently to ensure 
2209         // the box goes around the characters tightly. Seems to be no way to work out what height 
2210         // is taken by an individual character - internal leading gives varying results. 
2211         Font 
&ctrlCharsFont 
= vsDraw
.styles
[STYLE_CONTROLCHAR
].font
; 
2213         // See if something overrides the line background color:  Either if caret is on the line 
2214         // and background color is set for that, or if a marker is defined that forces its background 
2215         // color onto the line, or if a marker is defined but has no selection margin in which to 
2216         // display itself (as long as it's not an SC_MARK_EMPTY marker).  These are checked in order 
2217         // with the earlier taking precedence.  When multiple markers cause background override, 
2218         // the color for the highest numbered one is used. 
2219         bool overrideBackground 
= false; 
2220         ColourAllocated background
; 
2221         if (caret
.active 
&& vsDraw
.showCaretLineBackground 
&& ll
->containsCaret
) { 
2222                 overrideBackground 
= true; 
2223                 background 
= vsDraw
.caretLineBackground
.allocated
; 
2225         if (!overrideBackground
) { 
2226                 int marks 
= pdoc
->GetMark(line
); 
2227                 for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
2228                         if ((marks 
& 1) && vsDraw
.markers
[markBit
].markType 
== SC_MARK_BACKGROUND
) { 
2229                                 background 
= vsDraw
.markers
[markBit
].back
.allocated
; 
2230                                 overrideBackground 
= true; 
2235         if (!overrideBackground
) { 
2236                 if (vsDraw
.maskInLine
) { 
2237                         int marks 
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
; 
2239                                 for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
2240                                         if ((marks 
& 1) && (vsDraw
.markers
[markBit
].markType 
!= SC_MARK_EMPTY
)) { 
2241                                                 overrideBackground 
= true; 
2242                                                 background 
= vsDraw
.markers
[markBit
].back
.allocated
; 
2250         bool drawWhitespaceBackground 
= (vsDraw
.viewWhitespace 
!= wsInvisible
) && 
2251                                         (!overrideBackground
) && (vsDraw
.whitespaceBackgroundSet
); 
2253         bool inIndentation 
= subLine 
== 0;      // Do not handle indentation except on first subline. 
2254         int indentWidth 
= pdoc
->IndentSize() * vsDraw
.spaceWidth
; 
2256         int posLineStart 
= pdoc
->LineStart(line
); 
2258         int startseg 
= ll
->LineStart(subLine
); 
2259         int subLineStart 
= ll
->positions
[startseg
]; 
2262         if (subLine 
< ll
->lines
) { 
2263                 lineStart 
= ll
->LineStart(subLine
); 
2264                 lineEnd 
= ll
->LineStart(subLine 
+ 1); 
2267         bool drawWrapMarkEnd 
= false; 
2269         if (wrapVisualFlags 
& SC_WRAPVISUALFLAG_END
) { 
2270                 if (subLine 
+ 1 < ll
->lines
) { 
2271                         drawWrapMarkEnd 
= ll
->LineStart(subLine 
+ 1) != 0; 
2275         if (actualWrapVisualStartIndent 
!= 0) { 
2277                 bool continuedWrapLine 
= false; 
2278                 if (subLine 
< ll
->lines
) { 
2279                         continuedWrapLine 
= ll
->LineStart(subLine
) != 0; 
2282                 if (continuedWrapLine
) { 
2283                         // draw continuation rect 
2284                         PRectangle rcPlace 
= rcSegment
; 
2286                         rcPlace
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2287                         rcPlace
.right 
= rcPlace
.left 
+ actualWrapVisualStartIndent 
* vsDraw
.aveCharWidth
; 
2289                         // default bgnd here.. 
2290                         surface
->FillRectangle(rcSegment
, vsDraw
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2292                         // main line style would be below but this would be inconsistent with end markers 
2293                         // also would possibly not be the style at wrap point 
2294                         //int styleMain = ll->styles[lineStart]; 
2295                         //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back.allocated); 
2297                         if (wrapVisualFlags 
& SC_WRAPVISUALFLAG_START
) { 
2299                                 if (wrapVisualFlagsLocation 
& SC_WRAPVISUALFLAGLOC_START_BY_TEXT
) 
2300                                         rcPlace
.left 
= rcPlace
.right 
- vsDraw
.aveCharWidth
; 
2302                                         rcPlace
.right 
= rcPlace
.left 
+ vsDraw
.aveCharWidth
; 
2304                                 DrawWrapMarker(surface
, rcPlace
, false, vsDraw
.whitespaceForeground
.allocated
); 
2307                         xStart 
+= actualWrapVisualStartIndent 
* vsDraw
.aveCharWidth
; 
2313         // Background drawing loop 
2314         for (i 
= lineStart
; twoPhaseDraw 
&& (i 
< lineEnd
); i
++) { 
2316                 int iDoc 
= i 
+ posLineStart
; 
2317                 // If there is the end of a style run for any reason 
2318                 if ((ll
->styles
[i
] != ll
->styles
[i 
+ 1]) || 
2319                         i 
== (lineEnd 
- 1) || 
2320                         IsControlCharacter(ll
->chars
[i
]) || IsControlCharacter(ll
->chars
[i 
+ 1]) || 
2321                         ((ll
->selStart 
!= ll
->selEnd
) && ((iDoc 
+ 1 == ll
->selStart
) || (iDoc 
+ 1 == ll
->selEnd
))) || 
2322                         (i 
== (ll
->edgeColumn 
- 1))) { 
2323                         rcSegment
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2324                         rcSegment
.right 
= ll
->positions
[i 
+ 1] + xStart 
- subLineStart
; 
2325                         // Only try to draw if really visible - enhances performance by not calling environment to 
2326                         // draw strings that are completely past the right side of the window. 
2327                         if ((rcSegment
.left 
<= rcLine
.right
) && (rcSegment
.right 
>= rcLine
.left
)) { 
2328                                 int styleMain 
= ll
->styles
[i
]; 
2329                                 bool inSelection 
= (iDoc 
>= ll
->selStart
) && (iDoc 
< ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2330                                 bool inHotspot 
= (ll
->hsStart 
!= -1) && (iDoc 
>= ll
->hsStart
) && (iDoc 
< ll
->hsEnd
); 
2331                                 ColourAllocated textBack 
= TextBackground(vsDraw
, overrideBackground
, background
, inSelection
, inHotspot
, styleMain
, i
, ll
); 
2332                                 if (ll
->chars
[i
] == '\t') { 
2334                                         if (drawWhitespaceBackground 
&& 
2335                                                 (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) 
2336                                                 textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2337                                         surface
->FillRectangle(rcSegment
, textBack
); 
2338                                 } else if (IsControlCharacter(ll
->chars
[i
])) { 
2339                                         // Control character display 
2340                                         inIndentation 
= false; 
2341                                         surface
->FillRectangle(rcSegment
, textBack
); 
2343                                         // Normal text display 
2344                                         surface
->FillRectangle(rcSegment
, textBack
); 
2345                                         if (vsDraw
.viewWhitespace 
!= wsInvisible 
|| 
2346                                                 (inIndentation 
&& vsDraw
.viewIndentationGuides
)) { 
2347                                                 for (int cpos 
= 0; cpos 
<= i 
- startseg
; cpos
++) { 
2348                                                         if (ll
->chars
[cpos 
+ startseg
] == ' ') { 
2349                                                                 if (drawWhitespaceBackground 
&& 
2350                                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) { 
2351                                                                         PRectangle 
rcSpace(ll
->positions
[cpos 
+ startseg
] + xStart
, rcSegment
.top
, 
2352                                                                                            ll
->positions
[cpos 
+ startseg 
+ 1] + xStart
, rcSegment
.bottom
); 
2353                                                                         surface
->FillRectangle(rcSpace
, vsDraw
.whitespaceBackground
.allocated
); 
2356                                                                 inIndentation 
= false; 
2367                 DrawEOL(surface
, vsDraw
, rcLine
, ll
, line
, lineEnd
, 
2368                         xStart
, subLine
, subLineStart
, overrideBackground
, background
, 
2369                         drawWrapMarkEnd
, vsDraw
.whitespaceForeground
.allocated
); 
2372         inIndentation 
= subLine 
== 0;   // Do not handle indentation except on first subline. 
2373         startseg 
= ll
->LineStart(subLine
); 
2374         // Foreground drawing loop 
2375         for (i 
= lineStart
; i 
< lineEnd
; i
++) { 
2377                 int iDoc 
= i 
+ posLineStart
; 
2378                 // If there is the end of a style run for any reason 
2379                 if ((ll
->styles
[i
] != ll
->styles
[i 
+ 1]) || 
2380                         i 
== (lineEnd 
- 1) || 
2381                         IsControlCharacter(ll
->chars
[i
]) || IsControlCharacter(ll
->chars
[i 
+ 1]) || 
2382                         ((ll
->selStart 
!= ll
->selEnd
) && ((iDoc 
+ 1 == ll
->selStart
) || (iDoc 
+ 1 == ll
->selEnd
))) || 
2383                         (i 
== (ll
->edgeColumn 
- 1))) { 
2384                         rcSegment
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2385                         rcSegment
.right 
= ll
->positions
[i 
+ 1] + xStart 
- subLineStart
; 
2386                         // Only try to draw if really visible - enhances performance by not calling environment to 
2387                         // draw strings that are completely past the right side of the window. 
2388                         if ((rcSegment
.left 
<= rcLine
.right
) && (rcSegment
.right 
>= rcLine
.left
)) { 
2389                                 int styleMain 
= ll
->styles
[i
]; 
2390                                 ColourAllocated textFore 
= vsDraw
.styles
[styleMain
].fore
.allocated
; 
2391                                 Font 
&textFont 
= vsDraw
.styles
[styleMain
].font
; 
2392                                 //hotspot foreground 
2393                                 if (ll
->hsStart 
!= -1 && iDoc 
>= ll
->hsStart 
&& iDoc 
< hsEnd
) { 
2394                                         if (vsDraw
.hotspotForegroundSet
) 
2395                                                 textFore 
= vsDraw
.hotspotForeground
.allocated
; 
2397                                 bool inSelection 
= (iDoc 
>= ll
->selStart
) && (iDoc 
< ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2398                                 if (inSelection 
&& (vsDraw
.selforeset
)) { 
2399                                         textFore 
= vsDraw
.selforeground
.allocated
; 
2401                                 bool inHotspot 
= (ll
->hsStart 
!= -1) && (iDoc 
>= ll
->hsStart
) && (iDoc 
< ll
->hsEnd
); 
2402                                 ColourAllocated textBack 
= TextBackground(vsDraw
, overrideBackground
, background
, inSelection
, inHotspot
, styleMain
, i
, ll
); 
2403                                 if (ll
->chars
[i
] == '\t') { 
2405                                         if (!twoPhaseDraw
) { 
2406                                                 if (drawWhitespaceBackground 
&& 
2407                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) 
2408                                                         textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2409                                                 surface
->FillRectangle(rcSegment
, textBack
); 
2411                                         if ((vsDraw
.viewWhitespace 
!= wsInvisible
) || ((inIndentation 
&& vsDraw
.viewIndentationGuides
))) { 
2412                                                 if (vsDraw
.whitespaceForegroundSet
) 
2413                                                         textFore 
= vsDraw
.whitespaceForeground
.allocated
; 
2414                                                 surface
->PenColour(textFore
); 
2416                                         if (inIndentation 
&& vsDraw
.viewIndentationGuides
) { 
2417                                                 for (int xIG 
= ll
->positions
[i
] / indentWidth 
* indentWidth
; xIG 
< ll
->positions
[i 
+ 1]; xIG 
+= indentWidth
) { 
2418                                                         if (xIG 
>= ll
->positions
[i
] && xIG 
> 0) { 
2419                                                                 DrawIndentGuide(surface
, lineVisible
, vsDraw
.lineHeight
, xIG 
+ xStart
, rcSegment
, 
2420                                                                                 (ll
->xHighlightGuide 
== xIG
)); 
2424                                         if (vsDraw
.viewWhitespace 
!= wsInvisible
) { 
2425                                                 if (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
) { 
2426                                                         PRectangle 
rcTab(rcSegment
.left 
+ 1, rcSegment
.top 
+ 4, 
2427                                                                          rcSegment
.right 
- 1, rcSegment
.bottom 
- vsDraw
.maxDescent
); 
2428                                                         DrawTabArrow(surface
, rcTab
, rcSegment
.top 
+ vsDraw
.lineHeight 
/ 2); 
2431                                 } else if (IsControlCharacter(ll
->chars
[i
])) { 
2432                                         // Control character display 
2433                                         inIndentation 
= false; 
2434                                         if (controlCharSymbol 
< 32) { 
2435                                                 // Draw the character 
2436                                                 const char *ctrlChar 
= ControlCharacterString(ll
->chars
[i
]); 
2437                                                 if (!twoPhaseDraw
) { 
2438                                                         surface
->FillRectangle(rcSegment
, textBack
); 
2440                                                 int normalCharHeight 
= surface
->Ascent(ctrlCharsFont
) - 
2441                                                                        surface
->InternalLeading(ctrlCharsFont
); 
2442                                                 PRectangle rcCChar 
= rcSegment
; 
2443                                                 rcCChar
.left 
= rcCChar
.left 
+ 1; 
2444                                                 rcCChar
.top 
= rcSegment
.top 
+ vsDraw
.maxAscent 
- normalCharHeight
; 
2445                                                 rcCChar
.bottom 
= rcSegment
.top 
+ vsDraw
.maxAscent 
+ 1; 
2446                                                 PRectangle rcCentral 
= rcCChar
; 
2449                                                 surface
->FillRectangle(rcCentral
, textFore
); 
2450                                                 PRectangle rcChar 
= rcCChar
; 
2453                                                 surface
->DrawTextClipped(rcChar
, ctrlCharsFont
, 
2454                                                                          rcSegment
.top 
+ vsDraw
.maxAscent
, ctrlChar
, istrlen(ctrlChar
), 
2455                                                                          textBack
, textFore
); 
2457                                                 char cc
[2] = { static_cast<char>(controlCharSymbol
), '\0' }; 
2458                                                 surface
->DrawTextNoClip(rcSegment
, ctrlCharsFont
, 
2459                                                                         rcSegment
.top 
+ vsDraw
.maxAscent
, 
2460                                                                         cc
, 1, textBack
, textFore
); 
2463                                         // Normal text display 
2464                                         if (vsDraw
.styles
[styleMain
].visible
) { 
2466                                                         surface
->DrawTextTransparent(rcSegment
, textFont
, 
2467                                                                                      rcSegment
.top 
+ vsDraw
.maxAscent
, ll
->chars 
+ startseg
, 
2468                                                                                      i 
- startseg 
+ 1, textFore
); 
2470                                                         surface
->DrawTextNoClip(rcSegment
, textFont
, 
2471                                                                                 rcSegment
.top 
+ vsDraw
.maxAscent
, ll
->chars 
+ startseg
, 
2472                                                                                 i 
- startseg 
+ 1, textFore
, textBack
); 
2475                                         if (vsDraw
.viewWhitespace 
!= wsInvisible 
|| 
2476                                                 (inIndentation 
&& vsDraw
.viewIndentationGuides
)) { 
2477                                                 for (int cpos 
= 0; cpos 
<= i 
- startseg
; cpos
++) { 
2478                                                         if (ll
->chars
[cpos 
+ startseg
] == ' ') { 
2479                                                                 if (vsDraw
.viewWhitespace 
!= wsInvisible
) { 
2480                                                                         if (vsDraw
.whitespaceForegroundSet
) 
2481                                                                                 textFore 
= vsDraw
.whitespaceForeground
.allocated
; 
2482                                                                         if (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
) { 
2483                                                                                 int xmid 
= (ll
->positions
[cpos 
+ startseg
] + ll
->positions
[cpos 
+ startseg 
+ 1]) / 2; 
2484                                                                                 if (!twoPhaseDraw 
&& drawWhitespaceBackground 
&& 
2485                                                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) { 
2486                                                                                         textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2487                                                                                         PRectangle 
rcSpace(ll
->positions
[cpos 
+ startseg
] + xStart
, rcSegment
.top
, ll
->positions
[cpos 
+ startseg 
+ 1] + xStart
, rcSegment
.bottom
); 
2488                                                                                         surface
->FillRectangle(rcSpace
, textBack
); 
2490                                                                                 PRectangle 
rcDot(xmid 
+ xStart 
- subLineStart
, rcSegment
.top 
+ vsDraw
.lineHeight 
/ 2, 0, 0); 
2491                                                                                 rcDot
.right 
= rcDot
.left 
+ 1; 
2492                                                                                 rcDot
.bottom 
= rcDot
.top 
+ 1; 
2493                                                                                 surface
->FillRectangle(rcDot
, textFore
); 
2496                                                                 if (inIndentation 
&& vsDraw
.viewIndentationGuides
) { 
2497                                                                         int startSpace 
= ll
->positions
[cpos 
+ startseg
]; 
2498                                                                         if (startSpace 
> 0 && (startSpace 
% indentWidth 
== 0)) { 
2499                                                                                 DrawIndentGuide(surface
, lineVisible
, vsDraw
.lineHeight
, startSpace 
+ xStart
, rcSegment
, 
2500                                                                                                 (ll
->xHighlightGuide 
== ll
->positions
[cpos 
+ startseg
])); 
2504                                                                 inIndentation 
= false; 
2509                                 if (ll
->hsStart 
!= -1 && vsDraw
.hotspotUnderline 
&& iDoc 
>= ll
->hsStart 
&& iDoc 
< ll
->hsEnd 
) { 
2510                                         PRectangle rcUL 
= rcSegment
; 
2511                                         rcUL
.top 
= rcUL
.top 
+ vsDraw
.maxAscent 
+ 1; 
2512                                         rcUL
.bottom 
= rcUL
.top 
+ 1; 
2513                                         if (vsDraw
.hotspotForegroundSet
) 
2514                                                 surface
->FillRectangle(rcUL
, vsDraw
.hotspotForeground
.allocated
); 
2516                                                 surface
->FillRectangle(rcUL
, textFore
); 
2517                                 } else if (vsDraw
.styles
[styleMain
].underline
) { 
2518                                         PRectangle rcUL 
= rcSegment
; 
2519                                         rcUL
.top 
= rcUL
.top 
+ vsDraw
.maxAscent 
+ 1; 
2520                                         rcUL
.bottom 
= rcUL
.top 
+ 1; 
2521                                         surface
->FillRectangle(rcUL
, textFore
); 
2529         int indStart
[INDIC_MAX 
+ 1] = {0}; 
2530         for (int indica 
= 0; indica 
<= INDIC_MAX
; indica
++) 
2531                 indStart
[indica
] = 0; 
2533         for (int indicPos 
= lineStart
; indicPos 
<= lineEnd
; indicPos
++) { 
2534                 if ((indicPos 
== lineStart
) || (indicPos 
== lineEnd
) || 
2535                         (ll
->indicators
[indicPos
] != ll
->indicators
[indicPos 
+ 1])) { 
2536                         int mask 
= 1 << pdoc
->stylingBits
; 
2537                         for (int indicnum 
= 0; mask 
< 0x100; indicnum
++) { 
2538                                 if ((indicPos 
== lineStart
) || (indicPos 
== lineEnd
)) { 
2539                                         indStart
[indicnum
] = ll
->positions
[indicPos
]; 
2540                                 } else if ((ll
->indicators
[indicPos 
+ 1] & mask
) && !(ll
->indicators
[indicPos
] & mask
)) { 
2541                                         indStart
[indicnum
] = ll
->positions
[indicPos 
+ 1]; 
2543                                 if ((ll
->indicators
[indicPos
] & mask
) && 
2544                                         ((indicPos 
== lineEnd
) || !(ll
->indicators
[indicPos 
+ 1] & mask
))) { 
2545                                         int endIndicator 
= indicPos
; 
2546                                         if (endIndicator 
>= lineEnd
) 
2547                                                 endIndicator 
= lineEnd
-1; 
2549                                                 indStart
[indicnum
] + xStart 
- subLineStart
, 
2550                                                 rcLine
.top 
+ vsDraw
.maxAscent
, 
2551                                                 ll
->positions
[endIndicator 
+ 1] + xStart 
- subLineStart
, 
2552                                                 rcLine
.top 
+ vsDraw
.maxAscent 
+ 3); 
2553                                         vsDraw
.indicators
[indicnum
].Draw(surface
, rcIndic
, rcLine
); 
2559         // End of the drawing of the current line 
2560         if (!twoPhaseDraw
) { 
2561                 DrawEOL(surface
, vsDraw
, rcLine
, ll
, line
, lineEnd
, 
2562                         xStart
, subLine
, subLineStart
, overrideBackground
, background
, 
2563                         drawWrapMarkEnd
, vsDraw
.whitespaceForeground
.allocated
); 
2566         if (vsDraw
.edgeState 
== EDGE_LINE
) { 
2567                 int edgeX 
= theEdge 
* vsDraw
.spaceWidth
; 
2568                 rcSegment
.left 
= edgeX 
+ xStart
; 
2569                 rcSegment
.right 
= rcSegment
.left 
+ 1; 
2570                 surface
->FillRectangle(rcSegment
, vsDraw
.edgecolour
.allocated
); 
2574 void Editor::RefreshPixMaps(Surface 
*surfaceWindow
) { 
2575         if (!pixmapSelPattern
->Initialised()) { 
2576                 const int patternSize 
= 8; 
2577                 pixmapSelPattern
->InitPixMap(patternSize
, patternSize
, surfaceWindow
, wMain
.GetID()); 
2578                 // This complex procedure is to reproduce the checkerboard dithered pattern used by windows 
2579                 // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half 
2580                 // way between the chrome colour and the chrome highlight colour making a nice transition 
2581                 // between the window chrome and the content area. And it works in low colour depths. 
2582                 PRectangle 
rcPattern(0, 0, patternSize
, patternSize
); 
2584                 // Initialize default colours based on the chrome colour scheme.  Typically the highlight is white. 
2585                 ColourAllocated colourFMFill 
= vs
.selbar
.allocated
; 
2586                 ColourAllocated colourFMStripes 
= vs
.selbarlight
.allocated
; 
2588                 if (!(vs
.selbarlight
.desired 
== ColourDesired(0xff, 0xff, 0xff))) { 
2589                         // User has chosen an unusual chrome colour scheme so just use the highlight edge colour. 
2590                         // (Typically, the highlight colour is white.) 
2591                         colourFMFill 
= vs
.selbarlight
.allocated
; 
2594                 if (vs
.foldmarginColourSet
) { 
2595                         // override default fold margin colour 
2596                         colourFMFill 
= vs
.foldmarginColour
.allocated
; 
2598                 if (vs
.foldmarginHighlightColourSet
) { 
2599                         // override default fold margin highlight colour 
2600                         colourFMStripes 
= vs
.foldmarginHighlightColour
.allocated
; 
2603                 pixmapSelPattern
->FillRectangle(rcPattern
, colourFMFill
); 
2604                 pixmapSelPattern
->PenColour(colourFMStripes
); 
2605                 for (int stripe 
= 0; stripe 
< patternSize
; stripe
++) { 
2606                         // Alternating 1 pixel stripes is same as checkerboard. 
2607                         pixmapSelPattern
->MoveTo(0, stripe 
* 2); 
2608                         pixmapSelPattern
->LineTo(patternSize
, stripe 
* 2 - patternSize
); 
2612         if (!pixmapIndentGuide
->Initialised()) { 
2613                 // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line 
2614                 pixmapIndentGuide
->InitPixMap(1, vs
.lineHeight 
+ 1, surfaceWindow
, wMain
.GetID()); 
2615                 pixmapIndentGuideHighlight
->InitPixMap(1, vs
.lineHeight 
+ 1, surfaceWindow
, wMain
.GetID()); 
2616                 PRectangle 
rcIG(0, 0, 1, vs
.lineHeight
); 
2617                 pixmapIndentGuide
->FillRectangle(rcIG
, vs
.styles
[STYLE_INDENTGUIDE
].back
.allocated
); 
2618                 pixmapIndentGuide
->PenColour(vs
.styles
[STYLE_INDENTGUIDE
].fore
.allocated
); 
2619                 pixmapIndentGuideHighlight
->FillRectangle(rcIG
, vs
.styles
[STYLE_BRACELIGHT
].back
.allocated
); 
2620                 pixmapIndentGuideHighlight
->PenColour(vs
.styles
[STYLE_BRACELIGHT
].fore
.allocated
); 
2621                 for (int stripe 
= 1; stripe 
< vs
.lineHeight 
+ 1; stripe 
+= 2) { 
2622                         pixmapIndentGuide
->MoveTo(0, stripe
); 
2623                         pixmapIndentGuide
->LineTo(2, stripe
); 
2624                         pixmapIndentGuideHighlight
->MoveTo(0, stripe
); 
2625                         pixmapIndentGuideHighlight
->LineTo(2, stripe
); 
2630                 if (!pixmapLine
->Initialised()) { 
2631                         PRectangle rcClient 
= GetClientRectangle(); 
2632                         pixmapLine
->InitPixMap(rcClient
.Width(), rcClient
.Height(), 
2633                                                surfaceWindow
, wMain
.GetID()); 
2634                         pixmapSelMargin
->InitPixMap(vs
.fixedColumnWidth
, 
2635                                                     rcClient
.Height(), surfaceWindow
, wMain
.GetID()); 
2640 void Editor::Paint(Surface 
*surfaceWindow
, PRectangle rcArea
) { 
2641         //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n", 
2642         //      paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); 
2646         RefreshPixMaps(surfaceWindow
); 
2648         PRectangle rcClient 
= GetClientRectangle(); 
2649         //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n", 
2650         //      rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); 
2652         surfaceWindow
->SetPalette(&palette
, true); 
2653         pixmapLine
->SetPalette(&palette
, !hasFocus
); 
2655         int screenLinePaintFirst 
= rcArea
.top 
/ vs
.lineHeight
; 
2656         // The area to be painted plus one extra line is styled. 
2657         // The extra line is to determine when a style change, such as starting a comment flows on to other lines. 
2658         int lineStyleLast 
= topLine 
+ (rcArea
.bottom 
- 1) / vs
.lineHeight 
+ 1; 
2659         //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast); 
2660         int endPosPaint 
= pdoc
->Length(); 
2661         if (lineStyleLast 
< cs
.LinesDisplayed()) 
2662                 endPosPaint 
= pdoc
->LineStart(cs
.DocFromDisplay(lineStyleLast 
+ 1)); 
2664         int xStart 
= vs
.fixedColumnWidth 
- xOffset
; 
2667                 ypos 
+= screenLinePaintFirst 
* vs
.lineHeight
; 
2668         int yposScreen 
= screenLinePaintFirst 
* vs
.lineHeight
; 
2670         // Ensure we are styled as far as we are painting. 
2671         pdoc
->EnsureStyledTo(endPosPaint
); 
2672         bool paintAbandonedByStyling 
= paintState 
== paintAbandoned
; 
2675                 needUpdateUI 
= false; 
2678         // Call priority lines wrap on a window of lines which are likely 
2679         // to rendered with the following paint (that is wrap the visible 
2681         int startLineToWrap 
= cs
.DocFromDisplay(topLine
) - 5; 
2682         if (startLineToWrap 
< 0) 
2683                 startLineToWrap 
= -1; 
2684         if (WrapLines(false, startLineToWrap
)) { 
2685                 // The wrapping process has changed the height of some lines so 
2686                 // abandon this paint for a complete repaint. 
2687                 if (AbandonPaint()) { 
2690                 RefreshPixMaps(surfaceWindow
);  // In case pixmaps invalidated by scrollbar change 
2692         PLATFORM_ASSERT(pixmapSelPattern
->Initialised()); 
2694         PaintSelMargin(surfaceWindow
, rcArea
); 
2696         PRectangle rcRightMargin 
= rcClient
; 
2697         rcRightMargin
.left 
= rcRightMargin
.right 
- vs
.rightMarginWidth
; 
2698         if (rcArea
.Intersects(rcRightMargin
)) { 
2699                 surfaceWindow
->FillRectangle(rcRightMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2702         if (paintState 
== paintAbandoned
) { 
2703                 // Either styling or NotifyUpdateUI noticed that painting is needed 
2704                 // outside the current painting rectangle 
2705                 //Platform::DebugPrintf("Abandoning paint\n"); 
2706                 if (wrapState 
!= eWrapNone
) { 
2707                         if (paintAbandonedByStyling
) { 
2708                                 // Styling has spilled over a line end, such as occurs by starting a multiline 
2709                                 // comment. The width of subsequent text may have changed, so rewrap. 
2710                                 NeedWrapping(cs
.DocFromDisplay(topLine
)); 
2715         //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); 
2718         if (rcArea
.right 
> vs
.fixedColumnWidth
) { 
2720                 Surface 
*surface 
= surfaceWindow
; 
2722                         surface 
= pixmapLine
; 
2723                         PLATFORM_ASSERT(pixmapLine
->Initialised()); 
2725                 surface
->SetUnicodeMode(IsUnicodeMode()); 
2726                 surface
->SetDBCSMode(CodePage()); 
2728                 int visibleLine 
= topLine 
+ screenLinePaintFirst
; 
2730                 int posCaret 
= currentPos
; 
2733                 int lineCaret 
= pdoc
->LineFromPosition(posCaret
); 
2735                 // Remove selection margin from drawing area so text will not be drawn 
2736                 // on it in unbuffered mode. 
2737                 PRectangle rcTextArea 
= rcClient
; 
2738                 rcTextArea
.left 
= vs
.fixedColumnWidth
; 
2739                 rcTextArea
.right 
-= vs
.rightMarginWidth
; 
2740                 surfaceWindow
->SetClip(rcTextArea
); 
2742                 // Loop on visible lines 
2743                 //double durLayout = 0.0; 
2744                 //double durPaint = 0.0; 
2745                 //double durCopy = 0.0; 
2746                 //ElapsedTime etWhole; 
2747                 int lineDocPrevious 
= -1;       // Used to avoid laying out one document line multiple times 
2748                 AutoLineLayout 
ll(llc
, 0); 
2749                 SelectionLineIterator 
lineIterator(this); 
2750                 while (visibleLine 
< cs
.LinesDisplayed() && yposScreen 
< rcArea
.bottom
) { 
2752                         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
2753                         // Only visible lines should be handled by the code within the loop 
2754                         PLATFORM_ASSERT(cs
.GetVisible(lineDoc
)); 
2755                         int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
2756                         int subLine 
= visibleLine 
- lineStartSet
; 
2758                         // Copy this line and its styles from the document into local arrays 
2759                         // and determine the x position at which each character starts. 
2761                         if (lineDoc 
!= lineDocPrevious
) { 
2763                                 ll
.Set(RetrieveLineLayout(lineDoc
)); 
2764                                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
2765                                 lineDocPrevious 
= lineDoc
; 
2767                         //durLayout += et.Duration(true); 
2770                                 if (selType 
== selStream
) { 
2771                                         ll
->selStart 
= SelectionStart(); 
2772                                         ll
->selEnd 
= SelectionEnd(); 
2774                                         lineIterator
.SetAt(lineDoc
); 
2775                                         ll
->selStart 
= lineIterator
.startPos
; 
2776                                         ll
->selEnd 
= lineIterator
.endPos
; 
2778                                 ll
->containsCaret 
= lineDoc 
== lineCaret
; 
2779                                 if (hideSelection
) { 
2782                                         ll
->containsCaret 
= false; 
2785                                 GetHotSpotRange(ll
->hsStart
, ll
->hsEnd
); 
2787                                 PRectangle rcLine 
= rcClient
; 
2789                                 rcLine
.bottom 
= ypos 
+ vs
.lineHeight
; 
2791                                 Range 
rangeLine(pdoc
->LineStart(lineDoc
), pdoc
->LineStart(lineDoc 
+ 1)); 
2792                                 // Highlight the current braces if any 
2793                                 ll
->SetBracesHighlight(rangeLine
, braces
, static_cast<char>(bracesMatchStyle
), 
2794                                                        highlightGuideColumn 
* vs
.spaceWidth
); 
2797                                 DrawLine(surface
, vs
, lineDoc
, visibleLine
, xStart
, rcLine
, ll
, subLine
); 
2798                                 //durPaint += et.Duration(true); 
2800                                 // Restore the previous styles for the brace highlights in case layout is in cache. 
2801                                 ll
->RestoreBracesHighlight(rangeLine
, braces
); 
2803                                 bool expanded 
= cs
.GetExpanded(lineDoc
); 
2804                                 if ((foldFlags 
& SC_FOLDFLAG_BOX
) == 0) { 
2805                                         // Paint the line above the fold 
2806                                         if ((expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEBEFORE_EXPANDED
)) 
2808                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEBEFORE_CONTRACTED
))) { 
2809                                                 if (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELHEADERFLAG
) { 
2810                                                         PRectangle rcFoldLine 
= rcLine
; 
2811                                                         rcFoldLine
.bottom 
= rcFoldLine
.top 
+ 1; 
2812                                                         surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2815                                         // Paint the line below the fold 
2816                                         if ((expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_EXPANDED
)) 
2818                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_CONTRACTED
))) { 
2819                                                 if (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELHEADERFLAG
) { 
2820                                                         PRectangle rcFoldLine 
= rcLine
; 
2821                                                         rcFoldLine
.top 
= rcFoldLine
.bottom 
- 1; 
2822                                                         surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2826                                         int FoldLevelCurr 
= (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELNUMBERMASK
) - SC_FOLDLEVELBASE
; 
2827                                         int FoldLevelPrev 
= (pdoc
->GetLevel(lineDoc 
- 1) & SC_FOLDLEVELNUMBERMASK
) - SC_FOLDLEVELBASE
; 
2828                                         int FoldLevelFlags 
= (pdoc
->GetLevel(lineDoc
) & ~SC_FOLDLEVELNUMBERMASK
) & ~(0xFFF0000); 
2829                                         int indentationStep 
= pdoc
->IndentSize(); 
2830                                         // Draw line above fold 
2831                                         if ((FoldLevelPrev 
< FoldLevelCurr
) 
2833                                                 (FoldLevelFlags 
& SC_FOLDLEVELBOXHEADERFLAG
 
2835                                                  (pdoc
->GetLevel(lineDoc 
- 1) & SC_FOLDLEVELBOXFOOTERFLAG
) == 0)) { 
2836                                                 PRectangle rcFoldLine 
= rcLine
; 
2837                                                 rcFoldLine
.bottom 
= rcFoldLine
.top 
+ 1; 
2838                                                 rcFoldLine
.left 
+= xStart 
+ FoldLevelCurr 
* vs
.spaceWidth 
* indentationStep 
- 1; 
2839                                                 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2842                                         // Line below the fold (or below a contracted fold) 
2843                                         if (FoldLevelFlags 
& SC_FOLDLEVELBOXFOOTERFLAG
 
2845                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_CONTRACTED
))) { 
2846                                                 PRectangle rcFoldLine 
= rcLine
; 
2847                                                 rcFoldLine
.top 
= rcFoldLine
.bottom 
- 1; 
2848                                                 rcFoldLine
.left 
+= xStart 
+ (FoldLevelCurr
) * vs
.spaceWidth 
* indentationStep 
- 1; 
2849                                                 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2852                                         PRectangle rcBoxLine 
= rcLine
; 
2853                                         // Draw vertical line for every fold level 
2854                                         for (int i 
= 0; i 
<= FoldLevelCurr
; i
++) { 
2855                                                 rcBoxLine
.left 
= xStart 
+ i 
* vs
.spaceWidth 
* indentationStep 
- 1; 
2856                                                 rcBoxLine
.right 
= rcBoxLine
.left 
+ 1; 
2857                                                 surface
->FillRectangle(rcBoxLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2862                                 if (lineDoc 
== lineCaret
) { 
2863                                         int offset 
= Platform::Minimum(posCaret 
- rangeLine
.start
, ll
->maxLineLength
); 
2864                                         if ((offset 
>= ll
->LineStart(subLine
)) && 
2865                                                 ((offset 
< ll
->LineStart(subLine 
+ 1)) || offset 
== ll
->numCharsInLine
)) { 
2866                                                 int xposCaret 
= ll
->positions
[offset
] - ll
->positions
[ll
->LineStart(subLine
)] + xStart
; 
2868                                                 if (actualWrapVisualStartIndent 
!= 0) { 
2869                                                         int lineStart 
= ll
->LineStart(subLine
); 
2870                                                         if (lineStart 
!= 0)     // Wrapped 
2871                                                                 xposCaret 
+= actualWrapVisualStartIndent 
* vs
.aveCharWidth
; 
2873                                                 int widthOverstrikeCaret
; 
2874                                                 if (posCaret 
== pdoc
->Length()) {   // At end of document 
2875                                                         widthOverstrikeCaret 
= vs
.aveCharWidth
; 
2876                                                 } else if ((posCaret 
- rangeLine
.start
) >= ll
->numCharsInLine
) {        // At end of line 
2877                                                         widthOverstrikeCaret 
= vs
.aveCharWidth
; 
2879                                                         widthOverstrikeCaret 
= ll
->positions
[offset 
+ 1] - ll
->positions
[offset
]; 
2881                                                 if (widthOverstrikeCaret 
< 3)   // Make sure its visible 
2882                                                         widthOverstrikeCaret 
= 3; 
2883                                                 if (((caret
.active 
&& caret
.on
) || (posDrag 
>= 0)) && xposCaret 
>= 0) { 
2884                                                         PRectangle rcCaret 
= rcLine
; 
2885                                                         int caretWidthOffset 
= 0; 
2886                                                         if ((offset 
> 0) && (vs
.caretWidth 
> 1)) 
2887                                                                 caretWidthOffset 
= 1;   // Move back so overlaps both character cells. 
2889                                                                 rcCaret
.left 
= xposCaret 
- caretWidthOffset
; 
2890                                                                 rcCaret
.right 
= rcCaret
.left 
+ vs
.caretWidth
; 
2893                                                                         rcCaret
.top 
= rcCaret
.bottom 
- 2; 
2894                                                                         rcCaret
.left 
= xposCaret 
+ 1; 
2895                                                                         rcCaret
.right 
= rcCaret
.left 
+ widthOverstrikeCaret 
- 1; 
2897                                                                         rcCaret
.left 
= xposCaret 
- caretWidthOffset
; 
2898                                                                         rcCaret
.right 
= rcCaret
.left 
+ vs
.caretWidth
; 
2901                                                         surface
->FillRectangle(rcCaret
, vs
.caretcolour
.allocated
); 
2907                                         Point 
from(vs
.fixedColumnWidth
, 0); 
2908                                         PRectangle 
rcCopyArea(vs
.fixedColumnWidth
, yposScreen
, 
2909                                                               rcClient
.right
, yposScreen 
+ vs
.lineHeight
); 
2910                                         surfaceWindow
->Copy(rcCopyArea
, from
, *pixmapLine
); 
2912                                 //durCopy += et.Duration(true); 
2915                         if (!bufferedDraw
) { 
2916                                 ypos 
+= vs
.lineHeight
; 
2919                         yposScreen 
+= vs
.lineHeight
; 
2923                 //if (durPaint < 0.00000001) 
2924                 //      durPaint = 0.00000001; 
2926                 // Right column limit indicator 
2927                 PRectangle rcBeyondEOF 
= rcClient
; 
2928                 rcBeyondEOF
.left 
= vs
.fixedColumnWidth
; 
2929                 rcBeyondEOF
.right 
= rcBeyondEOF
.right
; 
2930                 rcBeyondEOF
.top 
= (cs
.LinesDisplayed() - topLine
) * vs
.lineHeight
; 
2931                 if (rcBeyondEOF
.top 
< rcBeyondEOF
.bottom
) { 
2932                         surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2933                         if (vs
.edgeState 
== EDGE_LINE
) { 
2934                                 int edgeX 
= theEdge 
* vs
.spaceWidth
; 
2935                                 rcBeyondEOF
.left 
= edgeX 
+ xStart
; 
2936                                 rcBeyondEOF
.right 
= rcBeyondEOF
.left 
+ 1; 
2937                                 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.edgecolour
.allocated
); 
2940                 //Platform::DebugPrintf( 
2941                 //"Layout:%9.6g    Paint:%9.6g    Ratio:%9.6g   Copy:%9.6g   Total:%9.6g\n", 
2942                 //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); 
2947 // Space (3 space characters) between line numbers and text when printing. 
2948 #define lineNumberPrintSpace "   " 
2950 ColourDesired 
InvertedLight(ColourDesired orig
) { 
2951         unsigned int r 
= orig
.GetRed(); 
2952         unsigned int g 
= orig
.GetGreen(); 
2953         unsigned int b 
= orig
.GetBlue(); 
2954         unsigned int l 
= (r 
+ g 
+ b
) / 3;       // There is a better calculation for this that matches human eye 
2955         unsigned int il 
= 0xff - l
; 
2957                 return ColourDesired(0xff, 0xff, 0xff); 
2961         return ColourDesired(Platform::Minimum(r
, 0xff), Platform::Minimum(g
, 0xff), Platform::Minimum(b
, 0xff)); 
2964 // This is mostly copied from the Paint method but with some things omitted 
2965 // such as the margin markers, line numbers, selection and caret 
2966 // Should be merged back into a combined Draw method. 
2967 long Editor::FormatRange(bool draw
, RangeToFormat 
*pfr
) { 
2971         AutoSurface 
surface(pfr
->hdc
, this); 
2974         AutoSurface 
surfaceMeasure(pfr
->hdcTarget
, this); 
2975         if (!surfaceMeasure
) { 
2979         ViewStyle 
vsPrint(vs
); 
2981         // Modify the view style for printing as do not normally want any of the transient features to be printed 
2982         // Printing supports only the line number margin. 
2983         int lineNumberIndex 
= -1; 
2984         for (int margin 
= 0; margin 
< ViewStyle::margins
; margin
++) { 
2985                 if ((!vsPrint
.ms
[margin
].symbol
) && (vsPrint
.ms
[margin
].width 
> 0)) { 
2986                         lineNumberIndex 
= margin
; 
2988                         vsPrint
.ms
[margin
].width 
= 0; 
2991         vsPrint
.showMarkedLines 
= false; 
2992         vsPrint
.fixedColumnWidth 
= 0; 
2993         vsPrint
.zoomLevel 
= printMagnification
; 
2994         vsPrint
.viewIndentationGuides 
= false; 
2995         // Don't show the selection when printing 
2996         vsPrint
.selbackset 
= false; 
2997         vsPrint
.selforeset 
= false; 
2998         vsPrint
.whitespaceBackgroundSet 
= false; 
2999         vsPrint
.whitespaceForegroundSet 
= false; 
3000         vsPrint
.showCaretLineBackground 
= false; 
3002         // Set colours for printing according to users settings 
3003         for (int sty 
= 0;sty 
<= STYLE_MAX
;sty
++) { 
3004                 if (printColourMode 
== SC_PRINT_INVERTLIGHT
) { 
3005                         vsPrint
.styles
[sty
].fore
.desired 
= InvertedLight(vsPrint
.styles
[sty
].fore
.desired
); 
3006                         vsPrint
.styles
[sty
].back
.desired 
= InvertedLight(vsPrint
.styles
[sty
].back
.desired
); 
3007                 } else if (printColourMode 
== SC_PRINT_BLACKONWHITE
) { 
3008                         vsPrint
.styles
[sty
].fore
.desired 
= ColourDesired(0, 0, 0); 
3009                         vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
3010                 } else if (printColourMode 
== SC_PRINT_COLOURONWHITE
) { 
3011                         vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
3012                 } else if (printColourMode 
== SC_PRINT_COLOURONWHITEDEFAULTBG
) { 
3013                         if (sty 
<= STYLE_DEFAULT
) { 
3014                                 vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
3018         // White background for the line numbers 
3019         vsPrint
.styles
[STYLE_LINENUMBER
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
3021         vsPrint
.Refresh(*surfaceMeasure
); 
3022         // Ensure colours are set up 
3023         vsPrint
.RefreshColourPalette(palette
, true); 
3024         vsPrint
.RefreshColourPalette(palette
, false); 
3025         // Determining width must hapen after fonts have been realised in Refresh 
3026         int lineNumberWidth 
= 0; 
3027         if (lineNumberIndex 
>= 0) { 
3028                 lineNumberWidth 
= surfaceMeasure
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
, 
3029                                   "99999" lineNumberPrintSpace
, 5 + istrlen(lineNumberPrintSpace
)); 
3030                 vsPrint
.ms
[lineNumberIndex
].width 
= lineNumberWidth
; 
3033         int linePrintStart 
= pdoc
->LineFromPosition(pfr
->chrg
.cpMin
); 
3034         int linePrintLast 
= linePrintStart 
+ (pfr
->rc
.bottom 
- pfr
->rc
.top
) / vsPrint
.lineHeight 
- 1; 
3035         if (linePrintLast 
< linePrintStart
) 
3036                 linePrintLast 
= linePrintStart
; 
3037         int linePrintMax 
= pdoc
->LineFromPosition(pfr
->chrg
.cpMax
); 
3038         if (linePrintLast 
> linePrintMax
) 
3039                 linePrintLast 
= linePrintMax
; 
3040         //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", 
3041         //      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight, 
3042         //      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font)); 
3043         int endPosPrint 
= pdoc
->Length(); 
3044         if (linePrintLast 
< pdoc
->LinesTotal()) 
3045                 endPosPrint 
= pdoc
->LineStart(linePrintLast 
+ 1); 
3047         // Ensure we are styled to where we are formatting. 
3048         pdoc
->EnsureStyledTo(endPosPrint
); 
3050         int xStart 
= vsPrint
.fixedColumnWidth 
+ pfr
->rc
.left 
+ lineNumberWidth
; 
3051         int ypos 
= pfr
->rc
.top
; 
3053         int lineDoc 
= linePrintStart
; 
3055         int nPrintPos 
= pfr
->chrg
.cpMin
; 
3056         int visibleLine 
= 0; 
3057         int widthPrint 
= pfr
->rc
.Width() - lineNumberWidth
; 
3058         if (printWrapState 
== eWrapNone
) 
3059                 widthPrint 
= LineLayout::wrapWidthInfinite
; 
3061         while (lineDoc 
<= linePrintLast 
&& ypos 
< pfr
->rc
.bottom
) { 
3063                 // When printing, the hdc and hdcTarget may be the same, so 
3064                 // changing the state of surfaceMeasure may change the underlying 
3065                 // state of surface. Therefore, any cached state is discarded before 
3066                 // using each surface. 
3067                 surfaceMeasure
->FlushCachedState(); 
3069                 // Copy this line and its styles from the document into local arrays 
3070                 // and determine the x position at which each character starts. 
3071                 LineLayout 
ll(8000); 
3072                 LayoutLine(lineDoc
, surfaceMeasure
, vsPrint
, &ll
, widthPrint
); 
3076                 ll
.containsCaret 
= false; 
3079                 rcLine
.left 
= pfr
->rc
.left 
+ lineNumberWidth
; 
3081                 rcLine
.right 
= pfr
->rc
.right 
- 1; 
3082                 rcLine
.bottom 
= ypos 
+ vsPrint
.lineHeight
; 
3084                 // When document line is wrapped over multiple display lines, find where 
3085                 // to start printing from to ensure a particular position is on the first 
3086                 // line of the page. 
3087                 if (visibleLine 
== 0) { 
3088                         int startWithinLine 
= nPrintPos 
- pdoc
->LineStart(lineDoc
); 
3089                         for (int iwl 
= 0; iwl 
< ll
.lines 
- 1; iwl
++) { 
3090                                 if (ll
.LineStart(iwl
) <= startWithinLine 
&& ll
.LineStart(iwl 
+ 1) >= startWithinLine
) { 
3095                         if (ll
.lines 
> 1 && startWithinLine 
>= ll
.LineStart(ll
.lines 
- 1)) { 
3096                                 visibleLine 
= -(ll
.lines 
- 1); 
3100                 if (draw 
&& lineNumberWidth 
&& 
3101                         (ypos 
+ vsPrint
.lineHeight 
<= pfr
->rc
.bottom
) && 
3102                         (visibleLine 
>= 0)) { 
3104                         sprintf(number
, "%d" lineNumberPrintSpace
, lineDoc 
+ 1); 
3105                         PRectangle rcNumber 
= rcLine
; 
3106                         rcNumber
.right 
= rcNumber
.left 
+ lineNumberWidth
; 
3108                         rcNumber
.left 
-= surfaceMeasure
->WidthText( 
3109                                              vsPrint
.styles
[STYLE_LINENUMBER
].font
, number
, istrlen(number
)); 
3110                         surface
->FlushCachedState(); 
3111                         surface
->DrawTextNoClip(rcNumber
, vsPrint
.styles
[STYLE_LINENUMBER
].font
, 
3112                                                 ypos 
+ vsPrint
.maxAscent
, number
, istrlen(number
), 
3113                                                 vsPrint
.styles
[STYLE_LINENUMBER
].fore
.allocated
, 
3114                                                 vsPrint
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
3118                 surface
->FlushCachedState(); 
3120                 for (int iwl 
= 0; iwl 
< ll
.lines
; iwl
++) { 
3121                         if (ypos 
+ vsPrint
.lineHeight 
<= pfr
->rc
.bottom
) { 
3122                                 if (visibleLine 
>= 0) { 
3125                                                 rcLine
.bottom 
= ypos 
+ vsPrint
.lineHeight
; 
3126                                                 DrawLine(surface
, vsPrint
, lineDoc
, visibleLine
, xStart
, rcLine
, &ll
, iwl
); 
3128                                         ypos 
+= vsPrint
.lineHeight
; 
3131                                 if (iwl 
== ll
.lines 
- 1) 
3132                                         nPrintPos 
= pdoc
->LineStart(lineDoc 
+ 1); 
3134                                         nPrintPos 
+= ll
.LineStart(iwl 
+ 1) - ll
.LineStart(iwl
); 
3144 int Editor::TextWidth(int style
, const char *text
) { 
3146         AutoSurface 
surface(this); 
3148                 return surface
->WidthText(vs
.styles
[style
].font
, text
, istrlen(text
)); 
3154 // Empty method is overridden on GTK+ to show / hide scrollbars 
3155 void Editor::ReconfigureScrollBars() {} 
3157 void Editor::SetScrollBars() { 
3160         int nMax 
= MaxScrollPos(); 
3161         int nPage 
= LinesOnScreen(); 
3162         bool modified 
= ModifyScrollBars(nMax 
+ nPage 
- 1, nPage
); 
3164         // TODO: ensure always showing as many lines as possible 
3165         // May not be, if, for example, window made larger 
3166         if (topLine 
> MaxScrollPos()) { 
3167                 SetTopLine(Platform::Clamp(topLine
, 0, MaxScrollPos())); 
3168                 SetVerticalScrollPos(); 
3172                 if (!AbandonPaint()) 
3175         //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage); 
3178 void Editor::ChangeSize() { 
3181         if (wrapState 
!= eWrapNone
) { 
3182                 PRectangle rcTextArea 
= GetClientRectangle(); 
3183                 rcTextArea
.left 
= vs
.fixedColumnWidth
; 
3184                 rcTextArea
.right 
-= vs
.rightMarginWidth
; 
3185                 if (wrapWidth 
!= rcTextArea
.Width()) { 
3192 void Editor::AddChar(char ch
) { 
3199 void Editor::AddCharUTF(char *s
, unsigned int len
, bool treatAsDBCS
) { 
3200         bool wasSelection 
= currentPos 
!= anchor
; 
3202         if (inOverstrike 
&& !wasSelection 
&& !RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3203                 if (currentPos 
< (pdoc
->Length())) { 
3204                         if (!IsEOLChar(pdoc
->CharAt(currentPos
))) { 
3205                                 pdoc
->DelChar(currentPos
); 
3209         if (pdoc
->InsertString(currentPos
, s
, len
)) { 
3210                 SetEmptySelection(currentPos 
+ len
); 
3212         EnsureCaretVisible(); 
3213         // Avoid blinking during rapid typing: 
3214         ShowCaretAtCurrentPosition(); 
3218                 NotifyChar((static_cast<unsigned char>(s
[0]) << 8) | 
3219                            static_cast<unsigned char>(s
[1])); 
3221                 int byte 
= static_cast<unsigned char>(s
[0]); 
3222                 if ((byte 
< 0xC0) || (1 == len
)) { 
3223                         // Handles UTF-8 characters between 0x01 and 0x7F and single byte 
3224                         // characters when not in UTF-8 mode. 
3225                         // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid 
3226                         // characters representing themselves. 
3228                         // Unroll 1 to 3 byte UTF-8 sequences.  See reference data at: 
3229                         // http://www.cl.cam.ac.uk/~mgk25/unicode.html 
3230                         // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 
3232                                 int byte2 
= static_cast<unsigned char>(s
[1]); 
3233                                 if ((byte2 
& 0xC0) == 0x80) { 
3234                                         // Two-byte-character lead-byte followed by a trail-byte. 
3235                                         byte 
= (((byte 
& 0x1F) << 6) | (byte2 
& 0x3F)); 
3237                                 // A two-byte-character lead-byte not followed by trail-byte 
3238                                 // represents itself. 
3239                         } else if (byte 
< 0xF0) { 
3240                                 int byte2 
= static_cast<unsigned char>(s
[1]); 
3241                                 int byte3 
= static_cast<unsigned char>(s
[2]); 
3242                                 if (((byte2 
& 0xC0) == 0x80) && ((byte3 
& 0xC0) == 0x80)) { 
3243                                         // Three-byte-character lead byte followed by two trail bytes. 
3244                                         byte 
= (((byte 
& 0x0F) << 12) | ((byte2 
& 0x3F) << 6) | 
3247                                 // A three-byte-character lead-byte not followed by two trail-bytes 
3248                                 // represents itself. 
3255 void Editor::ClearSelection() { 
3256         if (!SelectionContainsProtected()) { 
3257                 int startPos 
= SelectionStart(); 
3258                 if (selType 
== selStream
) { 
3259                         unsigned int chars 
= SelectionEnd() - startPos
; 
3261                                 pdoc
->BeginUndoAction(); 
3262                                 pdoc
->DeleteChars(startPos
, chars
); 
3263                                 pdoc
->EndUndoAction(); 
3266                         pdoc
->BeginUndoAction(); 
3267                         SelectionLineIterator 
lineIterator(this, false); 
3268                         while (lineIterator
.Iterate()) { 
3269                                 startPos 
= lineIterator
.startPos
; 
3270                                 unsigned int chars 
= lineIterator
.endPos 
- startPos
; 
3272                                         pdoc
->DeleteChars(startPos
, chars
); 
3275                         pdoc
->EndUndoAction(); 
3276                         selType 
= selStream
; 
3278                 SetEmptySelection(startPos
); 
3282 void Editor::ClearAll() { 
3283         pdoc
->BeginUndoAction(); 
3284         if (0 != pdoc
->Length()) { 
3285                 pdoc
->DeleteChars(0, pdoc
->Length()); 
3287         if (!pdoc
->IsReadOnly()) { 
3290         pdoc
->EndUndoAction(); 
3294         SetVerticalScrollPos(); 
3295         InvalidateStyleRedraw();        // RPD: patch #1106564 
3298 void Editor::ClearDocumentStyle() { 
3299         pdoc
->StartStyling(0, '\377'); 
3300         pdoc
->SetStyleFor(pdoc
->Length(), 0); 
3302         pdoc
->ClearLevels(); 
3305 void Editor::Cut() { 
3306         if (!pdoc
->IsReadOnly() && !SelectionContainsProtected()) { 
3312 void Editor::PasteRectangular(int pos
, const char *ptr
, int len
) { 
3313         if (pdoc
->IsReadOnly() || SelectionContainsProtected()) { 
3317         int xInsert 
= XFromPosition(currentPos
); 
3318         int line 
= pdoc
->LineFromPosition(currentPos
); 
3319         bool prevCr 
= false; 
3320         pdoc
->BeginUndoAction(); 
3321         for (int i 
= 0; i 
< len
; i
++) { 
3322                 if (IsEOLChar(ptr
[i
])) { 
3323                         if ((ptr
[i
] == '\r') || (!prevCr
)) 
3325                         if (line 
>= pdoc
->LinesTotal()) { 
3326                                 if (pdoc
->eolMode 
!= SC_EOL_LF
) 
3327                                         pdoc
->InsertChar(pdoc
->Length(), '\r'); 
3328                                 if (pdoc
->eolMode 
!= SC_EOL_CR
) 
3329                                         pdoc
->InsertChar(pdoc
->Length(), '\n'); 
3331                         // Pad the end of lines with spaces if required 
3332                         currentPos 
= PositionFromLineX(line
, xInsert
); 
3333                         if ((XFromPosition(currentPos
) < xInsert
) && (i 
+ 1 < len
)) { 
3334                                 for (int i 
= 0; i 
< xInsert 
- XFromPosition(currentPos
); i
++) { 
3335                                         pdoc
->InsertChar(currentPos
, ' '); 
3339                         prevCr 
= ptr
[i
] == '\r'; 
3341                         pdoc
->InsertString(currentPos
, ptr 
+ i
, 1); 
3346         pdoc
->EndUndoAction(); 
3347         SetEmptySelection(pos
); 
3350 bool Editor::CanPaste() { 
3351         return !pdoc
->IsReadOnly() && !SelectionContainsProtected(); 
3354 void Editor::Clear() { 
3355         if (currentPos 
== anchor
) { 
3356                 if (!RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3362         SetEmptySelection(currentPos
); 
3365 void Editor::SelectAll() { 
3366         SetSelection(0, pdoc
->Length()); 
3370 void Editor::Undo() { 
3371         if (pdoc
->CanUndo()) { 
3373                 int newPos 
= pdoc
->Undo(); 
3374                 SetEmptySelection(newPos
); 
3375                 EnsureCaretVisible(); 
3379 void Editor::Redo() { 
3380         if (pdoc
->CanRedo()) { 
3381                 int newPos 
= pdoc
->Redo(); 
3382                 SetEmptySelection(newPos
); 
3383                 EnsureCaretVisible(); 
3387 void Editor::DelChar() { 
3388         if (!RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3389                 pdoc
->DelChar(currentPos
); 
3391         // Avoid blinking during rapid typing: 
3392         ShowCaretAtCurrentPosition(); 
3395 void Editor::DelCharBack(bool allowLineStartDeletion
) { 
3396         if (currentPos 
== anchor
) { 
3397                 if (!RangeContainsProtected(currentPos 
- 1, currentPos
)) { 
3398                         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
3399                         if (allowLineStartDeletion 
|| (pdoc
->LineStart(lineCurrentPos
) != currentPos
)) { 
3400                                 if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetLineIndentation(lineCurrentPos
) && 
3401                                         pdoc
->GetColumn(currentPos
) > 0 && pdoc
->backspaceUnindents
) { 
3402                                         pdoc
->BeginUndoAction(); 
3403                                         int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
3404                                         int indentationStep 
= pdoc
->IndentSize(); 
3405                                         if (indentation 
% indentationStep 
== 0) { 
3406                                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- indentationStep
); 
3408                                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- (indentation 
% indentationStep
)); 
3410                                         SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
3411                                         pdoc
->EndUndoAction(); 
3413                                         pdoc
->DelCharBack(currentPos
); 
3419                 SetEmptySelection(currentPos
); 
3421         // Avoid blinking during rapid typing: 
3422         ShowCaretAtCurrentPosition(); 
3425 void Editor::NotifyFocus(bool) {} 
3427 void Editor::NotifyStyleToNeeded(int endStyleNeeded
) { 
3429         scn
.nmhdr
.code 
= SCN_STYLENEEDED
; 
3430         scn
.position 
= endStyleNeeded
; 
3434 void Editor::NotifyStyleNeeded(Document
*, void *, int endStyleNeeded
) { 
3435         NotifyStyleToNeeded(endStyleNeeded
); 
3438 void Editor::NotifyChar(int ch
) { 
3440         scn
.nmhdr
.code 
= SCN_CHARADDED
; 
3443         if (recordingMacro
) { 
3445                 txt
[0] = static_cast<char>(ch
); 
3447                 NotifyMacroRecord(SCI_REPLACESEL
, 0, reinterpret_cast<sptr_t
>(txt
)); 
3451 void Editor::NotifySavePoint(bool isSavePoint
) { 
3454                 scn
.nmhdr
.code 
= SCN_SAVEPOINTREACHED
; 
3456                 scn
.nmhdr
.code 
= SCN_SAVEPOINTLEFT
; 
3461 void Editor::NotifyModifyAttempt() { 
3463         scn
.nmhdr
.code 
= SCN_MODIFYATTEMPTRO
; 
3467 void Editor::NotifyDoubleClick(Point
, bool) { 
3469         scn
.nmhdr
.code 
= SCN_DOUBLECLICK
; 
3473 void Editor::NotifyHotSpotDoubleClicked(int position
, bool shift
, bool ctrl
, bool alt
) { 
3475         scn
.nmhdr
.code 
= SCN_HOTSPOTDOUBLECLICK
; 
3476         scn
.position 
= position
; 
3477         scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3478                         (alt 
? SCI_ALT 
: 0); 
3482 void Editor::NotifyHotSpotClicked(int position
, bool shift
, bool ctrl
, bool alt
) { 
3484         scn
.nmhdr
.code 
= SCN_HOTSPOTCLICK
; 
3485         scn
.position 
= position
; 
3486         scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3487                         (alt 
? SCI_ALT 
: 0); 
3491 void Editor::NotifyUpdateUI() { 
3493         scn
.nmhdr
.code 
= SCN_UPDATEUI
; 
3497 void Editor::NotifyPainted() { 
3499         scn
.nmhdr
.code 
= SCN_PAINTED
; 
3503 bool Editor::NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
) { 
3504         int marginClicked 
= -1; 
3506         for (int margin 
= 0; margin 
< ViewStyle::margins
; margin
++) { 
3507                 if ((pt
.x 
> x
) && (pt
.x 
< x 
+ vs
.ms
[margin
].width
)) 
3508                         marginClicked 
= margin
; 
3509                 x 
+= vs
.ms
[margin
].width
; 
3511         if ((marginClicked 
>= 0) && vs
.ms
[marginClicked
].sensitive
) { 
3513                 scn
.nmhdr
.code 
= SCN_MARGINCLICK
; 
3514                 scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3515                                 (alt 
? SCI_ALT 
: 0); 
3516                 scn
.position 
= pdoc
->LineStart(LineFromLocation(pt
)); 
3517                 scn
.margin 
= marginClicked
; 
3525 void Editor::NotifyNeedShown(int pos
, int len
) { 
3527         scn
.nmhdr
.code 
= SCN_NEEDSHOWN
; 
3533 void Editor::NotifyDwelling(Point pt
, bool state
) { 
3535         scn
.nmhdr
.code 
= state 
? SCN_DWELLSTART 
: SCN_DWELLEND
; 
3536         scn
.position 
= PositionFromLocationClose(pt
); 
3542 void Editor::NotifyZoom() { 
3544         scn
.nmhdr
.code 
= SCN_ZOOM
; 
3548 // Notifications from document 
3549 void Editor::NotifyModifyAttempt(Document
*, void *) { 
3550         //Platform::DebugPrintf("** Modify Attempt\n"); 
3551         NotifyModifyAttempt(); 
3554 void Editor::NotifyMove(int position
) { 
3556         scn
.nmhdr
.code 
= SCN_POSCHANGED
; 
3557         scn
.position 
= position
; 
3561 void Editor::NotifySavePoint(Document
*, void *, bool atSavePoint
) { 
3562         //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off"); 
3563         NotifySavePoint(atSavePoint
); 
3566 void Editor::CheckModificationForWrap(DocModification mh
) { 
3567         if ((mh
.modificationType 
& SC_MOD_INSERTTEXT
) || 
3568                 (mh
.modificationType 
& SC_MOD_DELETETEXT
)) { 
3569                 llc
.Invalidate(LineLayout::llCheckTextAndStyle
); 
3570                 if (wrapState 
!= eWrapNone
) { 
3571                         int lineDoc 
= pdoc
->LineFromPosition(mh
.position
); 
3572                         if (mh
.linesAdded 
<= 0) { 
3573                                 AutoSurface 
surface(this); 
3574                                 AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
3575                                 if (surface 
&& ll
) { 
3576                                         LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
3577                                         if (cs
.GetHeight(lineDoc
) != ll
->lines
) { 
3578                                                 NeedWrapping(lineDoc 
- 1, lineDoc 
+ 1); 
3583                                 NeedWrapping(lineDoc
, lineDoc 
+ 1 + mh
.linesAdded
); 
3589 // Move a position so it is still after the same character as before the insertion. 
3590 static inline int MovePositionForInsertion(int position
, int startInsertion
, int length
) { 
3591         if (position 
> startInsertion
) { 
3592                 return position 
+ length
; 
3597 // Move a position so it is still after the same character as before the deletion if that 
3598 // character is still present else after the previous surviving character. 
3599 static inline int MovePositionForDeletion(int position
, int startDeletion
, int length
) { 
3600         if (position 
> startDeletion
) { 
3601                 int endDeletion 
= startDeletion 
+ length
; 
3602                 if (position 
> endDeletion
) { 
3603                         return position 
- length
; 
3605                         return startDeletion
; 
3612 void Editor::NotifyModified(Document
*, DocModification mh
, void *) { 
3613         needUpdateUI 
= true; 
3614         if (paintState 
== painting
) { 
3615                 CheckForChangeOutsidePaint(Range(mh
.position
, mh
.position 
+ mh
.length
)); 
3617         if (mh
.modificationType 
& SC_MOD_CHANGESTYLE
) { 
3618                 pdoc
->IncrementStyleClock(); 
3619                 if (paintState 
== notPainting
) { 
3620                         if (mh
.position 
< pdoc
->LineStart(topLine
)) { 
3621                                 // Styling performed before this view 
3624                                 InvalidateRange(mh
.position
, mh
.position 
+ mh
.length
); 
3628                 // Move selection and brace highlights 
3629                 if (mh
.modificationType 
& SC_MOD_INSERTTEXT
) { 
3630                         currentPos 
= MovePositionForInsertion(currentPos
, mh
.position
, mh
.length
); 
3631                         anchor 
= MovePositionForInsertion(anchor
, mh
.position
, mh
.length
); 
3632                         braces
[0] = MovePositionForInsertion(braces
[0], mh
.position
, mh
.length
); 
3633                         braces
[1] = MovePositionForInsertion(braces
[1], mh
.position
, mh
.length
); 
3634                 } else if (mh
.modificationType 
& SC_MOD_DELETETEXT
) { 
3635                         currentPos 
= MovePositionForDeletion(currentPos
, mh
.position
, mh
.length
); 
3636                         anchor 
= MovePositionForDeletion(anchor
, mh
.position
, mh
.length
); 
3637                         braces
[0] = MovePositionForDeletion(braces
[0], mh
.position
, mh
.length
); 
3638                         braces
[1] = MovePositionForDeletion(braces
[1], mh
.position
, mh
.length
); 
3640                 if (cs
.LinesDisplayed() < cs
.LinesInDoc()) { 
3641                         // Some lines are hidden so may need shown. 
3642                         // TODO: check if the modified area is hidden. 
3643                         if (mh
.modificationType 
& SC_MOD_BEFOREINSERT
) { 
3644                                 NotifyNeedShown(mh
.position
, mh
.length
); 
3645                         } else if (mh
.modificationType 
& SC_MOD_BEFOREDELETE
) { 
3646                                 NotifyNeedShown(mh
.position
, mh
.length
); 
3649                 if (mh
.linesAdded 
!= 0) { 
3650                         // Update contraction state for inserted and removed lines 
3651                         // lineOfPos should be calculated in context of state before modification, shouldn't it 
3652                         int lineOfPos 
= pdoc
->LineFromPosition(mh
.position
); 
3653                         if (mh
.linesAdded 
> 0) { 
3654                                 cs
.InsertLines(lineOfPos
, mh
.linesAdded
); 
3656                                 cs
.DeleteLines(lineOfPos
, -mh
.linesAdded
); 
3659                 CheckModificationForWrap(mh
); 
3660                 if (mh
.linesAdded 
!= 0) { 
3661                         // Avoid scrolling of display if change before current display 
3662                         if (mh
.position 
< posTopLine
) { 
3663                                 int newTop 
= Platform::Clamp(topLine 
+ mh
.linesAdded
, 0, MaxScrollPos()); 
3664                                 if (newTop 
!= topLine
) { 
3666                                         SetVerticalScrollPos(); 
3670                         //Platform::DebugPrintf("** %x Doc Changed\n", this); 
3671                         // TODO: could invalidate from mh.startModification to end of screen 
3672                         //InvalidateRange(mh.position, mh.position + mh.length); 
3673                         if (paintState 
== notPainting
) { 
3677                         //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this, 
3678                         //      mh.position, mh.position + mh.length); 
3679                         if (paintState 
== notPainting
) { 
3680                                 InvalidateRange(mh
.position
, mh
.position 
+ mh
.length
); 
3685         if (mh
.linesAdded 
!= 0) { 
3689         if (mh
.modificationType 
& SC_MOD_CHANGEMARKER
) { 
3690                 if (paintState 
== notPainting
) { 
3695         // If client wants to see this modification 
3696         if (mh
.modificationType 
& modEventMask
) { 
3697                 if ((mh
.modificationType 
& SC_MOD_CHANGESTYLE
) == 0) { 
3698                         // Real modification made to text of document. 
3699                         NotifyChange(); // Send EN_CHANGE 
3703                 scn
.nmhdr
.code 
= SCN_MODIFIED
; 
3704                 scn
.position 
= mh
.position
; 
3705                 scn
.modificationType 
= mh
.modificationType
; 
3707                 scn
.length 
= mh
.length
; 
3708                 scn
.linesAdded 
= mh
.linesAdded
; 
3710                 scn
.foldLevelNow 
= mh
.foldLevelNow
; 
3711                 scn
.foldLevelPrev 
= mh
.foldLevelPrev
; 
3716 void Editor::NotifyDeleted(Document 
*, void *) { 
3720 void Editor::NotifyMacroRecord(unsigned int iMessage
, unsigned long wParam
, long lParam
) { 
3722         // Enumerates all macroable messages 
3728         case SCI_REPLACESEL
: 
3730         case SCI_INSERTTEXT
: 
3731         case SCI_APPENDTEXT
: 
3736         case SCI_SEARCHANCHOR
: 
3737         case SCI_SEARCHNEXT
: 
3738         case SCI_SEARCHPREV
: 
3740         case SCI_LINEDOWNEXTEND
: 
3742         case SCI_PARADOWNEXTEND
: 
3744         case SCI_LINEUPEXTEND
: 
3746         case SCI_PARAUPEXTEND
: 
3748         case SCI_CHARLEFTEXTEND
: 
3750         case SCI_CHARRIGHTEXTEND
: 
3752         case SCI_WORDLEFTEXTEND
: 
3754         case SCI_WORDRIGHTEXTEND
: 
3755         case SCI_WORDPARTLEFT
: 
3756         case SCI_WORDPARTLEFTEXTEND
: 
3757         case SCI_WORDPARTRIGHT
: 
3758         case SCI_WORDPARTRIGHTEXTEND
: 
3759         case SCI_WORDLEFTEND
: 
3760         case SCI_WORDLEFTENDEXTEND
: 
3761         case SCI_WORDRIGHTEND
: 
3762         case SCI_WORDRIGHTENDEXTEND
: 
3764         case SCI_HOMEEXTEND
: 
3766         case SCI_LINEENDEXTEND
: 
3768         case SCI_HOMEWRAPEXTEND
: 
3769         case SCI_LINEENDWRAP
: 
3770         case SCI_LINEENDWRAPEXTEND
: 
3771         case SCI_DOCUMENTSTART
: 
3772         case SCI_DOCUMENTSTARTEXTEND
: 
3773         case SCI_DOCUMENTEND
: 
3774         case SCI_DOCUMENTENDEXTEND
: 
3775         case SCI_STUTTEREDPAGEUP
: 
3776         case SCI_STUTTEREDPAGEUPEXTEND
: 
3777         case SCI_STUTTEREDPAGEDOWN
: 
3778         case SCI_STUTTEREDPAGEDOWNEXTEND
: 
3780         case SCI_PAGEUPEXTEND
: 
3782         case SCI_PAGEDOWNEXTEND
: 
3783         case SCI_EDITTOGGLEOVERTYPE
: 
3785         case SCI_DELETEBACK
: 
3790         case SCI_VCHOMEEXTEND
: 
3791         case SCI_VCHOMEWRAP
: 
3792         case SCI_VCHOMEWRAPEXTEND
: 
3793         case SCI_DELWORDLEFT
: 
3794         case SCI_DELWORDRIGHT
: 
3795         case SCI_DELLINELEFT
: 
3796         case SCI_DELLINERIGHT
: 
3799         case SCI_LINEDELETE
: 
3800         case SCI_LINETRANSPOSE
: 
3801         case SCI_LINEDUPLICATE
: 
3804         case SCI_LINESCROLLDOWN
: 
3805         case SCI_LINESCROLLUP
: 
3806         case SCI_DELETEBACKNOTLINE
: 
3807         case SCI_HOMEDISPLAY
: 
3808         case SCI_HOMEDISPLAYEXTEND
: 
3809         case SCI_LINEENDDISPLAY
: 
3810         case SCI_LINEENDDISPLAYEXTEND
: 
3811         case SCI_SETSELECTIONMODE
: 
3812         case SCI_LINEDOWNRECTEXTEND
: 
3813         case SCI_LINEUPRECTEXTEND
: 
3814         case SCI_CHARLEFTRECTEXTEND
: 
3815         case SCI_CHARRIGHTRECTEXTEND
: 
3816         case SCI_HOMERECTEXTEND
: 
3817         case SCI_VCHOMERECTEXTEND
: 
3818         case SCI_LINEENDRECTEXTEND
: 
3819         case SCI_PAGEUPRECTEXTEND
: 
3820         case SCI_PAGEDOWNRECTEXTEND
: 
3823         // Filter out all others like display changes. Also, newlines are redundant 
3824         // with char insert messages. 
3827                 //              printf("Filtered out %ld of macro recording\n", iMessage); 
3831         // Send notification 
3833         scn
.nmhdr
.code 
= SCN_MACRORECORD
; 
3834         scn
.message 
= iMessage
; 
3835         scn
.wParam 
= wParam
; 
3836         scn
.lParam 
= lParam
; 
3841  * Force scroll and keep position relative to top of window. 
3843  * If stuttered = true and not already at first/last row, move to first/last row of window. 
3844  * If stuttered = true and already at first/last row, scroll as normal. 
3846 void Editor::PageMove(int direction
, selTypes sel
, bool stuttered
) { 
3847         int topLineNew
, newPos
; 
3849         // I consider only the caretYSlop, and ignore the caretYPolicy-- is that a problem? 
3850         int currentLine 
= pdoc
->LineFromPosition(currentPos
); 
3851         int topStutterLine 
= topLine 
+ caretYSlop
; 
3852         int bottomStutterLine 
= topLine 
+ LinesToScroll() - caretYSlop
; 
3854         if (stuttered 
&& (direction 
< 0 && currentLine 
> topStutterLine
)) { 
3855                 topLineNew 
= topLine
; 
3856                 newPos 
= PositionFromLocation(Point(lastXChosen
, vs
.lineHeight 
* caretYSlop
)); 
3858         } else if (stuttered 
&& (direction 
> 0 && currentLine 
< bottomStutterLine
)) { 
3859                 topLineNew 
= topLine
; 
3860                 newPos 
= PositionFromLocation(Point(lastXChosen
, vs
.lineHeight 
* (LinesToScroll() - caretYSlop
))); 
3863                 Point pt 
= LocationFromPosition(currentPos
); 
3865                 topLineNew 
= Platform::Clamp( 
3866                              topLine 
+ direction 
* LinesToScroll(), 0, MaxScrollPos()); 
3867                 newPos 
= PositionFromLocation( 
3868                          Point(lastXChosen
, pt
.y 
+ direction 
* (vs
.lineHeight 
* LinesToScroll()))); 
3871         if (topLineNew 
!= topLine
) { 
3872                 SetTopLine(topLineNew
); 
3873                 MovePositionTo(newPos
, sel
); 
3875                 SetVerticalScrollPos(); 
3877                 MovePositionTo(newPos
, sel
); 
3881 void Editor::ChangeCaseOfSelection(bool makeUpperCase
) { 
3882         pdoc
->BeginUndoAction(); 
3883         int startCurrent 
= currentPos
; 
3884         int startAnchor 
= anchor
; 
3885         if (selType 
== selStream
) { 
3886                 pdoc
->ChangeCase(Range(SelectionStart(), SelectionEnd()), 
3888                 SetSelection(startCurrent
, startAnchor
); 
3890                 SelectionLineIterator 
lineIterator(this, false); 
3891                 while (lineIterator
.Iterate()) { 
3893                             Range(lineIterator
.startPos
, lineIterator
.endPos
), 
3896                 // Would be nicer to keep the rectangular selection but this is complex 
3897                 SetEmptySelection(startCurrent
); 
3899         pdoc
->EndUndoAction(); 
3902 void Editor::LineTranspose() { 
3903         int line 
= pdoc
->LineFromPosition(currentPos
); 
3905                 int startPrev 
= pdoc
->LineStart(line 
- 1); 
3906                 int endPrev 
= pdoc
->LineEnd(line 
- 1); 
3907                 int start 
= pdoc
->LineStart(line
); 
3908                 int end 
= pdoc
->LineEnd(line
); 
3909                 int startNext 
= pdoc
->LineStart(line 
+ 1); 
3910                 if (end 
< pdoc
->Length()) { 
3912                         char *thisLine 
= CopyRange(start
, end
); 
3913                         pdoc
->DeleteChars(start
, end 
- start
); 
3914                         if (pdoc
->InsertString(startPrev
, thisLine
, end 
- start
)) { 
3915                                 MovePositionTo(startPrev 
+ end 
- start
); 
3919                         // Last line so line has no line end 
3920                         char *thisLine 
= CopyRange(start
, end
); 
3921                         char *prevEnd 
= CopyRange(endPrev
, start
); 
3922                         pdoc
->DeleteChars(endPrev
, end 
- endPrev
); 
3923                         pdoc
->InsertString(startPrev
, thisLine
, end 
- start
); 
3924                         if (pdoc
->InsertString(startPrev 
+ end 
- start
, prevEnd
, start 
- endPrev
)) { 
3925                                 MovePositionTo(startPrev 
+ end 
- endPrev
); 
3934 void Editor::LineDuplicate() { 
3935         int line 
= pdoc
->LineFromPosition(currentPos
); 
3936         int start 
= pdoc
->LineStart(line
); 
3937         int end 
= pdoc
->LineEnd(line
); 
3938         char *thisLine 
= CopyRange(start
, end
); 
3939         const char *eol 
= StringFromEOLMode(pdoc
->eolMode
); 
3940         pdoc
->InsertString(end
, eol
); 
3941         pdoc
->InsertString(end 
+ istrlen(eol
), thisLine
, end 
- start
); 
3945 void Editor::CancelModes() { 
3946         moveExtendsSelection 
= false; 
3949 void Editor::NewLine() { 
3951         const char *eol 
= "\n"; 
3952         if (pdoc
->eolMode 
== SC_EOL_CRLF
) { 
3954         } else if (pdoc
->eolMode 
== SC_EOL_CR
) { 
3956         } // else SC_EOL_LF -> "\n" already set 
3957         if (pdoc
->InsertString(currentPos
, eol
)) { 
3958                 SetEmptySelection(currentPos 
+ istrlen(eol
)); 
3965         EnsureCaretVisible(); 
3968 void Editor::CursorUpOrDown(int direction
, selTypes sel
) { 
3969         Point pt 
= LocationFromPosition(currentPos
); 
3970         int posNew 
= PositionFromLocation( 
3971                          Point(lastXChosen
, pt
.y 
+ direction 
* vs
.lineHeight
)); 
3972         if (direction 
< 0) { 
3973                 // Line wrapping may lead to a location on the same line, so 
3974                 // seek back if that is the case. 
3975                 // There is an equivalent case when moving down which skips 
3976                 // over a line but as that does not trap the user it is fine. 
3977                 Point ptNew 
= LocationFromPosition(posNew
); 
3978                 while ((posNew 
> 0) && (pt
.y 
== ptNew
.y
)) { 
3980                         ptNew 
= LocationFromPosition(posNew
); 
3983         MovePositionTo(posNew
, sel
); 
3986 int Editor::StartEndDisplayLine(int pos
, bool start
) { 
3988         int line 
= pdoc
->LineFromPosition(pos
); 
3989         AutoSurface 
surface(this); 
3990         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
3991         int posRet 
= INVALID_POSITION
; 
3992         if (surface 
&& ll
) { 
3993                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
3994                 LayoutLine(line
, surface
, vs
, ll
, wrapWidth
); 
3995                 int posInLine 
= pos 
- posLineStart
; 
3996                 if (posInLine 
<= ll
->maxLineLength
) { 
3997                         for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
3998                                 if ((posInLine 
>= ll
->LineStart(subLine
)) && (posInLine 
<= ll
->LineStart(subLine 
+ 1))) { 
4000                                                 posRet 
= ll
->LineStart(subLine
) + posLineStart
; 
4002                                                 if (subLine 
== ll
->lines 
- 1) 
4003                                                         posRet 
= ll
->LineStart(subLine 
+ 1) + posLineStart
; 
4005                                                         posRet 
= ll
->LineStart(subLine 
+ 1) + posLineStart 
- 1; 
4011         if (posRet 
== INVALID_POSITION
) { 
4018 int Editor::KeyCommand(unsigned int iMessage
) { 
4023         case SCI_LINEDOWNEXTEND
: 
4024                 CursorUpOrDown(1, selStream
); 
4026         case SCI_LINEDOWNRECTEXTEND
: 
4027                 CursorUpOrDown(1, selRectangle
); 
4030                 MovePositionTo(pdoc
->ParaDown(currentPos
)); 
4032         case SCI_PARADOWNEXTEND
: 
4033                 MovePositionTo(pdoc
->ParaDown(currentPos
), selStream
); 
4035         case SCI_LINESCROLLDOWN
: 
4036                 ScrollTo(topLine 
+ 1); 
4037                 MoveCaretInsideView(false); 
4042         case SCI_LINEUPEXTEND
: 
4043                 CursorUpOrDown(-1, selStream
); 
4045         case SCI_LINEUPRECTEXTEND
: 
4046                 CursorUpOrDown(-1, selRectangle
); 
4049                 MovePositionTo(pdoc
->ParaUp(currentPos
)); 
4051         case SCI_PARAUPEXTEND
: 
4052                 MovePositionTo(pdoc
->ParaUp(currentPos
), selStream
); 
4054         case SCI_LINESCROLLUP
: 
4055                 ScrollTo(topLine 
- 1); 
4056                 MoveCaretInsideView(false); 
4059                 if (SelectionEmpty() || moveExtendsSelection
) { 
4060                         MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1)); 
4062                         MovePositionTo(SelectionStart()); 
4066         case SCI_CHARLEFTEXTEND
: 
4067                 MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1), selStream
); 
4070         case SCI_CHARLEFTRECTEXTEND
: 
4071                 MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1), selRectangle
); 
4075                 if (SelectionEmpty() || moveExtendsSelection
) { 
4076                         MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1)); 
4078                         MovePositionTo(SelectionEnd()); 
4082         case SCI_CHARRIGHTEXTEND
: 
4083                 MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1), selStream
); 
4086         case SCI_CHARRIGHTRECTEXTEND
: 
4087                 MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1), selRectangle
); 
4091                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1)); 
4094         case SCI_WORDLEFTEXTEND
: 
4095                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1), selStream
); 
4099                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1)); 
4102         case SCI_WORDRIGHTEXTEND
: 
4103                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1), selStream
); 
4107         case SCI_WORDLEFTEND
: 
4108                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, -1), -1)); 
4111         case SCI_WORDLEFTENDEXTEND
: 
4112                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, -1), -1), selStream
); 
4115         case SCI_WORDRIGHTEND
: 
4116                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, 1), 1)); 
4119         case SCI_WORDRIGHTENDEXTEND
: 
4120                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, 1), 1), selStream
); 
4125                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
))); 
4128         case SCI_HOMEEXTEND
: 
4129                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), selStream
); 
4132         case SCI_HOMERECTEXTEND
: 
4133                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), selRectangle
); 
4137                 MovePositionTo(pdoc
->LineEndPosition(currentPos
)); 
4140         case SCI_LINEENDEXTEND
: 
4141                 MovePositionTo(pdoc
->LineEndPosition(currentPos
), selStream
); 
4144         case SCI_LINEENDRECTEXTEND
: 
4145                 MovePositionTo(pdoc
->LineEndPosition(currentPos
), selRectangle
); 
4148         case SCI_HOMEWRAP
: { 
4149                         int homePos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
4150                         if (currentPos 
<= homePos
) 
4151                                 homePos 
= pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)); 
4152                         MovePositionTo(homePos
); 
4156         case SCI_HOMEWRAPEXTEND
: { 
4157                         int homePos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
4158                         if (currentPos 
<= homePos
) 
4159                                 homePos 
= pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)); 
4160                         MovePositionTo(homePos
, selStream
); 
4164         case SCI_LINEENDWRAP
: { 
4165                         int endPos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, false), 1); 
4166                         int realEndPos 
= pdoc
->LineEndPosition(currentPos
); 
4167                         if (endPos 
> realEndPos      
// if moved past visible EOLs 
4168                                 || currentPos 
>= endPos
) // if at end of display line already 
4169                                 endPos 
= realEndPos
; 
4170                         MovePositionTo(endPos
); 
4174         case SCI_LINEENDWRAPEXTEND
: { 
4175                         int endPos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, false), 1); 
4176                         int realEndPos 
= pdoc
->LineEndPosition(currentPos
); 
4177                         if (endPos 
> realEndPos      
// if moved past visible EOLs 
4178                                 || currentPos 
>= endPos
) // if at end of display line already 
4179                                 endPos 
= realEndPos
; 
4180                         MovePositionTo(endPos
, selStream
); 
4184         case SCI_DOCUMENTSTART
: 
4188         case SCI_DOCUMENTSTARTEXTEND
: 
4189                 MovePositionTo(0, selStream
); 
4192         case SCI_DOCUMENTEND
: 
4193                 MovePositionTo(pdoc
->Length()); 
4196         case SCI_DOCUMENTENDEXTEND
: 
4197                 MovePositionTo(pdoc
->Length(), selStream
); 
4200         case SCI_STUTTEREDPAGEUP
: 
4201                 PageMove(-1, noSel
, true); 
4203         case SCI_STUTTEREDPAGEUPEXTEND
: 
4204                 PageMove(-1, selStream
, true); 
4206         case SCI_STUTTEREDPAGEDOWN
: 
4207                 PageMove(1, noSel
, true); 
4209         case SCI_STUTTEREDPAGEDOWNEXTEND
: 
4210                 PageMove(1, selStream
, true); 
4215         case SCI_PAGEUPEXTEND
: 
4216                 PageMove(-1, selStream
); 
4218         case SCI_PAGEUPRECTEXTEND
: 
4219                 PageMove(-1, selRectangle
); 
4224         case SCI_PAGEDOWNEXTEND
: 
4225                 PageMove(1, selStream
); 
4227         case SCI_PAGEDOWNRECTEXTEND
: 
4228                 PageMove(1, selRectangle
); 
4230         case SCI_EDITTOGGLEOVERTYPE
: 
4231                 inOverstrike 
= !inOverstrike
; 
4233                 ShowCaretAtCurrentPosition(); 
4236         case SCI_CANCEL
:                // Cancel any modes - handled in subclass 
4237                 // Also unselect text 
4240         case SCI_DELETEBACK
: 
4243                 EnsureCaretVisible(); 
4245         case SCI_DELETEBACKNOTLINE
: 
4248                 EnsureCaretVisible(); 
4253                 EnsureCaretVisible(); 
4258                 EnsureCaretVisible(); 
4267                 MovePositionTo(pdoc
->VCHomePosition(currentPos
)); 
4270         case SCI_VCHOMEEXTEND
: 
4271                 MovePositionTo(pdoc
->VCHomePosition(currentPos
), selStream
); 
4274         case SCI_VCHOMERECTEXTEND
: 
4275                 MovePositionTo(pdoc
->VCHomePosition(currentPos
), selRectangle
); 
4278         case SCI_VCHOMEWRAP
: { 
4279                         int homePos 
= pdoc
->VCHomePosition(currentPos
); 
4280                         int viewLineStart 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
4281                         if ((viewLineStart 
< currentPos
) && (viewLineStart 
> homePos
)) 
4282                                 homePos 
= viewLineStart
; 
4284                         MovePositionTo(homePos
); 
4288         case SCI_VCHOMEWRAPEXTEND
: { 
4289                         int homePos 
= pdoc
->VCHomePosition(currentPos
); 
4290                         int viewLineStart 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
4291                         if ((viewLineStart 
< currentPos
) && (viewLineStart 
> homePos
)) 
4292                                 homePos 
= viewLineStart
; 
4294                         MovePositionTo(homePos
, selStream
); 
4299                 if (vs
.zoomLevel 
< 20) { 
4301                         InvalidateStyleRedraw(); 
4306                 if (vs
.zoomLevel 
> -10) { 
4308                         InvalidateStyleRedraw(); 
4312         case SCI_DELWORDLEFT
: { 
4313                         int startWord 
= pdoc
->NextWordStart(currentPos
, -1); 
4314                         pdoc
->DeleteChars(startWord
, currentPos 
- startWord
); 
4318         case SCI_DELWORDRIGHT
: { 
4319                         int endWord 
= pdoc
->NextWordStart(currentPos
, 1); 
4320                         pdoc
->DeleteChars(currentPos
, endWord 
- currentPos
); 
4323         case SCI_DELLINELEFT
: { 
4324                         int line 
= pdoc
->LineFromPosition(currentPos
); 
4325                         int start 
= pdoc
->LineStart(line
); 
4326                         pdoc
->DeleteChars(start
, currentPos 
- start
); 
4330         case SCI_DELLINERIGHT
: { 
4331                         int line 
= pdoc
->LineFromPosition(currentPos
); 
4332                         int end 
= pdoc
->LineEnd(line
); 
4333                         pdoc
->DeleteChars(currentPos
, end 
- currentPos
); 
4336         case SCI_LINECOPY
: { 
4337                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
4338                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
4339                         CopyRangeToClipboard(pdoc
->LineStart(lineStart
), 
4340                                 pdoc
->LineStart(lineEnd 
+ 1)); 
4344                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
4345                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
4346                         int start 
= pdoc
->LineStart(lineStart
); 
4347                         int end 
= pdoc
->LineStart(lineEnd 
+ 1); 
4348                         SetSelection(start
, end
); 
4353         case SCI_LINEDELETE
: { 
4354                         int line 
= pdoc
->LineFromPosition(currentPos
); 
4355                         int start 
= pdoc
->LineStart(line
); 
4356                         int end 
= pdoc
->LineStart(line 
+ 1); 
4357                         pdoc
->DeleteChars(start
, end 
- start
); 
4360         case SCI_LINETRANSPOSE
: 
4363         case SCI_LINEDUPLICATE
: 
4367                 ChangeCaseOfSelection(false); 
4370                 ChangeCaseOfSelection(true); 
4372         case SCI_WORDPARTLEFT
: 
4373                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartLeft(currentPos
), -1)); 
4376         case SCI_WORDPARTLEFTEXTEND
: 
4377                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartLeft(currentPos
), -1), selStream
); 
4380         case SCI_WORDPARTRIGHT
: 
4381                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartRight(currentPos
), 1)); 
4384         case SCI_WORDPARTRIGHTEXTEND
: 
4385                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartRight(currentPos
), 1), selStream
); 
4388         case SCI_HOMEDISPLAY
: 
4389                 MovePositionTo(MovePositionSoVisible( 
4390                                    StartEndDisplayLine(currentPos
, true), -1)); 
4393         case SCI_HOMEDISPLAYEXTEND
: 
4394                 MovePositionTo(MovePositionSoVisible( 
4395                                    StartEndDisplayLine(currentPos
, true), -1), selStream
); 
4398         case SCI_LINEENDDISPLAY
: 
4399                 MovePositionTo(MovePositionSoVisible( 
4400                                    StartEndDisplayLine(currentPos
, false), 1)); 
4403         case SCI_LINEENDDISPLAYEXTEND
: 
4404                 MovePositionTo(MovePositionSoVisible( 
4405                                    StartEndDisplayLine(currentPos
, false), 1), selStream
); 
4412 int Editor::KeyDefault(int, int) { 
4416 int Editor::KeyDown(int key
, bool shift
, bool ctrl
, bool alt
, bool *consumed
) { 
4418         int modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
4419                         (alt 
? SCI_ALT 
: 0); 
4420         int msg 
= kmap
.Find(key
, modifiers
); 
4424                 return WndProc(msg
, 0, 0); 
4428                 return KeyDefault(key
, modifiers
); 
4432 void Editor::SetWhitespaceVisible(int view
) { 
4433         vs
.viewWhitespace 
= static_cast<WhiteSpaceVisibility
>(view
); 
4436 int Editor::GetWhitespaceVisible() { 
4437         return vs
.viewWhitespace
; 
4440 void Editor::Indent(bool forwards
) { 
4441         //Platform::DebugPrintf("INdent %d\n", forwards); 
4442         int lineOfAnchor 
= pdoc
->LineFromPosition(anchor
); 
4443         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
4444         if (lineOfAnchor 
== lineCurrentPos
) { 
4446                         pdoc
->BeginUndoAction(); 
4448                         if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetColumn(pdoc
->GetLineIndentPosition(lineCurrentPos
)) && 
4450                                 int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
4451                                 int indentationStep 
= pdoc
->IndentSize(); 
4452                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
+ indentationStep 
- indentation 
% indentationStep
); 
4453                                 SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
4455                                 if (pdoc
->useTabs
) { 
4456                                         pdoc
->InsertChar(currentPos
, '\t'); 
4457                                         SetEmptySelection(currentPos 
+ 1); 
4459                                         int numSpaces 
= (pdoc
->tabInChars
) - 
4460                                                         (pdoc
->GetColumn(currentPos
) % (pdoc
->tabInChars
)); 
4462                                                 numSpaces 
= pdoc
->tabInChars
; 
4463                                         for (int i 
= 0; i 
< numSpaces
; i
++) { 
4464                                                 pdoc
->InsertChar(currentPos 
+ i
, ' '); 
4466                                         SetEmptySelection(currentPos 
+ numSpaces
); 
4469                         pdoc
->EndUndoAction(); 
4471                         if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetLineIndentation(lineCurrentPos
) && 
4473                                 pdoc
->BeginUndoAction(); 
4474                                 int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
4475                                 int indentationStep 
= pdoc
->IndentSize(); 
4476                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- indentationStep
); 
4477                                 SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
4478                                 pdoc
->EndUndoAction(); 
4480                                 int newColumn 
= ((pdoc
->GetColumn(currentPos
) - 1) / pdoc
->tabInChars
) * 
4484                                 int newPos 
= currentPos
; 
4485                                 while (pdoc
->GetColumn(newPos
) > newColumn
) 
4487                                 SetEmptySelection(newPos
); 
4491                 int anchorPosOnLine 
= anchor 
- pdoc
->LineStart(lineOfAnchor
); 
4492                 int currentPosPosOnLine 
= currentPos 
- pdoc
->LineStart(lineCurrentPos
); 
4493                 // Multiple lines selected so indent / dedent 
4494                 int lineTopSel 
= Platform::Minimum(lineOfAnchor
, lineCurrentPos
); 
4495                 int lineBottomSel 
= Platform::Maximum(lineOfAnchor
, lineCurrentPos
); 
4496                 if (pdoc
->LineStart(lineBottomSel
) == anchor 
|| pdoc
->LineStart(lineBottomSel
) == currentPos
) 
4497                         lineBottomSel
--;        // If not selecting any characters on a line, do not indent 
4498                 pdoc
->BeginUndoAction(); 
4499                 pdoc
->Indent(forwards
, lineBottomSel
, lineTopSel
); 
4500                 pdoc
->EndUndoAction(); 
4501                 if (lineOfAnchor 
< lineCurrentPos
) { 
4502                         if (currentPosPosOnLine 
== 0) 
4503                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
)); 
4505                                 SetSelection(pdoc
->LineStart(lineCurrentPos 
+ 1), pdoc
->LineStart(lineOfAnchor
)); 
4507                         if (anchorPosOnLine 
== 0) 
4508                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
)); 
4510                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor 
+ 1)); 
4516  * Search of a text in the document, in the given range. 
4517  * @return The position of the found text, -1 if not found. 
4519 long Editor::FindText( 
4520         uptr_t wParam
,          ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, 
4521                                                 ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. 
4522         sptr_t lParam
) {        ///< @c TextToFind structure: The text to search for in the given range. 
4524         TextToFind 
*ft 
= reinterpret_cast<TextToFind 
*>(lParam
); 
4525         int lengthFound 
= istrlen(ft
->lpstrText
); 
4526         int pos 
= pdoc
->FindText(ft
->chrg
.cpMin
, ft
->chrg
.cpMax
, ft
->lpstrText
, 
4527                                  (wParam 
& SCFIND_MATCHCASE
) != 0, 
4528                                  (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4529                                  (wParam 
& SCFIND_WORDSTART
) != 0, 
4530                                  (wParam 
& SCFIND_REGEXP
) != 0, 
4531                                  (wParam 
& SCFIND_POSIX
) != 0, 
4534                 ft
->chrgText
.cpMin 
= pos
; 
4535                 ft
->chrgText
.cpMax 
= pos 
+ lengthFound
; 
4541  * Relocatable search support : Searches relative to current selection 
4542  * point and sets the selection to the found text range with 
4546  * Anchor following searches at current selection start: This allows 
4547  * multiple incremental interactive searches to be macro recorded 
4548  * while still setting the selection to found text so the find/select 
4549  * operation is self-contained. 
4551 void Editor::SearchAnchor() { 
4552         searchAnchor 
= SelectionStart(); 
4556  * Find text from current search anchor: Must call @c SearchAnchor first. 
4557  * Used for next text and previous text requests. 
4558  * @return The position of the found text, -1 if not found. 
4560 long Editor::SearchText( 
4561     unsigned int iMessage
,              ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV. 
4562     uptr_t wParam
,                              ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, 
4563                                                                 ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. 
4564     sptr_t lParam
) {                    ///< The text to search for. 
4566         const char *txt 
= reinterpret_cast<char *>(lParam
); 
4568         int lengthFound 
= istrlen(txt
); 
4569         if (iMessage 
== SCI_SEARCHNEXT
) { 
4570                 pos 
= pdoc
->FindText(searchAnchor
, pdoc
->Length(), txt
, 
4571                                      (wParam 
& SCFIND_MATCHCASE
) != 0, 
4572                                      (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4573                                      (wParam 
& SCFIND_WORDSTART
) != 0, 
4574                                      (wParam 
& SCFIND_REGEXP
) != 0, 
4575                                      (wParam 
& SCFIND_POSIX
) != 0, 
4578                 pos 
= pdoc
->FindText(searchAnchor
, 0, txt
, 
4579                                      (wParam 
& SCFIND_MATCHCASE
) != 0, 
4580                                      (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4581                                      (wParam 
& SCFIND_WORDSTART
) != 0, 
4582                                      (wParam 
& SCFIND_REGEXP
) != 0, 
4583                                      (wParam 
& SCFIND_POSIX
) != 0, 
4588                 SetSelection(pos
, pos 
+ lengthFound
); 
4595  * Search for text in the target range of the document. 
4596  * @return The position of the found text, -1 if not found. 
4598 long Editor::SearchInTarget(const char *text
, int length
) { 
4599         int lengthFound 
= length
; 
4600         int pos 
= pdoc
->FindText(targetStart
, targetEnd
, text
, 
4601                                  (searchFlags 
& SCFIND_MATCHCASE
) != 0, 
4602                                  (searchFlags 
& SCFIND_WHOLEWORD
) != 0, 
4603                                  (searchFlags 
& SCFIND_WORDSTART
) != 0, 
4604                                  (searchFlags 
& SCFIND_REGEXP
) != 0, 
4605                                  (searchFlags 
& SCFIND_POSIX
) != 0, 
4609                 targetEnd 
= pos 
+ lengthFound
; 
4614 void Editor::GoToLine(int lineNo
) { 
4615         if (lineNo 
> pdoc
->LinesTotal()) 
4616                 lineNo 
= pdoc
->LinesTotal(); 
4619         SetEmptySelection(pdoc
->LineStart(lineNo
)); 
4620         ShowCaretAtCurrentPosition(); 
4621         EnsureCaretVisible(); 
4624 static bool Close(Point pt1
, Point pt2
) { 
4625         if (abs(pt1
.x 
- pt2
.x
) > 3) 
4627         if (abs(pt1
.y 
- pt2
.y
) > 3) 
4632 char *Editor::CopyRange(int start
, int end
) { 
4635                 int len 
= end 
- start
; 
4636                 text 
= new char[len 
+ 1]; 
4638                         for (int i 
= 0; i 
< len
; i
++) { 
4639                                 text
[i
] = pdoc
->CharAt(start 
+ i
); 
4647 void Editor::CopySelectionFromRange(SelectionText 
*ss
, int start
, int end
) { 
4648         ss
->Set(CopyRange(start
, end
), end 
- start 
+ 1, 
4649                 pdoc
->dbcsCodePage
, vs
.styles
[STYLE_DEFAULT
].characterSet
, false); 
4652 void Editor::CopySelectionRange(SelectionText 
*ss
) { 
4653         if (selType 
== selStream
) { 
4654                 CopySelectionFromRange(ss
, SelectionStart(), SelectionEnd()); 
4658                 SelectionLineIterator 
lineIterator(this); 
4659                 while (lineIterator
.Iterate()) { 
4660                         size 
+= lineIterator
.endPos 
- lineIterator
.startPos
; 
4661                         if (selType 
!= selLines
) { 
4663                                 if (pdoc
->eolMode 
== SC_EOL_CRLF
) { 
4669                         text 
= new char[size 
+ 1]; 
4672                                 lineIterator
.Reset(); 
4673                                 while (lineIterator
.Iterate()) { 
4674                                         for (int i 
= lineIterator
.startPos
; 
4675                                                  i 
< lineIterator
.endPos
; 
4677                                                 text
[j
++] = pdoc
->CharAt(i
); 
4679                                         if (selType 
!= selLines
) { 
4680                                                 if (pdoc
->eolMode 
!= SC_EOL_LF
) { 
4683                                                 if (pdoc
->eolMode 
!= SC_EOL_CR
) { 
4691                 ss
->Set(text
, size 
+ 1, pdoc
->dbcsCodePage
, 
4692                         vs
.styles
[STYLE_DEFAULT
].characterSet
, selType 
== selRectangle
); 
4696 void Editor::CopyRangeToClipboard(int start
, int end
) { 
4697         start 
= pdoc
->ClampPositionIntoDocument(start
); 
4698         end 
= pdoc
->ClampPositionIntoDocument(end
); 
4699         SelectionText selectedText
; 
4700         selectedText
.Set(CopyRange(start
, end
), end 
- start 
+ 1, 
4701                 pdoc
->dbcsCodePage
, vs
.styles
[STYLE_DEFAULT
].characterSet
, false); 
4702         CopyToClipboard(selectedText
); 
4705 void Editor::CopyText(int length
, const char *text
) { 
4706         SelectionText selectedText
; 
4707         selectedText
.Copy(text
, length
, 
4708                 pdoc
->dbcsCodePage
, vs
.styles
[STYLE_DEFAULT
].characterSet
, false); 
4709         CopyToClipboard(selectedText
); 
4712 void Editor::SetDragPosition(int newPos
) { 
4714                 newPos 
= MovePositionOutsideChar(newPos
, 1); 
4717         if (posDrag 
!= newPos
) { 
4726 void Editor::DisplayCursor(Window::Cursor c
) { 
4727         if (cursorMode 
== SC_CURSORNORMAL
) 
4730                 wMain
.SetCursor(static_cast<Window::Cursor
>(cursorMode
)); 
4733 void Editor::StartDrag() { 
4734         // Always handled by subclasses 
4735         //SetMouseCapture(true); 
4736         //DisplayCursor(Window::cursorArrow); 
4739 void Editor::DropAt(int position
, const char *value
, bool moving
, bool rectangular
) { 
4740         //Platform::DebugPrintf("DropAt %d\n", inDragDrop); 
4742                 dropWentOutside 
= false; 
4744         int positionWasInSelection 
= PositionInSelection(position
); 
4746         bool positionOnEdgeOfSelection 
= 
4747             (position 
== SelectionStart()) || (position 
== SelectionEnd()); 
4749         if ((!inDragDrop
) || !(0 == positionWasInSelection
) || 
4750                 (positionOnEdgeOfSelection 
&& !moving
)) { 
4752                 int selStart 
= SelectionStart(); 
4753                 int selEnd 
= SelectionEnd(); 
4755                 pdoc
->BeginUndoAction(); 
4757                 int positionAfterDeletion 
= position
; 
4758                 if (inDragDrop 
&& moving
) { 
4759                         // Remove dragged out text 
4760                         if (rectangular 
|| selType 
== selLines
) { 
4761                                 SelectionLineIterator 
lineIterator(this); 
4762                                 while (lineIterator
.Iterate()) { 
4763                                         if (position 
>= lineIterator
.startPos
) { 
4764                                                 if (position 
> lineIterator
.endPos
) { 
4765                                                         positionAfterDeletion 
-= lineIterator
.endPos 
- lineIterator
.startPos
; 
4767                                                         positionAfterDeletion 
-= position 
- lineIterator
.startPos
; 
4772                                 if (position 
> selStart
) { 
4773                                         positionAfterDeletion 
-= selEnd 
- selStart
; 
4778                 position 
= positionAfterDeletion
; 
4781                         PasteRectangular(position
, value
, istrlen(value
)); 
4782                         pdoc
->EndUndoAction(); 
4783                         // Should try to select new rectangle but it may not be a rectangle now so just select the drop position 
4784                         SetEmptySelection(position
); 
4786                         position 
= MovePositionOutsideChar(position
, currentPos 
- position
); 
4787                         if (pdoc
->InsertString(position
, value
)) { 
4788                                 SetSelection(position 
+ istrlen(value
), position
); 
4790                         pdoc
->EndUndoAction(); 
4792         } else if (inDragDrop
) { 
4793                 SetEmptySelection(position
); 
4798  * @return -1 if given position is before the selection, 
4799  *          1 if position is after the selection, 
4800  *          0 if position is inside the selection, 
4802 int Editor::PositionInSelection(int pos
) { 
4803         pos 
= MovePositionOutsideChar(pos
, currentPos 
- pos
); 
4804         if (pos 
< SelectionStart()) { 
4807         if (pos 
> SelectionEnd()) { 
4810         if (selType 
== selStream
) { 
4813                 SelectionLineIterator 
lineIterator(this); 
4814                 lineIterator
.SetAt(pdoc
->LineFromPosition(pos
)); 
4815                 if (pos 
< lineIterator
.startPos
) { 
4817                 } else if (pos 
> lineIterator
.endPos
) { 
4825 bool Editor::PointInSelection(Point pt
) { 
4826         int pos 
= PositionFromLocation(pt
); 
4827         if (0 == PositionInSelection(pos
)) { 
4828                 // Probably inside, but we must make a finer test 
4829                 int selStart
, selEnd
; 
4830                 if (selType 
== selStream
) { 
4831                         selStart 
= SelectionStart(); 
4832                         selEnd 
= SelectionEnd(); 
4834                         SelectionLineIterator 
lineIterator(this); 
4835                         lineIterator
.SetAt(pdoc
->LineFromPosition(pos
)); 
4836                         selStart 
= lineIterator
.startPos
; 
4837                         selEnd 
= lineIterator
.endPos
; 
4839                 if (pos 
== selStart
) { 
4840                         // see if just before selection 
4841                         Point locStart 
= LocationFromPosition(pos
); 
4842                         if (pt
.x 
< locStart
.x
) { 
4846                 if (pos 
== selEnd
) { 
4847                         // see if just after selection 
4848                         Point locEnd 
= LocationFromPosition(pos
); 
4849                         if (pt
.x 
> locEnd
.x
) { 
4858 bool Editor::PointInSelMargin(Point pt
) { 
4859         // Really means: "Point in a margin" 
4860         if (vs
.fixedColumnWidth 
> 0) {  // There is a margin 
4861                 PRectangle rcSelMargin 
= GetClientRectangle(); 
4862                 rcSelMargin
.right 
= vs
.fixedColumnWidth 
- vs
.leftMarginWidth
; 
4863                 return rcSelMargin
.Contains(pt
); 
4869 void Editor::LineSelection(int lineCurrent_
, int lineAnchor_
) { 
4870         if (lineAnchor_ 
< lineCurrent_
) { 
4871                 SetSelection(pdoc
->LineStart(lineCurrent_ 
+ 1), 
4872                              pdoc
->LineStart(lineAnchor_
)); 
4873         } else if (lineAnchor_ 
> lineCurrent_
) { 
4874                 SetSelection(pdoc
->LineStart(lineCurrent_
), 
4875                              pdoc
->LineStart(lineAnchor_ 
+ 1)); 
4876         } else { // Same line, select it 
4877                 SetSelection(pdoc
->LineStart(lineAnchor_ 
+ 1), 
4878                              pdoc
->LineStart(lineAnchor_
)); 
4882 void Editor::DwellEnd(bool mouseMoved
) { 
4884                 ticksToDwell 
= dwellDelay
; 
4886                 ticksToDwell 
= SC_TIME_FOREVER
; 
4887         if (dwelling 
&& (dwellDelay 
< SC_TIME_FOREVER
)) { 
4889                 NotifyDwelling(ptMouseLast
, dwelling
); 
4893 void Editor::ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
) { 
4894         //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt); 
4896         int newPos 
= PositionFromLocation(pt
); 
4897         newPos 
= MovePositionOutsideChar(newPos
, currentPos 
- newPos
); 
4899         moveExtendsSelection 
= false; 
4901         bool processed 
= NotifyMarginClick(pt
, shift
, ctrl
, alt
); 
4905         bool inSelMargin 
= PointInSelMargin(pt
); 
4906         if (shift 
& !inSelMargin
) { 
4907                 SetSelection(newPos
); 
4909         if (((curTime 
- lastClickTime
) < Platform::DoubleClickTime()) && Close(pt
, lastClick
)) { 
4910                 //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); 
4911                 SetMouseCapture(true); 
4912                 SetEmptySelection(newPos
); 
4913                 bool doubleClick 
= false; 
4914                 // Stop mouse button bounce changing selection type 
4915                 if (!Platform::MouseButtonBounce() || curTime 
!= lastClickTime
) { 
4916                         if (selectionType 
== selChar
) { 
4917                                 selectionType 
= selWord
; 
4919                         } else if (selectionType 
== selWord
) { 
4920                                 selectionType 
= selLine
; 
4922                                 selectionType 
= selChar
; 
4923                                 originalAnchorPos 
= currentPos
; 
4927                 if (selectionType 
== selWord
) { 
4928                         if (currentPos 
>= originalAnchorPos
) {  // Moved forward 
4929                                 SetSelection(pdoc
->ExtendWordSelect(currentPos
, 1), 
4930                                              pdoc
->ExtendWordSelect(originalAnchorPos
, -1)); 
4931                         } else {        // Moved backward 
4932                                 SetSelection(pdoc
->ExtendWordSelect(currentPos
, -1), 
4933                                              pdoc
->ExtendWordSelect(originalAnchorPos
, 1)); 
4935                 } else if (selectionType 
== selLine
) { 
4936                         lineAnchor 
= LineFromLocation(pt
); 
4937                         SetSelection(pdoc
->LineStart(lineAnchor 
+ 1), pdoc
->LineStart(lineAnchor
)); 
4938                         //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos); 
4940                         SetEmptySelection(currentPos
); 
4942                 //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos); 
4944                         NotifyDoubleClick(pt
, shift
); 
4945                         if (PositionIsHotspot(newPos
)) 
4946                                 NotifyHotSpotDoubleClicked(newPos
, shift
, ctrl
, alt
); 
4948         } else {        // Single click 
4950                         selType 
= selStream
; 
4953                                 lastClickTime 
= curTime
; 
4957                                 lineAnchor 
= LineFromLocation(pt
); 
4958                                 // Single click in margin: select whole line 
4959                                 LineSelection(lineAnchor
, lineAnchor
); 
4960                                 SetSelection(pdoc
->LineStart(lineAnchor 
+ 1), 
4961                                              pdoc
->LineStart(lineAnchor
)); 
4963                                 // Single shift+click in margin: select from line anchor to clicked line 
4964                                 if (anchor 
> currentPos
) 
4965                                         lineAnchor 
= pdoc
->LineFromPosition(anchor 
- 1); 
4967                                         lineAnchor 
= pdoc
->LineFromPosition(anchor
); 
4968                                 int lineStart 
= LineFromLocation(pt
); 
4969                                 LineSelection(lineStart
, lineAnchor
); 
4970                                 //lineAnchor = lineStart; // Keep the same anchor for ButtonMove 
4973                         SetDragPosition(invalidPosition
); 
4974                         SetMouseCapture(true); 
4975                         selectionType 
= selLine
; 
4977                         if (PointIsHotspot(pt
)) { 
4978                                 NotifyHotSpotClicked(newPos
, shift
, ctrl
, alt
); 
4981                                 inDragDrop 
= PointInSelection(pt
); 
4984                                 SetMouseCapture(false); 
4985                                 SetDragPosition(newPos
); 
4986                                 CopySelectionRange(&drag
); 
4989                                 SetDragPosition(invalidPosition
); 
4990                                 SetMouseCapture(true); 
4992                                         SetEmptySelection(newPos
); 
4994                                 selType 
= alt 
? selRectangle 
: selStream
; 
4995                                 xStartSelect 
= xEndSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4996                                 selectionType 
= selChar
; 
4997                                 originalAnchorPos 
= currentPos
; 
5001         lastClickTime 
= curTime
; 
5003         ShowCaretAtCurrentPosition(); 
5006 bool Editor::PositionIsHotspot(int position
) { 
5007         return vs
.styles
[pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
].hotspot
; 
5010 bool Editor::PointIsHotspot(Point pt
) { 
5011         int pos 
= PositionFromLocationClose(pt
); 
5012         if (pos 
== INVALID_POSITION
) 
5014         return PositionIsHotspot(pos
); 
5017 void Editor::SetHotSpotRange(Point 
*pt
) { 
5019                 int pos 
= PositionFromLocation(*pt
); 
5021                 // If we don't limit this to word characters then the 
5022                 // range can encompass more than the run range and then 
5023                 // the underline will not be drawn properly. 
5024                 int hsStart_ 
= pdoc
->ExtendStyleRange(pos
, -1, vs
.hotspotSingleLine
); 
5025                 int hsEnd_ 
= pdoc
->ExtendStyleRange(pos
, 1, vs
.hotspotSingleLine
); 
5027                 // Only invalidate the range if the hotspot range has changed... 
5028                 if (hsStart_ 
!= hsStart 
|| hsEnd_ 
!= hsEnd
) { 
5029                         if (hsStart 
!= -1) { 
5030                                 InvalidateRange(hsStart
, hsEnd
); 
5034                         InvalidateRange(hsStart
, hsEnd
); 
5037                 if (hsStart 
!= -1) { 
5038                         int hsStart_ 
= hsStart
; 
5042                         InvalidateRange(hsStart_
, hsEnd_
); 
5050 void Editor::GetHotSpotRange(int& hsStart_
, int& hsEnd_
) { 
5055 void Editor::ButtonMove(Point pt
) { 
5056         if ((ptMouseLast
.x 
!= pt
.x
) || (ptMouseLast
.y 
!= pt
.y
)) { 
5060         //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); 
5061         if (HaveMouseCapture()) { 
5063                 // Slow down autoscrolling/selection 
5064                 autoScrollTimer
.ticksToWait 
-= timer
.tickSize
; 
5065                 if (autoScrollTimer
.ticksToWait 
> 0) 
5067                 autoScrollTimer
.ticksToWait 
= autoScrollDelay
; 
5070                 int movePos 
= PositionFromLocation(pt
); 
5071                 movePos 
= MovePositionOutsideChar(movePos
, currentPos 
- movePos
); 
5073                         SetDragPosition(movePos
); 
5075                         if (selectionType 
== selChar
) { 
5076                                 SetSelection(movePos
); 
5077                         } else if (selectionType 
== selWord
) { 
5078                                 // Continue selecting by word 
5079                                 if (movePos 
== originalAnchorPos
) {     // Didn't move 
5080                                         // No need to do anything. Previously this case was lumped 
5081                                         // in with "Moved forward", but that can be harmful in this 
5082                                         // case: a handler for the NotifyDoubleClick re-adjusts 
5083                                         // the selection for a fancier definition of "word" (for 
5084                                         // example, in Perl it is useful to include the leading 
5085                                         // '$', '%' or '@' on variables for word selection). In this 
5086                                         // the ButtonMove() called via Tick() for auto-scrolling 
5087                                         // could result in the fancier word selection adjustment 
5089                                 } else if (movePos 
> originalAnchorPos
) {       // Moved forward 
5090                                         SetSelection(pdoc
->ExtendWordSelect(movePos
, 1), 
5091                                                      pdoc
->ExtendWordSelect(originalAnchorPos
, -1)); 
5092                                 } else {        // Moved backward 
5093                                         SetSelection(pdoc
->ExtendWordSelect(movePos
, -1), 
5094                                                      pdoc
->ExtendWordSelect(originalAnchorPos
, 1)); 
5097                                 // Continue selecting by line 
5098                                 int lineMove 
= LineFromLocation(pt
); 
5099                                 LineSelection(lineMove
, lineAnchor
); 
5102                 // While dragging to make rectangular selection, we don't want the current 
5103                 // position to jump to the end of smaller or empty lines. 
5104                 //xEndSelect = pt.x - vs.fixedColumnWidth + xOffset; 
5105                 xEndSelect 
= XFromPosition(movePos
); 
5108                 PRectangle rcClient 
= GetClientRectangle(); 
5109                 if (pt
.y 
> rcClient
.bottom
) { 
5110                         int lineMove 
= cs
.DisplayFromDoc(LineFromLocation(pt
)); 
5112                                 lineMove 
= cs
.DisplayFromDoc(pdoc
->LinesTotal() - 1); 
5114                         ScrollTo(lineMove 
- LinesOnScreen() + 5); 
5116                 } else if (pt
.y 
< rcClient
.top
) { 
5117                         int lineMove 
= cs
.DisplayFromDoc(LineFromLocation(pt
)); 
5118                         ScrollTo(lineMove 
- 5); 
5121                 EnsureCaretVisible(false, false, true); 
5123                 if (hsStart 
!= -1 && !PositionIsHotspot(movePos
)) 
5124                         SetHotSpotRange(NULL
); 
5127                 if (vs
.fixedColumnWidth 
> 0) {  // There is a margin 
5128                         if (PointInSelMargin(pt
)) { 
5129                                 DisplayCursor(Window::cursorReverseArrow
); 
5130                                 return;         // No need to test for selection 
5133                 // Display regular (drag) cursor over selection 
5134                 if (PointInSelection(pt
)) { 
5135                         DisplayCursor(Window::cursorArrow
); 
5136                 } else if (PointIsHotspot(pt
)) { 
5137                         DisplayCursor(Window::cursorHand
); 
5138                         SetHotSpotRange(&pt
); 
5140                         DisplayCursor(Window::cursorText
); 
5141                         SetHotSpotRange(NULL
); 
5146 void Editor::ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
) { 
5147         //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture()); 
5148         if (HaveMouseCapture()) { 
5149                 if (PointInSelMargin(pt
)) { 
5150                         DisplayCursor(Window::cursorReverseArrow
); 
5152                         DisplayCursor(Window::cursorText
); 
5153                         SetHotSpotRange(NULL
); 
5156                 SetMouseCapture(false); 
5157                 int newPos 
= PositionFromLocation(pt
); 
5158                 newPos 
= MovePositionOutsideChar(newPos
, currentPos 
- newPos
); 
5160                         int selStart 
= SelectionStart(); 
5161                         int selEnd 
= SelectionEnd(); 
5162                         if (selStart 
< selEnd
) { 
5165                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
5166                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
5168                                         } else if (newPos 
< selStart
) { 
5169                                                 pdoc
->DeleteChars(selStart
, drag
.len
); 
5170                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
5171                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
5173                                         } else if (newPos 
> selEnd
) { 
5174                                                 pdoc
->DeleteChars(selStart
, drag
.len
); 
5176                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
5177                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
5180                                                 SetEmptySelection(newPos
); 
5184                                 selectionType 
= selChar
; 
5187                         if (selectionType 
== selChar
) { 
5188                                 SetSelection(newPos
); 
5191                 // Now we rely on the current pos to compute rectangular selection 
5192                 xStartSelect 
= XFromPosition(anchor
); 
5193                 xEndSelect 
= XFromPosition(currentPos
); 
5194                 lastClickTime 
= curTime
; 
5197                 if (selType 
== selStream
) { 
5201                 EnsureCaretVisible(false); 
5205 // Called frequently to perform background UI including 
5206 // caret blinking and automatic scrolling. 
5207 void Editor::Tick() { 
5208         if (HaveMouseCapture()) { 
5210                 ButtonMove(ptMouseLast
); 
5212         if (caret
.period 
> 0) { 
5213                 timer
.ticksToWait 
-= timer
.tickSize
; 
5214                 if (timer
.ticksToWait 
<= 0) { 
5215                         caret
.on 
= !caret
.on
; 
5216                         timer
.ticksToWait 
= caret
.period
; 
5220         if ((dwellDelay 
< SC_TIME_FOREVER
) && 
5221                 (ticksToDwell 
> 0) && 
5222                 (!HaveMouseCapture())) { 
5223                 ticksToDwell 
-= timer
.tickSize
; 
5224                 if (ticksToDwell 
<= 0) { 
5226                         NotifyDwelling(ptMouseLast
, dwelling
); 
5231 bool Editor::Idle() { 
5235         bool wrappingDone 
= (wrapState 
== eWrapNone
) || (!backgroundWrapEnabled
); 
5237         if (!wrappingDone
) { 
5238                 // Wrap lines during idle. 
5239                 WrapLines(false, -1); 
5241                 if (docLineLastWrapped 
== docLastLineToWrap
) 
5242                         wrappingDone 
= true; 
5245         // Add more idle things to do here, but make sure idleDone is 
5246         // set correctly before the function returns. returning 
5247         // false will stop calling this idle funtion until SetIdle() is 
5250         idleDone 
= wrappingDone
; // && thatDone && theOtherThingDone... 
5255 void Editor::SetFocusState(bool focusState
) { 
5256         hasFocus 
= focusState
; 
5257         NotifyFocus(hasFocus
); 
5259                 ShowCaretAtCurrentPosition(); 
5266 static bool IsIn(int a
, int minimum
, int maximum
) { 
5267         return (a 
>= minimum
) && (a 
<= maximum
); 
5270 static bool IsOverlap(int mina
, int maxa
, int minb
, int maxb
) { 
5272             IsIn(mina
, minb
, maxb
) || 
5273             IsIn(maxa
, minb
, maxb
) || 
5274             IsIn(minb
, mina
, maxa
) || 
5275             IsIn(maxb
, mina
, maxa
); 
5278 void Editor::CheckForChangeOutsidePaint(Range r
) { 
5279         if (paintState 
== painting 
&& !paintingAllText
) { 
5280                 //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end); 
5284                 PRectangle rcText 
= GetTextRectangle(); 
5285                 // Determine number of lines displayed including a possible partially displayed last line 
5286                 int linesDisplayed 
= (rcText
.bottom 
- rcText
.top 
- 1) / vs
.lineHeight 
+ 1; 
5287                 int bottomLine 
= topLine 
+ linesDisplayed 
- 1; 
5289                 int lineRangeStart 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.start
)); 
5290                 int lineRangeEnd 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.end
)); 
5291                 if (!IsOverlap(topLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) { 
5292                         //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n", 
5293                         //              lineRangeStart, lineRangeEnd, topLine, bottomLine); 
5297                 // Assert rcPaint contained within or equal to rcText 
5298                 if (rcPaint
.top 
> rcText
.top
) { 
5299                         // does range intersect rcText.top .. rcPaint.top 
5300                         int paintTopLine 
= ((rcPaint
.top 
- rcText
.top 
- 1) / vs
.lineHeight
) + topLine
; 
5301                         // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle 
5302                         if (IsOverlap(topLine
, paintTopLine
, lineRangeStart
, lineRangeEnd
)) { 
5303                                 //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n", 
5304                                 //      lineRangeStart, lineRangeEnd, topLine, paintTopLine); 
5309                 if (rcPaint
.bottom 
< rcText
.bottom
) { 
5310                         // does range intersect rcPaint.bottom .. rcText.bottom 
5311                         int paintBottomLine 
= ((rcPaint
.bottom 
- rcText
.top 
- 1) / vs
.lineHeight 
+ 1) + topLine
; 
5312                         // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle 
5313                         if (IsOverlap(paintBottomLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) { 
5314                                 //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n", 
5315                                 //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine); 
5323 char BraceOpposite(char ch
) { 
5346 // TODO: should be able to extend styled region to find matching brace 
5347 // TODO: may need to make DBCS safe 
5348 // so should be moved into Document 
5349 int Editor::BraceMatch(int position
, int /*maxReStyle*/) { 
5350         char chBrace 
= pdoc
->CharAt(position
); 
5351         char chSeek 
= BraceOpposite(chBrace
); 
5354         char styBrace 
= static_cast<char>( 
5355                             pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
); 
5357         if (chBrace 
== '(' || chBrace 
== '[' || chBrace 
== '{' || chBrace 
== '<') 
5360         position 
= position 
+ direction
; 
5361         while ((position 
>= 0) && (position 
< pdoc
->Length())) { 
5362                 char chAtPos 
= pdoc
->CharAt(position
); 
5363                 char styAtPos 
= static_cast<char>(pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
); 
5364                 if ((position 
> pdoc
->GetEndStyled()) || (styAtPos 
== styBrace
)) { 
5365                         if (chAtPos 
== chBrace
) 
5367                         if (chAtPos 
== chSeek
) 
5372                 position 
= position 
+ direction
; 
5377 void Editor::SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
) { 
5378         if ((pos0 
!= braces
[0]) || (pos1 
!= braces
[1]) || (matchStyle 
!= bracesMatchStyle
)) { 
5379                 if ((braces
[0] != pos0
) || (matchStyle 
!= bracesMatchStyle
)) { 
5380                         CheckForChangeOutsidePaint(Range(braces
[0])); 
5381                         CheckForChangeOutsidePaint(Range(pos0
)); 
5384                 if ((braces
[1] != pos1
) || (matchStyle 
!= bracesMatchStyle
)) { 
5385                         CheckForChangeOutsidePaint(Range(braces
[1])); 
5386                         CheckForChangeOutsidePaint(Range(pos1
)); 
5389                 bracesMatchStyle 
= matchStyle
; 
5390                 if (paintState 
== notPainting
) { 
5396 void Editor::SetDocPointer(Document 
*document
) { 
5397         //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document); 
5398         pdoc
->RemoveWatcher(this, 0); 
5400         if (document 
== NULL
) { 
5401                 pdoc 
= new Document(); 
5407         // Ensure all positions within document 
5408         selType 
= selStream
; 
5414         braces
[0] = invalidPosition
; 
5415         braces
[1] = invalidPosition
; 
5417         // Reset the contraction state to fully shown. 
5419         cs
.InsertLines(0, pdoc
->LinesTotal() - 1); 
5423         pdoc
->AddWatcher(this, 0); 
5429  * Recursively expand a fold, making lines visible except where they have an unexpanded parent. 
5431 void Editor::Expand(int &line
, bool doExpand
) { 
5432         int lineMaxSubord 
= pdoc
->GetLastChild(line
); 
5434         while (line 
<= lineMaxSubord
) { 
5436                         cs
.SetVisible(line
, line
, true); 
5437                 int level 
= pdoc
->GetLevel(line
); 
5438                 if (level 
& SC_FOLDLEVELHEADERFLAG
) { 
5439                         if (doExpand 
&& cs
.GetExpanded(line
)) { 
5442                                 Expand(line
, false); 
5450 void Editor::ToggleContraction(int line
) { 
5452                 if ((pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) == 0) { 
5453                         line 
= pdoc
->GetFoldParent(line
); 
5458                 if (cs
.GetExpanded(line
)) { 
5459                         int lineMaxSubord 
= pdoc
->GetLastChild(line
); 
5460                         cs
.SetExpanded(line
, 0); 
5461                         if (lineMaxSubord 
> line
) { 
5462                                 cs
.SetVisible(line 
+ 1, lineMaxSubord
, false); 
5464                                 int lineCurrent 
= pdoc
->LineFromPosition(currentPos
); 
5465                                 if (lineCurrent 
> line 
&& lineCurrent 
<= lineMaxSubord
) { 
5466                                         // This does not re-expand the fold 
5467                                         EnsureCaretVisible(); 
5475                         if (!(cs
.GetVisible(line
))) { 
5476                                 EnsureLineVisible(line
, false); 
5479                         cs
.SetExpanded(line
, 1); 
5488  * Recurse up from this line to find any folds that prevent this line from being visible 
5489  * and unfold them all. 
5491 void Editor::EnsureLineVisible(int lineDoc
, bool enforcePolicy
) { 
5493         // In case in need of wrapping to ensure DisplayFromDoc works. 
5494         WrapLines(true, -1); 
5496         if (!cs
.GetVisible(lineDoc
)) { 
5497                 int lineParent 
= pdoc
->GetFoldParent(lineDoc
); 
5498                 if (lineParent 
>= 0) { 
5499                         if (lineDoc 
!= lineParent
) 
5500                                 EnsureLineVisible(lineParent
, enforcePolicy
); 
5501                         if (!cs
.GetExpanded(lineParent
)) { 
5502                                 cs
.SetExpanded(lineParent
, 1); 
5503                                 Expand(lineParent
, true); 
5509         if (enforcePolicy
) { 
5510                 int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
5511                 if (visiblePolicy 
& VISIBLE_SLOP
) { 
5512                         if ((topLine 
> lineDisplay
) || ((visiblePolicy 
& VISIBLE_STRICT
) && (topLine 
+ visibleSlop 
> lineDisplay
))) { 
5513                                 SetTopLine(Platform::Clamp(lineDisplay 
- visibleSlop
, 0, MaxScrollPos())); 
5514                                 SetVerticalScrollPos(); 
5516                         } else if ((lineDisplay 
> topLine 
+ LinesOnScreen() - 1) || 
5517                                    ((visiblePolicy 
& VISIBLE_STRICT
) && (lineDisplay 
> topLine 
+ LinesOnScreen() - 1 - visibleSlop
))) { 
5518                                 SetTopLine(Platform::Clamp(lineDisplay 
- LinesOnScreen() + 1 + visibleSlop
, 0, MaxScrollPos())); 
5519                                 SetVerticalScrollPos(); 
5523                         if ((topLine 
> lineDisplay
) || (lineDisplay 
> topLine 
+ LinesOnScreen() - 1) || (visiblePolicy 
& VISIBLE_STRICT
)) { 
5524                                 SetTopLine(Platform::Clamp(lineDisplay 
- LinesOnScreen() / 2 + 1, 0, MaxScrollPos())); 
5525                                 SetVerticalScrollPos(); 
5532 int Editor::ReplaceTarget(bool replacePatterns
, const char *text
, int length
) { 
5533         pdoc
->BeginUndoAction(); 
5535                 length 
= istrlen(text
); 
5536         if (replacePatterns
) { 
5537                 text 
= pdoc
->SubstituteByPosition(text
, &length
); 
5541         if (targetStart 
!= targetEnd
) 
5542                 pdoc
->DeleteChars(targetStart
, targetEnd 
- targetStart
); 
5543         targetEnd 
= targetStart
; 
5544         pdoc
->InsertString(targetStart
, text
, length
); 
5545         targetEnd 
= targetStart 
+ length
; 
5546         pdoc
->EndUndoAction(); 
5550 bool Editor::IsUnicodeMode() const { 
5551         return pdoc 
&& (SC_CP_UTF8 
== pdoc
->dbcsCodePage
); 
5554 int Editor::CodePage() const { 
5556                 return pdoc
->dbcsCodePage
; 
5561 static bool ValidMargin(unsigned long wParam
) { 
5562         return wParam 
< ViewStyle::margins
; 
5565 static char *CharPtrFromSPtr(sptr_t lParam
) { 
5566         return reinterpret_cast<char *>(lParam
); 
5569 sptr_t 
Editor::WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) { 
5570         //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam); 
5572         // Optional macro recording hook 
5574                 NotifyMacroRecord(iMessage
, wParam
, lParam
); 
5580                                 return pdoc
->Length() + 1; 
5583                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5584                         unsigned int iChar 
= 0; 
5585                         for (; iChar 
< wParam 
- 1; iChar
++) 
5586                                 ptr
[iChar
] = pdoc
->CharAt(iChar
); 
5594                         pdoc
->BeginUndoAction(); 
5595                         pdoc
->DeleteChars(0, pdoc
->Length()); 
5596                         SetEmptySelection(0); 
5597                         pdoc
->InsertString(0, CharPtrFromSPtr(lParam
)); 
5598                         pdoc
->EndUndoAction(); 
5602         case SCI_GETTEXTLENGTH
: 
5603                 return pdoc
->Length(); 
5615                 CopyRangeToClipboard(wParam
, lParam
); 
5619                 CopyText(wParam
, CharPtrFromSPtr(lParam
)); 
5625                 EnsureCaretVisible(); 
5631                 EnsureCaretVisible(); 
5640                 return pdoc
->CanUndo() ? 1 : 0; 
5642         case SCI_EMPTYUNDOBUFFER
: 
5643                 pdoc
->DeleteUndoHistory(); 
5646         case SCI_GETFIRSTVISIBLELINE
: 
5649         case SCI_GETLINE
: {     // Risk of overwriting the end of the buffer 
5650                         int lineStart 
= pdoc
->LineStart(wParam
); 
5651                         int lineEnd 
= pdoc
->LineStart(wParam 
+ 1); 
5653                                 return lineEnd 
- lineStart
; 
5655                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5657                         for (int iChar 
= lineStart
; iChar 
< lineEnd
; iChar
++) { 
5658                                 ptr
[iPlace
++] = pdoc
->CharAt(iChar
); 
5663         case SCI_GETLINECOUNT
: 
5664                 if (pdoc
->LinesTotal() == 0) 
5667                         return pdoc
->LinesTotal(); 
5670                 return !pdoc
->IsSavePoint(); 
5673                         int nStart 
= static_cast<int>(wParam
); 
5674                         int nEnd 
= static_cast<int>(lParam
); 
5676                                 nEnd 
= pdoc
->Length(); 
5678                                 nStart 
= nEnd
;  // Remove selection 
5679                         selType 
= selStream
; 
5680                         SetSelection(nEnd
, nStart
); 
5681                         EnsureCaretVisible(); 
5685         case SCI_GETSELTEXT
: { 
5687                                 if (selType 
== selStream
) { 
5688                                         return 1 + SelectionEnd() - SelectionStart(); 
5690                                         // TODO: why is selLines handled the slow way? 
5692                                         int extraCharsPerLine 
= 0; 
5693                                         if (selType 
!= selLines
) 
5694                                                 extraCharsPerLine 
= (pdoc
->eolMode 
== SC_EOL_CRLF
) ? 2 : 1; 
5695                                         SelectionLineIterator 
lineIterator(this); 
5696                                         while (lineIterator
.Iterate()) { 
5697                                                 size 
+= lineIterator
.endPos 
+ extraCharsPerLine 
- lineIterator
.startPos
; 
5703                         SelectionText selectedText
; 
5704                         CopySelectionRange(&selectedText
); 
5705                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5707                         if (selectedText
.len
) { 
5708                                 for (; iChar 
< selectedText
.len
; iChar
++) 
5709                                         ptr
[iChar
] = selectedText
.s
[iChar
]; 
5716         case SCI_LINEFROMPOSITION
: 
5717                 if (static_cast<int>(wParam
) < 0) 
5719                 return pdoc
->LineFromPosition(wParam
); 
5721         case SCI_POSITIONFROMLINE
: 
5722                 if (static_cast<int>(wParam
) < 0) 
5723                         wParam 
= pdoc
->LineFromPosition(SelectionStart()); 
5725                         return 0;       // Even if there is no text, there is a first line that starts at 0 
5726                 if (static_cast<int>(wParam
) > pdoc
->LinesTotal()) 
5728                 //if (wParam > pdoc->LineFromPosition(pdoc->Length()))  // Useful test, anyway... 
5730                 return pdoc
->LineStart(wParam
); 
5732                 // Replacement of the old Scintilla interpretation of EM_LINELENGTH 
5733         case SCI_LINELENGTH
: 
5734                 if ((static_cast<int>(wParam
) < 0) || 
5735                         (static_cast<int>(wParam
) > pdoc
->LineFromPosition(pdoc
->Length()))) 
5737                 return pdoc
->LineStart(wParam 
+ 1) - pdoc
->LineStart(wParam
); 
5739         case SCI_REPLACESEL
: { 
5742                         pdoc
->BeginUndoAction(); 
5744                         char *replacement 
= CharPtrFromSPtr(lParam
); 
5745                         pdoc
->InsertString(currentPos
, replacement
); 
5746                         pdoc
->EndUndoAction(); 
5747                         SetEmptySelection(currentPos 
+ istrlen(replacement
)); 
5748                         EnsureCaretVisible(); 
5752         case SCI_SETTARGETSTART
: 
5753                 targetStart 
= wParam
; 
5756         case SCI_GETTARGETSTART
: 
5759         case SCI_SETTARGETEND
: 
5763         case SCI_GETTARGETEND
: 
5766         case SCI_TARGETFROMSELECTION
: 
5767                 if (currentPos 
< anchor
) { 
5768                         targetStart 
= currentPos
; 
5771                         targetStart 
= anchor
; 
5772                         targetEnd 
= currentPos
; 
5776         case SCI_REPLACETARGET
: 
5777                 PLATFORM_ASSERT(lParam
); 
5778                 return ReplaceTarget(false, CharPtrFromSPtr(lParam
), wParam
); 
5780         case SCI_REPLACETARGETRE
: 
5781                 PLATFORM_ASSERT(lParam
); 
5782                 return ReplaceTarget(true, CharPtrFromSPtr(lParam
), wParam
); 
5784         case SCI_SEARCHINTARGET
: 
5785                 PLATFORM_ASSERT(lParam
); 
5786                 return SearchInTarget(CharPtrFromSPtr(lParam
), wParam
); 
5788         case SCI_SETSEARCHFLAGS
: 
5789                 searchFlags 
= wParam
; 
5792         case SCI_GETSEARCHFLAGS
: 
5795         case SCI_POSITIONBEFORE
: 
5796                 return pdoc
->MovePositionOutsideChar(wParam
-1, -1, true); 
5798         case SCI_POSITIONAFTER
: 
5799                 return pdoc
->MovePositionOutsideChar(wParam
+1, 1, true); 
5801         case SCI_LINESCROLL
: 
5802                 ScrollTo(topLine 
+ lParam
); 
5803                 HorizontalScrollTo(xOffset 
+ wParam 
* vs
.spaceWidth
); 
5806         case SCI_SETXOFFSET
: 
5808                 SetHorizontalScrollPos(); 
5812         case SCI_GETXOFFSET
: 
5815         case SCI_CHOOSECARETX
: 
5819         case SCI_SCROLLCARET
: 
5820                 EnsureCaretVisible(); 
5823         case SCI_SETREADONLY
: 
5824                 pdoc
->SetReadOnly(wParam 
!= 0); 
5827         case SCI_GETREADONLY
: 
5828                 return pdoc
->IsReadOnly(); 
5833         case SCI_POINTXFROMPOSITION
: 
5837                         Point pt 
= LocationFromPosition(lParam
); 
5841         case SCI_POINTYFROMPOSITION
: 
5845                         Point pt 
= LocationFromPosition(lParam
); 
5850                 return FindText(wParam
, lParam
); 
5852         case SCI_GETTEXTRANGE
: { 
5855                         TextRange 
*tr 
= reinterpret_cast<TextRange 
*>(lParam
); 
5856                         int cpMax 
= tr
->chrg
.cpMax
; 
5858                                 cpMax 
= pdoc
->Length(); 
5859                         PLATFORM_ASSERT(cpMax 
<= pdoc
->Length()); 
5860                         int len 
= cpMax 
- tr
->chrg
.cpMin
;       // No -1 as cpMin and cpMax are referring to inter character positions 
5861                         pdoc
->GetCharRange(tr
->lpstrText
, tr
->chrg
.cpMin
, len
); 
5862                         // Spec says copied text is terminated with a NUL 
5863                         tr
->lpstrText
[len
] = '\0'; 
5864                         return len
;     // Not including NUL 
5867         case SCI_HIDESELECTION
: 
5868                 hideSelection 
= wParam 
!= 0; 
5872         case SCI_FORMATRANGE
: 
5873                 return FormatRange(wParam 
!= 0, reinterpret_cast<RangeToFormat 
*>(lParam
)); 
5875         case SCI_GETMARGINLEFT
: 
5876                 return vs
.leftMarginWidth
; 
5878         case SCI_GETMARGINRIGHT
: 
5879                 return vs
.rightMarginWidth
; 
5881         case SCI_SETMARGINLEFT
: 
5882                 vs
.leftMarginWidth 
= lParam
; 
5883                 InvalidateStyleRedraw(); 
5886         case SCI_SETMARGINRIGHT
: 
5887                 vs
.rightMarginWidth 
= lParam
; 
5888                 InvalidateStyleRedraw(); 
5891                 // Control specific mesages 
5896                         pdoc
->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam
), wParam
); 
5897                         SetEmptySelection(currentPos 
+ wParam
); 
5901         case SCI_ADDSTYLEDTEXT
: { 
5904                         pdoc
->InsertStyledString(CurrentPosition() * 2, CharPtrFromSPtr(lParam
), wParam
); 
5905                         SetEmptySelection(currentPos 
+ wParam 
/ 2); 
5909         case SCI_INSERTTEXT
: { 
5912                         int insertPos 
= wParam
; 
5913                         if (static_cast<int>(wParam
) == -1) 
5914                                 insertPos 
= CurrentPosition(); 
5915                         int newCurrent 
= CurrentPosition(); 
5916                         char *sz 
= CharPtrFromSPtr(lParam
); 
5917                         pdoc
->InsertString(insertPos
, sz
); 
5918                         if (newCurrent 
> insertPos
) 
5919                                 newCurrent 
+= istrlen(sz
); 
5920                         SetEmptySelection(newCurrent
); 
5924         case SCI_APPENDTEXT
: 
5925                 pdoc
->InsertString(pdoc
->Length(), CharPtrFromSPtr(lParam
), wParam
); 
5932         case SCI_CLEARDOCUMENTSTYLE
: 
5933                 ClearDocumentStyle(); 
5936         case SCI_SETUNDOCOLLECTION
: 
5937                 pdoc
->SetUndoCollection(wParam 
!= 0); 
5940         case SCI_GETUNDOCOLLECTION
: 
5941                 return pdoc
->IsCollectingUndo(); 
5943         case SCI_BEGINUNDOACTION
: 
5944                 pdoc
->BeginUndoAction(); 
5947         case SCI_ENDUNDOACTION
: 
5948                 pdoc
->EndUndoAction(); 
5951         case SCI_GETCARETPERIOD
: 
5952                 return caret
.period
; 
5954         case SCI_SETCARETPERIOD
: 
5955                 caret
.period 
= wParam
; 
5958         case SCI_SETWORDCHARS
: { 
5959                         pdoc
->SetDefaultCharClasses(false); 
5962                         pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), Document::ccWord
); 
5966         case SCI_SETWHITESPACECHARS
: { 
5969                         pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), Document::ccSpace
); 
5973         case SCI_SETCHARSDEFAULT
: 
5974                 pdoc
->SetDefaultCharClasses(true); 
5978                 return pdoc
->Length(); 
5981                 pdoc
->Allocate(wParam
); 
5985                 return pdoc
->CharAt(wParam
); 
5987         case SCI_SETCURRENTPOS
: 
5988                 SetSelection(wParam
, anchor
); 
5991         case SCI_GETCURRENTPOS
: 
5995                 SetSelection(currentPos
, wParam
); 
6001         case SCI_SETSELECTIONSTART
: 
6002                 SetSelection(Platform::Maximum(currentPos
, wParam
), wParam
); 
6005         case SCI_GETSELECTIONSTART
: 
6006                 return Platform::Minimum(anchor
, currentPos
); 
6008         case SCI_SETSELECTIONEND
: 
6009                 SetSelection(wParam
, Platform::Minimum(anchor
, wParam
)); 
6012         case SCI_GETSELECTIONEND
: 
6013                 return Platform::Maximum(anchor
, currentPos
); 
6015         case SCI_SETPRINTMAGNIFICATION
: 
6016                 printMagnification 
= wParam
; 
6019         case SCI_GETPRINTMAGNIFICATION
: 
6020                 return printMagnification
; 
6022         case SCI_SETPRINTCOLOURMODE
: 
6023                 printColourMode 
= wParam
; 
6026         case SCI_GETPRINTCOLOURMODE
: 
6027                 return printColourMode
; 
6029         case SCI_SETPRINTWRAPMODE
: 
6030                 printWrapState 
= (wParam 
== SC_WRAP_WORD
) ? eWrapWord 
: eWrapNone
; 
6033         case SCI_GETPRINTWRAPMODE
: 
6034                 return printWrapState
; 
6036         case SCI_GETSTYLEAT
: 
6037                 if (static_cast<int>(wParam
) >= pdoc
->Length()) 
6040                         return pdoc
->StyleAt(wParam
); 
6050         case SCI_SETSAVEPOINT
: 
6051                 pdoc
->SetSavePoint(); 
6054         case SCI_GETSTYLEDTEXT
: { 
6057                         TextRange 
*tr 
= reinterpret_cast<TextRange 
*>(lParam
); 
6059                         for (int iChar 
= tr
->chrg
.cpMin
; iChar 
< tr
->chrg
.cpMax
; iChar
++) { 
6060                                 tr
->lpstrText
[iPlace
++] = pdoc
->CharAt(iChar
); 
6061                                 tr
->lpstrText
[iPlace
++] = pdoc
->StyleAt(iChar
); 
6063                         tr
->lpstrText
[iPlace
] = '\0'; 
6064                         tr
->lpstrText
[iPlace 
+ 1] = '\0'; 
6069                 return pdoc
->CanRedo() ? 1 : 0; 
6071         case SCI_MARKERLINEFROMHANDLE
: 
6072                 return pdoc
->LineFromHandle(wParam
); 
6074         case SCI_MARKERDELETEHANDLE
: 
6075                 pdoc
->DeleteMarkFromHandle(wParam
); 
6079                 return vs
.viewWhitespace
; 
6082                 vs
.viewWhitespace 
= static_cast<WhiteSpaceVisibility
>(wParam
); 
6086         case SCI_POSITIONFROMPOINT
: 
6087                 return PositionFromLocation(Point(wParam
, lParam
)); 
6089         case SCI_POSITIONFROMPOINTCLOSE
: 
6090                 return PositionFromLocationClose(Point(wParam
, lParam
)); 
6097                 SetEmptySelection(wParam
); 
6098                 EnsureCaretVisible(); 
6102         case SCI_GETCURLINE
: { 
6103                         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
6104                         int lineStart 
= pdoc
->LineStart(lineCurrentPos
); 
6105                         unsigned int lineEnd 
= pdoc
->LineStart(lineCurrentPos 
+ 1); 
6107                                 return 1 + lineEnd 
- lineStart
; 
6109                         char *ptr 
= CharPtrFromSPtr(lParam
); 
6110                         unsigned int iPlace 
= 0; 
6111                         for (unsigned int iChar 
= lineStart
; iChar 
< lineEnd 
&& iPlace 
< wParam 
- 1; iChar
++) { 
6112                                 ptr
[iPlace
++] = pdoc
->CharAt(iChar
); 
6115                         return currentPos 
- lineStart
; 
6118         case SCI_GETENDSTYLED
: 
6119                 return pdoc
->GetEndStyled(); 
6121         case SCI_GETEOLMODE
: 
6122                 return pdoc
->eolMode
; 
6124         case SCI_SETEOLMODE
: 
6125                 pdoc
->eolMode 
= wParam
; 
6128         case SCI_STARTSTYLING
: 
6129                 pdoc
->StartStyling(wParam
, static_cast<char>(lParam
)); 
6132         case SCI_SETSTYLING
: 
6133                 pdoc
->SetStyleFor(wParam
, static_cast<char>(lParam
)); 
6136         case SCI_SETSTYLINGEX
:             // Specify a complete styling buffer 
6139                 pdoc
->SetStyles(wParam
, CharPtrFromSPtr(lParam
)); 
6142         case SCI_SETBUFFEREDDRAW
: 
6143                 bufferedDraw 
= wParam 
!= 0; 
6146         case SCI_GETBUFFEREDDRAW
: 
6147                 return bufferedDraw
; 
6149         case SCI_GETTWOPHASEDRAW
: 
6150                 return twoPhaseDraw
; 
6152         case SCI_SETTWOPHASEDRAW
: 
6153                 twoPhaseDraw 
= wParam 
!= 0; 
6154                 InvalidateStyleRedraw(); 
6157         case SCI_SETTABWIDTH
: 
6159                         pdoc
->tabInChars 
= wParam
; 
6160                         if (pdoc
->indentInChars 
== 0) 
6161                                 pdoc
->actualIndentInChars 
= pdoc
->tabInChars
; 
6163                 InvalidateStyleRedraw(); 
6166         case SCI_GETTABWIDTH
: 
6167                 return pdoc
->tabInChars
; 
6170                 pdoc
->indentInChars 
= wParam
; 
6171                 if (pdoc
->indentInChars 
!= 0) 
6172                         pdoc
->actualIndentInChars 
= pdoc
->indentInChars
; 
6174                         pdoc
->actualIndentInChars 
= pdoc
->tabInChars
; 
6175                 InvalidateStyleRedraw(); 
6179                 return pdoc
->indentInChars
; 
6181         case SCI_SETUSETABS
: 
6182                 pdoc
->useTabs 
= wParam 
!= 0; 
6183                 InvalidateStyleRedraw(); 
6186         case SCI_GETUSETABS
: 
6187                 return pdoc
->useTabs
; 
6189         case SCI_SETLINEINDENTATION
: 
6190                 pdoc
->SetLineIndentation(wParam
, lParam
); 
6193         case SCI_GETLINEINDENTATION
: 
6194                 return pdoc
->GetLineIndentation(wParam
); 
6196         case SCI_GETLINEINDENTPOSITION
: 
6197                 return pdoc
->GetLineIndentPosition(wParam
); 
6199         case SCI_SETTABINDENTS
: 
6200                 pdoc
->tabIndents 
= wParam 
!= 0; 
6203         case SCI_GETTABINDENTS
: 
6204                 return pdoc
->tabIndents
; 
6206         case SCI_SETBACKSPACEUNINDENTS
: 
6207                 pdoc
->backspaceUnindents 
= wParam 
!= 0; 
6210         case SCI_GETBACKSPACEUNINDENTS
: 
6211                 return pdoc
->backspaceUnindents
; 
6213         case SCI_SETMOUSEDWELLTIME
: 
6214                 dwellDelay 
= wParam
; 
6215                 ticksToDwell 
= dwellDelay
; 
6218         case SCI_GETMOUSEDWELLTIME
: 
6221         case SCI_WORDSTARTPOSITION
: 
6222                 return pdoc
->ExtendWordSelect(wParam
, -1, lParam 
!= 0); 
6224         case SCI_WORDENDPOSITION
: 
6225                 return pdoc
->ExtendWordSelect(wParam
, 1, lParam 
!= 0); 
6227         case SCI_SETWRAPMODE
: 
6228                 wrapState 
= (wParam 
== SC_WRAP_WORD
) ? eWrapWord 
: eWrapNone
; 
6230                 InvalidateStyleRedraw(); 
6231                 ReconfigureScrollBars(); 
6234         case SCI_GETWRAPMODE
: 
6237         case SCI_SETWRAPVISUALFLAGS
: 
6238                 wrapVisualFlags 
= wParam
; 
6239                 actualWrapVisualStartIndent 
= wrapVisualStartIndent
; 
6240                 if ((wrapVisualFlags 
& SC_WRAPVISUALFLAG_START
) && (actualWrapVisualStartIndent 
== 0)) 
6241                         actualWrapVisualStartIndent 
= 1; // must indent to show start visual 
6242                 InvalidateStyleRedraw(); 
6243                 ReconfigureScrollBars(); 
6246         case SCI_GETWRAPVISUALFLAGS
: 
6247                 return wrapVisualFlags
; 
6249         case SCI_SETWRAPVISUALFLAGSLOCATION
: 
6250                 wrapVisualFlagsLocation 
= wParam
; 
6251                 InvalidateStyleRedraw(); 
6254         case SCI_GETWRAPVISUALFLAGSLOCATION
: 
6255                 return wrapVisualFlagsLocation
; 
6257         case SCI_SETWRAPSTARTINDENT
: 
6258                 wrapVisualStartIndent 
= wParam
; 
6259                 actualWrapVisualStartIndent 
= wrapVisualStartIndent
; 
6260                 if ((wrapVisualFlags 
& SC_WRAPVISUALFLAG_START
) && (actualWrapVisualStartIndent 
== 0)) 
6261                         actualWrapVisualStartIndent 
= 1; // must indent to show start visual 
6262                 InvalidateStyleRedraw(); 
6263                 ReconfigureScrollBars(); 
6266         case SCI_GETWRAPSTARTINDENT
: 
6267                 return wrapVisualStartIndent
; 
6269         case SCI_SETLAYOUTCACHE
: 
6270                 llc
.SetLevel(wParam
); 
6273         case SCI_GETLAYOUTCACHE
: 
6274                 return llc
.GetLevel(); 
6276         case SCI_SETSCROLLWIDTH
: 
6277                 PLATFORM_ASSERT(wParam 
> 0); 
6278                 if ((wParam 
> 0) && (wParam 
!= static_cast<unsigned int >(scrollWidth
))) { 
6279                         scrollWidth 
= wParam
; 
6284         case SCI_GETSCROLLWIDTH
: 
6291         case SCI_LINESSPLIT
: 
6296                 PLATFORM_ASSERT(wParam 
<= STYLE_MAX
); 
6297                 PLATFORM_ASSERT(lParam
); 
6298                 return TextWidth(wParam
, CharPtrFromSPtr(lParam
)); 
6300         case SCI_TEXTHEIGHT
: 
6301                 return vs
.lineHeight
; 
6303         case SCI_SETENDATLASTLINE
: 
6304                 PLATFORM_ASSERT((wParam 
== 0) || (wParam 
== 1)); 
6305                 if (endAtLastLine 
!= (wParam 
!= 0)) { 
6306                         endAtLastLine 
= wParam 
!= 0; 
6311         case SCI_GETENDATLASTLINE
: 
6312                 return endAtLastLine
; 
6315                 return pdoc
->GetColumn(wParam
); 
6317         case SCI_FINDCOLUMN
: 
6318                 return pdoc
->FindColumn(wParam
, lParam
); 
6320         case SCI_SETHSCROLLBAR 
: 
6321                 if (horizontalScrollBarVisible 
!= (wParam 
!= 0)) { 
6322                         horizontalScrollBarVisible 
= wParam 
!= 0; 
6324                         ReconfigureScrollBars(); 
6328         case SCI_GETHSCROLLBAR
: 
6329                 return horizontalScrollBarVisible
; 
6331         case SCI_SETVSCROLLBAR
: 
6332                 if (verticalScrollBarVisible 
!= (wParam 
!= 0)) { 
6333                         verticalScrollBarVisible 
= wParam 
!= 0; 
6335                         ReconfigureScrollBars(); 
6339         case SCI_GETVSCROLLBAR
: 
6340                 return verticalScrollBarVisible
; 
6342         case SCI_SETINDENTATIONGUIDES
: 
6343                 vs
.viewIndentationGuides 
= wParam 
!= 0; 
6347         case SCI_GETINDENTATIONGUIDES
: 
6348                 return vs
.viewIndentationGuides
; 
6350         case SCI_SETHIGHLIGHTGUIDE
: 
6351                 if ((highlightGuideColumn 
!= static_cast<int>(wParam
)) || (wParam 
> 0)) { 
6352                         highlightGuideColumn 
= wParam
; 
6357         case SCI_GETHIGHLIGHTGUIDE
: 
6358                 return highlightGuideColumn
; 
6360         case SCI_GETLINEENDPOSITION
: 
6361                 return pdoc
->LineEnd(wParam
); 
6363         case SCI_SETCODEPAGE
: 
6364                 pdoc
->dbcsCodePage 
= wParam
; 
6365                 InvalidateStyleRedraw(); 
6368         case SCI_GETCODEPAGE
: 
6369                 return pdoc
->dbcsCodePage
; 
6371         case SCI_SETUSEPALETTE
: 
6372                 palette
.allowRealization 
= wParam 
!= 0; 
6373                 InvalidateStyleRedraw(); 
6376         case SCI_GETUSEPALETTE
: 
6377                 return palette
.allowRealization
; 
6379                 // Marker definition and setting 
6380         case SCI_MARKERDEFINE
: 
6381                 if (wParam 
<= MARKER_MAX
) 
6382                         vs
.markers
[wParam
].markType 
= lParam
; 
6383                 InvalidateStyleData(); 
6386         case SCI_MARKERSETFORE
: 
6387                 if (wParam 
<= MARKER_MAX
) 
6388                         vs
.markers
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6389                 InvalidateStyleData(); 
6392         case SCI_MARKERSETBACK
: 
6393                 if (wParam 
<= MARKER_MAX
) 
6394                         vs
.markers
[wParam
].back
.desired 
= ColourDesired(lParam
); 
6395                 InvalidateStyleData(); 
6398         case SCI_MARKERADD
: { 
6399                         int markerID 
= pdoc
->AddMark(wParam
, lParam
); 
6403         case SCI_MARKERDELETE
: 
6404                 pdoc
->DeleteMark(wParam
, lParam
); 
6407         case SCI_MARKERDELETEALL
: 
6408                 pdoc
->DeleteAllMarks(static_cast<int>(wParam
)); 
6412                 return pdoc
->GetMark(wParam
); 
6414         case SCI_MARKERNEXT
: { 
6415                         int lt 
= pdoc
->LinesTotal(); 
6416                         for (int iLine 
= wParam
; iLine 
< lt
; iLine
++) { 
6417                                 if ((pdoc
->GetMark(iLine
) & lParam
) != 0) 
6423         case SCI_MARKERPREVIOUS
: { 
6424                         for (int iLine 
= wParam
; iLine 
>= 0; iLine
--) { 
6425                                 if ((pdoc
->GetMark(iLine
) & lParam
) != 0) 
6431         case SCI_MARKERDEFINEPIXMAP
: 
6432                 if (wParam 
<= MARKER_MAX
) { 
6433                         vs
.markers
[wParam
].SetXPM(CharPtrFromSPtr(lParam
)); 
6435                 InvalidateStyleData(); 
6439         case SCI_SETMARGINTYPEN
: 
6440                 if (ValidMargin(wParam
)) { 
6441                         vs
.ms
[wParam
].symbol 
= (lParam 
== SC_MARGIN_SYMBOL
); 
6442                         InvalidateStyleRedraw(); 
6446         case SCI_GETMARGINTYPEN
: 
6447                 if (ValidMargin(wParam
)) 
6448                         return vs
.ms
[wParam
].symbol 
? SC_MARGIN_SYMBOL 
: SC_MARGIN_NUMBER
; 
6452         case SCI_SETMARGINWIDTHN
: 
6453                 if (ValidMargin(wParam
)) { 
6454                         // Short-circuit if the width is unchanged, to avoid unnecessary redraw. 
6455                         if (vs
.ms
[wParam
].width 
!= lParam
) { 
6456                                 vs
.ms
[wParam
].width 
= lParam
; 
6457                                 InvalidateStyleRedraw(); 
6462         case SCI_GETMARGINWIDTHN
: 
6463                 if (ValidMargin(wParam
)) 
6464                         return vs
.ms
[wParam
].width
; 
6468         case SCI_SETMARGINMASKN
: 
6469                 if (ValidMargin(wParam
)) { 
6470                         vs
.ms
[wParam
].mask 
= lParam
; 
6471                         InvalidateStyleRedraw(); 
6475         case SCI_GETMARGINMASKN
: 
6476                 if (ValidMargin(wParam
)) 
6477                         return vs
.ms
[wParam
].mask
; 
6481         case SCI_SETMARGINSENSITIVEN
: 
6482                 if (ValidMargin(wParam
)) { 
6483                         vs
.ms
[wParam
].sensitive 
= lParam 
!= 0; 
6484                         InvalidateStyleRedraw(); 
6488         case SCI_GETMARGINSENSITIVEN
: 
6489                 if (ValidMargin(wParam
)) 
6490                         return vs
.ms
[wParam
].sensitive 
? 1 : 0; 
6494         case SCI_STYLECLEARALL
: 
6496                 InvalidateStyleRedraw(); 
6499         case SCI_STYLESETFORE
: 
6500                 if (wParam 
<= STYLE_MAX
) { 
6501                         vs
.styles
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6502                         InvalidateStyleRedraw(); 
6505         case SCI_STYLESETBACK
: 
6506                 if (wParam 
<= STYLE_MAX
) { 
6507                         vs
.styles
[wParam
].back
.desired 
= ColourDesired(lParam
); 
6508                         InvalidateStyleRedraw(); 
6511         case SCI_STYLESETBOLD
: 
6512                 if (wParam 
<= STYLE_MAX
) { 
6513                         vs
.styles
[wParam
].bold 
= lParam 
!= 0; 
6514                         InvalidateStyleRedraw(); 
6517         case SCI_STYLESETITALIC
: 
6518                 if (wParam 
<= STYLE_MAX
) { 
6519                         vs
.styles
[wParam
].italic 
= lParam 
!= 0; 
6520                         InvalidateStyleRedraw(); 
6523         case SCI_STYLESETEOLFILLED
: 
6524                 if (wParam 
<= STYLE_MAX
) { 
6525                         vs
.styles
[wParam
].eolFilled 
= lParam 
!= 0; 
6526                         InvalidateStyleRedraw(); 
6529         case SCI_STYLESETSIZE
: 
6530                 if (wParam 
<= STYLE_MAX
) { 
6531                         vs
.styles
[wParam
].size 
= lParam
; 
6532                         InvalidateStyleRedraw(); 
6535         case SCI_STYLESETFONT
: 
6538                 if (wParam 
<= STYLE_MAX
) { 
6539                         vs
.SetStyleFontName(wParam
, CharPtrFromSPtr(lParam
)); 
6540                         InvalidateStyleRedraw(); 
6543         case SCI_STYLESETUNDERLINE
: 
6544                 if (wParam 
<= STYLE_MAX
) { 
6545                         vs
.styles
[wParam
].underline 
= lParam 
!= 0; 
6546                         InvalidateStyleRedraw(); 
6549         case SCI_STYLESETCASE
: 
6550                 if (wParam 
<= STYLE_MAX
) { 
6551                         vs
.styles
[wParam
].caseForce 
= static_cast<Style::ecaseForced
>(lParam
); 
6552                         InvalidateStyleRedraw(); 
6555         case SCI_STYLESETCHARACTERSET
: 
6556                 if (wParam 
<= STYLE_MAX
) { 
6557                         vs
.styles
[wParam
].characterSet 
= lParam
; 
6558                         InvalidateStyleRedraw(); 
6561         case SCI_STYLESETVISIBLE
: 
6562                 if (wParam 
<= STYLE_MAX
) { 
6563                         vs
.styles
[wParam
].visible 
= lParam 
!= 0; 
6564                         InvalidateStyleRedraw(); 
6567         case SCI_STYLESETCHANGEABLE
: 
6568                 if (wParam 
<= STYLE_MAX
) { 
6569                         vs
.styles
[wParam
].changeable 
= lParam 
!= 0; 
6570                         InvalidateStyleRedraw(); 
6573         case SCI_STYLESETHOTSPOT
: 
6574                 if (wParam 
<= STYLE_MAX
) { 
6575                         vs
.styles
[wParam
].hotspot 
= lParam 
!= 0; 
6576                         InvalidateStyleRedraw(); 
6580         case SCI_STYLERESETDEFAULT
: 
6581                 vs
.ResetDefaultStyle(); 
6582                 InvalidateStyleRedraw(); 
6584         case SCI_SETSTYLEBITS
: 
6585                 pdoc
->SetStylingBits(wParam
); 
6588         case SCI_GETSTYLEBITS
: 
6589                 return pdoc
->stylingBits
; 
6591         case SCI_SETLINESTATE
: 
6592                 return pdoc
->SetLineState(wParam
, lParam
); 
6594         case SCI_GETLINESTATE
: 
6595                 return pdoc
->GetLineState(wParam
); 
6597         case SCI_GETMAXLINESTATE
: 
6598                 return pdoc
->GetMaxLineState(); 
6600         case SCI_GETCARETLINEVISIBLE
: 
6601                 return vs
.showCaretLineBackground
; 
6602         case SCI_SETCARETLINEVISIBLE
: 
6603                 vs
.showCaretLineBackground 
= wParam 
!= 0; 
6604                 InvalidateStyleRedraw(); 
6606         case SCI_GETCARETLINEBACK
: 
6607                 return vs
.caretLineBackground
.desired
.AsLong(); 
6608         case SCI_SETCARETLINEBACK
: 
6609                 vs
.caretLineBackground
.desired 
= wParam
; 
6610                 InvalidateStyleRedraw(); 
6615         case SCI_VISIBLEFROMDOCLINE
: 
6616                 return cs
.DisplayFromDoc(wParam
); 
6618         case SCI_DOCLINEFROMVISIBLE
: 
6619                 return cs
.DocFromDisplay(wParam
); 
6621         case SCI_SETFOLDLEVEL
: { 
6622                         int prev 
= pdoc
->SetLevel(wParam
, lParam
); 
6628         case SCI_GETFOLDLEVEL
: 
6629                 return pdoc
->GetLevel(wParam
); 
6631         case SCI_GETLASTCHILD
: 
6632                 return pdoc
->GetLastChild(wParam
, lParam
); 
6634         case SCI_GETFOLDPARENT
: 
6635                 return pdoc
->GetFoldParent(wParam
); 
6638                 cs
.SetVisible(wParam
, lParam
, true); 
6644                 cs
.SetVisible(wParam
, lParam
, false); 
6649         case SCI_GETLINEVISIBLE
: 
6650                 return cs
.GetVisible(wParam
); 
6652         case SCI_SETFOLDEXPANDED
: 
6653                 if (cs
.SetExpanded(wParam
, lParam 
!= 0)) { 
6658         case SCI_GETFOLDEXPANDED
: 
6659                 return cs
.GetExpanded(wParam
); 
6661         case SCI_SETFOLDFLAGS
: 
6666         case SCI_TOGGLEFOLD
: 
6667                 ToggleContraction(wParam
); 
6670         case SCI_ENSUREVISIBLE
: 
6671                 EnsureLineVisible(wParam
, false); 
6674         case SCI_ENSUREVISIBLEENFORCEPOLICY
: 
6675                 EnsureLineVisible(wParam
, true); 
6678         case SCI_SEARCHANCHOR
: 
6682         case SCI_SEARCHNEXT
: 
6683         case SCI_SEARCHPREV
: 
6684                 return SearchText(iMessage
, wParam
, lParam
); 
6686 #ifdef INCLUDE_DEPRECATED_FEATURES 
6687         case SCI_SETCARETPOLICY
:        // Deprecated 
6688                 caretXPolicy 
= caretYPolicy 
= wParam
; 
6689                 caretXSlop 
= caretYSlop 
= lParam
; 
6693         case SCI_SETXCARETPOLICY
: 
6694                 caretXPolicy 
= wParam
; 
6695                 caretXSlop 
= lParam
; 
6698         case SCI_SETYCARETPOLICY
: 
6699                 caretYPolicy 
= wParam
; 
6700                 caretYSlop 
= lParam
; 
6703         case SCI_SETVISIBLEPOLICY
: 
6704                 visiblePolicy 
= wParam
; 
6705                 visibleSlop 
= lParam
; 
6708         case SCI_LINESONSCREEN
: 
6709                 return LinesOnScreen(); 
6711         case SCI_SETSELFORE
: 
6712                 vs
.selforeset 
= wParam 
!= 0; 
6713                 vs
.selforeground
.desired 
= ColourDesired(lParam
); 
6714                 InvalidateStyleRedraw(); 
6717         case SCI_SETSELBACK
: 
6718                 vs
.selbackset 
= wParam 
!= 0; 
6719                 vs
.selbackground
.desired 
= ColourDesired(lParam
); 
6720                 InvalidateStyleRedraw(); 
6723         case SCI_SETWHITESPACEFORE
: 
6724                 vs
.whitespaceForegroundSet 
= wParam 
!= 0; 
6725                 vs
.whitespaceForeground
.desired 
= ColourDesired(lParam
); 
6726                 InvalidateStyleRedraw(); 
6729         case SCI_SETWHITESPACEBACK
: 
6730                 vs
.whitespaceBackgroundSet 
= wParam 
!= 0; 
6731                 vs
.whitespaceBackground
.desired 
= ColourDesired(lParam
); 
6732                 InvalidateStyleRedraw(); 
6735         case SCI_SETCARETFORE
: 
6736                 vs
.caretcolour
.desired 
= ColourDesired(wParam
); 
6737                 InvalidateStyleRedraw(); 
6740         case SCI_GETCARETFORE
: 
6741                 return vs
.caretcolour
.desired
.AsLong(); 
6743         case SCI_SETCARETWIDTH
: 
6746                 else if (wParam 
>= 3) 
6749                         vs
.caretWidth 
= wParam
; 
6750                 InvalidateStyleRedraw(); 
6753         case SCI_GETCARETWIDTH
: 
6754                 return vs
.caretWidth
; 
6756         case SCI_ASSIGNCMDKEY
: 
6757                 kmap
.AssignCmdKey(Platform::LowShortFromLong(wParam
), 
6758                                   Platform::HighShortFromLong(wParam
), lParam
); 
6761         case SCI_CLEARCMDKEY
: 
6762                 kmap
.AssignCmdKey(Platform::LowShortFromLong(wParam
), 
6763                                   Platform::HighShortFromLong(wParam
), SCI_NULL
); 
6766         case SCI_CLEARALLCMDKEYS
: 
6770         case SCI_INDICSETSTYLE
: 
6771                 if (wParam 
<= INDIC_MAX
) { 
6772                         vs
.indicators
[wParam
].style 
= lParam
; 
6773                         InvalidateStyleRedraw(); 
6777         case SCI_INDICGETSTYLE
: 
6778                 return (wParam 
<= INDIC_MAX
) ? vs
.indicators
[wParam
].style 
: 0; 
6780         case SCI_INDICSETFORE
: 
6781                 if (wParam 
<= INDIC_MAX
) { 
6782                         vs
.indicators
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6783                         InvalidateStyleRedraw(); 
6787         case SCI_INDICGETFORE
: 
6788                 return (wParam 
<= INDIC_MAX
) ? vs
.indicators
[wParam
].fore
.desired
.AsLong() : 0; 
6791         case SCI_LINEDOWNEXTEND
: 
6793         case SCI_PARADOWNEXTEND
: 
6795         case SCI_LINEUPEXTEND
: 
6797         case SCI_PARAUPEXTEND
: 
6799         case SCI_CHARLEFTEXTEND
: 
6801         case SCI_CHARRIGHTEXTEND
: 
6803         case SCI_WORDLEFTEXTEND
: 
6805         case SCI_WORDRIGHTEXTEND
: 
6806         case SCI_WORDLEFTEND
: 
6807         case SCI_WORDLEFTENDEXTEND
: 
6808         case SCI_WORDRIGHTEND
: 
6809         case SCI_WORDRIGHTENDEXTEND
: 
6811         case SCI_HOMEEXTEND
: 
6813         case SCI_LINEENDEXTEND
: 
6815         case SCI_HOMEWRAPEXTEND
: 
6816         case SCI_LINEENDWRAP
: 
6817         case SCI_LINEENDWRAPEXTEND
: 
6818         case SCI_DOCUMENTSTART
: 
6819         case SCI_DOCUMENTSTARTEXTEND
: 
6820         case SCI_DOCUMENTEND
: 
6821         case SCI_DOCUMENTENDEXTEND
: 
6823         case SCI_STUTTEREDPAGEUP
: 
6824         case SCI_STUTTEREDPAGEUPEXTEND
: 
6825         case SCI_STUTTEREDPAGEDOWN
: 
6826         case SCI_STUTTEREDPAGEDOWNEXTEND
: 
6829         case SCI_PAGEUPEXTEND
: 
6831         case SCI_PAGEDOWNEXTEND
: 
6832         case SCI_EDITTOGGLEOVERTYPE
: 
6834         case SCI_DELETEBACK
: 
6840         case SCI_VCHOMEEXTEND
: 
6841         case SCI_VCHOMEWRAP
: 
6842         case SCI_VCHOMEWRAPEXTEND
: 
6845         case SCI_DELWORDLEFT
: 
6846         case SCI_DELWORDRIGHT
: 
6847         case SCI_DELLINELEFT
: 
6848         case SCI_DELLINERIGHT
: 
6851         case SCI_LINEDELETE
: 
6852         case SCI_LINETRANSPOSE
: 
6853         case SCI_LINEDUPLICATE
: 
6856         case SCI_LINESCROLLDOWN
: 
6857         case SCI_LINESCROLLUP
: 
6858         case SCI_WORDPARTLEFT
: 
6859         case SCI_WORDPARTLEFTEXTEND
: 
6860         case SCI_WORDPARTRIGHT
: 
6861         case SCI_WORDPARTRIGHTEXTEND
: 
6862         case SCI_DELETEBACKNOTLINE
: 
6863         case SCI_HOMEDISPLAY
: 
6864         case SCI_HOMEDISPLAYEXTEND
: 
6865         case SCI_LINEENDDISPLAY
: 
6866         case SCI_LINEENDDISPLAYEXTEND
: 
6867         case SCI_LINEDOWNRECTEXTEND
: 
6868         case SCI_LINEUPRECTEXTEND
: 
6869         case SCI_CHARLEFTRECTEXTEND
: 
6870         case SCI_CHARRIGHTRECTEXTEND
: 
6871         case SCI_HOMERECTEXTEND
: 
6872         case SCI_VCHOMERECTEXTEND
: 
6873         case SCI_LINEENDRECTEXTEND
: 
6874         case SCI_PAGEUPRECTEXTEND
: 
6875         case SCI_PAGEDOWNRECTEXTEND
: 
6876                 return KeyCommand(iMessage
); 
6878         case SCI_BRACEHIGHLIGHT
: 
6879                 SetBraceHighlight(static_cast<int>(wParam
), lParam
, STYLE_BRACELIGHT
); 
6882         case SCI_BRACEBADLIGHT
: 
6883                 SetBraceHighlight(static_cast<int>(wParam
), -1, STYLE_BRACEBAD
); 
6886         case SCI_BRACEMATCH
: 
6887                 // wParam is position of char to find brace for, 
6888                 // lParam is maximum amount of text to restyle to find it 
6889                 return BraceMatch(wParam
, lParam
); 
6891         case SCI_GETVIEWEOL
: 
6894         case SCI_SETVIEWEOL
: 
6895                 vs
.viewEOL 
= wParam 
!= 0; 
6896                 InvalidateStyleRedraw(); 
6900                 vs
.zoomLevel 
= wParam
; 
6901                 InvalidateStyleRedraw(); 
6906                 return vs
.zoomLevel
; 
6908         case SCI_GETEDGECOLUMN
: 
6911         case SCI_SETEDGECOLUMN
: 
6913                 InvalidateStyleRedraw(); 
6916         case SCI_GETEDGEMODE
: 
6917                 return vs
.edgeState
; 
6919         case SCI_SETEDGEMODE
: 
6920                 vs
.edgeState 
= wParam
; 
6921                 InvalidateStyleRedraw(); 
6924         case SCI_GETEDGECOLOUR
: 
6925                 return vs
.edgecolour
.desired
.AsLong(); 
6927         case SCI_SETEDGECOLOUR
: 
6928                 vs
.edgecolour
.desired 
= ColourDesired(wParam
); 
6929                 InvalidateStyleRedraw(); 
6932         case SCI_GETDOCPOINTER
: 
6933                 return reinterpret_cast<sptr_t
>(pdoc
); 
6935         case SCI_SETDOCPOINTER
: 
6937                 SetDocPointer(reinterpret_cast<Document 
*>(lParam
)); 
6940         case SCI_CREATEDOCUMENT
: { 
6941                         Document 
*doc 
= new Document(); 
6945                         return reinterpret_cast<sptr_t
>(doc
); 
6948         case SCI_ADDREFDOCUMENT
: 
6949                 (reinterpret_cast<Document 
*>(lParam
))->AddRef(); 
6952         case SCI_RELEASEDOCUMENT
: 
6953                 (reinterpret_cast<Document 
*>(lParam
))->Release(); 
6956         case SCI_SETMODEVENTMASK
: 
6957                 modEventMask 
= wParam
; 
6960         case SCI_GETMODEVENTMASK
: 
6961                 return modEventMask
; 
6963         case SCI_CONVERTEOLS
: 
6964                 pdoc
->ConvertLineEnds(wParam
); 
6965                 SetSelection(currentPos
, anchor
);       // Ensure selection inside document 
6968         case SCI_SETLENGTHFORENCODE
: 
6969                 lengthForEncode 
= wParam
; 
6972         case SCI_SELECTIONISRECTANGLE
: 
6973                 return selType 
== selRectangle 
? 1 : 0; 
6975         case SCI_SETSELECTIONMODE
: { 
6978                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selStream
); 
6979                                 selType 
= selStream
; 
6981                         case SC_SEL_RECTANGLE
: 
6982                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selRectangle
); 
6983                                 selType 
= selRectangle
; 
6986                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selLines
); 
6990                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selStream
); 
6991                                 selType 
= selStream
; 
6993                         InvalidateSelection(currentPos
, anchor
); 
6995         case SCI_GETSELECTIONMODE
: 
6998                         return SC_SEL_STREAM
; 
7000                         return SC_SEL_RECTANGLE
; 
7002                         return SC_SEL_LINES
; 
7004                         return SC_SEL_STREAM
; 
7006         case SCI_GETLINESELSTARTPOSITION
: { 
7007                         SelectionLineIterator 
lineIterator(this); 
7008                         lineIterator
.SetAt(wParam
); 
7009                         return lineIterator
.startPos
; 
7011         case SCI_GETLINESELENDPOSITION
: { 
7012                         SelectionLineIterator 
lineIterator(this); 
7013                         lineIterator
.SetAt(wParam
); 
7014                         return lineIterator
.endPos
; 
7017         case SCI_SETOVERTYPE
: 
7018                 inOverstrike 
= wParam 
!= 0; 
7021         case SCI_GETOVERTYPE
: 
7022                 return inOverstrike 
? 1 : 0; 
7025                 SetFocusState(wParam 
!= 0); 
7032                 errorStatus 
= wParam
; 
7038         case SCI_SETMOUSEDOWNCAPTURES
: 
7039                 mouseDownCaptures 
= wParam 
!= 0; 
7042         case SCI_GETMOUSEDOWNCAPTURES
: 
7043                 return mouseDownCaptures
; 
7046                 cursorMode 
= wParam
; 
7047                 DisplayCursor(Window::cursorText
); 
7053         case SCI_SETCONTROLCHARSYMBOL
: 
7054                 controlCharSymbol 
= wParam
; 
7057         case SCI_GETCONTROLCHARSYMBOL
: 
7058                 return controlCharSymbol
; 
7060         case SCI_STARTRECORD
: 
7061                 recordingMacro 
= true; 
7064         case SCI_STOPRECORD
: 
7065                 recordingMacro 
= false; 
7068         case SCI_MOVECARETINSIDEVIEW
: 
7069                 MoveCaretInsideView(); 
7072         case SCI_SETFOLDMARGINCOLOUR
: 
7073                 vs
.foldmarginColourSet 
= wParam 
!= 0; 
7074                 vs
.foldmarginColour
.desired 
= ColourDesired(lParam
); 
7075                 InvalidateStyleRedraw(); 
7078         case SCI_SETFOLDMARGINHICOLOUR
: 
7079                 vs
.foldmarginHighlightColourSet 
= wParam 
!= 0; 
7080                 vs
.foldmarginHighlightColour
.desired 
= ColourDesired(lParam
); 
7081                 InvalidateStyleRedraw(); 
7084         case SCI_SETHOTSPOTACTIVEFORE
: 
7085                 vs
.hotspotForegroundSet 
= wParam 
!= 0; 
7086                 vs
.hotspotForeground
.desired 
= ColourDesired(lParam
); 
7087                 InvalidateStyleRedraw(); 
7090         case SCI_SETHOTSPOTACTIVEBACK
: 
7091                 vs
.hotspotBackgroundSet 
= wParam 
!= 0; 
7092                 vs
.hotspotBackground
.desired 
= ColourDesired(lParam
); 
7093                 InvalidateStyleRedraw(); 
7096         case SCI_SETHOTSPOTACTIVEUNDERLINE
: 
7097                 vs
.hotspotUnderline 
= wParam 
!= 0; 
7098                 InvalidateStyleRedraw(); 
7101         case SCI_SETHOTSPOTSINGLELINE
: 
7102                 vs
.hotspotSingleLine 
= wParam 
!= 0; 
7103                 InvalidateStyleRedraw(); 
7107                 return DefWndProc(iMessage
, wParam
, lParam
); 
7109         //Platform::DebugPrintf("end wnd proc\n");