1 // Scintilla source code edit control 
   3  ** Main code for the edit control. 
   5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> 
   6 // The License.txt file describes the conditions under which this software may be distributed. 
  16 #define INCLUDE_DEPRECATED_FEATURES 
  18 #include "Scintilla.h" 
  20 #include "ContractionState.h" 
  22 #include "CellBuffer.h" 
  24 #include "Indicator.h" 
  26 #include "LineMarker.h" 
  28 #include "ViewStyle.h" 
  33 active(false), on(false), period(500) {} 
  36 ticking(false), ticksToWait(0), tickerID(0) {} 
  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 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
) || (level 
== llcPage
)) && (lineNumber 
== lineCaret
)) { 
 245         } else if (level 
== llcPage
) { 
 246                 pos 
= lineNumber 
% length
; 
 247         } else if (level 
== llcDocument
) { 
 251                 if (cache 
&& (pos 
< length
)) { 
 253                                 if ((cache
[pos
]->lineNumber 
!= lineNumber
) || 
 254                                         (cache
[pos
]->maxLineLength 
< maxChars
)) { 
 260                                 cache
[pos
] = new LineLayout(maxChars
); 
 263                                 cache
[pos
]->lineNumber 
= lineNumber
; 
 264                                 cache
[pos
]->inCache 
= true; 
 271                 ret 
= new LineLayout(maxChars
); 
 272                 ret
->lineNumber 
= lineNumber
; 
 278 void LineLayoutCache::Dispose(LineLayout 
*ll
) { 
 279         allInvalidated 
= false; 
 292         printMagnification 
= 0; 
 293         printColourMode 
= SC_PRINT_NORMAL
; 
 294         printWrapState 
= eWrapWord
; 
 295         cursorMode 
= SC_CURSORNORMAL
; 
 296         controlCharSymbol 
= 0;  /* Draw the control characters */ 
 299         hideSelection 
= false; 
 300         inOverstrike 
= false; 
 302         mouseDownCaptures 
= true; 
 308         dwellDelay 
= SC_TIME_FOREVER
; 
 309         ticksToDwell 
= SC_TIME_FOREVER
; 
 314         dropWentOutside 
= false; 
 315         posDrag 
= invalidPosition
; 
 316         posDrop 
= invalidPosition
; 
 317         selectionType 
= selChar
; 
 321         originalAnchorPos 
= 0; 
 324         moveExtendsSelection 
= false; 
 327         primarySelection 
= true; 
 329         caretXPolicy 
= CARET_SLOP 
| CARET_EVEN
; 
 332         caretYPolicy 
= CARET_EVEN
; 
 339         horizontalScrollBarVisible 
= true; 
 341         verticalScrollBarVisible 
= true; 
 342         endAtLastLine 
= true; 
 344         pixmapLine 
= Surface::Allocate(); 
 345         pixmapSelMargin 
= Surface::Allocate(); 
 346         pixmapSelPattern 
= Surface::Allocate(); 
 347         pixmapIndentGuide 
= Surface::Allocate(); 
 348         pixmapIndentGuideHighlight 
= Surface::Allocate(); 
 361         braces
[0] = invalidPosition
; 
 362         braces
[1] = invalidPosition
; 
 363         bracesMatchStyle 
= STYLE_BRACEBAD
; 
 364         highlightGuideColumn 
= 0; 
 368         paintState 
= notPainting
; 
 370         modEventMask 
= SC_MODEVENTMASKALL
; 
 372         pdoc 
= new Document(); 
 374         pdoc
->AddWatcher(this, 0); 
 376         recordingMacro 
= false; 
 379         wrapState 
= eWrapNone
; 
 380         wrapWidth 
= LineLayout::wrapWidthInfinite
; 
 381         docLineLastWrapped 
= -1; 
 382         docLastLineToWrap 
= -1; 
 383         backgroundWrapEnabled 
= true; 
 388         llc
.SetLevel(LineLayoutCache::llcCaret
); 
 392         pdoc
->RemoveWatcher(this, 0); 
 397         delete pixmapSelMargin
; 
 398         delete pixmapSelPattern
; 
 399         delete pixmapIndentGuide
; 
 400         delete pixmapIndentGuideHighlight
; 
 403 void Editor::Finalise() { 
 408 void Editor::DropGraphics() { 
 409         pixmapLine
->Release(); 
 410         pixmapSelMargin
->Release(); 
 411         pixmapSelPattern
->Release(); 
 412         pixmapIndentGuide
->Release(); 
 415 void Editor::InvalidateStyleData() { 
 419         llc
.Invalidate(LineLayout::llInvalid
); 
 420         if (selType 
== selRectangle
) { 
 421                 xStartSelect 
= XFromPosition(anchor
); 
 422                 xEndSelect 
= XFromPosition(currentPos
); 
 426 void Editor::InvalidateStyleRedraw() { 
 428         InvalidateStyleData(); 
 432 void Editor::RefreshColourPalette(Palette 
&pal
, bool want
) { 
 433         vs
.RefreshColourPalette(pal
, want
); 
 436 void Editor::RefreshStyleData() { 
 439                 AutoSurface 
surface(this); 
 441                         vs
.Refresh(*surface
); 
 442                         RefreshColourPalette(palette
, true); 
 443                         palette
.Allocate(wMain
); 
 444                         RefreshColourPalette(palette
, false); 
 450 PRectangle 
Editor::GetClientRectangle() { 
 451         return wMain
.GetClientPosition(); 
 454 PRectangle 
Editor::GetTextRectangle() { 
 455         PRectangle rc 
= GetClientRectangle(); 
 456         rc
.left 
+= vs
.fixedColumnWidth
; 
 457         rc
.right 
-= vs
.rightMarginWidth
; 
 461 int Editor::LinesOnScreen() { 
 462         PRectangle rcClient 
= GetClientRectangle(); 
 463         int htClient 
= rcClient
.bottom 
- rcClient
.top
; 
 464         //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1); 
 465         return htClient 
/ vs
.lineHeight
; 
 468 int Editor::LinesToScroll() { 
 469         int retVal 
= LinesOnScreen() - 1; 
 476 int Editor::MaxScrollPos() { 
 477         //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n", 
 478         //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1); 
 479         int retVal 
= cs
.LinesDisplayed(); 
 481                 retVal 
-= LinesOnScreen(); 
 492 static inline bool IsControlCharacter(char ch
) { 
 493         // iscntrl returns true for lots of chars > 127 which are displayable 
 494         return ch 
>= 0 && ch 
< ' '; 
 497 const char *ControlCharacterString(unsigned char ch
) { 
 498         const char *reps
[] = { 
 499                 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", 
 500                 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", 
 501                 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", 
 502                 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" 
 504         if (ch 
< (sizeof(reps
) / sizeof(reps
[0]))) { 
 512  * Convenience class to ensure LineLayout objects are always disposed. 
 514 class AutoLineLayout 
{ 
 515         LineLayoutCache 
&llc
; 
 517         AutoLineLayout 
&operator=(const AutoLineLayout 
&) { return * this; } 
 519         AutoLineLayout(LineLayoutCache 
&llc_
, LineLayout 
*ll_
) : llc(llc_
), ll(ll_
) {} 
 524         LineLayout 
*operator->() const { 
 527         operator LineLayout 
*() const { 
 530         void Set(LineLayout 
*ll_
) { 
 537  * Allows to iterate through the lines of a selection. 
 538  * Althought it can be called for a stream selection, in most cases 
 539  * it is inefficient and it should be used only for 
 540  * a rectangular or a line selection. 
 542 class SelectionLineIterator 
{ 
 545         int line
;       ///< Current line within the iteration. 
 546         bool forward
;   ///< True if iterating by increasing line number, false otherwise. 
 547         int selStart
, selEnd
;   ///< Positions of the start and end of the selection relative to the start of the document. 
 548         int minX
, maxX
; ///< Left and right of selection rectangle. 
 551         int lineStart
, lineEnd
; ///< Line numbers, first and last lines of the selection. 
 552         int startPos
, endPos
;   ///< Positions of the beginning and end of the selection on the current line. 
 562         SelectionLineIterator(Editor 
*ed_
, bool forward_ 
= true) : line(0), startPos(0), endPos(0) { 
 565                 selStart 
= ed
->SelectionStart(); 
 566                 selEnd 
= ed
->SelectionEnd(); 
 567                 lineStart 
= ed
->pdoc
->LineFromPosition(selStart
); 
 568                 lineEnd 
= ed
->pdoc
->LineFromPosition(selEnd
); 
 570                 minX 
= Platform::Minimum(ed
->xStartSelect
, ed
->xEndSelect
); 
 571                 // Right of rectangle 
 572                 maxX 
= Platform::Maximum(ed
->xStartSelect
, ed
->xEndSelect
); 
 575         ~SelectionLineIterator() {} 
 577         void SetAt(int line
) { 
 578                 if (line 
< lineStart 
|| line 
> lineEnd
) { 
 579                         startPos 
= endPos 
= INVALID_POSITION
; 
 581                         if (ed
->selType 
== ed
->selRectangle
) { 
 582                                 // Measure line and return character closest to minX 
 583                                 startPos 
= ed
->PositionFromLineX(line
, minX
); 
 584                                 // Measure line and return character closest to maxX 
 585                                 endPos 
= ed
->PositionFromLineX(line
, maxX
); 
 586                         } else if (ed
->selType 
== ed
->selLines
) { 
 587                                 startPos 
= ed
->pdoc
->LineStart(line
); 
 588                                 endPos 
= ed
->pdoc
->LineStart(line 
+ 1); 
 589                         } else {        // Stream selection, here only for completion 
 590                                 if (line 
== lineStart
) { 
 593                                         startPos 
= ed
->pdoc
->LineStart(line
); 
 595                                 if (line 
== lineEnd
) { 
 598                                         endPos 
= ed
->pdoc
->LineStart(line 
+ 1); 
 610                 return startPos 
!= INVALID_POSITION
; 
 614 Point 
Editor::LocationFromPosition(int pos
) { 
 617         if (pos 
== INVALID_POSITION
) 
 619         int line 
= pdoc
->LineFromPosition(pos
); 
 620         int lineVisible 
= cs
.DisplayFromDoc(line
); 
 621         //Platform::DebugPrintf("line=%d\n", line); 
 622         AutoSurface 
surface(this); 
 623         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
 625                 // -1 because of adding in for visible lines in following loop. 
 626                 pt
.y 
= (lineVisible 
- topLine 
- 1) * vs
.lineHeight
; 
 628                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
 629                 LayoutLine(line
, surface
, vs
, ll
, wrapWidth
); 
 630                 int posInLine 
= pos 
- posLineStart
; 
 631                 // In case of very long line put x at arbitrary large position 
 632                 if (posInLine 
> ll
->maxLineLength
) { 
 633                         pt
.x 
= ll
->positions
[ll
->maxLineLength
] - ll
->positions
[ll
->LineStart(ll
->lines
)]; 
 635                 for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
 636                         if ((posInLine 
>= ll
->LineStart(subLine
)) && (posInLine 
<= ll
->LineStart(subLine 
+ 1))) { 
 637                                 pt
.x 
= ll
->positions
[posInLine
] - ll
->positions
[ll
->LineStart(subLine
)]; 
 639                         if (posInLine 
>= ll
->LineStart(subLine
)) { 
 640                                 pt
.y 
+= vs
.lineHeight
; 
 643                 pt
.x 
+= vs
.fixedColumnWidth 
- xOffset
; 
 648 int Editor::XFromPosition(int pos
) { 
 649         Point pt 
= LocationFromPosition(pos
); 
 650         return pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 653 int Editor::LineFromLocation(Point pt
) { 
 654         return cs
.DocFromDisplay(pt
.y 
/ vs
.lineHeight 
+ topLine
); 
 657 void Editor::SetTopLine(int topLineNew
) { 
 658         topLine 
= topLineNew
; 
 659         posTopLine 
= pdoc
->LineStart(topLine
); 
 662 static inline bool IsEOLChar(char ch
) { 
 663         return (ch 
== '\r') || (ch 
== '\n'); 
 666 int Editor::PositionFromLocation(Point pt
) { 
 668         pt
.x 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 669         int visibleLine 
= pt
.y 
/ vs
.lineHeight 
+ topLine
; 
 670         if (pt
.y 
< 0) { // Division rounds towards 0 
 671                 visibleLine 
= (pt
.y 
- (vs
.lineHeight 
- 1)) / vs
.lineHeight 
+ topLine
; 
 675         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
 676         if (lineDoc 
>= pdoc
->LinesTotal()) 
 677                 return pdoc
->Length(); 
 678         unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 679         int retVal 
= posLineStart
; 
 680         AutoSurface 
surface(this); 
 681         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 683                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 684                 int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
 685                 int subLine 
= visibleLine 
- lineStartSet
; 
 686                 if (subLine 
< ll
->lines
) { 
 687                         int lineStart 
= ll
->LineStart(subLine
); 
 688                         int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 689                         int subLineStart 
= ll
->positions
[lineStart
]; 
 690                         for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 691                                 if (pt
.x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 692                                         IsEOLChar(ll
->chars
[i
])) { 
 693                                         return pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 696                         return lineEnd 
+ posLineStart
; 
 698                 retVal 
= ll
->numCharsInLine 
+ posLineStart
; 
 703 // Like PositionFromLocation but INVALID_POSITION returned when not near any text. 
 704 int Editor::PositionFromLocationClose(Point pt
) { 
 706         PRectangle rcClient 
= GetTextRectangle(); 
 707         if (!rcClient
.Contains(pt
)) 
 708                 return INVALID_POSITION
; 
 709         if (pt
.x 
< vs
.fixedColumnWidth
) 
 710                 return INVALID_POSITION
; 
 712                 return INVALID_POSITION
; 
 713         pt
.x 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
 714         int visibleLine 
= pt
.y 
/ vs
.lineHeight 
+ topLine
; 
 715         if (pt
.y 
< 0) { // Division rounds towards 0 
 716                 visibleLine 
= (pt
.y 
- (vs
.lineHeight 
- 1)) / vs
.lineHeight 
+ topLine
; 
 718         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
 720                 return INVALID_POSITION
; 
 721         if (lineDoc 
>= pdoc
->LinesTotal()) 
 722                 return INVALID_POSITION
; 
 723         AutoSurface 
surface(this); 
 724         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 726                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 727                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 728                 int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
 729                 int subLine 
= visibleLine 
- lineStartSet
; 
 730                 if (subLine 
< ll
->lines
) { 
 731                         int lineStart 
= ll
->LineStart(subLine
); 
 732                         int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 733                         int subLineStart 
= ll
->positions
[lineStart
]; 
 734                         for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 735                                 if (pt
.x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 736                                         IsEOLChar(ll
->chars
[i
])) { 
 737                                         return pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 743         return INVALID_POSITION
; 
 747  * Find the document position corresponding to an x coordinate on a particular document line. 
 748  * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. 
 750 int Editor::PositionFromLineX(int lineDoc
, int x
) { 
 752         if (lineDoc 
>= pdoc
->LinesTotal()) 
 753                 return pdoc
->Length(); 
 754         //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); 
 755         AutoSurface 
surface(this); 
 756         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
 759                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
 760                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
 761                 retVal 
= ll
->numCharsInLine 
+ posLineStart
; 
 763                 int lineStart 
= ll
->LineStart(subLine
); 
 764                 int lineEnd 
= ll
->LineStart(subLine 
+ 1); 
 765                 int subLineStart 
= ll
->positions
[lineStart
]; 
 766                 for (int i 
= lineStart
; i 
< lineEnd
; i
++) { 
 767                         if (x 
< (((ll
->positions
[i
] + ll
->positions
[i 
+ 1]) / 2) - subLineStart
) || 
 768                                 IsEOLChar(ll
->chars
[i
])) { 
 769                                 retVal 
= pdoc
->MovePositionOutsideChar(i 
+ posLineStart
, 1); 
 778  * If painting then abandon the painting because a wider redraw is needed. 
 779  * @return true if calling code should stop drawing. 
 781 bool Editor::AbandonPaint() { 
 782         if ((paintState 
== painting
) && !paintingAllText
) { 
 783                 paintState 
= paintAbandoned
; 
 785         return paintState 
== paintAbandoned
; 
 788 void Editor::RedrawRect(PRectangle rc
) { 
 789         //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); 
 791         // Clip the redraw rectangle into the client area 
 792         PRectangle rcClient 
= GetClientRectangle(); 
 793         if (rc
.top 
< rcClient
.top
) 
 794                 rc
.top 
= rcClient
.top
; 
 795         if (rc
.bottom 
> rcClient
.bottom
) 
 796                 rc
.bottom 
= rcClient
.bottom
; 
 797         if (rc
.left 
< rcClient
.left
) 
 798                 rc
.left 
= rcClient
.left
; 
 799         if (rc
.right 
> rcClient
.right
) 
 800                 rc
.right 
= rcClient
.right
; 
 802         if ((rc
.bottom 
> rc
.top
) && (rc
.right 
> rc
.left
)) { 
 803                 wMain
.InvalidateRectangle(rc
); 
 807 void Editor::Redraw() { 
 808         //Platform::DebugPrintf("Redraw all\n"); 
 809         PRectangle rcClient 
= GetClientRectangle(); 
 810         wMain
.InvalidateRectangle(rcClient
); 
 811         //wMain.InvalidateAll(); 
 814 void Editor::RedrawSelMargin() { 
 815         if (!AbandonPaint()) { 
 819                         PRectangle rcSelMargin 
= GetClientRectangle(); 
 820                         rcSelMargin
.right 
= vs
.fixedColumnWidth
; 
 821                         wMain
.InvalidateRectangle(rcSelMargin
); 
 826 PRectangle 
Editor::RectangleFromRange(int start
, int end
) { 
 833         int minLine 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(minPos
)); 
 834         int lineDocMax 
= pdoc
->LineFromPosition(maxPos
); 
 835         int maxLine 
= cs
.DisplayFromDoc(lineDocMax
) + cs
.GetHeight(lineDocMax
) - 1; 
 836         PRectangle rcClient 
= GetTextRectangle(); 
 838         rc
.left 
= vs
.fixedColumnWidth
; 
 839         rc
.top 
= (minLine 
- topLine
) * vs
.lineHeight
; 
 842         rc
.right 
= rcClient
.right
; 
 843         rc
.bottom 
= (maxLine 
- topLine 
+ 1) * vs
.lineHeight
; 
 844         // Ensure PRectangle is within 16 bit space 
 845         rc
.top 
= Platform::Clamp(rc
.top
, -32000, 32000); 
 846         rc
.bottom 
= Platform::Clamp(rc
.bottom
, -32000, 32000); 
 851 void Editor::InvalidateRange(int start
, int end
) { 
 852         RedrawRect(RectangleFromRange(start
, end
)); 
 855 int Editor::CurrentPosition() { 
 859 bool Editor::SelectionEmpty() { 
 860         return anchor 
== currentPos
; 
 863 int Editor::SelectionStart() { 
 864         return Platform::Minimum(currentPos
, anchor
); 
 867 int Editor::SelectionEnd() { 
 868         return Platform::Maximum(currentPos
, anchor
); 
 871 void Editor::InvalidateSelection(int currentPos_
, int anchor_
) { 
 872         int firstAffected 
= anchor
; 
 873         if (firstAffected 
> currentPos
) 
 874                 firstAffected 
= currentPos
; 
 875         if (firstAffected 
> anchor_
) 
 876                 firstAffected 
= anchor_
; 
 877         if (firstAffected 
> currentPos_
) 
 878                 firstAffected 
= currentPos_
; 
 879         int lastAffected 
= anchor
; 
 880         if (lastAffected 
< currentPos
) 
 881                 lastAffected 
= currentPos
; 
 882         if (lastAffected 
< anchor_
) 
 883                 lastAffected 
= anchor_
; 
 884         if (lastAffected 
< (currentPos_ 
+ 1))   // +1 ensures caret repainted 
 885                 lastAffected 
= (currentPos_ 
+ 1); 
 887         InvalidateRange(firstAffected
, lastAffected
); 
 890 void Editor::SetSelection(int currentPos_
, int anchor_
) { 
 891         currentPos_ 
= pdoc
->ClampPositionIntoDocument(currentPos_
); 
 892         anchor_ 
= pdoc
->ClampPositionIntoDocument(anchor_
); 
 893         if ((currentPos 
!= currentPos_
) || (anchor 
!= anchor_
)) { 
 894                 InvalidateSelection(currentPos_
, anchor_
); 
 895                 currentPos 
= currentPos_
; 
 898         if (selType 
== selRectangle
) { 
 899                 xStartSelect 
= XFromPosition(anchor
); 
 900                 xEndSelect 
= XFromPosition(currentPos
); 
 905 void Editor::SetSelection(int currentPos_
) { 
 906         currentPos_ 
= pdoc
->ClampPositionIntoDocument(currentPos_
); 
 907         if (currentPos 
!= currentPos_
) { 
 908                 InvalidateSelection(currentPos_
, currentPos_
); 
 909                 currentPos 
= currentPos_
; 
 911         if (selType 
== selRectangle
) { 
 912                 xStartSelect 
= XFromPosition(anchor
); 
 913                 xEndSelect 
= XFromPosition(currentPos
); 
 918 void Editor::SetEmptySelection(int currentPos_
) { 
 920         moveExtendsSelection 
= false; 
 921         SetSelection(currentPos_
, currentPos_
); 
 924 bool Editor::RangeContainsProtected(int start
, int end
) const { 
 925         if (vs
.ProtectionActive()) { 
 931                 int mask 
= pdoc
->stylingBitsMask
; 
 932                 for (int pos 
= start
; pos 
< end
; pos
++) { 
 933                         if (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected()) 
 940 bool Editor::SelectionContainsProtected() { 
 941         // DONE, but untested...: make support rectangular selection 
 943         if (selType 
== selStream
) { 
 944                 scp 
= RangeContainsProtected(anchor
, currentPos
); 
 946                 SelectionLineIterator 
lineIterator(this); 
 947                 while (lineIterator
.Iterate()) { 
 948                         if (RangeContainsProtected(lineIterator
.startPos
, lineIterator
.endPos
)) { 
 958  * Asks document to find a good position and then moves out of any invisible positions. 
 960 int Editor::MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
) { 
 961         pos 
= pdoc
->MovePositionOutsideChar(pos
, moveDir
, checkLineEnd
); 
 962         if (vs
.ProtectionActive()) { 
 963                 int mask 
= pdoc
->stylingBitsMask
; 
 965                         if ((pos 
> 0) && vs
.styles
[pdoc
->StyleAt(pos 
- 1) & mask
].IsProtected()) { 
 966                                 while ((pos 
< pdoc
->Length()) && 
 967                                         (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected())) 
 970                 } else if (moveDir 
< 0) { 
 971                         if (vs
.styles
[pdoc
->StyleAt(pos
) & mask
].IsProtected()) { 
 973                                         (vs
.styles
[pdoc
->StyleAt(pos 
- 1) & mask
].IsProtected())) 
 981 int Editor::MovePositionTo(int newPos
, selTypes sel
, bool ensureVisible
) { 
 982         int delta 
= newPos 
- currentPos
; 
 983         newPos 
= pdoc
->ClampPositionIntoDocument(newPos
); 
 984         newPos 
= MovePositionOutsideChar(newPos
, delta
); 
 988         if (sel 
!= noSel 
|| moveExtendsSelection
) { 
 989                 SetSelection(newPos
); 
 991                 SetEmptySelection(newPos
); 
 993         ShowCaretAtCurrentPosition(); 
 995                 EnsureCaretVisible(); 
1001 int Editor::MovePositionSoVisible(int pos
, int moveDir
) { 
1002         pos 
= pdoc
->ClampPositionIntoDocument(pos
); 
1003         pos 
= MovePositionOutsideChar(pos
, moveDir
); 
1004         int lineDoc 
= pdoc
->LineFromPosition(pos
); 
1005         if (cs
.GetVisible(lineDoc
)) { 
1008                 int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
1010                         // lineDisplay is already line before fold as lines in fold use display line of line after fold 
1011                         lineDisplay 
= Platform::Clamp(lineDisplay
, 0, cs
.LinesDisplayed()); 
1012                         return pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
)); 
1014                         lineDisplay 
= Platform::Clamp(lineDisplay 
- 1, 0, cs
.LinesDisplayed()); 
1015                         return pdoc
->LineEnd(cs
.DocFromDisplay(lineDisplay
)); 
1021  * Choose the x position that the caret will try to stick to 
1022  * as it moves up and down. 
1024 void Editor::SetLastXChosen() { 
1025         Point pt 
= LocationFromPosition(currentPos
); 
1029 void Editor::ScrollTo(int line
, bool moveThumb
) { 
1030         int topLineNew 
= Platform::Clamp(line
, 0, MaxScrollPos()); 
1031         if (topLineNew 
!= topLine
) { 
1032                 // Try to optimise small scrolls 
1033                 int linesToMove 
= topLine 
- topLineNew
; 
1034                 SetTopLine(topLineNew
); 
1035                 ShowCaretAtCurrentPosition(); 
1036                 // Perform redraw rather than scroll if many lines would be redrawn anyway. 
1037                 if (abs(linesToMove
) <= 10) { 
1038                         ScrollText(linesToMove
); 
1043                         SetVerticalScrollPos(); 
1048 void Editor::ScrollText(int /* linesToMove */) { 
1049         //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove); 
1053 void Editor::HorizontalScrollTo(int xPos
) { 
1054         //Platform::DebugPrintf("HorizontalScroll %d\n", xPos); 
1057         if ((wrapState 
== eWrapNone
) && (xOffset 
!= xPos
)) { 
1059                 SetHorizontalScrollPos(); 
1060                 RedrawRect(GetClientRectangle()); 
1064 void Editor::MoveCaretInsideView(bool ensureVisible
) { 
1065         PRectangle rcClient 
= GetTextRectangle(); 
1066         Point pt 
= LocationFromPosition(currentPos
); 
1067         if (pt
.y 
< rcClient
.top
) { 
1068                 MovePositionTo(PositionFromLocation( 
1069                                    Point(lastXChosen
, rcClient
.top
)), 
1070                                noSel
, ensureVisible
); 
1071         } else if ((pt
.y 
+ vs
.lineHeight 
- 1) > rcClient
.bottom
) { 
1072                 int yOfLastLineFullyDisplayed 
= rcClient
.top 
+ (LinesOnScreen() - 1) * vs
.lineHeight
; 
1073                 MovePositionTo(PositionFromLocation( 
1074                                    Point(lastXChosen
, rcClient
.top 
+ yOfLastLineFullyDisplayed
)), 
1075                                noSel
, ensureVisible
); 
1079 int Editor::DisplayFromPosition(int pos
) { 
1080         int lineDoc 
= pdoc
->LineFromPosition(pos
); 
1081         int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
1082         AutoSurface 
surface(this); 
1083         AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
1084         if (surface 
&& ll
) { 
1085                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
1086                 unsigned int posLineStart 
= pdoc
->LineStart(lineDoc
); 
1087                 int posInLine 
= pos 
- posLineStart
; 
1088                 lineDisplay
--; // To make up for first increment ahead. 
1089                 for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
1090                         if (posInLine 
>= ll
->LineStart(subLine
)) { 
1099  * Ensure the caret is reasonably visible in context. 
1101 Caret policy in SciTE 
1103 If slop is set, we can define a slop value. 
1104 This value defines an unwanted zone (UZ) where the caret is... unwanted. 
1105 This zone is defined as a number of pixels near the vertical margins, 
1106 and as a number of lines near the horizontal margins. 
1107 By keeping the caret away from the edges, it is seen within its context, 
1108 so it is likely that the identifier that the caret is on can be completely seen, 
1109 and that the current line is seen with some of the lines following it which are 
1110 often dependent on that line. 
1112 If strict is set, the policy is enforced... strictly. 
1113 The caret is centred on the display if slop is not set, 
1114 and cannot go in the UZ if slop is set. 
1116 If jumps is set, the display is moved more energetically 
1117 so the caret can move in the same direction longer before the policy is applied again. 
1118 '3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin. 
1120 If even is not set, instead of having symmetrical UZs, 
1121 the left and bottom UZs are extended up to right and top UZs respectively. 
1122 This way, we favour the displaying of useful information: the begining of lines, 
1123 where most code reside, and the lines after the caret, eg. the body of a function. 
1126 slop | strict | jumps | even | Caret can go to the margin                 | When reaching limitÝ(caret going out of 
1127      |        |       |      |                                            | visibility or going into the UZ) display is... 
1128 -----+--------+-------+------+--------------------------------------------+-------------------------------------------------------------- 
1129   0  |   0    |   0   |   0  | Yes                                        | moved to put caret on top/on right 
1130   0  |   0    |   0   |   1  | Yes                                        | moved by one position 
1131   0  |   0    |   1   |   0  | Yes                                        | moved to put caret on top/on right 
1132   0  |   0    |   1   |   1  | Yes                                        | centred on the caret 
1133   0  |   1    |   -   |   0  | Caret is always on top/on right of display | - 
1134   0  |   1    |   -   |   1  | No, caret is always centred                | - 
1135   1  |   0    |   0   |   0  | Yes                                        | moved to put caret out of the asymmetrical UZ 
1136   1  |   0    |   0   |   1  | Yes                                        | moved to put caret out of the UZ 
1137   1  |   0    |   1   |   0  | Yes                                        | moved to put caret at 3UZ of the top or right margin 
1138   1  |   0    |   1   |   1  | Yes                                        | moved to put caret at 3UZ of the margin 
1139   1  |   1    |   -   |   0  | Caret is always at UZ of top/right margin  | - 
1140   1  |   1    |   0   |   1  | No, kept out of UZ                         | moved by one position 
1141   1  |   1    |   1   |   1  | No, kept out of UZ                         | moved to put caret at 3UZ of the margin 
1143 void Editor::EnsureCaretVisible(bool useMargin
, bool vert
, bool horiz
) { 
1144         //Platform::DebugPrintf("EnsureCaretVisible %d %s\n", xOffset, useMargin ? " margin" : " "); 
1145         PRectangle rcClient 
= GetTextRectangle(); 
1146         //int rcClientFullWidth = rcClient.Width(); 
1147         int posCaret 
= currentPos
; 
1151         Point pt 
= LocationFromPosition(posCaret
); 
1152         Point ptBottomCaret 
= pt
; 
1153         ptBottomCaret
.y 
+= vs
.lineHeight 
- 1; 
1154         int lineCaret 
= DisplayFromPosition(posCaret
); 
1155         bool bSlop
, bStrict
, bJump
, bEven
; 
1157         // Vertical positioning 
1158         if (vert 
&& (pt
.y 
< rcClient
.top 
|| ptBottomCaret
.y 
> rcClient
.bottom 
|| (caretYPolicy 
& CARET_STRICT
) != 0)) { 
1159                 int linesOnScreen 
= LinesOnScreen(); 
1160                 int halfScreen 
= Platform::Maximum(linesOnScreen 
- 1, 2) / 2; 
1161                 int newTopLine 
= topLine
; 
1162                 bSlop 
= (caretYPolicy 
& CARET_SLOP
) != 0; 
1163                 bStrict 
= (caretYPolicy 
& CARET_STRICT
) != 0; 
1164                 bJump 
= (caretYPolicy 
& CARET_JUMPS
) != 0; 
1165                 bEven 
= (caretYPolicy 
& CARET_EVEN
) != 0; 
1167                 // It should be possible to scroll the window to show the caret, 
1168                 // but this fails to remove the caret on GTK+ 
1169                 if (bSlop
) {    // A margin is defined 
1172                                 int yMarginT
, yMarginB
; 
1174                                         // In drag mode, avoid moves 
1175                                         // otherwise, a double click will select several lines. 
1176                                         yMarginT 
= yMarginB 
= 0; 
1178                                         // yMarginT must equal to caretYSlop, with a minimum of 1 and 
1179                                         // a maximum of slightly less than half the heigth of the text area. 
1180                                         yMarginT 
= Platform::Clamp(caretYSlop
, 1, halfScreen
); 
1182                                                 yMarginB 
= yMarginT
; 
1184                                                 yMarginB 
= linesOnScreen 
- yMarginT 
- 1; 
1190                                                 yMoveT 
= Platform::Clamp(caretYSlop 
* 3, 1, halfScreen
); 
1194                                         yMoveB 
= linesOnScreen 
- yMoveT 
- 1; 
1196                                 if (lineCaret 
< topLine 
+ yMarginT
) { 
1197                                         // Caret goes too high 
1198                                         newTopLine 
= lineCaret 
- yMoveT
; 
1199                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1 - yMarginB
) { 
1200                                         // Caret goes too low 
1201                                         newTopLine 
= lineCaret 
- linesOnScreen 
+ 1 + yMoveB
; 
1203                         } else {        // Not strict 
1204                                 yMoveT 
= bJump 
? caretYSlop 
* 3 : caretYSlop
; 
1205                                 yMoveT 
= Platform::Clamp(yMoveT
, 1, halfScreen
); 
1209                                         yMoveB 
= linesOnScreen 
- yMoveT 
- 1; 
1211                                 if (lineCaret 
< topLine
) { 
1212                                         // Caret goes too high 
1213                                         newTopLine 
= lineCaret 
- yMoveT
; 
1214                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1) { 
1215                                         // Caret goes too low 
1216                                         newTopLine 
= lineCaret 
- linesOnScreen 
+ 1 + yMoveB
; 
1220                         if (!bStrict 
&& !bJump
) { 
1222                                 if (lineCaret 
< topLine
) { 
1223                                         // Caret goes too high 
1224                                         newTopLine 
= lineCaret
; 
1225                                 } else if (lineCaret 
> topLine 
+ linesOnScreen 
- 1) { 
1226                                         // Caret goes too low 
1228                                                 newTopLine 
= lineCaret 
- linesOnScreen 
+ 1; 
1230                                                 newTopLine 
= lineCaret
; 
1233                         } else {        // Strict or going out of display 
1235                                         // Always center caret 
1236                                         newTopLine 
= lineCaret 
- halfScreen
; 
1238                                         // Always put caret on top of display 
1239                                         newTopLine 
= lineCaret
; 
1243                 newTopLine 
= Platform::Clamp(newTopLine
, 0, MaxScrollPos()); 
1244                 if (newTopLine 
!= topLine
) { 
1246                         SetTopLine(newTopLine
); 
1247                         SetVerticalScrollPos(); 
1251         // Horizontal positioning 
1252         if (horiz 
&& (wrapState 
== eWrapNone
)) { 
1253                 int halfScreen 
= Platform::Maximum(rcClient
.Width() - 4, 4) / 2; 
1254                 int xOffsetNew 
= xOffset
; 
1255                 bSlop 
= (caretXPolicy 
& CARET_SLOP
) != 0; 
1256                 bStrict 
= (caretXPolicy 
& CARET_STRICT
) != 0; 
1257                 bJump 
= (caretXPolicy 
& CARET_JUMPS
) != 0; 
1258                 bEven 
= (caretXPolicy 
& CARET_EVEN
) != 0; 
1260                 if (bSlop
) {    // A margin is defined 
1263                                 int xMarginL
, xMarginR
; 
1265                                         // In drag mode, avoid moves unless very near of the margin 
1266                                         // otherwise, a simple click will select text. 
1267                                         xMarginL 
= xMarginR 
= 2; 
1269                                         // xMargin must equal to caretXSlop, with a minimum of 2 and 
1270                                         // a maximum of slightly less than half the width of the text area. 
1271                                         xMarginR 
= Platform::Clamp(caretXSlop
, 2, halfScreen
); 
1273                                                 xMarginL 
= xMarginR
; 
1275                                                 xMarginL 
= rcClient
.Width() - xMarginR 
- 4; 
1278                                 if (bJump 
&& bEven
) { 
1279                                         // Jump is used only in even mode 
1280                                         xMoveL 
= xMoveR 
= Platform::Clamp(caretXSlop 
* 3, 1, halfScreen
); 
1282                                         xMoveL 
= xMoveR 
= 0;    // Not used, avoid a warning 
1284                                 if (pt
.x 
< rcClient
.left 
+ xMarginL
) { 
1285                                         // Caret is on the left of the display 
1286                                         if (bJump 
&& bEven
) { 
1287                                                 xOffsetNew 
-= xMoveL
; 
1289                                                 // Move just enough to allow to display the caret 
1290                                                 xOffsetNew 
-= (rcClient
.left 
+ xMarginL
) - pt
.x
; 
1292                                 } else if (pt
.x 
>= rcClient
.right 
- xMarginR
) { 
1293                                         // Caret is on the right of the display 
1294                                         if (bJump 
&& bEven
) { 
1295                                                 xOffsetNew 
+= xMoveR
; 
1297                                                 // Move just enough to allow to display the caret 
1298                                                 xOffsetNew 
+= pt
.x 
- (rcClient
.right 
- xMarginR
) + 1; 
1301                         } else {        // Not strict 
1302                                 xMoveR 
= bJump 
? caretXSlop 
* 3 : caretXSlop
; 
1303                                 xMoveR 
= Platform::Clamp(xMoveR
, 1, halfScreen
); 
1307                                         xMoveL 
= rcClient
.Width() - xMoveR 
- 4; 
1309                                 if (pt
.x 
< rcClient
.left
) { 
1310                                         // Caret is on the left of the display 
1311                                         xOffsetNew 
-= xMoveL
; 
1312                                 } else if (pt
.x 
>= rcClient
.right
) { 
1313                                         // Caret is on the right of the display 
1314                                         xOffsetNew 
+= xMoveR
; 
1319                                 (bJump 
&& (pt
.x 
< rcClient
.left 
|| pt
.x 
>= rcClient
.right
))) { 
1320                                 // Strict or going out of display 
1323                                         xOffsetNew 
+= pt
.x 
- rcClient
.left 
- halfScreen
; 
1325                                         // Put caret on right 
1326                                         xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1329                                 // Move just enough to allow to display the caret 
1330                                 if (pt
.x 
< rcClient
.left
) { 
1331                                         // Caret is on the left of the display 
1333                                                 xOffsetNew 
-= rcClient
.left 
- pt
.x
; 
1335                                                 xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1337                                 } else if (pt
.x 
>= rcClient
.right
) { 
1338                                         // Caret is on the right of the display 
1339                                         xOffsetNew 
+= pt
.x 
- rcClient
.right 
+ 1; 
1343                 // In case of a jump (find result) largely out of display, adjust the offset to display the caret 
1344                 if (pt
.x 
+ xOffset 
< rcClient
.left 
+ xOffsetNew
) { 
1345                         xOffsetNew 
= pt
.x 
+ xOffset 
- rcClient
.left
; 
1346                 } else if (pt
.x 
+ xOffset 
>= rcClient
.right 
+ xOffsetNew
) { 
1347                         xOffsetNew 
= pt
.x 
+ xOffset 
- rcClient
.right 
+ 1; 
1349                 if (xOffsetNew 
< 0) { 
1352                 if (xOffset 
!= xOffsetNew
) { 
1353                         xOffset 
= xOffsetNew
; 
1354                         if (xOffsetNew 
> 0) { 
1355                                 PRectangle rcText 
= GetTextRectangle(); 
1356                                 if (horizontalScrollBarVisible 
== true && 
1357                                         rcText
.Width() + xOffset 
> scrollWidth
) { 
1358                                         scrollWidth 
= xOffset 
+ rcText
.Width(); 
1362                         SetHorizontalScrollPos(); 
1368 void Editor::ShowCaretAtCurrentPosition() { 
1370                 caret
.active 
= true; 
1374                 caret
.active 
= false; 
1380 void Editor::DropCaret() { 
1381         caret
.active 
= false; 
1385 void Editor::InvalidateCaret() { 
1387                 InvalidateRange(posDrag
, posDrag 
+ 1); 
1389                 InvalidateRange(currentPos
, currentPos 
+ 1); 
1392 void Editor::NeedWrapping(int docLineStartWrapping
, int docLineEndWrapping
) { 
1393         bool noWrap 
= (docLastLineToWrap 
== docLineLastWrapped
); 
1394         if (docLineLastWrapped 
> (docLineStartWrapping 
- 1)) { 
1395                 docLineLastWrapped 
= docLineStartWrapping 
- 1; 
1396                 if (docLineLastWrapped 
< -1) 
1397                         docLineLastWrapped 
= -1; 
1398                 llc
.Invalidate(LineLayout::llPositions
); 
1401                 docLastLineToWrap 
= docLineEndWrapping
; 
1402         } else if (docLastLineToWrap 
< docLineEndWrapping
) { 
1403                 docLastLineToWrap 
= docLineEndWrapping 
+ 1; 
1405         if (docLastLineToWrap 
< -1) 
1406                 docLastLineToWrap 
= -1; 
1407         if (docLastLineToWrap 
>= pdoc
->LinesTotal()) 
1408                 docLastLineToWrap 
= pdoc
->LinesTotal()-1; 
1409         // Wrap lines during idle. 
1410         if (backgroundWrapEnabled 
&& docLastLineToWrap 
!= docLineLastWrapped 
) { 
1415 // Check if wrapping needed and perform any needed wrapping. 
1416 // fullwrap: if true, all lines which need wrapping will be done, 
1417 //           in this single call. 
1418 // priorityWrapLineStart: If greater than zero, all lines starting from 
1419 //           here to 100 lines past will be wrapped (even if there are 
1420 //           more lines under wrapping process in idle). 
1421 // If it is neither fullwrap, nor priorityWrap, then 100 lines will be 
1422 // wrapped, if there are any wrapping going on in idle. (Generally this 
1423 // condition is called only from idler). 
1424 // Return true if wrapping occurred. 
1425 bool Editor::WrapLines(bool fullWrap
, int priorityWrapLineStart
) { 
1426         // If there are any pending wraps, do them during idle if possible. 
1427         if (wrapState 
!= eWrapNone
) { 
1428                 if (docLineLastWrapped 
< docLastLineToWrap
) { 
1429                         if (!(backgroundWrapEnabled 
&& SetIdle(true))) { 
1430                                 // Background wrapping is disabled, or idle processing 
1431                                 // not supported.  A full wrap is required. 
1435                 if (!fullWrap 
&& priorityWrapLineStart 
>= 0 && 
1436                         // .. and if the paint window is outside pending wraps 
1437                         (((priorityWrapLineStart 
+ 100) < docLineLastWrapped
) || 
1438                          (priorityWrapLineStart 
> docLastLineToWrap
))) { 
1439                         // No priority wrap pending 
1443         int goodTopLine 
= topLine
; 
1444         bool wrapOccurred 
= false; 
1445         if (docLineLastWrapped 
< pdoc
->LinesTotal()) { 
1446                 if (wrapState 
== eWrapNone
) { 
1447                         if (wrapWidth 
!= LineLayout::wrapWidthInfinite
) { 
1448                                 wrapWidth 
= LineLayout::wrapWidthInfinite
; 
1449                                 for (int lineDoc 
= 0; lineDoc 
< pdoc
->LinesTotal(); lineDoc
++) { 
1450                                         cs
.SetHeight(lineDoc
, 1); 
1452                                 wrapOccurred 
= true; 
1454                         docLineLastWrapped 
= 0x7ffffff; 
1457                         int lineDocTop 
= cs
.DocFromDisplay(topLine
); 
1458                         int subLineTop 
= topLine 
- cs
.DisplayFromDoc(lineDocTop
); 
1459                         PRectangle rcTextArea 
= GetClientRectangle(); 
1460                         rcTextArea
.left 
= vs
.fixedColumnWidth
; 
1461                         rcTextArea
.right 
-= vs
.rightMarginWidth
; 
1462                         wrapWidth 
= rcTextArea
.Width(); 
1463                         // Ensure all of the document is styled. 
1464                         pdoc
->EnsureStyledTo(pdoc
->Length()); 
1466                         AutoSurface 
surface(this); 
1468                                 bool priorityWrap 
= false; 
1469                                 int lastLineToWrap 
= docLastLineToWrap
; 
1470                                 int firstLineToWrap 
= docLineLastWrapped
; 
1472                                         if (priorityWrapLineStart 
>= 0) { 
1473                                                 // This is a priority wrap. 
1474                                                 firstLineToWrap 
= priorityWrapLineStart
; 
1475                                                 lastLineToWrap 
= firstLineToWrap 
+ 100; 
1476                                                 priorityWrap 
= true; 
1478                                                 // This is idle wrap. 
1479                                                 lastLineToWrap 
= docLineLastWrapped 
+ 100; 
1481                                         if (lastLineToWrap 
>= docLastLineToWrap
) 
1482                                                 lastLineToWrap 
= docLastLineToWrap
; 
1483                                 } // else do a fullWrap. 
1485                                 // printf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, firstLineToWrap, lastLineToWrap); 
1486                                 // printf("Pending wraps: %d to %d\n", docLineLastWrapped, docLastLineToWrap); 
1487                                 while (firstLineToWrap 
< lastLineToWrap
) { 
1490                                                 docLineLastWrapped
++; 
1491                                         AutoLineLayout 
ll(llc
, RetrieveLineLayout(firstLineToWrap
)); 
1492                                         int linesWrapped 
= 1; 
1494                                                 LayoutLine(firstLineToWrap
, surface
, vs
, ll
, wrapWidth
); 
1495                                                 linesWrapped 
= ll
->lines
; 
1497                                         if (cs
.SetHeight(firstLineToWrap
, linesWrapped
)) { 
1498                                                 wrapOccurred 
= true; 
1501                                 // If wrapping is done, bring it to resting position 
1502                                 if (docLineLastWrapped 
> docLastLineToWrap
) { 
1503                                         docLineLastWrapped 
= -1; 
1504                                         docLastLineToWrap 
= -1; 
1507                         goodTopLine 
= cs
.DisplayFromDoc(lineDocTop
); 
1508                         if (subLineTop 
< cs
.GetHeight(lineDocTop
)) 
1509                                 goodTopLine 
+= subLineTop
; 
1511                                 goodTopLine 
+= cs
.GetHeight(lineDocTop
); 
1512                         //double durWrap = et.Duration(true); 
1513                         //Platform::DebugPrintf("Wrap:%9.6g \n", durWrap); 
1518                 SetTopLine(Platform::Clamp(goodTopLine
, 0, MaxScrollPos())); 
1519                 SetVerticalScrollPos(); 
1521         return wrapOccurred
; 
1524 void Editor::LinesJoin() { 
1525         if (!RangeContainsProtected(targetStart
, targetEnd
)) { 
1526                 pdoc
->BeginUndoAction(); 
1527                 bool prevNonWS 
= true; 
1528                 for (int pos 
= targetStart
; pos 
< targetEnd
; pos
++) { 
1529                         if (IsEOLChar(pdoc
->CharAt(pos
))) { 
1530                                 targetEnd 
-= pdoc
->LenChar(pos
); 
1533                                         // Ensure at least one space separating previous lines 
1534                                         pdoc
->InsertChar(pos
, ' '); 
1537                                 prevNonWS 
= pdoc
->CharAt(pos
) != ' '; 
1540                 pdoc
->EndUndoAction(); 
1544 const char *StringFromEOLMode(int eolMode
) { 
1545         if (eolMode 
== SC_EOL_CRLF
) { 
1547         } else if (eolMode 
== SC_EOL_CR
) { 
1554 void Editor::LinesSplit(int pixelWidth
) { 
1555         if (!RangeContainsProtected(targetStart
, targetEnd
)) { 
1556                 if (pixelWidth 
== 0) { 
1557                         PRectangle rcText 
= GetTextRectangle(); 
1558                         pixelWidth 
= rcText
.Width(); 
1560                 int lineStart 
= pdoc
->LineFromPosition(targetStart
); 
1561                 int lineEnd 
= pdoc
->LineFromPosition(targetEnd
); 
1562                 const char *eol 
= StringFromEOLMode(pdoc
->eolMode
); 
1563                 pdoc
->BeginUndoAction(); 
1564                 for (int line 
= lineStart
; line 
<= lineEnd
; line
++) { 
1565                         AutoSurface 
surface(this); 
1566                         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
1567                         if (surface 
&& ll
) { 
1568                                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
1569                                 LayoutLine(line
, surface
, vs
, ll
, pixelWidth
); 
1570                                 for (int subLine 
= 1; subLine 
< ll
->lines
; subLine
++) { 
1571                                         pdoc
->InsertString(posLineStart 
+ (subLine 
- 1) * strlen(eol
) + 
1572                                                 ll
->LineStart(subLine
), eol
); 
1573                                         targetEnd 
+= static_cast<int>(strlen(eol
)); 
1577                 pdoc
->EndUndoAction(); 
1581 int Editor::SubstituteMarkerIfEmpty(int markerCheck
, int markerDefault
) { 
1582         if (vs
.markers
[markerCheck
].markType 
== SC_MARK_EMPTY
) 
1583                 return markerDefault
; 
1587 // Avoid 64 bit compiler warnings. 
1588 // Scintilla does not support text buffers larger than 2**31 
1589 static int istrlen(const char *s
) { 
1590         return static_cast<int>(strlen(s
)); 
1593 void Editor::PaintSelMargin(Surface 
*surfWindow
, PRectangle 
&rc
) { 
1594         if (vs
.fixedColumnWidth 
== 0) 
1597         PRectangle rcMargin 
= GetClientRectangle(); 
1598         rcMargin
.right 
= vs
.fixedColumnWidth
; 
1600         if (!rc
.Intersects(rcMargin
)) 
1605                 surface 
= pixmapSelMargin
; 
1607                 surface 
= surfWindow
; 
1610         PRectangle rcSelMargin 
= rcMargin
; 
1611         rcSelMargin
.right 
= rcMargin
.left
; 
1613         for (int margin 
= 0; margin 
< vs
.margins
; margin
++) { 
1614                 if (vs
.ms
[margin
].width 
> 0) { 
1616                         rcSelMargin
.left 
= rcSelMargin
.right
; 
1617                         rcSelMargin
.right 
= rcSelMargin
.left 
+ vs
.ms
[margin
].width
; 
1619                         if (vs
.ms
[margin
].symbol
) { 
1620                                 /* alternate scheme: 
1621                                 if (vs.ms[margin].mask & SC_MASK_FOLDERS) 
1622                                         surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
1624                                         // Required because of special way brush is created for selection margin 
1625                                         surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
1627                                 if (vs
.ms
[margin
].mask 
& SC_MASK_FOLDERS
) 
1628                                         // Required because of special way brush is created for selection margin 
1629                                         surface
->FillRectangle(rcSelMargin
, *pixmapSelPattern
); 
1631                                         surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1633                                 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1636                         int visibleLine 
= topLine
; 
1639                         // Work out whether the top line is whitespace located after a 
1640                         // lessening of fold level which implies a 'fold tail' but which should not 
1641                         // be displayed until the last of a sequence of whitespace. 
1642                         bool needWhiteClosure 
= false; 
1643                         int level 
= pdoc
->GetLevel(cs
.DocFromDisplay(topLine
)); 
1644                         if (level 
& SC_FOLDLEVELWHITEFLAG
) { 
1645                                 int lineBack 
= cs
.DocFromDisplay(topLine
); 
1646                                 int levelPrev 
= level
; 
1647                                 while ((lineBack 
> 0) && (levelPrev 
& SC_FOLDLEVELWHITEFLAG
)) { 
1649                                         levelPrev 
= pdoc
->GetLevel(lineBack
); 
1651                                 if (!(levelPrev 
& SC_FOLDLEVELHEADERFLAG
)) { 
1652                                         if ((level 
& SC_FOLDLEVELNUMBERMASK
) < (levelPrev 
& SC_FOLDLEVELNUMBERMASK
)) 
1653                                                 needWhiteClosure 
= true; 
1657                         // Old code does not know about new markers needed to distinguish all cases 
1658                         int folderOpenMid 
= SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID
, 
1659                                             SC_MARKNUM_FOLDEROPEN
); 
1660                         int folderEnd 
= SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND
, 
1663                         while ((visibleLine 
< cs
.LinesDisplayed()) && yposScreen 
< rcMargin
.bottom
) { 
1665                                 PLATFORM_ASSERT(visibleLine 
< cs
.LinesDisplayed()); 
1667                                 int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
1668                                 PLATFORM_ASSERT(cs
.GetVisible(lineDoc
)); 
1669                                 bool firstSubLine 
= visibleLine 
== cs
.DisplayFromDoc(lineDoc
); 
1671                                 // Decide which fold indicator should be displayed 
1672                                 level 
= pdoc
->GetLevel(lineDoc
); 
1673                                 int levelNext 
= pdoc
->GetLevel(lineDoc 
+ 1); 
1674                                 int marks 
= pdoc
->GetMark(lineDoc
); 
1677                                 int levelNum 
= level 
& SC_FOLDLEVELNUMBERMASK
; 
1678                                 int levelNextNum 
= levelNext 
& SC_FOLDLEVELNUMBERMASK
; 
1679                                 if (level 
& SC_FOLDLEVELHEADERFLAG
) { 
1681                                                 if (cs
.GetExpanded(lineDoc
)) { 
1682                                                         if (levelNum 
== SC_FOLDLEVELBASE
) 
1683                                                                 marks 
|= 1 << SC_MARKNUM_FOLDEROPEN
; 
1685                                                                 marks 
|= 1 << folderOpenMid
; 
1687                                                         if (levelNum 
== SC_FOLDLEVELBASE
) 
1688                                                                 marks 
|= 1 << SC_MARKNUM_FOLDER
; 
1690                                                                 marks 
|= 1 << folderEnd
; 
1693                                                 marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1695                                         needWhiteClosure 
= false; 
1696                                 } else if (level 
& SC_FOLDLEVELWHITEFLAG
) { 
1697                                         if (needWhiteClosure
) { 
1698                                                 if (levelNext 
& SC_FOLDLEVELWHITEFLAG
) { 
1699                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1700                                                 } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1701                                                         marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1702                                                         needWhiteClosure 
= false; 
1704                                                         marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1705                                                         needWhiteClosure 
= false; 
1707                                         } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1708                                                 if (levelNextNum 
< levelNum
) { 
1709                                                         if (levelNextNum 
> SC_FOLDLEVELBASE
) { 
1710                                                                 marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1712                                                                 marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1715                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1718                                 } else if (levelNum 
> SC_FOLDLEVELBASE
) { 
1719                                         if (levelNextNum 
< levelNum
) { 
1720                                                 needWhiteClosure 
= false; 
1721                                                 if (levelNext 
& SC_FOLDLEVELWHITEFLAG
) { 
1722                                                         marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1723                                                         needWhiteClosure 
= true; 
1724                                                 } else if (levelNextNum 
> SC_FOLDLEVELBASE
) { 
1725                                                         marks 
|= 1 << SC_MARKNUM_FOLDERMIDTAIL
; 
1727                                                         marks 
|= 1 << SC_MARKNUM_FOLDERTAIL
; 
1730                                                 marks 
|= 1 << SC_MARKNUM_FOLDERSUB
; 
1734                                 marks 
&= vs
.ms
[margin
].mask
; 
1735                                 PRectangle rcMarker 
= rcSelMargin
; 
1736                                 rcMarker
.top 
= yposScreen
; 
1737                                 rcMarker
.bottom 
= yposScreen 
+ vs
.lineHeight
; 
1738                                 if (!vs
.ms
[margin
].symbol
) { 
1742                                                 sprintf(number
, "%d", lineDoc 
+ 1); 
1743                                         if (foldFlags 
& SC_FOLDFLAG_LEVELNUMBERS
) { 
1744                                                 int lev 
= pdoc
->GetLevel(lineDoc
); 
1745                                                 sprintf(number
, "%c%c %03X %03X", 
1746                                                         (lev 
& SC_FOLDLEVELHEADERFLAG
) ? 'H' : '_', 
1747                                                         (lev 
& SC_FOLDLEVELWHITEFLAG
) ? 'W' : '_', 
1748                                                         lev 
& SC_FOLDLEVELNUMBERMASK
, 
1752                                         PRectangle rcNumber 
= rcMarker
; 
1754                                         int width 
= surface
->WidthText(vs
.styles
[STYLE_LINENUMBER
].font
, number
, istrlen(number
)); 
1755                                         int xpos 
= rcNumber
.right 
- width 
- 3; 
1756                                         rcNumber
.left 
= xpos
; 
1757                                         surface
->DrawTextNoClip(rcNumber
, vs
.styles
[STYLE_LINENUMBER
].font
, 
1758                                                                 rcNumber
.top 
+ vs
.maxAscent
, number
, istrlen(number
), 
1759                                                                 vs
.styles
[STYLE_LINENUMBER
].fore
.allocated
, 
1760                                                                 vs
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
1764                                         for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
1766                                                         vs
.markers
[markBit
].Draw(surface
, rcMarker
, vs
.styles
[STYLE_LINENUMBER
].font
); 
1773                                 yposScreen 
+= vs
.lineHeight
; 
1778         PRectangle rcBlankMargin 
= rcMargin
; 
1779         rcBlankMargin
.left 
= rcSelMargin
.right
; 
1780         surface
->FillRectangle(rcBlankMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
1783                 surfWindow
->Copy(rcMargin
, Point(), *pixmapSelMargin
); 
1787 void DrawTabArrow(Surface 
*surface
, PRectangle rcTab
, int ymid
) { 
1788         int ydiff 
= (rcTab
.bottom 
- rcTab
.top
) / 2; 
1789         int xhead 
= rcTab
.right 
- 1 - ydiff
; 
1790         if (xhead 
<= rcTab
.left
) { 
1791                 ydiff 
-= rcTab
.left 
- xhead 
- 1; 
1792                 xhead 
= rcTab
.left 
- 1; 
1794         if ((rcTab
.left 
+ 2) < (rcTab
.right 
- 1)) 
1795                 surface
->MoveTo(rcTab
.left 
+ 2, ymid
); 
1797                 surface
->MoveTo(rcTab
.right 
- 1, ymid
); 
1798         surface
->LineTo(rcTab
.right 
- 1, ymid
); 
1799         surface
->LineTo(xhead
, ymid 
- ydiff
); 
1800         surface
->MoveTo(rcTab
.right 
- 1, ymid
); 
1801         surface
->LineTo(xhead
, ymid 
+ ydiff
); 
1804 static bool IsSpaceOrTab(char ch
) { 
1805         return ch 
== ' ' || ch 
== '\t'; 
1808 LineLayout 
*Editor::RetrieveLineLayout(int lineNumber
) { 
1809         int posLineStart 
= pdoc
->LineStart(lineNumber
); 
1810         int posLineEnd 
= pdoc
->LineStart(lineNumber 
+ 1); 
1811         int lineCaret 
= pdoc
->LineFromPosition(currentPos
); 
1812         return llc
.Retrieve(lineNumber
, lineCaret
, 
1813                             posLineEnd 
- posLineStart
, pdoc
->GetStyleClock(), 
1814                             LinesOnScreen() + 1, pdoc
->LinesTotal()); 
1818  * Fill in the LineLayout data for the given line. 
1819  * Copy the given @a line and its styles from the document into local arrays. 
1820  * Also determine the x position at which each character starts. 
1822 void Editor::LayoutLine(int line
, Surface 
*surface
, ViewStyle 
&vstyle
, LineLayout 
*ll
, int width
) { 
1825         PLATFORM_ASSERT(line 
< pdoc
->LinesTotal()); 
1826         int posLineStart 
= pdoc
->LineStart(line
); 
1827         int posLineEnd 
= pdoc
->LineStart(line 
+ 1); 
1828         // If the line is very long, limit the treatment to a length that should fit in the viewport 
1829         if (posLineEnd 
> (posLineStart 
+ ll
->maxLineLength
)) { 
1830                 posLineEnd 
= posLineStart 
+ ll
->maxLineLength
; 
1832         if (ll
->validity 
== LineLayout::llCheckTextAndStyle
) { 
1834                 for (int cid 
= posLineStart
; cid 
< posLineEnd
; cid
++) { 
1835                         char chDoc 
= pdoc
->CharAt(cid
); 
1836                         if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1840                 if (lineLength 
== ll
->numCharsInLine
) { 
1841                         int numCharsInLine 
= 0; 
1842                         // See if chars, styles, indicators, are all the same 
1843                         bool allSame 
= true; 
1844                         const int styleMask 
= pdoc
->stylingBitsMask
; 
1845                         // Check base line layout 
1846                         for (int charInDoc 
= posLineStart
; allSame 
&& (charInDoc 
< posLineEnd
); charInDoc
++) { 
1847                                 char chDoc 
= pdoc
->CharAt(charInDoc
); 
1848                                 if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1849                                         char styleByte 
= pdoc
->StyleAt(charInDoc
); 
1850                                         allSame 
= allSame 
&& 
1851                                                   (ll
->styles
[numCharsInLine
] == static_cast<char>(styleByte 
& styleMask
)); 
1852                                         allSame 
= allSame 
&& 
1853                                                   (ll
->indicators
[numCharsInLine
] == static_cast<char>(styleByte 
& ~styleMask
)); 
1854                                         if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseUpper
) 
1855                                                 allSame 
= allSame 
&& 
1856                                                           (ll
->chars
[numCharsInLine
] == static_cast<char>(toupper(chDoc
))); 
1857                                         else if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseLower
) 
1858                                                 allSame 
= allSame 
&& 
1859                                                           (ll
->chars
[numCharsInLine
] == static_cast<char>(tolower(chDoc
))); 
1861                                                 allSame 
= allSame 
&& 
1862                                                           (ll
->chars
[numCharsInLine
] == chDoc
); 
1867                                 ll
->validity 
= LineLayout::llPositions
; 
1869                                 ll
->validity 
= LineLayout::llInvalid
; 
1872                         ll
->validity 
= LineLayout::llInvalid
; 
1875         if (ll
->validity 
== LineLayout::llInvalid
) { 
1876                 ll
->widthLine 
= LineLayout::wrapWidthInfinite
; 
1878                 int numCharsInLine 
= 0; 
1879                 if (vstyle
.edgeState 
== EDGE_BACKGROUND
) { 
1880                         ll
->edgeColumn 
= pdoc
->FindColumn(line
, theEdge
); 
1881                         if (ll
->edgeColumn 
>= posLineStart
) { 
1882                                 ll
->edgeColumn 
-= posLineStart
; 
1885                         ll
->edgeColumn 
= -1; 
1889                 int styleMask 
= pdoc
->stylingBitsMask
; 
1890                 // Fill base line layout 
1891                 for (int charInDoc 
= posLineStart
; charInDoc 
< posLineEnd
; charInDoc
++) { 
1892                         char chDoc 
= pdoc
->CharAt(charInDoc
); 
1893                         styleByte 
= pdoc
->StyleAt(charInDoc
); 
1894                         if (vstyle
.viewEOL 
|| (!IsEOLChar(chDoc
))) { 
1895                                 ll
->chars
[numCharsInLine
] = chDoc
; 
1896                                 ll
->styles
[numCharsInLine
] = static_cast<char>(styleByte 
& styleMask
); 
1897                                 ll
->indicators
[numCharsInLine
] = static_cast<char>(styleByte 
& ~styleMask
); 
1898                                 if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseUpper
) 
1899                                         ll
->chars
[numCharsInLine
] = static_cast<char>(toupper(chDoc
)); 
1900                                 else if (vstyle
.styles
[ll
->styles
[numCharsInLine
]].caseForce 
== Style::caseLower
) 
1901                                         ll
->chars
[numCharsInLine
] = static_cast<char>(tolower(chDoc
)); 
1905                 ll
->xHighlightGuide 
= 0; 
1906                 // Extra element at the end of the line to hold end x position and act as 
1907                 ll
->chars
[numCharsInLine
] = 0;   // Also triggers processing in the loops as this is a control character 
1908                 ll
->styles
[numCharsInLine
] = styleByte
; // For eolFilled 
1909                 ll
->indicators
[numCharsInLine
] = 0; 
1911                 // Layout the line, determining the position of each character, 
1912                 // with an extra element at the end for the end of the line. 
1913                 int startseg 
= 0;       // Start of the current segment, in char. number 
1914                 int startsegx 
= 0;      // Start of the current segment, in pixels 
1915                 ll
->positions
[0] = 0; 
1916                 unsigned int tabWidth 
= vstyle
.spaceWidth 
* pdoc
->tabInChars
; 
1917                 bool lastSegItalics 
= false; 
1918                 Font 
&ctrlCharsFont 
= vstyle
.styles
[STYLE_CONTROLCHAR
].font
; 
1920                 bool isControlNext 
= IsControlCharacter(ll
->chars
[0]); 
1921                 for (int charInLine 
= 0; charInLine 
< numCharsInLine
; charInLine
++) { 
1922                         bool isControl 
= isControlNext
; 
1923                         isControlNext 
= IsControlCharacter(ll
->chars
[charInLine 
+ 1]); 
1924                         if ((ll
->styles
[charInLine
] != ll
->styles
[charInLine 
+ 1]) || 
1925                                 isControl 
|| isControlNext
) { 
1926                                 ll
->positions
[startseg
] = 0; 
1927                                 if (vstyle
.styles
[ll
->styles
[charInLine
]].visible
) { 
1929                                                 if (ll
->chars
[charInLine
] == '\t') { 
1930                                                         ll
->positions
[charInLine 
+ 1] = ((((startsegx 
+ 2) / 
1931                                                                                            tabWidth
) + 1) * tabWidth
) - startsegx
; 
1932                                                 } else if (controlCharSymbol 
< 32) { 
1933                                                         const char *ctrlChar 
= ControlCharacterString(ll
->chars
[charInLine
]); 
1934                                                         // +3 For a blank on front and rounded edge each side: 
1935                                                         ll
->positions
[charInLine 
+ 1] = surface
->WidthText(ctrlCharsFont
, ctrlChar
, istrlen(ctrlChar
)) + 3; 
1937                                                         char cc
[2] = { static_cast<char>(controlCharSymbol
), '\0' }; 
1938                                                         surface
->MeasureWidths(ctrlCharsFont
, cc
, 1, 
1939                                                                                ll
->positions 
+ startseg 
+ 1); 
1941                                                 lastSegItalics 
= false; 
1942                                         } else {        // Regular character 
1943                                                 int lenSeg 
= charInLine 
- startseg 
+ 1; 
1944                                                 if ((lenSeg 
== 1) && (' ' == ll
->chars
[startseg
])) { 
1945                                                         lastSegItalics 
= false; 
1946                                                         // Over half the segments are single characters and of these about half are space characters. 
1947                                                         ll
->positions
[charInLine 
+ 1] = vstyle
.styles
[ll
->styles
[charInLine
]].spaceWidth
; 
1949                                                         lastSegItalics 
= vstyle
.styles
[ll
->styles
[charInLine
]].italic
; 
1950                                                         surface
->MeasureWidths(vstyle
.styles
[ll
->styles
[charInLine
]].font
, ll
->chars 
+ startseg
, 
1951                                                                                lenSeg
, ll
->positions 
+ startseg 
+ 1); 
1954                                 } else {    // invisible 
1955                                         for (int posToZero 
= startseg
; posToZero 
<= (charInLine 
+ 1); posToZero
++) { 
1956                                                 ll
->positions
[posToZero
] = 0; 
1959                                 for (int posToIncrease 
= startseg
; posToIncrease 
<= (charInLine 
+ 1); posToIncrease
++) { 
1960                                         ll
->positions
[posToIncrease
] += startsegx
; 
1962                                 startsegx 
= ll
->positions
[charInLine 
+ 1]; 
1963                                 startseg 
= charInLine 
+ 1; 
1966                 // Small hack to make lines that end with italics not cut off the edge of the last character 
1967                 if ((startseg 
> 0) && lastSegItalics
) { 
1968                         ll
->positions
[startseg
] += 2; 
1970                 ll
->numCharsInLine 
= numCharsInLine
; 
1971                 ll
->validity 
= LineLayout::llPositions
; 
1973         // Hard to cope when too narrow, so just assume there is space 
1977         if ((ll
->validity 
== LineLayout::llPositions
) || (ll
->widthLine 
!= width
)) { 
1978                 ll
->widthLine 
= width
; 
1979                 if (width 
== LineLayout::wrapWidthInfinite
) { 
1981                 } else if (width 
> ll
->positions
[ll
->numCharsInLine
]) { 
1982                         // Simple common case where line does not need wrapping. 
1986                         // Calculate line start positions based upon width. 
1987                         // For now this is simplistic - wraps on byte rather than character and 
1988                         // in the middle of words. Should search for spaces or style changes. 
1989                         int lastGoodBreak 
= 0; 
1990                         int lastLineStart 
= 0; 
1991                         int startOffset 
= 0; 
1993                         while (p 
< ll
->numCharsInLine
) { 
1994                                 if ((ll
->positions
[p 
+ 1] - startOffset
) >= width
) { 
1995                                         if (lastGoodBreak 
== lastLineStart
) { 
1996                                                 // Try moving to start of last character 
1998                                                         lastGoodBreak 
= pdoc
->MovePositionOutsideChar(p 
+ posLineStart
, -1) 
2001                                                 if (lastGoodBreak 
== lastLineStart
) { 
2002                                                         // Ensure at least one character on line. 
2003                                                         lastGoodBreak 
= pdoc
->MovePositionOutsideChar(lastGoodBreak 
+ posLineStart 
+ 1, 1) 
2007                                         lastLineStart 
= lastGoodBreak
; 
2009                                         ll
->SetLineStart(ll
->lines
, lastGoodBreak
); 
2010                                         startOffset 
= ll
->positions
[lastGoodBreak
]; 
2011                                         p 
= lastGoodBreak 
+ 1; 
2015                                         if (ll
->styles
[p
] != ll
->styles
[p 
- 1]) { 
2017                                         } else if (IsSpaceOrTab(ll
->chars
[p 
- 1]) && !IsSpaceOrTab(ll
->chars
[p
])) { 
2025                 ll
->validity 
= LineLayout::llLines
; 
2029 ColourAllocated 
Editor::TextBackground(ViewStyle 
&vsDraw
, bool overrideBackground
, 
2030                                        ColourAllocated background
, bool inSelection
, bool inHotspot
, int styleMain
, int i
, LineLayout 
*ll
) { 
2032                 if (vsDraw
.selbackset
) { 
2033                         if (primarySelection
) 
2034                                 return vsDraw
.selbackground
.allocated
; 
2036                                 return vsDraw
.selbackground2
.allocated
; 
2039                 if ((vsDraw
.edgeState 
== EDGE_BACKGROUND
) && 
2040                         (i 
>= ll
->edgeColumn
) && 
2041                         !IsEOLChar(ll
->chars
[i
])) 
2042                         return vsDraw
.edgecolour
.allocated
; 
2043                 if (inHotspot 
&& vsDraw
.hotspotBackgroundSet
) 
2044                         return vsDraw
.hotspotBackground
.allocated
; 
2045                 if (overrideBackground
) 
2048         return vsDraw
.styles
[styleMain
].back
.allocated
; 
2051 void Editor::DrawIndentGuide(Surface 
*surface
, int lineVisible
, int lineHeight
, int start
, PRectangle rcSegment
, bool highlight
) { 
2052         Point 
from(0, ((lineVisible 
& 1) && (lineHeight 
& 1)) ? 1 : 0); 
2053         PRectangle 
rcCopyArea(start 
+ 1, rcSegment
.top
, start 
+ 2, rcSegment
.bottom
); 
2054         surface
->Copy(rcCopyArea
, from
, 
2055                       highlight 
? *pixmapIndentGuideHighlight 
: *pixmapIndentGuide
); 
2058 void Editor::DrawEOL(Surface 
*surface
, ViewStyle 
&vsDraw
, PRectangle rcLine
, LineLayout 
*ll
, 
2059                      int line
, int lineEnd
, int xStart
, int subLine
, int subLineStart
, 
2060                      bool overrideBackground
, ColourAllocated background
) { 
2062         int styleMask 
= pdoc
->stylingBitsMask
; 
2063         PRectangle rcSegment 
= rcLine
; 
2065         // Fill in a PRectangle representing the end of line characters 
2066         int xEol 
= ll
->positions
[lineEnd
] - subLineStart
; 
2067         rcSegment
.left 
= xEol 
+ xStart
; 
2068         rcSegment
.right 
= xEol 
+ vsDraw
.aveCharWidth 
+ xStart
; 
2069         int posLineEnd 
= pdoc
->LineStart(line 
+ 1); 
2070         bool eolInSelection 
= (subLine 
== (ll
->lines 
- 1)) && 
2071                               (posLineEnd 
> ll
->selStart
) && (posLineEnd 
<= ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2072         if (eolInSelection 
&& vsDraw
.selbackset 
&& (line 
< pdoc
->LinesTotal() - 1)) { 
2073                 if (primarySelection
) 
2074                         surface
->FillRectangle(rcSegment
, vsDraw
.selbackground
.allocated
); 
2076                         surface
->FillRectangle(rcSegment
, vsDraw
.selbackground2
.allocated
); 
2077         } else if (overrideBackground
) { 
2078                 surface
->FillRectangle(rcSegment
, background
); 
2080                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].back
.allocated
); 
2083         rcSegment
.left 
= xEol 
+ vsDraw
.aveCharWidth 
+ xStart
; 
2084         rcSegment
.right 
= rcLine
.right
; 
2085         if (overrideBackground
) { 
2086                 surface
->FillRectangle(rcSegment
, background
); 
2087         } else if (vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].eolFilled
) { 
2088                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
->styles
[ll
->numCharsInLine
] & styleMask
].back
.allocated
); 
2090                 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2094 void Editor::DrawLine(Surface 
*surface
, ViewStyle 
&vsDraw
, int line
, int lineVisible
, int xStart
, 
2095                       PRectangle rcLine
, LineLayout 
*ll
, int subLine
) { 
2097         PRectangle rcSegment 
= rcLine
; 
2099         // Using one font for all control characters so it can be controlled independently to ensure 
2100         // the box goes around the characters tightly. Seems to be no way to work out what height 
2101         // is taken by an individual character - internal leading gives varying results. 
2102         Font 
&ctrlCharsFont 
= vsDraw
.styles
[STYLE_CONTROLCHAR
].font
; 
2104         // See if something overrides the line background color:  Either if caret is on the line 
2105         // and background color is set for that, or if a marker is defined that forces its background 
2106         // color onto the line, or if a marker is defined but has no selection margin in which to 
2107         // display itself.  These are checked in order with the earlier taking precedence.  When 
2108         // multiple markers cause background override, the color for the highest numbered one is used. 
2109         bool overrideBackground 
= false; 
2110         ColourAllocated background
; 
2111         if (caret
.active 
&& vsDraw
.showCaretLineBackground 
&& ll
->containsCaret
) { 
2112                 overrideBackground 
= true; 
2113                 background 
= vsDraw
.caretLineBackground
.allocated
; 
2115         if (!overrideBackground
) { 
2116                 int marks 
= pdoc
->GetMark(line
); 
2117                 for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
2118                         if ((marks 
& 1) && vsDraw
.markers
[markBit
].markType 
== SC_MARK_BACKGROUND
) { 
2119                                 background 
= vsDraw
.markers
[markBit
].back
.allocated
; 
2120                                 overrideBackground 
= true; 
2125         if (!overrideBackground
) { 
2126                 if (vsDraw
.maskInLine
) { 
2127                         int marks 
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
; 
2129                                 overrideBackground 
= true; 
2130                                 for (int markBit 
= 0; (markBit 
< 32) && marks
; markBit
++) { 
2132                                                 background 
= vsDraw
.markers
[markBit
].back
.allocated
; 
2140         bool drawWhitespaceBackground 
= (vsDraw
.viewWhitespace 
!= wsInvisible
) && 
2141                                         (!overrideBackground
) && (vsDraw
.whitespaceBackgroundSet
); 
2143         bool inIndentation 
= subLine 
== 0;      // Do not handle indentation except on first subline. 
2144         int indentWidth 
= pdoc
->indentInChars 
* vsDraw
.spaceWidth
; 
2145         if (indentWidth 
== 0) 
2146                 indentWidth 
= pdoc
->tabInChars 
* vsDraw
.spaceWidth
; 
2148         int posLineStart 
= pdoc
->LineStart(line
); 
2150         int startseg 
= ll
->LineStart(subLine
); 
2151         int subLineStart 
= ll
->positions
[startseg
]; 
2154         if (subLine 
< ll
->lines
) { 
2155                 lineStart 
= ll
->LineStart(subLine
); 
2156                 lineEnd 
= ll
->LineStart(subLine 
+ 1); 
2160         // Background drawing loop 
2161         for (i 
= lineStart
; twoPhaseDraw 
&& (i 
< lineEnd
); i
++) { 
2163                 int iDoc 
= i 
+ posLineStart
; 
2164                 // If there is the end of a style run for any reason 
2165                 if ((ll
->styles
[i
] != ll
->styles
[i 
+ 1]) || 
2166                         i 
== (lineEnd 
- 1) || 
2167                         IsControlCharacter(ll
->chars
[i
]) || IsControlCharacter(ll
->chars
[i 
+ 1]) || 
2168                         ((ll
->selStart 
!= ll
->selEnd
) && ((iDoc 
+ 1 == ll
->selStart
) || (iDoc 
+ 1 == ll
->selEnd
))) || 
2169                         (i 
== (ll
->edgeColumn 
- 1))) { 
2170                         rcSegment
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2171                         rcSegment
.right 
= ll
->positions
[i 
+ 1] + xStart 
- subLineStart
; 
2172                         // Only try to draw if really visible - enhances performance by not calling environment to 
2173                         // draw strings that are completely past the right side of the window. 
2174                         if ((rcSegment
.left 
<= rcLine
.right
) && (rcSegment
.right 
>= rcLine
.left
)) { 
2175                                 int styleMain 
= ll
->styles
[i
]; 
2176                                 bool inSelection 
= (iDoc 
>= ll
->selStart
) && (iDoc 
< ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2177                                 bool inHotspot 
= (ll
->hsStart 
!= -1) && (iDoc 
>= ll
->hsStart
) && (iDoc 
< ll
->hsEnd
); 
2178                                 ColourAllocated textBack 
= TextBackground(vsDraw
, overrideBackground
, background
, inSelection
, inHotspot
, styleMain
, i
, ll
); 
2179                                 if (ll
->chars
[i
] == '\t') { 
2181                                         if (drawWhitespaceBackground 
&& 
2182                                                 (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) 
2183                                                 textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2184                                         surface
->FillRectangle(rcSegment
, textBack
); 
2185                                 } else if (IsControlCharacter(ll
->chars
[i
])) { 
2186                                         // Control character display 
2187                                         inIndentation 
= false; 
2188                                         surface
->FillRectangle(rcSegment
, textBack
); 
2190                                         // Normal text display 
2191                                         surface
->FillRectangle(rcSegment
, textBack
); 
2192                                         if (vsDraw
.viewWhitespace 
!= wsInvisible 
|| 
2193                                                 (inIndentation 
&& vsDraw
.viewIndentationGuides
)) { 
2194                                                 for (int cpos 
= 0; cpos 
<= i 
- startseg
; cpos
++) { 
2195                                                         if (ll
->chars
[cpos 
+ startseg
] == ' ') { 
2196                                                                 if (drawWhitespaceBackground 
&& 
2197                                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) { 
2198                                                                         PRectangle 
rcSpace(ll
->positions
[cpos 
+ startseg
] + xStart
, rcSegment
.top
, 
2199                                                                                            ll
->positions
[cpos 
+ startseg 
+ 1] + xStart
, rcSegment
.bottom
); 
2200                                                                         surface
->FillRectangle(rcSpace
, vsDraw
.whitespaceBackground
.allocated
); 
2203                                                                 inIndentation 
= false; 
2214                 DrawEOL(surface
, vsDraw
, rcLine
, ll
, line
, lineEnd
, 
2215                         xStart
, subLine
, subLineStart
, overrideBackground
, background
); 
2218         inIndentation 
= subLine 
== 0;   // Do not handle indentation except on first subline. 
2219         startseg 
= ll
->LineStart(subLine
); 
2220         // Foreground drawing loop 
2221         for (i 
= lineStart
; i 
< lineEnd
; i
++) { 
2223                 int iDoc 
= i 
+ posLineStart
; 
2224                 // If there is the end of a style run for any reason 
2225                 if ((ll
->styles
[i
] != ll
->styles
[i 
+ 1]) || 
2226                         i 
== (lineEnd 
- 1) || 
2227                         IsControlCharacter(ll
->chars
[i
]) || IsControlCharacter(ll
->chars
[i 
+ 1]) || 
2228                         ((ll
->selStart 
!= ll
->selEnd
) && ((iDoc 
+ 1 == ll
->selStart
) || (iDoc 
+ 1 == ll
->selEnd
))) || 
2229                         (i 
== (ll
->edgeColumn 
- 1))) { 
2230                         rcSegment
.left 
= ll
->positions
[startseg
] + xStart 
- subLineStart
; 
2231                         rcSegment
.right 
= ll
->positions
[i 
+ 1] + xStart 
- subLineStart
; 
2232                         // Only try to draw if really visible - enhances performance by not calling environment to 
2233                         // draw strings that are completely past the right side of the window. 
2234                         if ((rcSegment
.left 
<= rcLine
.right
) && (rcSegment
.right 
>= rcLine
.left
)) { 
2235                                 int styleMain 
= ll
->styles
[i
]; 
2236                                 ColourAllocated textFore 
= vsDraw
.styles
[styleMain
].fore
.allocated
; 
2237                                 Font 
&textFont 
= vsDraw
.styles
[styleMain
].font
; 
2238                                 //hotspot foreground 
2239                                 if (ll
->hsStart 
!= -1 && iDoc 
>= ll
->hsStart 
&& iDoc 
< hsEnd
) { 
2240                                         if (vsDraw
.hotspotForegroundSet
) 
2241                                                 textFore 
= vsDraw
.hotspotForeground
.allocated
; 
2243                                 bool inSelection 
= (iDoc 
>= ll
->selStart
) && (iDoc 
< ll
->selEnd
) && (ll
->selStart 
!= ll
->selEnd
); 
2244                                 if (inSelection 
&& (vsDraw
.selforeset
)) { 
2245                                         textFore 
= vsDraw
.selforeground
.allocated
; 
2247                                 bool inHotspot 
= (ll
->hsStart 
!= -1) && (iDoc 
>= ll
->hsStart
) && (iDoc 
< ll
->hsEnd
); 
2248                                 ColourAllocated textBack 
= TextBackground(vsDraw
, overrideBackground
, background
, inSelection
, inHotspot
, styleMain
, i
, ll
); 
2249                                 if (ll
->chars
[i
] == '\t') { 
2251                                         if (!twoPhaseDraw
) { 
2252                                                 if (drawWhitespaceBackground 
&& 
2253                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) 
2254                                                         textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2255                                                 surface
->FillRectangle(rcSegment
, textBack
); 
2257                                         if ((vsDraw
.viewWhitespace 
!= wsInvisible
) || ((inIndentation 
&& vsDraw
.viewIndentationGuides
))) { 
2258                                                 if (vsDraw
.whitespaceForegroundSet
) 
2259                                                         textFore 
= vsDraw
.whitespaceForeground
.allocated
; 
2260                                                 surface
->PenColour(textFore
); 
2262                                         if (inIndentation 
&& vsDraw
.viewIndentationGuides
) { 
2263                                                 for (int xIG 
= ll
->positions
[i
] / indentWidth 
* indentWidth
; xIG 
< ll
->positions
[i 
+ 1]; xIG 
+= indentWidth
) { 
2264                                                         if (xIG 
>= ll
->positions
[i
] && xIG 
> 0) { 
2265                                                                 DrawIndentGuide(surface
, lineVisible
, vsDraw
.lineHeight
, xIG 
+ xStart
, rcSegment
, 
2266                                                                                 (ll
->xHighlightGuide 
== xIG
)); 
2270                                         if (vsDraw
.viewWhitespace 
!= wsInvisible
) { 
2271                                                 if (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
) { 
2272                                                         PRectangle 
rcTab(rcSegment
.left 
+ 1, rcSegment
.top 
+ 4, 
2273                                                                          rcSegment
.right 
- 1, rcSegment
.bottom 
- vsDraw
.maxDescent
); 
2274                                                         DrawTabArrow(surface
, rcTab
, rcSegment
.top 
+ vsDraw
.lineHeight 
/ 2); 
2277                                 } else if (IsControlCharacter(ll
->chars
[i
])) { 
2278                                         // Control character display 
2279                                         inIndentation 
= false; 
2280                                         if (controlCharSymbol 
< 32) { 
2281                                                 // Draw the character 
2282                                                 const char *ctrlChar 
= ControlCharacterString(ll
->chars
[i
]); 
2283                                                 if (!twoPhaseDraw
) { 
2284                                                         surface
->FillRectangle(rcSegment
, textBack
); 
2286                                                 int normalCharHeight 
= surface
->Ascent(ctrlCharsFont
) - 
2287                                                                        surface
->InternalLeading(ctrlCharsFont
); 
2288                                                 PRectangle rcCChar 
= rcSegment
; 
2289                                                 rcCChar
.left 
= rcCChar
.left 
+ 1; 
2290                                                 rcCChar
.top 
= rcSegment
.top 
+ vsDraw
.maxAscent 
- normalCharHeight
; 
2291                                                 rcCChar
.bottom 
= rcSegment
.top 
+ vsDraw
.maxAscent 
+ 1; 
2292                                                 PRectangle rcCentral 
= rcCChar
; 
2295                                                 surface
->FillRectangle(rcCentral
, textFore
); 
2296                                                 PRectangle rcChar 
= rcCChar
; 
2299                                                 surface
->DrawTextClipped(rcChar
, ctrlCharsFont
, 
2300                                                                          rcSegment
.top 
+ vsDraw
.maxAscent
, ctrlChar
, istrlen(ctrlChar
), 
2301                                                                          textBack
, textFore
); 
2303                                                 char cc
[2] = { static_cast<char>(controlCharSymbol
), '\0' }; 
2304                                                 surface
->DrawTextNoClip(rcSegment
, ctrlCharsFont
, 
2305                                                                         rcSegment
.top 
+ vsDraw
.maxAscent
, 
2306                                                                         cc
, 1, textBack
, textFore
); 
2309                                         // Normal text display 
2310                                         if (vsDraw
.styles
[styleMain
].visible
) { 
2312                                                         surface
->DrawTextTransparent(rcSegment
, textFont
, 
2313                                                                                      rcSegment
.top 
+ vsDraw
.maxAscent
, ll
->chars 
+ startseg
, 
2314                                                                                      i 
- startseg 
+ 1, textFore
); 
2316                                                         surface
->DrawTextNoClip(rcSegment
, textFont
, 
2317                                                                                 rcSegment
.top 
+ vsDraw
.maxAscent
, ll
->chars 
+ startseg
, 
2318                                                                                 i 
- startseg 
+ 1, textFore
, textBack
); 
2321                                         if (vsDraw
.viewWhitespace 
!= wsInvisible 
|| 
2322                                                 (inIndentation 
&& vsDraw
.viewIndentationGuides
)) { 
2323                                                 for (int cpos 
= 0; cpos 
<= i 
- startseg
; cpos
++) { 
2324                                                         if (ll
->chars
[cpos 
+ startseg
] == ' ') { 
2325                                                                 if (vsDraw
.viewWhitespace 
!= wsInvisible
) { 
2326                                                                         if (vsDraw
.whitespaceForegroundSet
) 
2327                                                                                 textFore 
= vsDraw
.whitespaceForeground
.allocated
; 
2328                                                                         if (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
) { 
2329                                                                                 int xmid 
= (ll
->positions
[cpos 
+ startseg
] + ll
->positions
[cpos 
+ startseg 
+ 1]) / 2; 
2330                                                                                 if (!twoPhaseDraw 
&& drawWhitespaceBackground 
&& 
2331                                                                                         (!inIndentation 
|| vsDraw
.viewWhitespace 
== wsVisibleAlways
)) { 
2332                                                                                         textBack 
= vsDraw
.whitespaceBackground
.allocated
; 
2333                                                                                         PRectangle 
rcSpace(ll
->positions
[cpos 
+ startseg
] + xStart
, rcSegment
.top
, ll
->positions
[cpos 
+ startseg 
+ 1] + xStart
, rcSegment
.bottom
); 
2334                                                                                         surface
->FillRectangle(rcSpace
, textBack
); 
2336                                                                                 PRectangle 
rcDot(xmid 
+ xStart 
- subLineStart
, rcSegment
.top 
+ vsDraw
.lineHeight 
/ 2, 0, 0); 
2337                                                                                 rcDot
.right 
= rcDot
.left 
+ 1; 
2338                                                                                 rcDot
.bottom 
= rcDot
.top 
+ 1; 
2339                                                                                 surface
->FillRectangle(rcDot
, textFore
); 
2342                                                                 if (inIndentation 
&& vsDraw
.viewIndentationGuides
) { 
2343                                                                         int startSpace 
= ll
->positions
[cpos 
+ startseg
]; 
2344                                                                         if (startSpace 
> 0 && (startSpace 
% indentWidth 
== 0)) { 
2345                                                                                 DrawIndentGuide(surface
, lineVisible
, vsDraw
.lineHeight
, startSpace 
+ xStart
, rcSegment
, 
2346                                                                                                 (ll
->xHighlightGuide 
== ll
->positions
[cpos 
+ startseg
])); 
2350                                                                 inIndentation 
= false; 
2355                                 if (ll
->hsStart 
!= -1 && vsDraw
.hotspotUnderline 
&& iDoc 
>= ll
->hsStart 
&& iDoc 
< ll
->hsEnd 
) { 
2356                                         PRectangle rcUL 
= rcSegment
; 
2357                                         rcUL
.top 
= rcUL
.top 
+ vsDraw
.maxAscent 
+ 1; 
2358                                         rcUL
.bottom 
= rcUL
.top 
+ 1; 
2359                                         if (vsDraw
.hotspotForegroundSet
) 
2360                                                 surface
->FillRectangle(rcUL
, vsDraw
.hotspotForeground
.allocated
); 
2362                                                 surface
->FillRectangle(rcUL
, textFore
); 
2363                                 } else if (vsDraw
.styles
[styleMain
].underline
) { 
2364                                         PRectangle rcUL 
= rcSegment
; 
2365                                         rcUL
.top 
= rcUL
.top 
+ vsDraw
.maxAscent 
+ 1; 
2366                                         rcUL
.bottom 
= rcUL
.top 
+ 1; 
2367                                         surface
->FillRectangle(rcUL
, textFore
); 
2375         int indStart
[INDIC_MAX 
+ 1] = {0}; 
2376         for (int indica 
= 0; indica 
<= INDIC_MAX
; indica
++) 
2377                 indStart
[indica
] = 0; 
2379         for (int indicPos 
= lineStart
; indicPos 
<= lineEnd
; indicPos
++) { 
2380                 if ((indicPos 
== lineEnd
) || (ll
->indicators
[indicPos
] != ll
->indicators
[indicPos 
+ 1])) { 
2381                         int mask 
= 1 << pdoc
->stylingBits
; 
2382                         for (int indicnum 
= 0; mask 
< 0x100; indicnum
++) { 
2383                                 if ((indicPos 
== lineEnd
)) { 
2384                                         indStart
[indicnum
] = ll
->positions
[indicPos
]; 
2385                                 } else if ((ll
->indicators
[indicPos 
+ 1] & mask
) && !(ll
->indicators
[indicPos
] & mask
)) { 
2386                                         indStart
[indicnum
] = ll
->positions
[indicPos 
+ 1]; 
2388                                 if ((ll
->indicators
[indicPos
] & mask
) && 
2389                                         ((indicPos 
== lineEnd
) || !(ll
->indicators
[indicPos 
+ 1] & mask
))) { 
2390                                         int endIndicator 
= indicPos
; 
2391                                         if (endIndicator 
>= lineEnd
) 
2392                                                 endIndicator 
= lineEnd
-1; 
2394                                                 indStart
[indicnum
] + xStart 
- subLineStart
, 
2395                                                 rcLine
.top 
+ vsDraw
.maxAscent
, 
2396                                                 ll
->positions
[endIndicator 
+ 1] + xStart 
- subLineStart
, 
2397                                                 rcLine
.top 
+ vsDraw
.maxAscent 
+ 3); 
2398                                         vsDraw
.indicators
[indicnum
].Draw(surface
, rcIndic
, rcLine
); 
2404         // End of the drawing of the current line 
2406         if (!twoPhaseDraw
) { 
2407                 DrawEOL(surface
, vsDraw
, rcLine
, ll
, line
, lineEnd
, 
2408                         xStart
, subLine
, subLineStart
, overrideBackground
, background
); 
2411         if (vsDraw
.edgeState 
== EDGE_LINE
) { 
2412                 int edgeX 
= theEdge 
* vsDraw
.spaceWidth
; 
2413                 rcSegment
.left 
= edgeX 
+ xStart
; 
2414                 rcSegment
.right 
= rcSegment
.left 
+ 1; 
2415                 surface
->FillRectangle(rcSegment
, vsDraw
.edgecolour
.allocated
); 
2419 void Editor::RefreshPixMaps(Surface 
*surfaceWindow
) { 
2420         if (!pixmapSelPattern
->Initialised()) { 
2421                 const int patternSize 
= 8; 
2422                 pixmapSelPattern
->InitPixMap(patternSize
, patternSize
, surfaceWindow
, wMain
.GetID()); 
2423                 // This complex procedure is to reproduce the checkerboard dithered pattern used by windows 
2424                 // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half 
2425                 // way between the chrome colour and the chrome highlight colour making a nice transition 
2426                 // between the window chrome and the content area. And it works in low colour depths. 
2427                 PRectangle 
rcPattern(0, 0, patternSize
, patternSize
); 
2429                 // Initialize default colours based on the chrome colour scheme.  Typically the highlight is white. 
2430                 ColourAllocated colourFMFill 
= vs
.selbar
.allocated
; 
2431                 ColourAllocated colourFMStripes 
= vs
.selbarlight
.allocated
; 
2433                 if (!(vs
.selbarlight
.desired 
== ColourDesired(0xff, 0xff, 0xff))) { 
2434                         // User has chosen an unusual chrome colour scheme so just use the highlight edge colour. 
2435                         // (Typically, the highlight colour is white.) 
2436                         colourFMFill 
= vs
.selbarlight
.allocated
; 
2439                 if (vs
.foldmarginColourSet
) { 
2440                         // override default fold margin colour 
2441                         colourFMFill 
= vs
.foldmarginColour
.allocated
; 
2443                 if (vs
.foldmarginHighlightColourSet
) { 
2444                         // override default fold margin highlight colour 
2445                         colourFMStripes 
= vs
.foldmarginHighlightColour
.allocated
; 
2448                 pixmapSelPattern
->FillRectangle(rcPattern
, colourFMFill
); 
2449                 pixmapSelPattern
->PenColour(colourFMStripes
); 
2450                 for (int stripe 
= 0; stripe 
< patternSize
; stripe
++) { 
2451                         // Alternating 1 pixel stripes is same as checkerboard. 
2452                         pixmapSelPattern
->MoveTo(0, stripe 
* 2); 
2453                         pixmapSelPattern
->LineTo(patternSize
, stripe 
* 2 - patternSize
); 
2457         if (!pixmapIndentGuide
->Initialised()) { 
2458                 // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line 
2459                 pixmapIndentGuide
->InitPixMap(1, vs
.lineHeight 
+ 1, surfaceWindow
, wMain
.GetID()); 
2460                 pixmapIndentGuideHighlight
->InitPixMap(1, vs
.lineHeight 
+ 1, surfaceWindow
, wMain
.GetID()); 
2461                 PRectangle 
rcIG(0, 0, 1, vs
.lineHeight
); 
2462                 pixmapIndentGuide
->FillRectangle(rcIG
, vs
.styles
[STYLE_INDENTGUIDE
].back
.allocated
); 
2463                 pixmapIndentGuide
->PenColour(vs
.styles
[STYLE_INDENTGUIDE
].fore
.allocated
); 
2464                 pixmapIndentGuideHighlight
->FillRectangle(rcIG
, vs
.styles
[STYLE_BRACELIGHT
].back
.allocated
); 
2465                 pixmapIndentGuideHighlight
->PenColour(vs
.styles
[STYLE_BRACELIGHT
].fore
.allocated
); 
2466                 for (int stripe 
= 1; stripe 
< vs
.lineHeight 
+ 1; stripe 
+= 2) { 
2467                         pixmapIndentGuide
->MoveTo(0, stripe
); 
2468                         pixmapIndentGuide
->LineTo(2, stripe
); 
2469                         pixmapIndentGuideHighlight
->MoveTo(0, stripe
); 
2470                         pixmapIndentGuideHighlight
->LineTo(2, stripe
); 
2475                 if (!pixmapLine
->Initialised()) { 
2476                         PRectangle rcClient 
= GetClientRectangle(); 
2477                         pixmapLine
->InitPixMap(rcClient
.Width(), rcClient
.Height(), 
2478                                                surfaceWindow
, wMain
.GetID()); 
2479                         pixmapSelMargin
->InitPixMap(vs
.fixedColumnWidth
, 
2480                                                     rcClient
.Height(), surfaceWindow
, wMain
.GetID()); 
2485 void Editor::Paint(Surface 
*surfaceWindow
, PRectangle rcArea
) { 
2486         //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n", 
2487         //      paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); 
2491         RefreshPixMaps(surfaceWindow
); 
2493         PRectangle rcClient 
= GetClientRectangle(); 
2494         //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n", 
2495         //      rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); 
2497         surfaceWindow
->SetPalette(&palette
, true); 
2498         pixmapLine
->SetPalette(&palette
, !hasFocus
); 
2500         int screenLinePaintFirst 
= rcArea
.top 
/ vs
.lineHeight
; 
2501         // The area to be painted plus one extra line is styled. 
2502         // The extra line is to determine when a style change, such as starting a comment flows on to other lines. 
2503         int lineStyleLast 
= topLine 
+ (rcArea
.bottom 
- 1) / vs
.lineHeight 
+ 1; 
2504         //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast); 
2505         int endPosPaint 
= pdoc
->Length(); 
2506         if (lineStyleLast 
< cs
.LinesDisplayed()) 
2507                 endPosPaint 
= pdoc
->LineStart(cs
.DocFromDisplay(lineStyleLast 
+ 1)); 
2509         int xStart 
= vs
.fixedColumnWidth 
- xOffset
; 
2512                 ypos 
+= screenLinePaintFirst 
* vs
.lineHeight
; 
2513         int yposScreen 
= screenLinePaintFirst 
* vs
.lineHeight
; 
2515         // Ensure we are styled as far as we are painting. 
2516         pdoc
->EnsureStyledTo(endPosPaint
); 
2517         bool paintAbandonedByStyling 
= paintState 
== paintAbandoned
; 
2520                 needUpdateUI 
= false; 
2523         // Call priority lines wrap on a window of lines which are likely 
2524         // to rendered with the following paint (that is wrap the visible 
2526         int startLineToWrap 
= cs
.DocFromDisplay(topLine
) - 5; 
2527         if (startLineToWrap 
< 0) 
2528                 startLineToWrap 
= -1; 
2529         if (WrapLines(false, startLineToWrap
)) { 
2530                 // The wrapping process has changed the height of some lines so 
2531                 // abandon this paint for a complete repaint. 
2532                 if (AbandonPaint()) { 
2535                 RefreshPixMaps(surfaceWindow
);  // In case pixmaps invalidated by scrollbar change 
2537         PLATFORM_ASSERT(pixmapSelPattern
->Initialised()); 
2539         PaintSelMargin(surfaceWindow
, rcArea
); 
2541         PRectangle rcRightMargin 
= rcClient
; 
2542         rcRightMargin
.left 
= rcRightMargin
.right 
- vs
.rightMarginWidth
; 
2543         if (rcArea
.Intersects(rcRightMargin
)) { 
2544                 surfaceWindow
->FillRectangle(rcRightMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2547         if (paintState 
== paintAbandoned
) { 
2548                 // Either styling or NotifyUpdateUI noticed that painting is needed 
2549                 // outside the current painting rectangle 
2550                 //Platform::DebugPrintf("Abandoning paint\n"); 
2551                 if (wrapState 
!= eWrapNone
) { 
2552                         if (paintAbandonedByStyling
) { 
2553                                 // Styling has spilled over a line end, such as occurs by starting a multiline 
2554                                 // comment. The width of subsequent text may have changed, so rewrap. 
2555                                 NeedWrapping(cs
.DocFromDisplay(topLine
)); 
2560         //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); 
2563         if (rcArea
.right 
> vs
.fixedColumnWidth
) { 
2565                 Surface 
*surface 
= surfaceWindow
; 
2567                         surface 
= pixmapLine
; 
2568                         PLATFORM_ASSERT(pixmapLine
->Initialised()); 
2570                 surface
->SetUnicodeMode(IsUnicodeMode()); 
2571                 surface
->SetDBCSMode(CodePage()); 
2573                 int visibleLine 
= topLine 
+ screenLinePaintFirst
; 
2575                 int posCaret 
= currentPos
; 
2578                 int lineCaret 
= pdoc
->LineFromPosition(posCaret
); 
2580                 // Remove selection margin from drawing area so text will not be drawn 
2581                 // on it in unbuffered mode. 
2582                 PRectangle rcTextArea 
= rcClient
; 
2583                 rcTextArea
.left 
= vs
.fixedColumnWidth
; 
2584                 rcTextArea
.right 
-= vs
.rightMarginWidth
; 
2585                 surfaceWindow
->SetClip(rcTextArea
); 
2587                 // Loop on visible lines 
2588                 //double durLayout = 0.0; 
2589                 //double durPaint = 0.0; 
2590                 //double durCopy = 0.0; 
2591                 //ElapsedTime etWhole; 
2592                 int lineDocPrevious 
= -1;       // Used to avoid laying out one document line multiple times 
2593                 AutoLineLayout 
ll(llc
, 0); 
2594                 SelectionLineIterator 
lineIterator(this); 
2595                 while (visibleLine 
< cs
.LinesDisplayed() && yposScreen 
< rcArea
.bottom
) { 
2597                         int lineDoc 
= cs
.DocFromDisplay(visibleLine
); 
2598                         // Only visible lines should be handled by the code within the loop 
2599                         PLATFORM_ASSERT(cs
.GetVisible(lineDoc
)); 
2600                         int lineStartSet 
= cs
.DisplayFromDoc(lineDoc
); 
2601                         int subLine 
= visibleLine 
- lineStartSet
; 
2603                         // Copy this line and its styles from the document into local arrays 
2604                         // and determine the x position at which each character starts. 
2606                         if (lineDoc 
!= lineDocPrevious
) { 
2607                                 ll
.Set(RetrieveLineLayout(lineDoc
)); 
2608                                 LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
2609                                 lineDocPrevious 
= lineDoc
; 
2611                         //durLayout += et.Duration(true); 
2614                                 if (selType 
== selStream
) { 
2615                                         ll
->selStart 
= SelectionStart(); 
2616                                         ll
->selEnd 
= SelectionEnd(); 
2618                                         lineIterator
.SetAt(lineDoc
); 
2619                                         ll
->selStart 
= lineIterator
.startPos
; 
2620                                         ll
->selEnd 
= lineIterator
.endPos
; 
2622                                 ll
->containsCaret 
= lineDoc 
== lineCaret
; 
2623                                 if (hideSelection
) { 
2626                                         ll
->containsCaret 
= false; 
2629                                 GetHotSpotRange(ll
->hsStart
, ll
->hsEnd
); 
2631                                 PRectangle rcLine 
= rcClient
; 
2633                                 rcLine
.bottom 
= ypos 
+ vs
.lineHeight
; 
2635                                 Range 
rangeLine(pdoc
->LineStart(lineDoc
), pdoc
->LineStart(lineDoc 
+ 1)); 
2636                                 // Highlight the current braces if any 
2637                                 ll
->SetBracesHighlight(rangeLine
, braces
, static_cast<char>(bracesMatchStyle
), 
2638                                                        highlightGuideColumn 
* vs
.spaceWidth
); 
2641                                 DrawLine(surface
, vs
, lineDoc
, visibleLine
, xStart
, rcLine
, ll
, subLine
); 
2642                                 //durPaint += et.Duration(true); 
2644                                 // Restore the previous styles for the brace highlights in case layout is in cache. 
2645                                 ll
->RestoreBracesHighlight(rangeLine
, braces
); 
2647                                 bool expanded 
= cs
.GetExpanded(lineDoc
); 
2648                                 if ((foldFlags 
& SC_FOLDFLAG_BOX
) == 0) { 
2649                                         // Paint the line above the fold 
2650                                         if ((expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEBEFORE_EXPANDED
)) 
2652                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEBEFORE_CONTRACTED
))) { 
2653                                                 if (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELHEADERFLAG
) { 
2654                                                         PRectangle rcFoldLine 
= rcLine
; 
2655                                                         rcFoldLine
.bottom 
= rcFoldLine
.top 
+ 1; 
2656                                                         surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2659                                         // Paint the line below the fold 
2660                                         if ((expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_EXPANDED
)) 
2662                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_CONTRACTED
))) { 
2663                                                 if (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELHEADERFLAG
) { 
2664                                                         PRectangle rcFoldLine 
= rcLine
; 
2665                                                         rcFoldLine
.top 
= rcFoldLine
.bottom 
- 1; 
2666                                                         surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2670                                         int FoldLevelCurr 
= (pdoc
->GetLevel(lineDoc
) & SC_FOLDLEVELNUMBERMASK
) - SC_FOLDLEVELBASE
; 
2671                                         int FoldLevelPrev 
= (pdoc
->GetLevel(lineDoc 
- 1) & SC_FOLDLEVELNUMBERMASK
) - SC_FOLDLEVELBASE
; 
2672                                         int FoldLevelFlags 
= (pdoc
->GetLevel(lineDoc
) & ~SC_FOLDLEVELNUMBERMASK
) & ~(0xFFF0000); 
2673                                         int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
2674                                         // Draw line above fold 
2675                                         if ((FoldLevelPrev 
< FoldLevelCurr
) 
2677                                                 (FoldLevelFlags 
& SC_FOLDLEVELBOXHEADERFLAG
 
2679                                                  (pdoc
->GetLevel(lineDoc 
- 1) & SC_FOLDLEVELBOXFOOTERFLAG
) == 0)) { 
2680                                                 PRectangle rcFoldLine 
= rcLine
; 
2681                                                 rcFoldLine
.bottom 
= rcFoldLine
.top 
+ 1; 
2682                                                 rcFoldLine
.left 
+= xStart 
+ FoldLevelCurr 
* vs
.spaceWidth 
* indentationStep 
- 1; 
2683                                                 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2686                                         // Line below the fold (or below a contracted fold) 
2687                                         if (FoldLevelFlags 
& SC_FOLDLEVELBOXFOOTERFLAG
 
2689                                                 (!expanded 
&& (foldFlags 
& SC_FOLDFLAG_LINEAFTER_CONTRACTED
))) { 
2690                                                 PRectangle rcFoldLine 
= rcLine
; 
2691                                                 rcFoldLine
.top 
= rcFoldLine
.bottom 
- 1; 
2692                                                 rcFoldLine
.left 
+= xStart 
+ (FoldLevelCurr
) * vs
.spaceWidth 
* indentationStep 
- 1; 
2693                                                 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2696                                         PRectangle rcBoxLine 
= rcLine
; 
2697                                         // Draw vertical line for every fold level 
2698                                         for (int i 
= 0; i 
<= FoldLevelCurr
; i
++) { 
2699                                                 rcBoxLine
.left 
= xStart 
+ i 
* vs
.spaceWidth 
* indentationStep 
- 1; 
2700                                                 rcBoxLine
.right 
= rcBoxLine
.left 
+ 1; 
2701                                                 surface
->FillRectangle(rcBoxLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
); 
2706                                 if (lineDoc 
== lineCaret
) { 
2707                                         int offset 
= Platform::Minimum(posCaret 
- rangeLine
.start
, ll
->maxLineLength
); 
2708                                         if ((offset 
>= ll
->LineStart(subLine
)) && 
2709                                                 ((offset 
< ll
->LineStart(subLine 
+ 1)) || offset 
== ll
->numCharsInLine
)) { 
2710                                                 int xposCaret 
= ll
->positions
[offset
] - ll
->positions
[ll
->LineStart(subLine
)] + xStart
; 
2711                                                 int widthOverstrikeCaret
; 
2712                                                 if (posCaret 
== pdoc
->Length()) {   // At end of document 
2713                                                         widthOverstrikeCaret 
= vs
.aveCharWidth
; 
2714                                                 } else if ((posCaret 
- rangeLine
.start
) >= ll
->numCharsInLine
) {        // At end of line 
2715                                                         widthOverstrikeCaret 
= vs
.aveCharWidth
; 
2717                                                         widthOverstrikeCaret 
= ll
->positions
[offset 
+ 1] - ll
->positions
[offset
]; 
2719                                                 if (widthOverstrikeCaret 
< 3)   // Make sure its visible 
2720                                                         widthOverstrikeCaret 
= 3; 
2721                                                 if (((caret
.active 
&& caret
.on
) || (posDrag 
>= 0)) && xposCaret 
>= 0) { 
2722                                                         PRectangle rcCaret 
= rcLine
; 
2723                                                         int caretWidthOffset 
= 0; 
2724                                                         if ((offset 
> 0) && (vs
.caretWidth 
> 1)) 
2725                                                                 caretWidthOffset 
= 1;   // Move back so overlaps both character cells. 
2727                                                                 rcCaret
.left 
= xposCaret 
- caretWidthOffset
; 
2728                                                                 rcCaret
.right 
= rcCaret
.left 
+ vs
.caretWidth
; 
2731                                                                         rcCaret
.top 
= rcCaret
.bottom 
- 2; 
2732                                                                         rcCaret
.left 
= xposCaret 
+ 1; 
2733                                                                         rcCaret
.right 
= rcCaret
.left 
+ widthOverstrikeCaret 
- 1; 
2735                                                                         rcCaret
.left 
= xposCaret 
- caretWidthOffset
; 
2736                                                                         rcCaret
.right 
= rcCaret
.left 
+ vs
.caretWidth
; 
2739                                                         surface
->FillRectangle(rcCaret
, vs
.caretcolour
.allocated
); 
2745                                         Point 
from(vs
.fixedColumnWidth
, 0); 
2746                                         PRectangle 
rcCopyArea(vs
.fixedColumnWidth
, yposScreen
, 
2747                                                               rcClient
.right
, yposScreen 
+ vs
.lineHeight
); 
2748                                         surfaceWindow
->Copy(rcCopyArea
, from
, *pixmapLine
); 
2750                                 //durCopy += et.Duration(true); 
2753                         if (!bufferedDraw
) { 
2754                                 ypos 
+= vs
.lineHeight
; 
2757                         yposScreen 
+= vs
.lineHeight
; 
2761                 //if (durPaint < 0.00000001) 
2762                 //      durPaint = 0.00000001; 
2764                 // Right column limit indicator 
2765                 PRectangle rcBeyondEOF 
= rcClient
; 
2766                 rcBeyondEOF
.left 
= vs
.fixedColumnWidth
; 
2767                 rcBeyondEOF
.right 
= rcBeyondEOF
.right
; 
2768                 rcBeyondEOF
.top 
= (cs
.LinesDisplayed() - topLine
) * vs
.lineHeight
; 
2769                 if (rcBeyondEOF
.top 
< rcBeyondEOF
.bottom
) { 
2770                         surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
); 
2771                         if (vs
.edgeState 
== EDGE_LINE
) { 
2772                                 int edgeX 
= theEdge 
* vs
.spaceWidth
; 
2773                                 rcBeyondEOF
.left 
= edgeX 
+ xStart
; 
2774                                 rcBeyondEOF
.right 
= rcBeyondEOF
.left 
+ 1; 
2775                                 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.edgecolour
.allocated
); 
2778                 //Platform::DebugPrintf( 
2779                 //"Layout:%9.6g    Paint:%9.6g    Ratio:%9.6g   Copy:%9.6g   Total:%9.6g\n", 
2780                 //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); 
2785 // Space (3 space characters) between line numbers and text when printing. 
2786 #define lineNumberPrintSpace "   " 
2788 ColourDesired 
InvertedLight(ColourDesired orig
) { 
2789         unsigned int r 
= orig
.GetRed(); 
2790         unsigned int g 
= orig
.GetGreen(); 
2791         unsigned int b 
= orig
.GetBlue(); 
2792         unsigned int l 
= (r 
+ g 
+ b
) / 3;       // There is a better calculation for this that matches human eye 
2793         unsigned int il 
= 0xff - l
; 
2795                 return ColourDesired(0xff, 0xff, 0xff); 
2799         return ColourDesired(Platform::Minimum(r
, 0xff), Platform::Minimum(g
, 0xff), Platform::Minimum(b
, 0xff)); 
2802 // This is mostly copied from the Paint method but with some things omitted 
2803 // such as the margin markers, line numbers, selection and caret 
2804 // Should be merged back into a combined Draw method. 
2805 long Editor::FormatRange(bool draw
, RangeToFormat 
*pfr
) { 
2809         AutoSurface 
surface(pfr
->hdc
, this); 
2812         AutoSurface 
surfaceMeasure(pfr
->hdcTarget
, this); 
2813         if (!surfaceMeasure
) { 
2817         ViewStyle 
vsPrint(vs
); 
2819         // Modify the view style for printing as do not normally want any of the transient features to be printed 
2820         // Printing supports only the line number margin. 
2821         int lineNumberIndex 
= -1; 
2822         for (int margin 
= 0; margin 
< ViewStyle::margins
; margin
++) { 
2823                 if ((!vsPrint
.ms
[margin
].symbol
) && (vsPrint
.ms
[margin
].width 
> 0)) { 
2824                         lineNumberIndex 
= margin
; 
2826                         vsPrint
.ms
[margin
].width 
= 0; 
2829         vsPrint
.showMarkedLines 
= false; 
2830         vsPrint
.fixedColumnWidth 
= 0; 
2831         vsPrint
.zoomLevel 
= printMagnification
; 
2832         vsPrint
.viewIndentationGuides 
= false; 
2833         // Don't show the selection when printing 
2834         vsPrint
.selbackset 
= false; 
2835         vsPrint
.selforeset 
= false; 
2836         vsPrint
.whitespaceBackgroundSet 
= false; 
2837         vsPrint
.whitespaceForegroundSet 
= false; 
2838         vsPrint
.showCaretLineBackground 
= false; 
2840         // Set colours for printing according to users settings 
2841         for (int sty 
= 0;sty 
<= STYLE_MAX
;sty
++) { 
2842                 if (printColourMode 
== SC_PRINT_INVERTLIGHT
) { 
2843                         vsPrint
.styles
[sty
].fore
.desired 
= InvertedLight(vsPrint
.styles
[sty
].fore
.desired
); 
2844                         vsPrint
.styles
[sty
].back
.desired 
= InvertedLight(vsPrint
.styles
[sty
].back
.desired
); 
2845                 } else if (printColourMode 
== SC_PRINT_BLACKONWHITE
) { 
2846                         vsPrint
.styles
[sty
].fore
.desired 
= ColourDesired(0, 0, 0); 
2847                         vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2848                 } else if (printColourMode 
== SC_PRINT_COLOURONWHITE
) { 
2849                         vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2850                 } else if (printColourMode 
== SC_PRINT_COLOURONWHITEDEFAULTBG
) { 
2851                         if (sty 
<= STYLE_DEFAULT
) { 
2852                                 vsPrint
.styles
[sty
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2856         // White background for the line numbers 
2857         vsPrint
.styles
[STYLE_LINENUMBER
].back
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
2859         vsPrint
.Refresh(*surfaceMeasure
); 
2860         // Ensure colours are set up 
2861         vsPrint
.RefreshColourPalette(palette
, true); 
2862         vsPrint
.RefreshColourPalette(palette
, false); 
2863         // Determining width must hapen after fonts have been realised in Refresh 
2864         int lineNumberWidth 
= 0; 
2865         if (lineNumberIndex 
>= 0) { 
2866                 lineNumberWidth 
= surfaceMeasure
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
, 
2867                                   "99999" lineNumberPrintSpace
, 5 + istrlen(lineNumberPrintSpace
)); 
2868                 vsPrint
.ms
[lineNumberIndex
].width 
= lineNumberWidth
; 
2871         int linePrintStart 
= pdoc
->LineFromPosition(pfr
->chrg
.cpMin
); 
2872         int linePrintLast 
= linePrintStart 
+ (pfr
->rc
.bottom 
- pfr
->rc
.top
) / vsPrint
.lineHeight 
- 1; 
2873         if (linePrintLast 
< linePrintStart
) 
2874                 linePrintLast 
= linePrintStart
; 
2875         int linePrintMax 
= pdoc
->LineFromPosition(pfr
->chrg
.cpMax
); 
2876         if (linePrintLast 
> linePrintMax
) 
2877                 linePrintLast 
= linePrintMax
; 
2878         //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", 
2879         //      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight, 
2880         //      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font)); 
2881         int endPosPrint 
= pdoc
->Length(); 
2882         if (linePrintLast 
< pdoc
->LinesTotal()) 
2883                 endPosPrint 
= pdoc
->LineStart(linePrintLast 
+ 1); 
2885         // Ensure we are styled to where we are formatting. 
2886         pdoc
->EnsureStyledTo(endPosPrint
); 
2888         int xStart 
= vsPrint
.fixedColumnWidth 
+ pfr
->rc
.left 
+ lineNumberWidth
; 
2889         int ypos 
= pfr
->rc
.top
; 
2891         int lineDoc 
= linePrintStart
; 
2893         int nPrintPos 
= pfr
->chrg
.cpMin
; 
2894         int visibleLine 
= 0; 
2895         int widthPrint 
= pfr
->rc
.Width() - lineNumberWidth
; 
2896         if (printWrapState 
== eWrapNone
) 
2897                 widthPrint 
= LineLayout::wrapWidthInfinite
; 
2899         while (lineDoc 
<= linePrintLast 
&& ypos 
< pfr
->rc
.bottom
) { 
2901                 // When printing, the hdc and hdcTarget may be the same, so 
2902                 // changing the state of surfaceMeasure may change the underlying 
2903                 // state of surface. Therefore, any cached state is discarded before 
2904                 // using each surface. 
2905                 surfaceMeasure
->FlushCachedState(); 
2907                 // Copy this line and its styles from the document into local arrays 
2908                 // and determine the x position at which each character starts. 
2909                 LineLayout 
ll(8000); 
2910                 LayoutLine(lineDoc
, surfaceMeasure
, vsPrint
, &ll
, widthPrint
); 
2914                 ll
.containsCaret 
= false; 
2917                 rcLine
.left 
= pfr
->rc
.left 
+ lineNumberWidth
; 
2919                 rcLine
.right 
= pfr
->rc
.right 
- 1; 
2920                 rcLine
.bottom 
= ypos 
+ vsPrint
.lineHeight
; 
2922                 // When document line is wrapped over multiple display lines, find where 
2923                 // to start printing from to ensure a particular position is on the first 
2924                 // line of the page. 
2925                 if (visibleLine 
== 0) { 
2926                         int startWithinLine 
= nPrintPos 
- pdoc
->LineStart(lineDoc
); 
2927                         for (int iwl 
= 0; iwl 
< ll
.lines 
- 1; iwl
++) { 
2928                                 if (ll
.LineStart(iwl
) <= startWithinLine 
&& ll
.LineStart(iwl 
+ 1) >= startWithinLine
) { 
2933                         if (ll
.lines 
> 1 && startWithinLine 
>= ll
.LineStart(ll
.lines 
- 1)) { 
2934                                 visibleLine 
= -(ll
.lines 
- 1); 
2938                 if (draw 
&& lineNumberWidth 
&& 
2939                         (ypos 
+ vsPrint
.lineHeight 
<= pfr
->rc
.bottom
) && 
2940                         (visibleLine 
>= 0)) { 
2942                         sprintf(number
, "%d" lineNumberPrintSpace
, lineDoc 
+ 1); 
2943                         PRectangle rcNumber 
= rcLine
; 
2944                         rcNumber
.right 
= rcNumber
.left 
+ lineNumberWidth
; 
2946                         rcNumber
.left 
-= surfaceMeasure
->WidthText( 
2947                                              vsPrint
.styles
[STYLE_LINENUMBER
].font
, number
, istrlen(number
)); 
2948                         surface
->FlushCachedState(); 
2949                         surface
->DrawTextNoClip(rcNumber
, vsPrint
.styles
[STYLE_LINENUMBER
].font
, 
2950                                                 ypos 
+ vsPrint
.maxAscent
, number
, istrlen(number
), 
2951                                                 vsPrint
.styles
[STYLE_LINENUMBER
].fore
.allocated
, 
2952                                                 vsPrint
.styles
[STYLE_LINENUMBER
].back
.allocated
); 
2956                 surface
->FlushCachedState(); 
2958                 for (int iwl 
= 0; iwl 
< ll
.lines
; iwl
++) { 
2959                         if (ypos 
+ vsPrint
.lineHeight 
<= pfr
->rc
.bottom
) { 
2960                                 if (visibleLine 
>= 0) { 
2963                                                 rcLine
.bottom 
= ypos 
+ vsPrint
.lineHeight
; 
2964                                                 DrawLine(surface
, vsPrint
, lineDoc
, visibleLine
, xStart
, rcLine
, &ll
, iwl
); 
2966                                         ypos 
+= vsPrint
.lineHeight
; 
2969                                 if (iwl 
== ll
.lines 
- 1) 
2970                                         nPrintPos 
= pdoc
->LineStart(lineDoc 
+ 1); 
2972                                         nPrintPos 
+= ll
.LineStart(iwl 
+ 1) - ll
.LineStart(iwl
); 
2982 int Editor::TextWidth(int style
, const char *text
) { 
2984         AutoSurface 
surface(this); 
2986                 return surface
->WidthText(vs
.styles
[style
].font
, text
, istrlen(text
)); 
2992 // Empty method is overridden on GTK+ to show / hide scrollbars 
2993 void Editor::ReconfigureScrollBars() {} 
2995 void Editor::SetScrollBars() { 
2998         int nMax 
= MaxScrollPos(); 
2999         int nPage 
= LinesOnScreen(); 
3000         bool modified 
= ModifyScrollBars(nMax 
+ nPage 
- 1, nPage
); 
3002         // TODO: ensure always showing as many lines as possible 
3003         // May not be, if, for example, window made larger 
3004         if (topLine 
> MaxScrollPos()) { 
3005                 SetTopLine(Platform::Clamp(topLine
, 0, MaxScrollPos())); 
3006                 SetVerticalScrollPos(); 
3010                 if (!AbandonPaint()) 
3013         //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage); 
3016 void Editor::ChangeSize() { 
3019         if (wrapState 
!= eWrapNone
) { 
3020                 PRectangle rcTextArea 
= GetClientRectangle(); 
3021                 rcTextArea
.left 
= vs
.fixedColumnWidth
; 
3022                 rcTextArea
.right 
-= vs
.rightMarginWidth
; 
3023                 if (wrapWidth 
!= rcTextArea
.Width()) { 
3030 void Editor::AddChar(char ch
) { 
3037 void Editor::AddCharUTF(char *s
, unsigned int len
, bool treatAsDBCS
) { 
3038         bool wasSelection 
= currentPos 
!= anchor
; 
3040         if (inOverstrike 
&& !wasSelection 
&& !RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3041                 if (currentPos 
< (pdoc
->Length())) { 
3042                         if (!IsEOLChar(pdoc
->CharAt(currentPos
))) { 
3043                                 pdoc
->DelChar(currentPos
); 
3047         if (pdoc
->InsertString(currentPos
, s
, len
)) { 
3048                 SetEmptySelection(currentPos 
+ len
); 
3050         EnsureCaretVisible(); 
3051         // Avoid blinking during rapid typing: 
3052         ShowCaretAtCurrentPosition(); 
3056                 NotifyChar((static_cast<unsigned char>(s
[0]) << 8) | 
3057                            static_cast<unsigned char>(s
[1])); 
3059                 int byte 
= static_cast<unsigned char>(s
[0]); 
3060                 if ((byte 
< 0xC0) || (1 == len
)) { 
3061                         // Handles UTF-8 characters between 0x01 and 0x7F and single byte 
3062                         // characters when not in UTF-8 mode. 
3063                         // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid 
3064                         // characters representing themselves. 
3066                         // Unroll 1 to 3 byte UTF-8 sequences.  See reference data at: 
3067                         // http://www.cl.cam.ac.uk/~mgk25/unicode.html 
3068                         // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 
3070                                 int byte2 
= static_cast<unsigned char>(s
[1]); 
3071                                 if ((byte2 
& 0xC0) == 0x80) { 
3072                                         // Two-byte-character lead-byte followed by a trail-byte. 
3073                                         byte 
= (((byte 
& 0x1F) << 6) | (byte2 
& 0x3F)); 
3075                                 // A two-byte-character lead-byte not followed by trail-byte 
3076                                 // represents itself. 
3077                         } else if (byte 
< 0xF0) { 
3078                                 int byte2 
= static_cast<unsigned char>(s
[1]); 
3079                                 int byte3 
= static_cast<unsigned char>(s
[2]); 
3080                                 if (((byte2 
& 0xC0) == 0x80) && ((byte3 
& 0xC0) == 0x80)) { 
3081                                         // Three-byte-character lead byte followed by two trail bytes. 
3082                                         byte 
= (((byte 
& 0x0F) << 12) | ((byte2 
& 0x3F) << 6) | 
3085                                 // A three-byte-character lead-byte not followed by two trail-bytes 
3086                                 // represents itself. 
3093 void Editor::ClearSelection() { 
3094         if (!SelectionContainsProtected()) { 
3095                 int startPos 
= SelectionStart(); 
3096                 if (selType 
== selStream
) { 
3097                         unsigned int chars 
= SelectionEnd() - startPos
; 
3099                                 pdoc
->BeginUndoAction(); 
3100                                 pdoc
->DeleteChars(startPos
, chars
); 
3101                                 pdoc
->EndUndoAction(); 
3104                         pdoc
->BeginUndoAction(); 
3105                         SelectionLineIterator 
lineIterator(this, false); 
3106                         while (lineIterator
.Iterate()) { 
3107                                 startPos 
= lineIterator
.startPos
; 
3108                                 unsigned int chars 
= lineIterator
.endPos 
- startPos
; 
3110                                         pdoc
->DeleteChars(startPos
, chars
); 
3113                         pdoc
->EndUndoAction(); 
3114                         selType 
= selStream
; 
3116                 SetEmptySelection(startPos
); 
3120 void Editor::ClearAll() { 
3121         pdoc
->BeginUndoAction(); 
3122         if (0 != pdoc
->Length()) { 
3123                 pdoc
->DeleteChars(0, pdoc
->Length()); 
3125         if (!pdoc
->IsReadOnly()) { 
3128         pdoc
->EndUndoAction(); 
3132         SetVerticalScrollPos(); 
3135 void Editor::ClearDocumentStyle() { 
3136         pdoc
->StartStyling(0, '\377'); 
3137         pdoc
->SetStyleFor(pdoc
->Length(), 0); 
3139         pdoc
->ClearLevels(); 
3142 void Editor::Cut() { 
3143         if (!pdoc
->IsReadOnly() && !SelectionContainsProtected()) { 
3149 void Editor::PasteRectangular(int pos
, const char *ptr
, int len
) { 
3150         if (pdoc
->IsReadOnly() || SelectionContainsProtected()) { 
3154         int xInsert 
= XFromPosition(currentPos
); 
3155         int line 
= pdoc
->LineFromPosition(currentPos
); 
3156         bool prevCr 
= false; 
3157         pdoc
->BeginUndoAction(); 
3158         for (int i 
= 0; i 
< len
; i
++) { 
3159                 if (IsEOLChar(ptr
[i
])) { 
3160                         if ((ptr
[i
] == '\r') || (!prevCr
)) 
3162                         if (line 
>= pdoc
->LinesTotal()) { 
3163                                 if (pdoc
->eolMode 
!= SC_EOL_LF
) 
3164                                         pdoc
->InsertChar(pdoc
->Length(), '\r'); 
3165                                 if (pdoc
->eolMode 
!= SC_EOL_CR
) 
3166                                         pdoc
->InsertChar(pdoc
->Length(), '\n'); 
3168                         // Pad the end of lines with spaces if required 
3169                         currentPos 
= PositionFromLineX(line
, xInsert
); 
3170                         if ((XFromPosition(currentPos
) < xInsert
) && (i 
+ 1 < len
)) { 
3171                                 for (int i 
= 0; i 
< xInsert 
- XFromPosition(currentPos
); i
++) { 
3172                                         pdoc
->InsertChar(currentPos
, ' '); 
3176                         prevCr 
= ptr
[i
] == '\r'; 
3178                         pdoc
->InsertString(currentPos
, ptr 
+ i
, 1); 
3183         pdoc
->EndUndoAction(); 
3184         SetEmptySelection(pos
); 
3187 bool Editor::CanPaste() { 
3188         return !pdoc
->IsReadOnly() && !SelectionContainsProtected(); 
3191 void Editor::Clear() { 
3192         if (currentPos 
== anchor
) { 
3193                 if (!RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3199         SetEmptySelection(currentPos
); 
3202 void Editor::SelectAll() { 
3203         SetSelection(0, pdoc
->Length()); 
3207 void Editor::Undo() { 
3208         if (pdoc
->CanUndo()) { 
3210                 int newPos 
= pdoc
->Undo(); 
3211                 SetEmptySelection(newPos
); 
3212                 EnsureCaretVisible(); 
3216 void Editor::Redo() { 
3217         if (pdoc
->CanRedo()) { 
3218                 int newPos 
= pdoc
->Redo(); 
3219                 SetEmptySelection(newPos
); 
3220                 EnsureCaretVisible(); 
3224 void Editor::DelChar() { 
3225         if (!RangeContainsProtected(currentPos
, currentPos 
+ 1)) { 
3226                 pdoc
->DelChar(currentPos
); 
3228         // Avoid blinking during rapid typing: 
3229         ShowCaretAtCurrentPosition(); 
3232 void Editor::DelCharBack(bool allowLineStartDeletion
) { 
3233         if (currentPos 
== anchor
) { 
3234                 if (!RangeContainsProtected(currentPos 
- 1, currentPos
)) { 
3235                         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
3236                         if (allowLineStartDeletion 
|| (pdoc
->LineStart(lineCurrentPos
) != currentPos
)) { 
3237                                 if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetLineIndentation(lineCurrentPos
) && 
3238                                         pdoc
->GetColumn(currentPos
) > 0 && pdoc
->backspaceUnindents
) { 
3239                                         pdoc
->BeginUndoAction(); 
3240                                         int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
3241                                         int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
3242                                         if (indentation 
% indentationStep 
== 0) { 
3243                                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- indentationStep
); 
3245                                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- (indentation 
% indentationStep
)); 
3247                                         SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
3248                                         pdoc
->EndUndoAction(); 
3250                                         pdoc
->DelCharBack(currentPos
); 
3256                 SetEmptySelection(currentPos
); 
3258         // Avoid blinking during rapid typing: 
3259         ShowCaretAtCurrentPosition(); 
3262 void Editor::NotifyFocus(bool) {} 
3264 void Editor::NotifyStyleToNeeded(int endStyleNeeded
) { 
3266         scn
.nmhdr
.code 
= SCN_STYLENEEDED
; 
3267         scn
.position 
= endStyleNeeded
; 
3271 void Editor::NotifyStyleNeeded(Document
*, void *, int endStyleNeeded
) { 
3272         NotifyStyleToNeeded(endStyleNeeded
); 
3275 void Editor::NotifyChar(int ch
) { 
3277         scn
.nmhdr
.code 
= SCN_CHARADDED
; 
3280         if (recordingMacro
) { 
3282                 txt
[0] = static_cast<char>(ch
); 
3284                 NotifyMacroRecord(SCI_REPLACESEL
, 0, reinterpret_cast<sptr_t
>(txt
)); 
3288 void Editor::NotifySavePoint(bool isSavePoint
) { 
3291                 scn
.nmhdr
.code 
= SCN_SAVEPOINTREACHED
; 
3293                 scn
.nmhdr
.code 
= SCN_SAVEPOINTLEFT
; 
3298 void Editor::NotifyModifyAttempt() { 
3300         scn
.nmhdr
.code 
= SCN_MODIFYATTEMPTRO
; 
3304 void Editor::NotifyDoubleClick(Point
, bool) { 
3306         scn
.nmhdr
.code 
= SCN_DOUBLECLICK
; 
3310 void Editor::NotifyHotSpotDoubleClicked(int position
, bool shift
, bool ctrl
, bool alt
) { 
3312         scn
.nmhdr
.code 
= SCN_HOTSPOTDOUBLECLICK
; 
3313         scn
.position 
= position
; 
3314         scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3315                         (alt 
? SCI_ALT 
: 0); 
3319 void Editor::NotifyHotSpotClicked(int position
, bool shift
, bool ctrl
, bool alt
) { 
3321         scn
.nmhdr
.code 
= SCN_HOTSPOTCLICK
; 
3322         scn
.position 
= position
; 
3323         scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3324                         (alt 
? SCI_ALT 
: 0); 
3328 void Editor::NotifyUpdateUI() { 
3330         scn
.nmhdr
.code 
= SCN_UPDATEUI
; 
3334 void Editor::NotifyPainted() { 
3336         scn
.nmhdr
.code 
= SCN_PAINTED
; 
3340 bool Editor::NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
) { 
3341         int marginClicked 
= -1; 
3343         for (int margin 
= 0; margin 
< ViewStyle::margins
; margin
++) { 
3344                 if ((pt
.x 
> x
) && (pt
.x 
< x 
+ vs
.ms
[margin
].width
)) 
3345                         marginClicked 
= margin
; 
3346                 x 
+= vs
.ms
[margin
].width
; 
3348         if ((marginClicked 
>= 0) && vs
.ms
[marginClicked
].sensitive
) { 
3350                 scn
.nmhdr
.code 
= SCN_MARGINCLICK
; 
3351                 scn
.modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
3352                                 (alt 
? SCI_ALT 
: 0); 
3353                 scn
.position 
= pdoc
->LineStart(LineFromLocation(pt
)); 
3354                 scn
.margin 
= marginClicked
; 
3362 void Editor::NotifyNeedShown(int pos
, int len
) { 
3364         scn
.nmhdr
.code 
= SCN_NEEDSHOWN
; 
3370 void Editor::NotifyDwelling(Point pt
, bool state
) { 
3372         scn
.nmhdr
.code 
= state 
? SCN_DWELLSTART 
: SCN_DWELLEND
; 
3373         scn
.position 
= PositionFromLocationClose(pt
); 
3379 void Editor::NotifyZoom() { 
3381         scn
.nmhdr
.code 
= SCN_ZOOM
; 
3385 // Notifications from document 
3386 void Editor::NotifyModifyAttempt(Document
*, void *) { 
3387         //Platform::DebugPrintf("** Modify Attempt\n"); 
3388         NotifyModifyAttempt(); 
3391 void Editor::NotifyMove(int position
) { 
3393         scn
.nmhdr
.code 
= SCN_POSCHANGED
; 
3394         scn
.position 
= position
; 
3398 void Editor::NotifySavePoint(Document
*, void *, bool atSavePoint
) { 
3399         //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off"); 
3400         NotifySavePoint(atSavePoint
); 
3403 void Editor::CheckModificationForWrap(DocModification mh
) { 
3404         if ((mh
.modificationType 
& SC_MOD_INSERTTEXT
) || 
3405                 (mh
.modificationType 
& SC_MOD_DELETETEXT
)) { 
3406                 llc
.Invalidate(LineLayout::llCheckTextAndStyle
); 
3407                 if (wrapState 
!= eWrapNone
) { 
3408                         int lineDoc 
= pdoc
->LineFromPosition(mh
.position
); 
3409                         if (mh
.linesAdded 
<= 0) { 
3410                                 AutoSurface 
surface(this); 
3411                                 AutoLineLayout 
ll(llc
, RetrieveLineLayout(lineDoc
)); 
3412                                 if (surface 
&& ll
) { 
3413                                         LayoutLine(lineDoc
, surface
, vs
, ll
, wrapWidth
); 
3414                                         if (cs
.GetHeight(lineDoc
) != ll
->lines
) { 
3415                                                 NeedWrapping(lineDoc 
- 1, lineDoc 
+ 1); 
3420                                 NeedWrapping(lineDoc
, lineDoc 
+ 1 + mh
.linesAdded
); 
3426 // Move a position so it is still after the same character as before the insertion. 
3427 static inline int MovePositionForInsertion(int position
, int startInsertion
, int length
) { 
3428         if (position 
> startInsertion
) { 
3429                 return position 
+ length
; 
3434 // Move a position so it is still after the same character as before the deletion if that 
3435 // character is still present else after the previous surviving character. 
3436 static inline int MovePositionForDeletion(int position
, int startDeletion
, int length
) { 
3437         if (position 
> startDeletion
) { 
3438                 int endDeletion 
= startDeletion 
+ length
; 
3439                 if (position 
> endDeletion
) { 
3440                         return position 
- length
; 
3442                         return startDeletion
; 
3449 void Editor::NotifyModified(Document
*, DocModification mh
, void *) { 
3450         needUpdateUI 
= true; 
3451         if (paintState 
== painting
) { 
3452                 CheckForChangeOutsidePaint(Range(mh
.position
, mh
.position 
+ mh
.length
)); 
3454         if (mh
.modificationType 
& SC_MOD_CHANGESTYLE
) { 
3455                 if (paintState 
== notPainting
) { 
3456                         if (mh
.position 
< pdoc
->LineStart(topLine
)) { 
3457                                 // Styling performed before this view 
3460                                 InvalidateRange(mh
.position
, mh
.position 
+ mh
.length
); 
3464                 // Move selection and brace highlights 
3465                 if (mh
.modificationType 
& SC_MOD_INSERTTEXT
) { 
3466                         currentPos 
= MovePositionForInsertion(currentPos
, mh
.position
, mh
.length
); 
3467                         anchor 
= MovePositionForInsertion(anchor
, mh
.position
, mh
.length
); 
3468                         braces
[0] = MovePositionForInsertion(braces
[0], mh
.position
, mh
.length
); 
3469                         braces
[1] = MovePositionForInsertion(braces
[1], mh
.position
, mh
.length
); 
3470                 } else if (mh
.modificationType 
& SC_MOD_DELETETEXT
) { 
3471                         currentPos 
= MovePositionForDeletion(currentPos
, mh
.position
, mh
.length
); 
3472                         anchor 
= MovePositionForDeletion(anchor
, mh
.position
, mh
.length
); 
3473                         braces
[0] = MovePositionForDeletion(braces
[0], mh
.position
, mh
.length
); 
3474                         braces
[1] = MovePositionForDeletion(braces
[1], mh
.position
, mh
.length
); 
3476                 if (cs
.LinesDisplayed() < cs
.LinesInDoc()) { 
3477                         // Some lines are hidden so may need shown. 
3478                         // TODO: check if the modified area is hidden. 
3479                         if (mh
.modificationType 
& SC_MOD_BEFOREINSERT
) { 
3480                                 NotifyNeedShown(mh
.position
, mh
.length
); 
3481                         } else if (mh
.modificationType 
& SC_MOD_BEFOREDELETE
) { 
3482                                 NotifyNeedShown(mh
.position
, mh
.length
); 
3485                 if (mh
.linesAdded 
!= 0) { 
3486                         // Update contraction state for inserted and removed lines 
3487                         // lineOfPos should be calculated in context of state before modification, shouldn't it 
3488                         int lineOfPos 
= pdoc
->LineFromPosition(mh
.position
); 
3489                         if (mh
.linesAdded 
> 0) { 
3490                                 cs
.InsertLines(lineOfPos
, mh
.linesAdded
); 
3492                                 cs
.DeleteLines(lineOfPos
, -mh
.linesAdded
); 
3495                 CheckModificationForWrap(mh
); 
3496                 if (mh
.linesAdded 
!= 0) { 
3497                         // Avoid scrolling of display if change before current display 
3498                         if (mh
.position 
< posTopLine
) { 
3499                                 int newTop 
= Platform::Clamp(topLine 
+ mh
.linesAdded
, 0, MaxScrollPos()); 
3500                                 if (newTop 
!= topLine
) { 
3502                                         SetVerticalScrollPos(); 
3506                         //Platform::DebugPrintf("** %x Doc Changed\n", this); 
3507                         // TODO: could invalidate from mh.startModification to end of screen 
3508                         //InvalidateRange(mh.position, mh.position + mh.length); 
3509                         if (paintState 
== notPainting
) { 
3513                         //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this, 
3514                         //      mh.position, mh.position + mh.length); 
3515                         if (paintState 
== notPainting
) { 
3516                                 InvalidateRange(mh
.position
, mh
.position 
+ mh
.length
); 
3521         if (mh
.linesAdded 
!= 0) { 
3525         if (mh
.modificationType 
& SC_MOD_CHANGEMARKER
) { 
3526                 if (paintState 
== notPainting
) { 
3531         // If client wants to see this modification 
3532         if (mh
.modificationType 
& modEventMask
) { 
3533                 if ((mh
.modificationType 
& SC_MOD_CHANGESTYLE
) == 0) { 
3534                         // Real modification made to text of document. 
3535                         NotifyChange(); // Send EN_CHANGE 
3539                 scn
.nmhdr
.code 
= SCN_MODIFIED
; 
3540                 scn
.position 
= mh
.position
; 
3541                 scn
.modificationType 
= mh
.modificationType
; 
3543                 scn
.length 
= mh
.length
; 
3544                 scn
.linesAdded 
= mh
.linesAdded
; 
3546                 scn
.foldLevelNow 
= mh
.foldLevelNow
; 
3547                 scn
.foldLevelPrev 
= mh
.foldLevelPrev
; 
3552 void Editor::NotifyDeleted(Document 
*, void *) { 
3556 void Editor::NotifyMacroRecord(unsigned int iMessage
, unsigned long wParam
, long lParam
) { 
3558         // Enumerates all macroable messages 
3564         case SCI_REPLACESEL
: 
3566         case SCI_INSERTTEXT
: 
3567         case SCI_APPENDTEXT
: 
3572         case SCI_SEARCHANCHOR
: 
3573         case SCI_SEARCHNEXT
: 
3574         case SCI_SEARCHPREV
: 
3576         case SCI_LINEDOWNEXTEND
: 
3578         case SCI_PARADOWNEXTEND
: 
3580         case SCI_LINEUPEXTEND
: 
3582         case SCI_PARAUPEXTEND
: 
3584         case SCI_CHARLEFTEXTEND
: 
3586         case SCI_CHARRIGHTEXTEND
: 
3588         case SCI_WORDLEFTEXTEND
: 
3590         case SCI_WORDRIGHTEXTEND
: 
3591         case SCI_WORDPARTLEFT
: 
3592         case SCI_WORDPARTLEFTEXTEND
: 
3593         case SCI_WORDPARTRIGHT
: 
3594         case SCI_WORDPARTRIGHTEXTEND
: 
3595         case SCI_WORDLEFTEND
: 
3596         case SCI_WORDLEFTENDEXTEND
: 
3597         case SCI_WORDRIGHTEND
: 
3598         case SCI_WORDRIGHTENDEXTEND
: 
3600         case SCI_HOMEEXTEND
: 
3602         case SCI_LINEENDEXTEND
: 
3604         case SCI_HOMEWRAPEXTEND
: 
3605         case SCI_LINEENDWRAP
: 
3606         case SCI_LINEENDWRAPEXTEND
: 
3607         case SCI_DOCUMENTSTART
: 
3608         case SCI_DOCUMENTSTARTEXTEND
: 
3609         case SCI_DOCUMENTEND
: 
3610         case SCI_DOCUMENTENDEXTEND
: 
3611         case SCI_STUTTEREDPAGEUP
: 
3612         case SCI_STUTTEREDPAGEUPEXTEND
: 
3613         case SCI_STUTTEREDPAGEDOWN
: 
3614         case SCI_STUTTEREDPAGEDOWNEXTEND
: 
3616         case SCI_PAGEUPEXTEND
: 
3618         case SCI_PAGEDOWNEXTEND
: 
3619         case SCI_EDITTOGGLEOVERTYPE
: 
3621         case SCI_DELETEBACK
: 
3626         case SCI_VCHOMEEXTEND
: 
3627         case SCI_VCHOMEWRAP
: 
3628         case SCI_VCHOMEWRAPEXTEND
: 
3629         case SCI_DELWORDLEFT
: 
3630         case SCI_DELWORDRIGHT
: 
3631         case SCI_DELLINELEFT
: 
3632         case SCI_DELLINERIGHT
: 
3635         case SCI_LINEDELETE
: 
3636         case SCI_LINETRANSPOSE
: 
3637         case SCI_LINEDUPLICATE
: 
3640         case SCI_LINESCROLLDOWN
: 
3641         case SCI_LINESCROLLUP
: 
3642         case SCI_DELETEBACKNOTLINE
: 
3643         case SCI_HOMEDISPLAY
: 
3644         case SCI_HOMEDISPLAYEXTEND
: 
3645         case SCI_LINEENDDISPLAY
: 
3646         case SCI_LINEENDDISPLAYEXTEND
: 
3647         case SCI_SETSELECTIONMODE
: 
3648         case SCI_LINEDOWNRECTEXTEND
: 
3649         case SCI_LINEUPRECTEXTEND
: 
3650         case SCI_CHARLEFTRECTEXTEND
: 
3651         case SCI_CHARRIGHTRECTEXTEND
: 
3652         case SCI_HOMERECTEXTEND
: 
3653         case SCI_VCHOMERECTEXTEND
: 
3654         case SCI_LINEENDRECTEXTEND
: 
3655         case SCI_PAGEUPRECTEXTEND
: 
3656         case SCI_PAGEDOWNRECTEXTEND
: 
3659         // Filter out all others like display changes. Also, newlines are redundant 
3660         // with char insert messages. 
3663                 //              printf("Filtered out %ld of macro recording\n", iMessage); 
3667         // Send notification 
3669         scn
.nmhdr
.code 
= SCN_MACRORECORD
; 
3670         scn
.message 
= iMessage
; 
3671         scn
.wParam 
= wParam
; 
3672         scn
.lParam 
= lParam
; 
3677  * Force scroll and keep position relative to top of window. 
3679  * If stuttered = true and not already at first/last row, move to first/last row of window. 
3680  * If stuttered = true and already at first/last row, scroll as normal. 
3682 void Editor::PageMove(int direction
, selTypes sel
, bool stuttered
) { 
3683         int topLineNew
, newPos
; 
3685         // I consider only the caretYSlop, and ignore the caretYPolicy-- is that a problem? 
3686         int currentLine 
= pdoc
->LineFromPosition(currentPos
); 
3687         int topStutterLine 
= topLine 
+ caretYSlop
; 
3688         int bottomStutterLine 
= topLine 
+ LinesToScroll() - caretYSlop
; 
3690         if (stuttered 
&& (direction 
< 0 && currentLine 
> topStutterLine
)) { 
3691                 topLineNew 
= topLine
; 
3692                 newPos 
= PositionFromLocation(Point(lastXChosen
, vs
.lineHeight 
* caretYSlop
)); 
3694         } else if (stuttered 
&& (direction 
> 0 && currentLine 
< bottomStutterLine
)) { 
3695                 topLineNew 
= topLine
; 
3696                 newPos 
= PositionFromLocation(Point(lastXChosen
, vs
.lineHeight 
* (LinesToScroll() - caretYSlop
))); 
3699                 Point pt 
= LocationFromPosition(currentPos
); 
3701                 topLineNew 
= Platform::Clamp( 
3702                              topLine 
+ direction 
* LinesToScroll(), 0, MaxScrollPos()); 
3703                 newPos 
= PositionFromLocation( 
3704                          Point(lastXChosen
, pt
.y 
+ direction 
* (vs
.lineHeight 
* LinesToScroll()))); 
3707         if (topLineNew 
!= topLine
) { 
3708                 SetTopLine(topLineNew
); 
3709                 MovePositionTo(newPos
, sel
); 
3711                 SetVerticalScrollPos(); 
3713                 MovePositionTo(newPos
, sel
); 
3717 void Editor::ChangeCaseOfSelection(bool makeUpperCase
) { 
3718         pdoc
->BeginUndoAction(); 
3719         int startCurrent 
= currentPos
; 
3720         int startAnchor 
= anchor
; 
3721         if (selType 
== selStream
) { 
3722                 pdoc
->ChangeCase(Range(SelectionStart(), SelectionEnd()), 
3724                 SetSelection(startCurrent
, startAnchor
); 
3726                 SelectionLineIterator 
lineIterator(this, false); 
3727                 while (lineIterator
.Iterate()) { 
3729                             Range(lineIterator
.startPos
, lineIterator
.endPos
), 
3732                 // Would be nicer to keep the rectangular selection but this is complex 
3733                 SetEmptySelection(startCurrent
); 
3735         pdoc
->EndUndoAction(); 
3738 void Editor::LineTranspose() { 
3739         int line 
= pdoc
->LineFromPosition(currentPos
); 
3741                 int startPrev 
= pdoc
->LineStart(line 
- 1); 
3742                 int endPrev 
= pdoc
->LineEnd(line 
- 1); 
3743                 int start 
= pdoc
->LineStart(line
); 
3744                 int end 
= pdoc
->LineEnd(line
); 
3745                 int startNext 
= pdoc
->LineStart(line 
+ 1); 
3746                 if (end 
< pdoc
->Length()) { 
3748                         char *thisLine 
= CopyRange(start
, end
); 
3749                         pdoc
->DeleteChars(start
, end 
- start
); 
3750                         if (pdoc
->InsertString(startPrev
, thisLine
, end 
- start
)) { 
3751                                 MovePositionTo(startPrev 
+ end 
- start
); 
3755                         // Last line so line has no line end 
3756                         char *thisLine 
= CopyRange(start
, end
); 
3757                         char *prevEnd 
= CopyRange(endPrev
, start
); 
3758                         pdoc
->DeleteChars(endPrev
, end 
- endPrev
); 
3759                         pdoc
->InsertString(startPrev
, thisLine
, end 
- start
); 
3760                         if (pdoc
->InsertString(startPrev 
+ end 
- start
, prevEnd
, start 
- endPrev
)) { 
3761                                 MovePositionTo(startPrev 
+ end 
- endPrev
); 
3770 void Editor::LineDuplicate() { 
3771         int line 
= pdoc
->LineFromPosition(currentPos
); 
3772         int start 
= pdoc
->LineStart(line
); 
3773         int end 
= pdoc
->LineEnd(line
); 
3774         char *thisLine 
= CopyRange(start
, end
); 
3775         const char *eol 
= StringFromEOLMode(pdoc
->eolMode
); 
3776         pdoc
->InsertString(end
, eol
); 
3777         pdoc
->InsertString(end 
+ istrlen(eol
), thisLine
, end 
- start
); 
3781 void Editor::CancelModes() { 
3782         moveExtendsSelection 
= false; 
3785 void Editor::NewLine() { 
3787         const char *eol 
= "\n"; 
3788         if (pdoc
->eolMode 
== SC_EOL_CRLF
) { 
3790         } else if (pdoc
->eolMode 
== SC_EOL_CR
) { 
3792         } // else SC_EOL_LF -> "\n" already set 
3793         if (pdoc
->InsertString(currentPos
, eol
)) { 
3794                 SetEmptySelection(currentPos 
+ istrlen(eol
)); 
3801         EnsureCaretVisible(); 
3804 void Editor::CursorUpOrDown(int direction
, selTypes sel
) { 
3805         Point pt 
= LocationFromPosition(currentPos
); 
3806         int posNew 
= PositionFromLocation( 
3807                          Point(lastXChosen
, pt
.y 
+ direction 
* vs
.lineHeight
)); 
3808         if (direction 
< 0) { 
3809                 // Line wrapping may lead to a location on the same line, so 
3810                 // seek back if that is the case. 
3811                 // There is an equivalent case when moving down which skips 
3812                 // over a line but as that does not trap the user it is fine. 
3813                 Point ptNew 
= LocationFromPosition(posNew
); 
3814                 while ((posNew 
> 0) && (pt
.y 
== ptNew
.y
)) { 
3816                         ptNew 
= LocationFromPosition(posNew
); 
3819         MovePositionTo(posNew
, sel
); 
3822 int Editor::StartEndDisplayLine(int pos
, bool start
) { 
3824         int line 
= pdoc
->LineFromPosition(pos
); 
3825         AutoSurface 
surface(this); 
3826         AutoLineLayout 
ll(llc
, RetrieveLineLayout(line
)); 
3827         int posRet 
= INVALID_POSITION
; 
3828         if (surface 
&& ll
) { 
3829                 unsigned int posLineStart 
= pdoc
->LineStart(line
); 
3830                 LayoutLine(line
, surface
, vs
, ll
, wrapWidth
); 
3831                 int posInLine 
= pos 
- posLineStart
; 
3832                 if (posInLine 
<= ll
->maxLineLength
) { 
3833                         for (int subLine 
= 0; subLine 
< ll
->lines
; subLine
++) { 
3834                                 if ((posInLine 
>= ll
->LineStart(subLine
)) && (posInLine 
<= ll
->LineStart(subLine 
+ 1))) { 
3836                                                 posRet 
= ll
->LineStart(subLine
) + posLineStart
; 
3838                                                 if (subLine 
== ll
->lines 
- 1) 
3839                                                         posRet 
= ll
->LineStart(subLine 
+ 1) + posLineStart
; 
3841                                                         posRet 
= ll
->LineStart(subLine 
+ 1) + posLineStart 
- 1; 
3847         if (posRet 
== INVALID_POSITION
) { 
3854 int Editor::KeyCommand(unsigned int iMessage
) { 
3859         case SCI_LINEDOWNEXTEND
: 
3860                 CursorUpOrDown(1, selStream
); 
3862         case SCI_LINEDOWNRECTEXTEND
: 
3863                 CursorUpOrDown(1, selRectangle
); 
3866                 MovePositionTo(pdoc
->ParaDown(currentPos
)); 
3868         case SCI_PARADOWNEXTEND
: 
3869                 MovePositionTo(pdoc
->ParaDown(currentPos
), selStream
); 
3871         case SCI_LINESCROLLDOWN
: 
3872                 ScrollTo(topLine 
+ 1); 
3873                 MoveCaretInsideView(false); 
3878         case SCI_LINEUPEXTEND
: 
3879                 CursorUpOrDown(-1, selStream
); 
3881         case SCI_LINEUPRECTEXTEND
: 
3882                 CursorUpOrDown(-1, selRectangle
); 
3885                 MovePositionTo(pdoc
->ParaUp(currentPos
)); 
3887         case SCI_PARAUPEXTEND
: 
3888                 MovePositionTo(pdoc
->ParaUp(currentPos
), selStream
); 
3890         case SCI_LINESCROLLUP
: 
3891                 ScrollTo(topLine 
- 1); 
3892                 MoveCaretInsideView(false); 
3895                 if (SelectionEmpty() || moveExtendsSelection
) { 
3896                         MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1)); 
3898                         MovePositionTo(SelectionStart()); 
3902         case SCI_CHARLEFTEXTEND
: 
3903                 MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1), selStream
); 
3906         case SCI_CHARLEFTRECTEXTEND
: 
3907                 MovePositionTo(MovePositionSoVisible(currentPos 
- 1, -1), selRectangle
); 
3911                 if (SelectionEmpty() || moveExtendsSelection
) { 
3912                         MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1)); 
3914                         MovePositionTo(SelectionEnd()); 
3918         case SCI_CHARRIGHTEXTEND
: 
3919                 MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1), selStream
); 
3922         case SCI_CHARRIGHTRECTEXTEND
: 
3923                 MovePositionTo(MovePositionSoVisible(currentPos 
+ 1, 1), selRectangle
); 
3927                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1)); 
3930         case SCI_WORDLEFTEXTEND
: 
3931                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1), selStream
); 
3935                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1)); 
3938         case SCI_WORDRIGHTEXTEND
: 
3939                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1), selStream
); 
3943         case SCI_WORDLEFTEND
: 
3944                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, -1), -1)); 
3947         case SCI_WORDLEFTENDEXTEND
: 
3948                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, -1), -1), selStream
); 
3951         case SCI_WORDRIGHTEND
: 
3952                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, 1), 1)); 
3955         case SCI_WORDRIGHTENDEXTEND
: 
3956                 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordEnd(currentPos
, 1), 1), selStream
); 
3961                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
))); 
3964         case SCI_HOMEEXTEND
: 
3965                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), selStream
); 
3968         case SCI_HOMERECTEXTEND
: 
3969                 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), selRectangle
); 
3973                 MovePositionTo(pdoc
->LineEndPosition(currentPos
)); 
3976         case SCI_LINEENDEXTEND
: 
3977                 MovePositionTo(pdoc
->LineEndPosition(currentPos
), selStream
); 
3980         case SCI_LINEENDRECTEXTEND
: 
3981                 MovePositionTo(pdoc
->LineEndPosition(currentPos
), selRectangle
); 
3984         case SCI_HOMEWRAP
: { 
3985                         int homePos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
3986                         if (currentPos 
<= homePos
) 
3987                                 homePos 
= pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)); 
3988                         MovePositionTo(homePos
); 
3992         case SCI_HOMEWRAPEXTEND
: { 
3993                         int homePos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
3994                         if (currentPos 
<= homePos
) 
3995                                 homePos 
= pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)); 
3996                         MovePositionTo(homePos
, selStream
); 
4000         case SCI_LINEENDWRAP
: { 
4001                         int endPos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, false), 1); 
4002                         if (currentPos 
>= endPos
) 
4003                                 endPos 
= pdoc
->LineEndPosition(currentPos
); 
4004                         MovePositionTo(endPos
); 
4008         case SCI_LINEENDWRAPEXTEND
: { 
4009                         int endPos 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, false), 1); 
4010                         if (currentPos 
>= endPos
) 
4011                                 endPos 
= pdoc
->LineEndPosition(currentPos
); 
4012                         MovePositionTo(endPos
, selStream
); 
4016         case SCI_DOCUMENTSTART
: 
4020         case SCI_DOCUMENTSTARTEXTEND
: 
4021                 MovePositionTo(0, selStream
); 
4024         case SCI_DOCUMENTEND
: 
4025                 MovePositionTo(pdoc
->Length()); 
4028         case SCI_DOCUMENTENDEXTEND
: 
4029                 MovePositionTo(pdoc
->Length(), selStream
); 
4032         case SCI_STUTTEREDPAGEUP
: 
4033                 PageMove(-1, noSel
, true); 
4035         case SCI_STUTTEREDPAGEUPEXTEND
: 
4036                 PageMove(-1, selStream
, true); 
4038         case SCI_STUTTEREDPAGEDOWN
: 
4039                 PageMove(1, noSel
, true); 
4041         case SCI_STUTTEREDPAGEDOWNEXTEND
: 
4042                 PageMove(1, selStream
, true); 
4047         case SCI_PAGEUPEXTEND
: 
4048                 PageMove(-1, selStream
); 
4050         case SCI_PAGEUPRECTEXTEND
: 
4051                 PageMove(-1, selRectangle
); 
4056         case SCI_PAGEDOWNEXTEND
: 
4057                 PageMove(1, selStream
); 
4059         case SCI_PAGEDOWNRECTEXTEND
: 
4060                 PageMove(1, selRectangle
); 
4062         case SCI_EDITTOGGLEOVERTYPE
: 
4063                 inOverstrike 
= !inOverstrike
; 
4065                 ShowCaretAtCurrentPosition(); 
4068         case SCI_CANCEL
:                // Cancel any modes - handled in subclass 
4069                 // Also unselect text 
4072         case SCI_DELETEBACK
: 
4075                 EnsureCaretVisible(); 
4077         case SCI_DELETEBACKNOTLINE
: 
4080                 EnsureCaretVisible(); 
4085                 EnsureCaretVisible(); 
4090                 EnsureCaretVisible(); 
4099                 MovePositionTo(pdoc
->VCHomePosition(currentPos
)); 
4102         case SCI_VCHOMEEXTEND
: 
4103                 MovePositionTo(pdoc
->VCHomePosition(currentPos
), selStream
); 
4106         case SCI_VCHOMERECTEXTEND
: 
4107                 MovePositionTo(pdoc
->VCHomePosition(currentPos
), selRectangle
); 
4110         case SCI_VCHOMEWRAP
: { 
4111                         int homePos 
= pdoc
->VCHomePosition(currentPos
); 
4112                         int viewLineStart 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
4113                         if ((viewLineStart 
< currentPos
) && (viewLineStart 
> homePos
)) 
4114                                 homePos 
= viewLineStart
; 
4116                         MovePositionTo(homePos
); 
4120         case SCI_VCHOMEWRAPEXTEND
: { 
4121                         int homePos 
= pdoc
->VCHomePosition(currentPos
); 
4122                         int viewLineStart 
= MovePositionSoVisible(StartEndDisplayLine(currentPos
, true), -1); 
4123                         if ((viewLineStart 
< currentPos
) && (viewLineStart 
> homePos
)) 
4124                                 homePos 
= viewLineStart
; 
4126                         MovePositionTo(homePos
, selStream
); 
4131                 if (vs
.zoomLevel 
< 20) { 
4133                         InvalidateStyleRedraw(); 
4138                 if (vs
.zoomLevel 
> -10) { 
4140                         InvalidateStyleRedraw(); 
4144         case SCI_DELWORDLEFT
: { 
4145                         int startWord 
= pdoc
->NextWordStart(currentPos
, -1); 
4146                         pdoc
->DeleteChars(startWord
, currentPos 
- startWord
); 
4150         case SCI_DELWORDRIGHT
: { 
4151                         int endWord 
= pdoc
->NextWordStart(currentPos
, 1); 
4152                         pdoc
->DeleteChars(currentPos
, endWord 
- currentPos
); 
4155         case SCI_DELLINELEFT
: { 
4156                         int line 
= pdoc
->LineFromPosition(currentPos
); 
4157                         int start 
= pdoc
->LineStart(line
); 
4158                         pdoc
->DeleteChars(start
, currentPos 
- start
); 
4162         case SCI_DELLINERIGHT
: { 
4163                         int line 
= pdoc
->LineFromPosition(currentPos
); 
4164                         int end 
= pdoc
->LineEnd(line
); 
4165                         pdoc
->DeleteChars(currentPos
, end 
- currentPos
); 
4168         case SCI_LINECOPY
: { 
4169                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
4170                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
4171                         CopyRangeToClipboard(pdoc
->LineStart(lineStart
), 
4172                                 pdoc
->LineStart(lineEnd 
+ 1)); 
4176                         int lineStart 
= pdoc
->LineFromPosition(SelectionStart()); 
4177                         int lineEnd 
= pdoc
->LineFromPosition(SelectionEnd()); 
4178                         int start 
= pdoc
->LineStart(lineStart
); 
4179                         int end 
= pdoc
->LineStart(lineEnd 
+ 1); 
4180                         SetSelection(start
, end
); 
4185         case SCI_LINEDELETE
: { 
4186                         int line 
= pdoc
->LineFromPosition(currentPos
); 
4187                         int start 
= pdoc
->LineStart(line
); 
4188                         int end 
= pdoc
->LineStart(line 
+ 1); 
4189                         pdoc
->DeleteChars(start
, end 
- start
); 
4192         case SCI_LINETRANSPOSE
: 
4195         case SCI_LINEDUPLICATE
: 
4199                 ChangeCaseOfSelection(false); 
4202                 ChangeCaseOfSelection(true); 
4204         case SCI_WORDPARTLEFT
: 
4205                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartLeft(currentPos
), -1)); 
4208         case SCI_WORDPARTLEFTEXTEND
: 
4209                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartLeft(currentPos
), -1), selStream
); 
4212         case SCI_WORDPARTRIGHT
: 
4213                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartRight(currentPos
), 1)); 
4216         case SCI_WORDPARTRIGHTEXTEND
: 
4217                 MovePositionTo(MovePositionSoVisible(pdoc
->WordPartRight(currentPos
), 1), selStream
); 
4220         case SCI_HOMEDISPLAY
: 
4221                 MovePositionTo(MovePositionSoVisible( 
4222                                    StartEndDisplayLine(currentPos
, true), -1)); 
4225         case SCI_HOMEDISPLAYEXTEND
: 
4226                 MovePositionTo(MovePositionSoVisible( 
4227                                    StartEndDisplayLine(currentPos
, true), -1), selStream
); 
4230         case SCI_LINEENDDISPLAY
: 
4231                 MovePositionTo(MovePositionSoVisible( 
4232                                    StartEndDisplayLine(currentPos
, false), 1)); 
4235         case SCI_LINEENDDISPLAYEXTEND
: 
4236                 MovePositionTo(MovePositionSoVisible( 
4237                                    StartEndDisplayLine(currentPos
, false), 1), selStream
); 
4244 int Editor::KeyDefault(int, int) { 
4248 int Editor::KeyDown(int key
, bool shift
, bool ctrl
, bool alt
, bool *consumed
) { 
4250         int modifiers 
= (shift 
? SCI_SHIFT 
: 0) | (ctrl 
? SCI_CTRL 
: 0) | 
4251                         (alt 
? SCI_ALT 
: 0); 
4252         int msg 
= kmap
.Find(key
, modifiers
); 
4256                 return WndProc(msg
, 0, 0); 
4260                 return KeyDefault(key
, modifiers
); 
4264 void Editor::SetWhitespaceVisible(int view
) { 
4265         vs
.viewWhitespace 
= static_cast<WhiteSpaceVisibility
>(view
); 
4268 int Editor::GetWhitespaceVisible() { 
4269         return vs
.viewWhitespace
; 
4272 void Editor::Indent(bool forwards
) { 
4273         //Platform::DebugPrintf("INdent %d\n", forwards); 
4274         int lineOfAnchor 
= pdoc
->LineFromPosition(anchor
); 
4275         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
4276         if (lineOfAnchor 
== lineCurrentPos
) { 
4278                         pdoc
->BeginUndoAction(); 
4280                         if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetColumn(pdoc
->GetLineIndentPosition(lineCurrentPos
)) && 
4282                                 int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
4283                                 int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
4284                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
+ indentationStep
); 
4285                                 SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
4287                                 if (pdoc
->useTabs
) { 
4288                                         pdoc
->InsertChar(currentPos
, '\t'); 
4289                                         SetEmptySelection(currentPos 
+ 1); 
4291                                         int numSpaces 
= (pdoc
->tabInChars
) - 
4292                                                         (pdoc
->GetColumn(currentPos
) % (pdoc
->tabInChars
)); 
4294                                                 numSpaces 
= pdoc
->tabInChars
; 
4295                                         for (int i 
= 0; i 
< numSpaces
; i
++) { 
4296                                                 pdoc
->InsertChar(currentPos 
+ i
, ' '); 
4298                                         SetEmptySelection(currentPos 
+ numSpaces
); 
4301                         pdoc
->EndUndoAction(); 
4303                         if (pdoc
->GetColumn(currentPos
) <= pdoc
->GetLineIndentation(lineCurrentPos
) && 
4305                                 pdoc
->BeginUndoAction(); 
4306                                 int indentation 
= pdoc
->GetLineIndentation(lineCurrentPos
); 
4307                                 int indentationStep 
= (pdoc
->indentInChars 
? pdoc
->indentInChars 
: pdoc
->tabInChars
); 
4308                                 pdoc
->SetLineIndentation(lineCurrentPos
, indentation 
- indentationStep
); 
4309                                 SetEmptySelection(pdoc
->GetLineIndentPosition(lineCurrentPos
)); 
4310                                 pdoc
->EndUndoAction(); 
4312                                 int newColumn 
= ((pdoc
->GetColumn(currentPos
) - 1) / pdoc
->tabInChars
) * 
4316                                 int newPos 
= currentPos
; 
4317                                 while (pdoc
->GetColumn(newPos
) > newColumn
) 
4319                                 SetEmptySelection(newPos
); 
4323                 int anchorPosOnLine 
= anchor 
- pdoc
->LineStart(lineOfAnchor
); 
4324                 int currentPosPosOnLine 
= currentPos 
- pdoc
->LineStart(lineCurrentPos
); 
4325                 // Multiple lines selected so indent / dedent 
4326                 int lineTopSel 
= Platform::Minimum(lineOfAnchor
, lineCurrentPos
); 
4327                 int lineBottomSel 
= Platform::Maximum(lineOfAnchor
, lineCurrentPos
); 
4328                 if (pdoc
->LineStart(lineBottomSel
) == anchor 
|| pdoc
->LineStart(lineBottomSel
) == currentPos
) 
4329                         lineBottomSel
--;        // If not selecting any characters on a line, do not indent 
4330                 pdoc
->BeginUndoAction(); 
4331                 pdoc
->Indent(forwards
, lineBottomSel
, lineTopSel
); 
4332                 pdoc
->EndUndoAction(); 
4333                 if (lineOfAnchor 
< lineCurrentPos
) { 
4334                         if (currentPosPosOnLine 
== 0) 
4335                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
)); 
4337                                 SetSelection(pdoc
->LineStart(lineCurrentPos 
+ 1), pdoc
->LineStart(lineOfAnchor
)); 
4339                         if (anchorPosOnLine 
== 0) 
4340                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
)); 
4342                                 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor 
+ 1)); 
4348  * Search of a text in the document, in the given range. 
4349  * @return The position of the found text, -1 if not found. 
4351 long Editor::FindText( 
4352         uptr_t wParam
,          ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, 
4353                                                 ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. 
4354         sptr_t lParam
) {        ///< @c TextToFind structure: The text to search for in the given range. 
4356         TextToFind 
*ft 
= reinterpret_cast<TextToFind 
*>(lParam
); 
4357         int lengthFound 
= istrlen(ft
->lpstrText
); 
4358         int pos 
= pdoc
->FindText(ft
->chrg
.cpMin
, ft
->chrg
.cpMax
, ft
->lpstrText
, 
4359                                  (wParam 
& SCFIND_MATCHCASE
) != 0, 
4360                                  (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4361                                  (wParam 
& SCFIND_WORDSTART
) != 0, 
4362                                  (wParam 
& SCFIND_REGEXP
) != 0, 
4363                                  (wParam 
& SCFIND_POSIX
) != 0, 
4366                 ft
->chrgText
.cpMin 
= pos
; 
4367                 ft
->chrgText
.cpMax 
= pos 
+ lengthFound
; 
4373  * Relocatable search support : Searches relative to current selection 
4374  * point and sets the selection to the found text range with 
4378  * Anchor following searches at current selection start: This allows 
4379  * multiple incremental interactive searches to be macro recorded 
4380  * while still setting the selection to found text so the find/select 
4381  * operation is self-contained. 
4383 void Editor::SearchAnchor() { 
4384         searchAnchor 
= SelectionStart(); 
4388  * Find text from current search anchor: Must call @c SearchAnchor first. 
4389  * Used for next text and previous text requests. 
4390  * @return The position of the found text, -1 if not found. 
4392 long Editor::SearchText( 
4393     unsigned int iMessage
,              ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV. 
4394     uptr_t wParam
,                              ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, 
4395                                                                 ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. 
4396     sptr_t lParam
) {                    ///< The text to search for. 
4398         const char *txt 
= reinterpret_cast<char *>(lParam
); 
4400         int lengthFound 
= istrlen(txt
); 
4401         if (iMessage 
== SCI_SEARCHNEXT
) { 
4402                 pos 
= pdoc
->FindText(searchAnchor
, pdoc
->Length(), txt
, 
4403                                      (wParam 
& SCFIND_MATCHCASE
) != 0, 
4404                                      (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4405                                      (wParam 
& SCFIND_WORDSTART
) != 0, 
4406                                      (wParam 
& SCFIND_REGEXP
) != 0, 
4407                                      (wParam 
& SCFIND_POSIX
) != 0, 
4410                 pos 
= pdoc
->FindText(searchAnchor
, 0, txt
, 
4411                                      (wParam 
& SCFIND_MATCHCASE
) != 0, 
4412                                      (wParam 
& SCFIND_WHOLEWORD
) != 0, 
4413                                      (wParam 
& SCFIND_WORDSTART
) != 0, 
4414                                      (wParam 
& SCFIND_REGEXP
) != 0, 
4415                                      (wParam 
& SCFIND_POSIX
) != 0, 
4420                 SetSelection(pos
, pos 
+ lengthFound
); 
4427  * Search for text in the target range of the document. 
4428  * @return The position of the found text, -1 if not found. 
4430 long Editor::SearchInTarget(const char *text
, int length
) { 
4431         int lengthFound 
= length
; 
4432         int pos 
= pdoc
->FindText(targetStart
, targetEnd
, text
, 
4433                                  (searchFlags 
& SCFIND_MATCHCASE
) != 0, 
4434                                  (searchFlags 
& SCFIND_WHOLEWORD
) != 0, 
4435                                  (searchFlags 
& SCFIND_WORDSTART
) != 0, 
4436                                  (searchFlags 
& SCFIND_REGEXP
) != 0, 
4437                                  (searchFlags 
& SCFIND_POSIX
) != 0, 
4441                 targetEnd 
= pos 
+ lengthFound
; 
4446 void Editor::GoToLine(int lineNo
) { 
4447         if (lineNo 
> pdoc
->LinesTotal()) 
4448                 lineNo 
= pdoc
->LinesTotal(); 
4451         SetEmptySelection(pdoc
->LineStart(lineNo
)); 
4452         ShowCaretAtCurrentPosition(); 
4453         EnsureCaretVisible(); 
4456 static bool Close(Point pt1
, Point pt2
) { 
4457         if (abs(pt1
.x 
- pt2
.x
) > 3) 
4459         if (abs(pt1
.y 
- pt2
.y
) > 3) 
4464 char *Editor::CopyRange(int start
, int end
) { 
4467                 int len 
= end 
- start
; 
4468                 text 
= new char[len 
+ 1]; 
4470                         for (int i 
= 0; i 
< len
; i
++) { 
4471                                 text
[i
] = pdoc
->CharAt(start 
+ i
); 
4479 void Editor::CopySelectionFromRange(SelectionText 
*ss
, int start
, int end
) { 
4480         ss
->Set(CopyRange(start
, end
), end 
- start 
+ 1, false); 
4483 void Editor::CopySelectionRange(SelectionText 
*ss
) { 
4484         if (selType 
== selStream
) { 
4485                 CopySelectionFromRange(ss
, SelectionStart(), SelectionEnd()); 
4489                 SelectionLineIterator 
lineIterator(this); 
4490                 while (lineIterator
.Iterate()) { 
4491                         size 
+= lineIterator
.endPos 
- lineIterator
.startPos
; 
4492                         if (selType 
!= selLines
) { 
4494                                 if (pdoc
->eolMode 
== SC_EOL_CRLF
) { 
4500                         text 
= new char[size 
+ 1]; 
4503                                 lineIterator
.Reset(); 
4504                                 while (lineIterator
.Iterate()) { 
4505                                         for (int i 
= lineIterator
.startPos
; 
4506                                                  i 
< lineIterator
.endPos
; 
4508                                                 text
[j
++] = pdoc
->CharAt(i
); 
4510                                         if (selType 
!= selLines
) { 
4511                                                 if (pdoc
->eolMode 
!= SC_EOL_LF
) { 
4514                                                 if (pdoc
->eolMode 
!= SC_EOL_CR
) { 
4522                 ss
->Set(text
, size 
+ 1, selType 
== selRectangle
); 
4526 void Editor::CopyRangeToClipboard(int start
, int end
) { 
4527         start 
= pdoc
->ClampPositionIntoDocument(start
); 
4528         end 
= pdoc
->ClampPositionIntoDocument(end
); 
4529         SelectionText selectedText
; 
4530         selectedText
.Set(CopyRange(start
, end
), end 
- start 
+ 1); 
4531         CopyToClipboard(selectedText
); 
4534 void Editor::CopyText(int length
, const char *text
) { 
4535         SelectionText selectedText
; 
4536         selectedText
.Copy(text
, length
); 
4537         CopyToClipboard(selectedText
); 
4540 void Editor::SetDragPosition(int newPos
) { 
4542                 newPos 
= MovePositionOutsideChar(newPos
, 1); 
4545         if (posDrag 
!= newPos
) { 
4554 void Editor::DisplayCursor(Window::Cursor c
) { 
4555         if (cursorMode 
== SC_CURSORNORMAL
) 
4558                 wMain
.SetCursor(static_cast<Window::Cursor
>(cursorMode
)); 
4561 void Editor::StartDrag() { 
4562         // Always handled by subclasses 
4563         //SetMouseCapture(true); 
4564         //DisplayCursor(Window::cursorArrow); 
4567 void Editor::DropAt(int position
, const char *value
, bool moving
, bool rectangular
) { 
4568         //Platform::DebugPrintf("DropAt %d\n", inDragDrop); 
4570                 dropWentOutside 
= false; 
4572         int positionWasInSelection 
= PositionInSelection(position
); 
4574         bool positionOnEdgeOfSelection 
= 
4575             (position 
== SelectionStart()) || (position 
== SelectionEnd()); 
4577         if ((!inDragDrop
) || !(0 == positionWasInSelection
) || 
4578                 (positionOnEdgeOfSelection 
&& !moving
)) { 
4580                 int selStart 
= SelectionStart(); 
4581                 int selEnd 
= SelectionEnd(); 
4583                 pdoc
->BeginUndoAction(); 
4585                 int positionAfterDeletion 
= position
; 
4586                 if (inDragDrop 
&& moving
) { 
4587                         // Remove dragged out text 
4588                         if (rectangular 
|| selType 
== selLines
) { 
4589                                 SelectionLineIterator 
lineIterator(this); 
4590                                 while (lineIterator
.Iterate()) { 
4591                                         if (position 
>= lineIterator
.startPos
) { 
4592                                                 if (position 
> lineIterator
.endPos
) { 
4593                                                         positionAfterDeletion 
-= lineIterator
.endPos 
- lineIterator
.startPos
; 
4595                                                         positionAfterDeletion 
-= position 
- lineIterator
.startPos
; 
4600                                 if (position 
> selStart
) { 
4601                                         positionAfterDeletion 
-= selEnd 
- selStart
; 
4606                 position 
= positionAfterDeletion
; 
4609                         PasteRectangular(position
, value
, istrlen(value
)); 
4610                         pdoc
->EndUndoAction(); 
4611                         // Should try to select new rectangle but it may not be a rectangle now so just select the drop position 
4612                         SetEmptySelection(position
); 
4614                         position 
= MovePositionOutsideChar(position
, currentPos 
- position
); 
4615                         if (pdoc
->InsertString(position
, value
)) { 
4616                                 SetSelection(position 
+ istrlen(value
), position
); 
4618                         pdoc
->EndUndoAction(); 
4620         } else if (inDragDrop
) { 
4621                 SetEmptySelection(position
); 
4626  * @return -1 if given position is before the selection, 
4627  *          1 if position is after the selection, 
4628  *          0 if position is inside the selection, 
4630 int Editor::PositionInSelection(int pos
) { 
4631         pos 
= MovePositionOutsideChar(pos
, currentPos 
- pos
); 
4632         if (pos 
< SelectionStart()) { 
4635         if (pos 
> SelectionEnd()) { 
4638         if (selType 
== selStream
) { 
4641                 SelectionLineIterator 
lineIterator(this); 
4642                 lineIterator
.SetAt(pdoc
->LineFromPosition(pos
)); 
4643                 if (pos 
< lineIterator
.startPos
) { 
4645                 } else if (pos 
> lineIterator
.endPos
) { 
4653 bool Editor::PointInSelection(Point pt
) { 
4654         int pos 
= PositionFromLocation(pt
); 
4655         if (0 == PositionInSelection(pos
)) { 
4656                 // Probably inside, but we must make a finer test 
4657                 int selStart
, selEnd
; 
4658                 if (selType 
== selStream
) { 
4659                         selStart 
= SelectionStart(); 
4660                         selEnd 
= SelectionEnd(); 
4662                         SelectionLineIterator 
lineIterator(this); 
4663                         lineIterator
.SetAt(pdoc
->LineFromPosition(pos
)); 
4664                         selStart 
= lineIterator
.startPos
; 
4665                         selEnd 
= lineIterator
.endPos
; 
4667                 if (pos 
== selStart
) { 
4668                         // see if just before selection 
4669                         Point locStart 
= LocationFromPosition(pos
); 
4670                         if (pt
.x 
< locStart
.x
) { 
4674                 if (pos 
== selEnd
) { 
4675                         // see if just after selection 
4676                         Point locEnd 
= LocationFromPosition(pos
); 
4677                         if (pt
.x 
> locEnd
.x
) { 
4686 bool Editor::PointInSelMargin(Point pt
) { 
4687         // Really means: "Point in a margin" 
4688         if (vs
.fixedColumnWidth 
> 0) {  // There is a margin 
4689                 PRectangle rcSelMargin 
= GetClientRectangle(); 
4690                 rcSelMargin
.right 
= vs
.fixedColumnWidth 
- vs
.leftMarginWidth
; 
4691                 return rcSelMargin
.Contains(pt
); 
4697 void Editor::LineSelection(int lineCurrent_
, int lineAnchor_
) { 
4698         if (lineAnchor_ 
< lineCurrent_
) { 
4699                 SetSelection(pdoc
->LineStart(lineCurrent_ 
+ 1), 
4700                              pdoc
->LineStart(lineAnchor_
)); 
4701         } else if (lineAnchor_ 
> lineCurrent_
) { 
4702                 SetSelection(pdoc
->LineStart(lineCurrent_
), 
4703                              pdoc
->LineStart(lineAnchor_ 
+ 1)); 
4704         } else { // Same line, select it 
4705                 SetSelection(pdoc
->LineStart(lineAnchor_ 
+ 1), 
4706                              pdoc
->LineStart(lineAnchor_
)); 
4710 void Editor::DwellEnd(bool mouseMoved
) { 
4712                 ticksToDwell 
= dwellDelay
; 
4714                 ticksToDwell 
= SC_TIME_FOREVER
; 
4715         if (dwelling 
&& (dwellDelay 
< SC_TIME_FOREVER
)) { 
4717                 NotifyDwelling(ptMouseLast
, dwelling
); 
4721 void Editor::ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
) { 
4722         //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt); 
4724         int newPos 
= PositionFromLocation(pt
); 
4725         newPos 
= MovePositionOutsideChar(newPos
, currentPos 
- newPos
); 
4727         moveExtendsSelection 
= false; 
4729         bool processed 
= NotifyMarginClick(pt
, shift
, ctrl
, alt
); 
4733         bool inSelMargin 
= PointInSelMargin(pt
); 
4734         if (shift 
& !inSelMargin
) { 
4735                 SetSelection(newPos
); 
4737         if (((curTime 
- lastClickTime
) < Platform::DoubleClickTime()) && Close(pt
, lastClick
)) { 
4738                 //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); 
4739                 SetMouseCapture(true); 
4740                 SetEmptySelection(newPos
); 
4741                 bool doubleClick 
= false; 
4742                 // Stop mouse button bounce changing selection type 
4743                 if (!Platform::MouseButtonBounce() || curTime 
!= lastClickTime
) { 
4744                         if (selectionType 
== selChar
) { 
4745                                 selectionType 
= selWord
; 
4747                         } else if (selectionType 
== selWord
) { 
4748                                 selectionType 
= selLine
; 
4750                                 selectionType 
= selChar
; 
4751                                 originalAnchorPos 
= currentPos
; 
4755                 if (selectionType 
== selWord
) { 
4756                         if (currentPos 
>= originalAnchorPos
) {  // Moved forward 
4757                                 SetSelection(pdoc
->ExtendWordSelect(currentPos
, 1), 
4758                                              pdoc
->ExtendWordSelect(originalAnchorPos
, -1)); 
4759                         } else {        // Moved backward 
4760                                 SetSelection(pdoc
->ExtendWordSelect(currentPos
, -1), 
4761                                              pdoc
->ExtendWordSelect(originalAnchorPos
, 1)); 
4763                 } else if (selectionType 
== selLine
) { 
4764                         lineAnchor 
= LineFromLocation(pt
); 
4765                         SetSelection(pdoc
->LineStart(lineAnchor 
+ 1), pdoc
->LineStart(lineAnchor
)); 
4766                         //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos); 
4768                         SetEmptySelection(currentPos
); 
4770                 //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos); 
4772                         NotifyDoubleClick(pt
, shift
); 
4773                         if (PointIsHotspot(newPos
)) 
4774                                 NotifyHotSpotDoubleClicked(newPos
, shift
, ctrl
, alt
); 
4776         } else {        // Single click 
4778                         selType 
= selStream
; 
4781                                 lastClickTime 
= curTime
; 
4785                                 lineAnchor 
= LineFromLocation(pt
); 
4786                                 // Single click in margin: select whole line 
4787                                 LineSelection(lineAnchor
, lineAnchor
); 
4788                                 SetSelection(pdoc
->LineStart(lineAnchor 
+ 1), 
4789                                              pdoc
->LineStart(lineAnchor
)); 
4791                                 // Single shift+click in margin: select from line anchor to clicked line 
4792                                 if (anchor 
> currentPos
) 
4793                                         lineAnchor 
= pdoc
->LineFromPosition(anchor 
- 1); 
4795                                         lineAnchor 
= pdoc
->LineFromPosition(anchor
); 
4796                                 int lineStart 
= LineFromLocation(pt
); 
4797                                 LineSelection(lineStart
, lineAnchor
); 
4798                                 //lineAnchor = lineStart; // Keep the same anchor for ButtonMove 
4801                         SetDragPosition(invalidPosition
); 
4802                         SetMouseCapture(true); 
4803                         selectionType 
= selLine
; 
4805                         if (PointIsHotspot(pt
)) { 
4806                                 NotifyHotSpotClicked(newPos
, shift
, ctrl
, alt
); 
4809                                 inDragDrop 
= PointInSelection(pt
); 
4812                                 SetMouseCapture(false); 
4813                                 SetDragPosition(newPos
); 
4814                                 CopySelectionRange(&drag
); 
4817                                 SetDragPosition(invalidPosition
); 
4818                                 SetMouseCapture(true); 
4820                                         SetEmptySelection(newPos
); 
4822                                 selType 
= alt 
? selRectangle 
: selStream
; 
4823                                 xStartSelect 
= xEndSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4824                                 selectionType 
= selChar
; 
4825                                 originalAnchorPos 
= currentPos
; 
4829         lastClickTime 
= curTime
; 
4831         ShowCaretAtCurrentPosition(); 
4834 bool Editor::PositionIsHotspot(int position
) { 
4835         return vs
.styles
[pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
].hotspot
; 
4838 bool Editor::PointIsHotspot(Point pt
) { 
4839         int pos 
= PositionFromLocationClose(pt
); 
4840         if (pos 
== INVALID_POSITION
) 
4842         return PositionIsHotspot(pos
); 
4845 void Editor::SetHotSpotRange(Point 
*pt
) { 
4847                 int pos 
= PositionFromLocation(*pt
); 
4849                 // If we don't limit this to word characters then the 
4850                 // range can encompass more than the run range and then 
4851                 // the underline will not be drawn properly. 
4852                 int hsStart_ 
= pdoc
->ExtendStyleRange(pos
, -1, vs
.hotspotSingleLine
); 
4853                 int hsEnd_ 
= pdoc
->ExtendStyleRange(pos
, 1, vs
.hotspotSingleLine
); 
4855                 // Only invalidate the range if the hotspot range has changed... 
4856                 if (hsStart_ 
!= hsStart 
|| hsEnd_ 
!= hsEnd
) { 
4857                         if (hsStart 
!= -1) { 
4858                                 InvalidateRange(hsStart
, hsEnd
); 
4862                         InvalidateRange(hsStart
, hsEnd
); 
4865                 if (hsStart 
!= -1) { 
4866                         int hsStart_ 
= hsStart
; 
4870                         InvalidateRange(hsStart_
, hsEnd_
); 
4878 void Editor::GetHotSpotRange(int& hsStart_
, int& hsEnd_
) { 
4883 void Editor::ButtonMove(Point pt
) { 
4884         if ((ptMouseLast
.x 
!= pt
.x
) || (ptMouseLast
.y 
!= pt
.y
)) { 
4888         //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); 
4889         if (HaveMouseCapture()) { 
4891                 // Slow down autoscrolling/selection 
4892                 autoScrollTimer
.ticksToWait 
-= timer
.tickSize
; 
4893                 if (autoScrollTimer
.ticksToWait 
> 0) 
4895                 autoScrollTimer
.ticksToWait 
= autoScrollDelay
; 
4898                 int movePos 
= PositionFromLocation(pt
); 
4899                 movePos 
= MovePositionOutsideChar(movePos
, currentPos 
- movePos
); 
4901                         SetDragPosition(movePos
); 
4903                         if (selectionType 
== selChar
) { 
4904                                 SetSelection(movePos
); 
4905                         } else if (selectionType 
== selWord
) { 
4906                                 // Continue selecting by word 
4907                                 if (movePos 
== originalAnchorPos
) {     // Didn't move 
4908                                         // No need to do anything. Previously this case was lumped 
4909                                         // in with "Moved forward", but that can be harmful in this 
4910                                         // case: a handler for the NotifyDoubleClick re-adjusts 
4911                                         // the selection for a fancier definition of "word" (for 
4912                                         // example, in Perl it is useful to include the leading 
4913                                         // '$', '%' or '@' on variables for word selection). In this 
4914                                         // the ButtonMove() called via Tick() for auto-scrolling 
4915                                         // could result in the fancier word selection adjustment 
4917                                 } else if (movePos 
> originalAnchorPos
) {       // Moved forward 
4918                                         SetSelection(pdoc
->ExtendWordSelect(movePos
, 1), 
4919                                                      pdoc
->ExtendWordSelect(originalAnchorPos
, -1)); 
4920                                 } else {        // Moved backward 
4921                                         SetSelection(pdoc
->ExtendWordSelect(movePos
, -1), 
4922                                                      pdoc
->ExtendWordSelect(originalAnchorPos
, 1)); 
4925                                 // Continue selecting by line 
4926                                 int lineMove 
= LineFromLocation(pt
); 
4927                                 LineSelection(lineMove
, lineAnchor
); 
4930                 // While dragging to make rectangular selection, we don't want the current 
4931                 // position to jump to the end of smaller or empty lines. 
4932                 xEndSelect 
= pt
.x 
- vs
.fixedColumnWidth 
+ xOffset
; 
4935                 PRectangle rcClient 
= GetClientRectangle(); 
4936                 if (pt
.y 
> rcClient
.bottom
) { 
4937                         int lineMove 
= cs
.DisplayFromDoc(LineFromLocation(pt
)); 
4939                                 lineMove 
= cs
.DisplayFromDoc(pdoc
->LinesTotal() - 1); 
4941                         ScrollTo(lineMove 
- LinesOnScreen() + 5); 
4943                 } else if (pt
.y 
< rcClient
.top
) { 
4944                         int lineMove 
= cs
.DisplayFromDoc(LineFromLocation(pt
)); 
4945                         ScrollTo(lineMove 
- 5); 
4948                 EnsureCaretVisible(false, false, true); 
4950                 if (hsStart 
!= -1 && !PositionIsHotspot(movePos
)) 
4951                         SetHotSpotRange(NULL
); 
4954                 if (vs
.fixedColumnWidth 
> 0) {  // There is a margin 
4955                         if (PointInSelMargin(pt
)) { 
4956                                 DisplayCursor(Window::cursorReverseArrow
); 
4957                                 return;         // No need to test for selection 
4960                 // Display regular (drag) cursor over selection 
4961                 if (PointInSelection(pt
)) { 
4962                         DisplayCursor(Window::cursorArrow
); 
4963                 } else if (PointIsHotspot(pt
)) { 
4964                         DisplayCursor(Window::cursorHand
); 
4965                         SetHotSpotRange(&pt
); 
4967                         DisplayCursor(Window::cursorText
); 
4968                         SetHotSpotRange(NULL
); 
4973 void Editor::ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
) { 
4974         //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture()); 
4975         if (HaveMouseCapture()) { 
4976                 if (PointInSelMargin(pt
)) { 
4977                         DisplayCursor(Window::cursorReverseArrow
); 
4979                         DisplayCursor(Window::cursorText
); 
4980                         SetHotSpotRange(NULL
); 
4983                 SetMouseCapture(false); 
4984                 int newPos 
= PositionFromLocation(pt
); 
4985                 newPos 
= MovePositionOutsideChar(newPos
, currentPos 
- newPos
); 
4987                         int selStart 
= SelectionStart(); 
4988                         int selEnd 
= SelectionEnd(); 
4989                         if (selStart 
< selEnd
) { 
4992                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
4993                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
4995                                         } else if (newPos 
< selStart
) { 
4996                                                 pdoc
->DeleteChars(selStart
, drag
.len
); 
4997                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
4998                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
5000                                         } else if (newPos 
> selEnd
) { 
5001                                                 pdoc
->DeleteChars(selStart
, drag
.len
); 
5003                                                 if (pdoc
->InsertString(newPos
, drag
.s
, drag
.len
)) { 
5004                                                         SetSelection(newPos
, newPos 
+ drag
.len
); 
5007                                                 SetEmptySelection(newPos
); 
5011                                 selectionType 
= selChar
; 
5014                         if (selectionType 
== selChar
) { 
5015                                 SetSelection(newPos
); 
5018                 // Now we rely on the current pos to compute rectangular selection 
5019                 xStartSelect 
= XFromPosition(anchor
); 
5020                 xEndSelect 
= XFromPosition(currentPos
); 
5021                 lastClickTime 
= curTime
; 
5024                 if (selType 
== selStream
) { 
5028                 EnsureCaretVisible(false); 
5032 // Called frequently to perform background UI including 
5033 // caret blinking and automatic scrolling. 
5034 void Editor::Tick() { 
5035         if (HaveMouseCapture()) { 
5037                 ButtonMove(ptMouseLast
); 
5039         if (caret
.period 
> 0) { 
5040                 timer
.ticksToWait 
-= timer
.tickSize
; 
5041                 if (timer
.ticksToWait 
<= 0) { 
5042                         caret
.on 
= !caret
.on
; 
5043                         timer
.ticksToWait 
= caret
.period
; 
5047         if ((dwellDelay 
< SC_TIME_FOREVER
) && 
5048                 (ticksToDwell 
> 0) && 
5049                 (!HaveMouseCapture())) { 
5050                 ticksToDwell 
-= timer
.tickSize
; 
5051                 if (ticksToDwell 
<= 0) { 
5053                         NotifyDwelling(ptMouseLast
, dwelling
); 
5058 bool Editor::Idle() { 
5062         bool wrappingDone 
= (wrapState 
== eWrapNone
) || (!backgroundWrapEnabled
); 
5064         if (!wrappingDone
) { 
5065                 // Wrap lines during idle. 
5066                 WrapLines(false, -1); 
5068                 if (docLineLastWrapped 
== docLastLineToWrap
) 
5069                         wrappingDone 
= true; 
5072         // Add more idle things to do here, but make sure idleDone is 
5073         // set correctly before the function returns. returning 
5074         // false will stop calling this idle funtion until SetIdle() is 
5077         idleDone 
= wrappingDone
; // && thatDone && theOtherThingDone... 
5082 void Editor::SetFocusState(bool focusState
) { 
5083         hasFocus 
= focusState
; 
5084         NotifyFocus(hasFocus
); 
5086                 ShowCaretAtCurrentPosition(); 
5093 static bool IsIn(int a
, int minimum
, int maximum
) { 
5094         return (a 
>= minimum
) && (a 
<= maximum
); 
5097 static bool IsOverlap(int mina
, int maxa
, int minb
, int maxb
) { 
5099             IsIn(mina
, minb
, maxb
) || 
5100             IsIn(maxa
, minb
, maxb
) || 
5101             IsIn(minb
, mina
, maxa
) || 
5102             IsIn(maxb
, mina
, maxa
); 
5105 void Editor::CheckForChangeOutsidePaint(Range r
) { 
5106         if (paintState 
== painting 
&& !paintingAllText
) { 
5107                 //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end); 
5111                 PRectangle rcText 
= GetTextRectangle(); 
5112                 // Determine number of lines displayed including a possible partially displayed last line 
5113                 int linesDisplayed 
= (rcText
.bottom 
- rcText
.top 
- 1) / vs
.lineHeight 
+ 1; 
5114                 int bottomLine 
= topLine 
+ linesDisplayed 
- 1; 
5116                 int lineRangeStart 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.start
)); 
5117                 int lineRangeEnd 
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.end
)); 
5118                 if (!IsOverlap(topLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) { 
5119                         //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n", 
5120                         //              lineRangeStart, lineRangeEnd, topLine, bottomLine); 
5124                 // Assert rcPaint contained within or equal to rcText 
5125                 if (rcPaint
.top 
> rcText
.top
) { 
5126                         // does range intersect rcText.top .. rcPaint.top 
5127                         int paintTopLine 
= ((rcPaint
.top 
- rcText
.top 
- 1) / vs
.lineHeight
) + topLine
; 
5128                         // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle 
5129                         if (IsOverlap(topLine
, paintTopLine
, lineRangeStart
, lineRangeEnd
)) { 
5130                                 //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n", 
5131                                 //      lineRangeStart, lineRangeEnd, topLine, paintTopLine); 
5136                 if (rcPaint
.bottom 
< rcText
.bottom
) { 
5137                         // does range intersect rcPaint.bottom .. rcText.bottom 
5138                         int paintBottomLine 
= ((rcPaint
.bottom 
- rcText
.top 
- 1) / vs
.lineHeight 
+ 1) + topLine
; 
5139                         // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle 
5140                         if (IsOverlap(paintBottomLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) { 
5141                                 //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n", 
5142                                 //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine); 
5150 char BraceOpposite(char ch
) { 
5173 // TODO: should be able to extend styled region to find matching brace 
5174 // TODO: may need to make DBCS safe 
5175 // so should be moved into Document 
5176 int Editor::BraceMatch(int position
, int /*maxReStyle*/) { 
5177         char chBrace 
= pdoc
->CharAt(position
); 
5178         char chSeek 
= BraceOpposite(chBrace
); 
5181         char styBrace 
= static_cast<char>( 
5182                             pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
); 
5184         if (chBrace 
== '(' || chBrace 
== '[' || chBrace 
== '{' || chBrace 
== '<') 
5187         position 
= position 
+ direction
; 
5188         while ((position 
>= 0) && (position 
< pdoc
->Length())) { 
5189                 char chAtPos 
= pdoc
->CharAt(position
); 
5190                 char styAtPos 
= static_cast<char>(pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
); 
5191                 if ((position 
> pdoc
->GetEndStyled()) || (styAtPos 
== styBrace
)) { 
5192                         if (chAtPos 
== chBrace
) 
5194                         if (chAtPos 
== chSeek
) 
5199                 position 
= position 
+ direction
; 
5204 void Editor::SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
) { 
5205         if ((pos0 
!= braces
[0]) || (pos1 
!= braces
[1]) || (matchStyle 
!= bracesMatchStyle
)) { 
5206                 if ((braces
[0] != pos0
) || (matchStyle 
!= bracesMatchStyle
)) { 
5207                         CheckForChangeOutsidePaint(Range(braces
[0])); 
5208                         CheckForChangeOutsidePaint(Range(pos0
)); 
5211                 if ((braces
[1] != pos1
) || (matchStyle 
!= bracesMatchStyle
)) { 
5212                         CheckForChangeOutsidePaint(Range(braces
[1])); 
5213                         CheckForChangeOutsidePaint(Range(pos1
)); 
5216                 bracesMatchStyle 
= matchStyle
; 
5217                 if (paintState 
== notPainting
) { 
5223 void Editor::SetDocPointer(Document 
*document
) { 
5224         //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document); 
5225         pdoc
->RemoveWatcher(this, 0); 
5227         if (document 
== NULL
) { 
5228                 pdoc 
= new Document(); 
5234         // Ensure all positions within document 
5235         selType 
= selStream
; 
5241         // Reset the contraction state to fully shown. 
5243         cs
.InsertLines(0, pdoc
->LinesTotal() - 1); 
5247         pdoc
->AddWatcher(this, 0); 
5253  * Recursively expand a fold, making lines visible except where they have an unexpanded parent. 
5255 void Editor::Expand(int &line
, bool doExpand
) { 
5256         int lineMaxSubord 
= pdoc
->GetLastChild(line
); 
5258         while (line 
<= lineMaxSubord
) { 
5260                         cs
.SetVisible(line
, line
, true); 
5261                 int level 
= pdoc
->GetLevel(line
); 
5262                 if (level 
& SC_FOLDLEVELHEADERFLAG
) { 
5263                         if (doExpand 
&& cs
.GetExpanded(line
)) { 
5266                                 Expand(line
, false); 
5274 void Editor::ToggleContraction(int line
) { 
5275         if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) { 
5276                 if (cs
.GetExpanded(line
)) { 
5277                         int lineMaxSubord 
= pdoc
->GetLastChild(line
); 
5278                         cs
.SetExpanded(line
, 0); 
5279                         if (lineMaxSubord 
> line
) { 
5280                                 cs
.SetVisible(line 
+ 1, lineMaxSubord
, false); 
5285                         cs
.SetExpanded(line
, 1); 
5294  * Recurse up from this line to find any folds that prevent this line from being visible 
5295  * and unfold them all. 
5297 void Editor::EnsureLineVisible(int lineDoc
, bool enforcePolicy
) { 
5299         // In case in need of wrapping to ensure DisplayFromDoc works. 
5300         WrapLines(true, -1); 
5302         if (!cs
.GetVisible(lineDoc
)) { 
5303                 int lineParent 
= pdoc
->GetFoldParent(lineDoc
); 
5304                 if (lineParent 
>= 0) { 
5305                         if (lineDoc 
!= lineParent
) 
5306                                 EnsureLineVisible(lineParent
, enforcePolicy
); 
5307                         if (!cs
.GetExpanded(lineParent
)) { 
5308                                 cs
.SetExpanded(lineParent
, 1); 
5309                                 Expand(lineParent
, true); 
5315         if (enforcePolicy
) { 
5316                 int lineDisplay 
= cs
.DisplayFromDoc(lineDoc
); 
5317                 if (visiblePolicy 
& VISIBLE_SLOP
) { 
5318                         if ((topLine 
> lineDisplay
) || ((visiblePolicy 
& VISIBLE_STRICT
) && (topLine 
+ visibleSlop 
> lineDisplay
))) { 
5319                                 SetTopLine(Platform::Clamp(lineDisplay 
- visibleSlop
, 0, MaxScrollPos())); 
5320                                 SetVerticalScrollPos(); 
5322                         } else if ((lineDisplay 
> topLine 
+ LinesOnScreen() - 1) || 
5323                                    ((visiblePolicy 
& VISIBLE_STRICT
) && (lineDisplay 
> topLine 
+ LinesOnScreen() - 1 - visibleSlop
))) { 
5324                                 SetTopLine(Platform::Clamp(lineDisplay 
- LinesOnScreen() + 1 + visibleSlop
, 0, MaxScrollPos())); 
5325                                 SetVerticalScrollPos(); 
5329                         if ((topLine 
> lineDisplay
) || (lineDisplay 
> topLine 
+ LinesOnScreen() - 1) || (visiblePolicy 
& VISIBLE_STRICT
)) { 
5330                                 SetTopLine(Platform::Clamp(lineDisplay 
- LinesOnScreen() / 2 + 1, 0, MaxScrollPos())); 
5331                                 SetVerticalScrollPos(); 
5338 int Editor::ReplaceTarget(bool replacePatterns
, const char *text
, int length
) { 
5339         pdoc
->BeginUndoAction(); 
5341                 length 
= istrlen(text
); 
5342         if (replacePatterns
) { 
5343                 text 
= pdoc
->SubstituteByPosition(text
, &length
); 
5347         if (targetStart 
!= targetEnd
) 
5348                 pdoc
->DeleteChars(targetStart
, targetEnd 
- targetStart
); 
5349         targetEnd 
= targetStart
; 
5350         pdoc
->InsertString(targetStart
, text
, length
); 
5351         targetEnd 
= targetStart 
+ length
; 
5352         pdoc
->EndUndoAction(); 
5356 bool Editor::IsUnicodeMode() const { 
5357         return pdoc 
&& (SC_CP_UTF8 
== pdoc
->dbcsCodePage
); 
5360 int Editor::CodePage() const { 
5362                 return pdoc
->dbcsCodePage
; 
5367 static bool ValidMargin(unsigned long wParam
) { 
5368         return wParam 
< ViewStyle::margins
; 
5371 static char *CharPtrFromSPtr(sptr_t lParam
) { 
5372         return reinterpret_cast<char *>(lParam
); 
5375 sptr_t 
Editor::WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) { 
5376         //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam); 
5378         // Optional macro recording hook 
5380                 NotifyMacroRecord(iMessage
, wParam
, lParam
); 
5389                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5390                         unsigned int iChar 
= 0; 
5391                         for (; iChar 
< wParam 
- 1; iChar
++) 
5392                                 ptr
[iChar
] = pdoc
->CharAt(iChar
); 
5400                         pdoc
->DeleteChars(0, pdoc
->Length()); 
5401                         SetEmptySelection(0); 
5402                         pdoc
->InsertString(0, CharPtrFromSPtr(lParam
)); 
5406         case SCI_GETTEXTLENGTH
: 
5407                 return pdoc
->Length(); 
5419                 CopyRangeToClipboard(wParam
, lParam
); 
5423                 CopyText(wParam
, CharPtrFromSPtr(lParam
)); 
5429                 EnsureCaretVisible(); 
5435                 EnsureCaretVisible(); 
5444                 return pdoc
->CanUndo() ? 1 : 0; 
5446         case SCI_EMPTYUNDOBUFFER
: 
5447                 pdoc
->DeleteUndoHistory(); 
5450         case SCI_GETFIRSTVISIBLELINE
: 
5453         case SCI_GETLINE
: {     // Risk of overwriting the end of the buffer 
5457                         int lineStart 
= pdoc
->LineStart(wParam
); 
5458                         int lineEnd 
= pdoc
->LineStart(wParam 
+ 1); 
5459                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5461                         for (int iChar 
= lineStart
; iChar 
< lineEnd
; iChar
++) { 
5462                                 ptr
[iPlace
++] = pdoc
->CharAt(iChar
); 
5467         case SCI_GETLINECOUNT
: 
5468                 if (pdoc
->LinesTotal() == 0) 
5471                         return pdoc
->LinesTotal(); 
5474                 return !pdoc
->IsSavePoint(); 
5477                         int nStart 
= static_cast<int>(wParam
); 
5478                         int nEnd 
= static_cast<int>(lParam
); 
5480                                 nEnd 
= pdoc
->Length(); 
5482                                 nStart 
= nEnd
;  // Remove selection 
5483                         selType 
= selStream
; 
5484                         SetSelection(nEnd
, nStart
); 
5485                         EnsureCaretVisible(); 
5489         case SCI_GETSELTEXT
: { 
5492                         SelectionText selectedText
; 
5493                         CopySelectionRange(&selectedText
); 
5494                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5496                         if (selectedText
.len
) { 
5497                                 for (; iChar 
< selectedText
.len
; iChar
++) 
5498                                         ptr
[iChar
] = selectedText
.s
[iChar
]; 
5505         case SCI_LINEFROMPOSITION
: 
5506                 if (static_cast<int>(wParam
) < 0) 
5508                 return pdoc
->LineFromPosition(wParam
); 
5510         case SCI_POSITIONFROMLINE
: 
5511                 if (static_cast<int>(wParam
) < 0) 
5512                         wParam 
= pdoc
->LineFromPosition(SelectionStart()); 
5514                         return 0;       // Even if there is no text, there is a first line that starts at 0 
5515                 if (static_cast<int>(wParam
) > pdoc
->LinesTotal()) 
5517                 //if (wParam > pdoc->LineFromPosition(pdoc->Length()))  // Useful test, anyway... 
5519                 return pdoc
->LineStart(wParam
); 
5521                 // Replacement of the old Scintilla interpretation of EM_LINELENGTH 
5522         case SCI_LINELENGTH
: 
5523                 if ((static_cast<int>(wParam
) < 0) || 
5524                         (static_cast<int>(wParam
) > pdoc
->LineFromPosition(pdoc
->Length()))) 
5526                 return pdoc
->LineStart(wParam 
+ 1) - pdoc
->LineStart(wParam
); 
5528         case SCI_REPLACESEL
: { 
5531                         pdoc
->BeginUndoAction(); 
5533                         char *replacement 
= CharPtrFromSPtr(lParam
); 
5534                         pdoc
->InsertString(currentPos
, replacement
); 
5535                         pdoc
->EndUndoAction(); 
5536                         SetEmptySelection(currentPos 
+ istrlen(replacement
)); 
5537                         EnsureCaretVisible(); 
5541         case SCI_SETTARGETSTART
: 
5542                 targetStart 
= wParam
; 
5545         case SCI_GETTARGETSTART
: 
5548         case SCI_SETTARGETEND
: 
5552         case SCI_GETTARGETEND
: 
5555         case SCI_TARGETFROMSELECTION
: 
5556                 if (currentPos 
< anchor
) { 
5557                         targetStart 
= currentPos
; 
5560                         targetStart 
= anchor
; 
5561                         targetEnd 
= currentPos
; 
5565         case SCI_REPLACETARGET
: 
5566                 PLATFORM_ASSERT(lParam
); 
5567                 return ReplaceTarget(false, CharPtrFromSPtr(lParam
), wParam
); 
5569         case SCI_REPLACETARGETRE
: 
5570                 PLATFORM_ASSERT(lParam
); 
5571                 return ReplaceTarget(true, CharPtrFromSPtr(lParam
), wParam
); 
5573         case SCI_SEARCHINTARGET
: 
5574                 PLATFORM_ASSERT(lParam
); 
5575                 return SearchInTarget(CharPtrFromSPtr(lParam
), wParam
); 
5577         case SCI_SETSEARCHFLAGS
: 
5578                 searchFlags 
= wParam
; 
5581         case SCI_GETSEARCHFLAGS
: 
5584         case SCI_POSITIONBEFORE
: 
5585                 return pdoc
->MovePositionOutsideChar(wParam
-1, -1, true); 
5587         case SCI_POSITIONAFTER
: 
5588                 return pdoc
->MovePositionOutsideChar(wParam
+1, 1, true); 
5590         case SCI_LINESCROLL
: 
5591                 ScrollTo(topLine 
+ lParam
); 
5592                 HorizontalScrollTo(xOffset 
+ wParam 
* vs
.spaceWidth
); 
5595         case SCI_SETXOFFSET
: 
5597                 SetHorizontalScrollPos(); 
5601         case SCI_GETXOFFSET
: 
5604         case SCI_CHOOSECARETX
: 
5608         case SCI_SCROLLCARET
: 
5609                 EnsureCaretVisible(); 
5612         case SCI_SETREADONLY
: 
5613                 pdoc
->SetReadOnly(wParam 
!= 0); 
5616         case SCI_GETREADONLY
: 
5617                 return pdoc
->IsReadOnly(); 
5622         case SCI_POINTXFROMPOSITION
: 
5626                         Point pt 
= LocationFromPosition(lParam
); 
5630         case SCI_POINTYFROMPOSITION
: 
5634                         Point pt 
= LocationFromPosition(lParam
); 
5639                 return FindText(wParam
, lParam
); 
5641         case SCI_GETTEXTRANGE
: { 
5644                         TextRange 
*tr 
= reinterpret_cast<TextRange 
*>(lParam
); 
5645                         int cpMax 
= tr
->chrg
.cpMax
; 
5647                                 cpMax 
= pdoc
->Length(); 
5648                         PLATFORM_ASSERT(cpMax 
<= pdoc
->Length()); 
5649                         int len 
= cpMax 
- tr
->chrg
.cpMin
;       // No -1 as cpMin and cpMax are referring to inter character positions 
5650                         pdoc
->GetCharRange(tr
->lpstrText
, tr
->chrg
.cpMin
, len
); 
5651                         // Spec says copied text is terminated with a NUL 
5652                         tr
->lpstrText
[len
] = '\0'; 
5653                         return len
;     // Not including NUL 
5656         case SCI_HIDESELECTION
: 
5657                 hideSelection 
= wParam 
!= 0; 
5661         case SCI_FORMATRANGE
: 
5662                 return FormatRange(wParam 
!= 0, reinterpret_cast<RangeToFormat 
*>(lParam
)); 
5664         case SCI_GETMARGINLEFT
: 
5665                 return vs
.leftMarginWidth
; 
5667         case SCI_GETMARGINRIGHT
: 
5668                 return vs
.rightMarginWidth
; 
5670         case SCI_SETMARGINLEFT
: 
5671                 vs
.leftMarginWidth 
= lParam
; 
5672                 InvalidateStyleRedraw(); 
5675         case SCI_SETMARGINRIGHT
: 
5676                 vs
.rightMarginWidth 
= lParam
; 
5677                 InvalidateStyleRedraw(); 
5680                 // Control specific mesages 
5685                         pdoc
->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam
), wParam
); 
5686                         SetEmptySelection(currentPos 
+ wParam
); 
5690         case SCI_ADDSTYLEDTEXT
: { 
5693                         pdoc
->InsertStyledString(CurrentPosition() * 2, CharPtrFromSPtr(lParam
), wParam
); 
5694                         SetEmptySelection(currentPos 
+ wParam 
/ 2); 
5698         case SCI_INSERTTEXT
: { 
5701                         int insertPos 
= wParam
; 
5702                         if (static_cast<int>(wParam
) == -1) 
5703                                 insertPos 
= CurrentPosition(); 
5704                         int newCurrent 
= CurrentPosition(); 
5705                         char *sz 
= CharPtrFromSPtr(lParam
); 
5706                         pdoc
->InsertString(insertPos
, sz
); 
5707                         if (newCurrent 
> insertPos
) 
5708                                 newCurrent 
+= istrlen(sz
); 
5709                         SetEmptySelection(newCurrent
); 
5713         case SCI_APPENDTEXT
: 
5714                 pdoc
->InsertString(pdoc
->Length(), CharPtrFromSPtr(lParam
), wParam
); 
5721         case SCI_CLEARDOCUMENTSTYLE
: 
5722                 ClearDocumentStyle(); 
5725         case SCI_SETUNDOCOLLECTION
: 
5726                 pdoc
->SetUndoCollection(wParam 
!= 0); 
5729         case SCI_GETUNDOCOLLECTION
: 
5730                 return pdoc
->IsCollectingUndo(); 
5732         case SCI_BEGINUNDOACTION
: 
5733                 pdoc
->BeginUndoAction(); 
5736         case SCI_ENDUNDOACTION
: 
5737                 pdoc
->EndUndoAction(); 
5740         case SCI_GETCARETPERIOD
: 
5741                 return caret
.period
; 
5743         case SCI_SETCARETPERIOD
: 
5744                 caret
.period 
= wParam
; 
5747         case SCI_SETWORDCHARS
: { 
5748                         pdoc
->SetDefaultCharClasses(); 
5751                         pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), Document::ccWord
); 
5755         case SCI_SETWHITESPACECHARS
: { 
5758                         pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), Document::ccSpace
); 
5762         case SCI_SETCHARSDEFAULT
: 
5763                 pdoc
->SetDefaultCharClasses(); 
5767                 return pdoc
->Length(); 
5770                 return pdoc
->CharAt(wParam
); 
5772         case SCI_SETCURRENTPOS
: 
5773                 SetSelection(wParam
, anchor
); 
5776         case SCI_GETCURRENTPOS
: 
5780                 SetSelection(currentPos
, wParam
); 
5786         case SCI_SETSELECTIONSTART
: 
5787                 SetSelection(Platform::Maximum(currentPos
, wParam
), wParam
); 
5790         case SCI_GETSELECTIONSTART
: 
5791                 return Platform::Minimum(anchor
, currentPos
); 
5793         case SCI_SETSELECTIONEND
: 
5794                 SetSelection(wParam
, Platform::Minimum(anchor
, wParam
)); 
5797         case SCI_GETSELECTIONEND
: 
5798                 return Platform::Maximum(anchor
, currentPos
); 
5800         case SCI_SETPRINTMAGNIFICATION
: 
5801                 printMagnification 
= wParam
; 
5804         case SCI_GETPRINTMAGNIFICATION
: 
5805                 return printMagnification
; 
5807         case SCI_SETPRINTCOLOURMODE
: 
5808                 printColourMode 
= wParam
; 
5811         case SCI_GETPRINTCOLOURMODE
: 
5812                 return printColourMode
; 
5814         case SCI_SETPRINTWRAPMODE
: 
5815                 printWrapState 
= (wParam 
== SC_WRAP_WORD
) ? eWrapWord 
: eWrapNone
; 
5818         case SCI_GETPRINTWRAPMODE
: 
5819                 return printWrapState
; 
5821         case SCI_GETSTYLEAT
: 
5822                 if (static_cast<int>(wParam
) >= pdoc
->Length()) 
5825                         return pdoc
->StyleAt(wParam
); 
5835         case SCI_SETSAVEPOINT
: 
5836                 pdoc
->SetSavePoint(); 
5839         case SCI_GETSTYLEDTEXT
: { 
5842                         TextRange 
*tr 
= reinterpret_cast<TextRange 
*>(lParam
); 
5844                         for (int iChar 
= tr
->chrg
.cpMin
; iChar 
< tr
->chrg
.cpMax
; iChar
++) { 
5845                                 tr
->lpstrText
[iPlace
++] = pdoc
->CharAt(iChar
); 
5846                                 tr
->lpstrText
[iPlace
++] = pdoc
->StyleAt(iChar
); 
5848                         tr
->lpstrText
[iPlace
] = '\0'; 
5849                         tr
->lpstrText
[iPlace 
+ 1] = '\0'; 
5854                 return pdoc
->CanRedo() ? 1 : 0; 
5856         case SCI_MARKERLINEFROMHANDLE
: 
5857                 return pdoc
->LineFromHandle(wParam
); 
5859         case SCI_MARKERDELETEHANDLE
: 
5860                 pdoc
->DeleteMarkFromHandle(wParam
); 
5864                 return vs
.viewWhitespace
; 
5867                 vs
.viewWhitespace 
= static_cast<WhiteSpaceVisibility
>(wParam
); 
5871         case SCI_POSITIONFROMPOINT
: 
5872                 return PositionFromLocation(Point(wParam
, lParam
)); 
5874         case SCI_POSITIONFROMPOINTCLOSE
: 
5875                 return PositionFromLocationClose(Point(wParam
, lParam
)); 
5882                 SetEmptySelection(wParam
); 
5883                 EnsureCaretVisible(); 
5887         case SCI_GETCURLINE
: { 
5891                         int lineCurrentPos 
= pdoc
->LineFromPosition(currentPos
); 
5892                         int lineStart 
= pdoc
->LineStart(lineCurrentPos
); 
5893                         unsigned int lineEnd 
= pdoc
->LineStart(lineCurrentPos 
+ 1); 
5894                         char *ptr 
= CharPtrFromSPtr(lParam
); 
5895                         unsigned int iPlace 
= 0; 
5896                         for (unsigned int iChar 
= lineStart
; iChar 
< lineEnd 
&& iPlace 
< wParam 
- 1; iChar
++) { 
5897                                 ptr
[iPlace
++] = pdoc
->CharAt(iChar
); 
5900                         return currentPos 
- lineStart
; 
5903         case SCI_GETENDSTYLED
: 
5904                 return pdoc
->GetEndStyled(); 
5906         case SCI_GETEOLMODE
: 
5907                 return pdoc
->eolMode
; 
5909         case SCI_SETEOLMODE
: 
5910                 pdoc
->eolMode 
= wParam
; 
5913         case SCI_STARTSTYLING
: 
5914                 pdoc
->StartStyling(wParam
, static_cast<char>(lParam
)); 
5917         case SCI_SETSTYLING
: 
5918                 pdoc
->SetStyleFor(wParam
, static_cast<char>(lParam
)); 
5921         case SCI_SETSTYLINGEX
:             // Specify a complete styling buffer 
5924                 pdoc
->SetStyles(wParam
, CharPtrFromSPtr(lParam
)); 
5927         case SCI_SETBUFFEREDDRAW
: 
5928                 bufferedDraw 
= wParam 
!= 0; 
5931         case SCI_GETBUFFEREDDRAW
: 
5932                 return bufferedDraw
; 
5934         case SCI_GETTWOPHASEDRAW
: 
5935                 return twoPhaseDraw
; 
5937         case SCI_SETTWOPHASEDRAW
: 
5938                 twoPhaseDraw 
= wParam 
!= 0; 
5939                 InvalidateStyleRedraw(); 
5942         case SCI_SETTABWIDTH
: 
5944                         pdoc
->tabInChars 
= wParam
; 
5945                 InvalidateStyleRedraw(); 
5948         case SCI_GETTABWIDTH
: 
5949                 return pdoc
->tabInChars
; 
5952                 pdoc
->indentInChars 
= wParam
; 
5953                 InvalidateStyleRedraw(); 
5957                 return pdoc
->indentInChars
; 
5959         case SCI_SETUSETABS
: 
5960                 pdoc
->useTabs 
= wParam 
!= 0; 
5961                 InvalidateStyleRedraw(); 
5964         case SCI_GETUSETABS
: 
5965                 return pdoc
->useTabs
; 
5967         case SCI_SETLINEINDENTATION
: 
5968                 pdoc
->SetLineIndentation(wParam
, lParam
); 
5971         case SCI_GETLINEINDENTATION
: 
5972                 return pdoc
->GetLineIndentation(wParam
); 
5974         case SCI_GETLINEINDENTPOSITION
: 
5975                 return pdoc
->GetLineIndentPosition(wParam
); 
5977         case SCI_SETTABINDENTS
: 
5978                 pdoc
->tabIndents 
= wParam 
!= 0; 
5981         case SCI_GETTABINDENTS
: 
5982                 return pdoc
->tabIndents
; 
5984         case SCI_SETBACKSPACEUNINDENTS
: 
5985                 pdoc
->backspaceUnindents 
= wParam 
!= 0; 
5988         case SCI_GETBACKSPACEUNINDENTS
: 
5989                 return pdoc
->backspaceUnindents
; 
5991         case SCI_SETMOUSEDWELLTIME
: 
5992                 dwellDelay 
= wParam
; 
5993                 ticksToDwell 
= dwellDelay
; 
5996         case SCI_GETMOUSEDWELLTIME
: 
5999         case SCI_WORDSTARTPOSITION
: 
6000                 return pdoc
->ExtendWordSelect(wParam
, -1, lParam 
!= 0); 
6002         case SCI_WORDENDPOSITION
: 
6003                 return pdoc
->ExtendWordSelect(wParam
, 1, lParam 
!= 0); 
6005         case SCI_SETWRAPMODE
: 
6006                 wrapState 
= (wParam 
== SC_WRAP_WORD
) ? eWrapWord 
: eWrapNone
; 
6008                 InvalidateStyleRedraw(); 
6009                 ReconfigureScrollBars(); 
6012         case SCI_GETWRAPMODE
: 
6015         case SCI_SETLAYOUTCACHE
: 
6016                 llc
.SetLevel(wParam
); 
6019         case SCI_GETLAYOUTCACHE
: 
6020                 return llc
.GetLevel(); 
6022         case SCI_SETSCROLLWIDTH
: 
6023                 PLATFORM_ASSERT(wParam 
> 0); 
6024                 if ((wParam 
> 0) && (wParam 
!= static_cast<unsigned int >(scrollWidth
))) { 
6025                         scrollWidth 
= wParam
; 
6030         case SCI_GETSCROLLWIDTH
: 
6037         case SCI_LINESSPLIT
: 
6042                 PLATFORM_ASSERT(wParam 
<= STYLE_MAX
); 
6043                 PLATFORM_ASSERT(lParam
); 
6044                 return TextWidth(wParam
, CharPtrFromSPtr(lParam
)); 
6046         case SCI_TEXTHEIGHT
: 
6047                 return vs
.lineHeight
; 
6049         case SCI_SETENDATLASTLINE
: 
6050                 PLATFORM_ASSERT((wParam 
== 0) || (wParam 
== 1)); 
6051                 if (endAtLastLine 
!= (wParam 
!= 0)) { 
6052                         endAtLastLine 
= wParam 
!= 0; 
6057         case SCI_GETENDATLASTLINE
: 
6058                 return endAtLastLine
; 
6061                 return pdoc
->GetColumn(wParam
); 
6063         case SCI_SETHSCROLLBAR 
: 
6064                 if (horizontalScrollBarVisible 
!= (wParam 
!= 0)) { 
6065                         horizontalScrollBarVisible 
= wParam 
!= 0; 
6067                         ReconfigureScrollBars(); 
6071         case SCI_GETHSCROLLBAR
: 
6072                 return horizontalScrollBarVisible
; 
6074         case SCI_SETVSCROLLBAR
: 
6075                 if (verticalScrollBarVisible 
!= (wParam 
!= 0)) { 
6076                         verticalScrollBarVisible 
= wParam 
!= 0; 
6078                         ReconfigureScrollBars(); 
6082         case SCI_GETVSCROLLBAR
: 
6083                 return verticalScrollBarVisible
; 
6085         case SCI_SETINDENTATIONGUIDES
: 
6086                 vs
.viewIndentationGuides 
= wParam 
!= 0; 
6090         case SCI_GETINDENTATIONGUIDES
: 
6091                 return vs
.viewIndentationGuides
; 
6093         case SCI_SETHIGHLIGHTGUIDE
: 
6094                 if ((highlightGuideColumn 
!= static_cast<int>(wParam
)) || (wParam 
> 0)) { 
6095                         highlightGuideColumn 
= wParam
; 
6100         case SCI_GETHIGHLIGHTGUIDE
: 
6101                 return highlightGuideColumn
; 
6103         case SCI_GETLINEENDPOSITION
: 
6104                 return pdoc
->LineEnd(wParam
); 
6106         case SCI_SETCODEPAGE
: 
6107                 pdoc
->dbcsCodePage 
= wParam
; 
6108                 InvalidateStyleRedraw(); 
6111         case SCI_GETCODEPAGE
: 
6112                 return pdoc
->dbcsCodePage
; 
6114         case SCI_SETUSEPALETTE
: 
6115                 palette
.allowRealization 
= wParam 
!= 0; 
6116                 InvalidateStyleRedraw(); 
6119         case SCI_GETUSEPALETTE
: 
6120                 return palette
.allowRealization
; 
6122                 // Marker definition and setting 
6123         case SCI_MARKERDEFINE
: 
6124                 if (wParam 
<= MARKER_MAX
) 
6125                         vs
.markers
[wParam
].markType 
= lParam
; 
6126                 InvalidateStyleData(); 
6129         case SCI_MARKERSETFORE
: 
6130                 if (wParam 
<= MARKER_MAX
) 
6131                         vs
.markers
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6132                 InvalidateStyleData(); 
6135         case SCI_MARKERSETBACK
: 
6136                 if (wParam 
<= MARKER_MAX
) 
6137                         vs
.markers
[wParam
].back
.desired 
= ColourDesired(lParam
); 
6138                 InvalidateStyleData(); 
6141         case SCI_MARKERADD
: { 
6142                         int markerID 
= pdoc
->AddMark(wParam
, lParam
); 
6146         case SCI_MARKERDELETE
: 
6147                 pdoc
->DeleteMark(wParam
, lParam
); 
6150         case SCI_MARKERDELETEALL
: 
6151                 pdoc
->DeleteAllMarks(static_cast<int>(wParam
)); 
6155                 return pdoc
->GetMark(wParam
); 
6157         case SCI_MARKERNEXT
: { 
6158                         int lt 
= pdoc
->LinesTotal(); 
6159                         for (int iLine 
= wParam
; iLine 
< lt
; iLine
++) { 
6160                                 if ((pdoc
->GetMark(iLine
) & lParam
) != 0) 
6166         case SCI_MARKERPREVIOUS
: { 
6167                         for (int iLine 
= wParam
; iLine 
>= 0; iLine
--) { 
6168                                 if ((pdoc
->GetMark(iLine
) & lParam
) != 0) 
6174         case SCI_MARKERDEFINEPIXMAP
: 
6175                 if (wParam 
<= MARKER_MAX
) { 
6176                         vs
.markers
[wParam
].SetXPM(CharPtrFromSPtr(lParam
)); 
6178                 InvalidateStyleData(); 
6182         case SCI_SETMARGINTYPEN
: 
6183                 if (ValidMargin(wParam
)) { 
6184                         vs
.ms
[wParam
].symbol 
= (lParam 
== SC_MARGIN_SYMBOL
); 
6185                         InvalidateStyleRedraw(); 
6189         case SCI_GETMARGINTYPEN
: 
6190                 if (ValidMargin(wParam
)) 
6191                         return vs
.ms
[wParam
].symbol 
? SC_MARGIN_SYMBOL 
: SC_MARGIN_NUMBER
; 
6195         case SCI_SETMARGINWIDTHN
: 
6196                 if (ValidMargin(wParam
)) { 
6197                         // Short-circuit if the width is unchanged, to avoid unnecessary redraw. 
6198                         if (vs
.ms
[wParam
].width 
!= lParam
) { 
6199                                 vs
.ms
[wParam
].width 
= lParam
; 
6200                                 InvalidateStyleRedraw(); 
6205         case SCI_GETMARGINWIDTHN
: 
6206                 if (ValidMargin(wParam
)) 
6207                         return vs
.ms
[wParam
].width
; 
6211         case SCI_SETMARGINMASKN
: 
6212                 if (ValidMargin(wParam
)) { 
6213                         vs
.ms
[wParam
].mask 
= lParam
; 
6214                         InvalidateStyleRedraw(); 
6218         case SCI_GETMARGINMASKN
: 
6219                 if (ValidMargin(wParam
)) 
6220                         return vs
.ms
[wParam
].mask
; 
6224         case SCI_SETMARGINSENSITIVEN
: 
6225                 if (ValidMargin(wParam
)) { 
6226                         vs
.ms
[wParam
].sensitive 
= lParam 
!= 0; 
6227                         InvalidateStyleRedraw(); 
6231         case SCI_GETMARGINSENSITIVEN
: 
6232                 if (ValidMargin(wParam
)) 
6233                         return vs
.ms
[wParam
].sensitive 
? 1 : 0; 
6237         case SCI_STYLECLEARALL
: 
6239                 InvalidateStyleRedraw(); 
6242         case SCI_STYLESETFORE
: 
6243                 if (wParam 
<= STYLE_MAX
) { 
6244                         vs
.styles
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6245                         InvalidateStyleRedraw(); 
6248         case SCI_STYLESETBACK
: 
6249                 if (wParam 
<= STYLE_MAX
) { 
6250                         vs
.styles
[wParam
].back
.desired 
= ColourDesired(lParam
); 
6251                         InvalidateStyleRedraw(); 
6254         case SCI_STYLESETBOLD
: 
6255                 if (wParam 
<= STYLE_MAX
) { 
6256                         vs
.styles
[wParam
].bold 
= lParam 
!= 0; 
6257                         InvalidateStyleRedraw(); 
6260         case SCI_STYLESETITALIC
: 
6261                 if (wParam 
<= STYLE_MAX
) { 
6262                         vs
.styles
[wParam
].italic 
= lParam 
!= 0; 
6263                         InvalidateStyleRedraw(); 
6266         case SCI_STYLESETEOLFILLED
: 
6267                 if (wParam 
<= STYLE_MAX
) { 
6268                         vs
.styles
[wParam
].eolFilled 
= lParam 
!= 0; 
6269                         InvalidateStyleRedraw(); 
6272         case SCI_STYLESETSIZE
: 
6273                 if (wParam 
<= STYLE_MAX
) { 
6274                         vs
.styles
[wParam
].size 
= lParam
; 
6275                         InvalidateStyleRedraw(); 
6278         case SCI_STYLESETFONT
: 
6281                 if (wParam 
<= STYLE_MAX
) { 
6282                         vs
.SetStyleFontName(wParam
, CharPtrFromSPtr(lParam
)); 
6283                         InvalidateStyleRedraw(); 
6286         case SCI_STYLESETUNDERLINE
: 
6287                 if (wParam 
<= STYLE_MAX
) { 
6288                         vs
.styles
[wParam
].underline 
= lParam 
!= 0; 
6289                         InvalidateStyleRedraw(); 
6292         case SCI_STYLESETCASE
: 
6293                 if (wParam 
<= STYLE_MAX
) { 
6294                         vs
.styles
[wParam
].caseForce 
= static_cast<Style::ecaseForced
>(lParam
); 
6295                         InvalidateStyleRedraw(); 
6298         case SCI_STYLESETCHARACTERSET
: 
6299                 if (wParam 
<= STYLE_MAX
) { 
6300                         vs
.styles
[wParam
].characterSet 
= lParam
; 
6301                         InvalidateStyleRedraw(); 
6304         case SCI_STYLESETVISIBLE
: 
6305                 if (wParam 
<= STYLE_MAX
) { 
6306                         vs
.styles
[wParam
].visible 
= lParam 
!= 0; 
6307                         InvalidateStyleRedraw(); 
6310         case SCI_STYLESETCHANGEABLE
: 
6311                 if (wParam 
<= STYLE_MAX
) { 
6312                         vs
.styles
[wParam
].changeable 
= lParam 
!= 0; 
6313                         InvalidateStyleRedraw(); 
6316         case SCI_STYLESETHOTSPOT
: 
6317                 if (wParam 
<= STYLE_MAX
) { 
6318                         vs
.styles
[wParam
].hotspot 
= lParam 
!= 0; 
6319                         InvalidateStyleRedraw(); 
6323         case SCI_STYLERESETDEFAULT
: 
6324                 vs
.ResetDefaultStyle(); 
6325                 InvalidateStyleRedraw(); 
6327         case SCI_SETSTYLEBITS
: 
6328                 pdoc
->SetStylingBits(wParam
); 
6331         case SCI_GETSTYLEBITS
: 
6332                 return pdoc
->stylingBits
; 
6334         case SCI_SETLINESTATE
: 
6335                 return pdoc
->SetLineState(wParam
, lParam
); 
6337         case SCI_GETLINESTATE
: 
6338                 return pdoc
->GetLineState(wParam
); 
6340         case SCI_GETMAXLINESTATE
: 
6341                 return pdoc
->GetMaxLineState(); 
6343         case SCI_GETCARETLINEVISIBLE
: 
6344                 return vs
.showCaretLineBackground
; 
6345         case SCI_SETCARETLINEVISIBLE
: 
6346                 vs
.showCaretLineBackground 
= wParam 
!= 0; 
6347                 InvalidateStyleRedraw(); 
6349         case SCI_GETCARETLINEBACK
: 
6350                 return vs
.caretLineBackground
.desired
.AsLong(); 
6351         case SCI_SETCARETLINEBACK
: 
6352                 vs
.caretLineBackground
.desired 
= wParam
; 
6353                 InvalidateStyleRedraw(); 
6358         case SCI_VISIBLEFROMDOCLINE
: 
6359                 return cs
.DisplayFromDoc(wParam
); 
6361         case SCI_DOCLINEFROMVISIBLE
: 
6362                 return cs
.DocFromDisplay(wParam
); 
6364         case SCI_SETFOLDLEVEL
: { 
6365                         int prev 
= pdoc
->SetLevel(wParam
, lParam
); 
6371         case SCI_GETFOLDLEVEL
: 
6372                 return pdoc
->GetLevel(wParam
); 
6374         case SCI_GETLASTCHILD
: 
6375                 return pdoc
->GetLastChild(wParam
, lParam
); 
6377         case SCI_GETFOLDPARENT
: 
6378                 return pdoc
->GetFoldParent(wParam
); 
6381                 cs
.SetVisible(wParam
, lParam
, true); 
6387                 cs
.SetVisible(wParam
, lParam
, false); 
6392         case SCI_GETLINEVISIBLE
: 
6393                 return cs
.GetVisible(wParam
); 
6395         case SCI_SETFOLDEXPANDED
: 
6396                 if (cs
.SetExpanded(wParam
, lParam 
!= 0)) { 
6401         case SCI_GETFOLDEXPANDED
: 
6402                 return cs
.GetExpanded(wParam
); 
6404         case SCI_SETFOLDFLAGS
: 
6409         case SCI_TOGGLEFOLD
: 
6410                 ToggleContraction(wParam
); 
6413         case SCI_ENSUREVISIBLE
: 
6414                 EnsureLineVisible(wParam
, false); 
6417         case SCI_ENSUREVISIBLEENFORCEPOLICY
: 
6418                 EnsureLineVisible(wParam
, true); 
6421         case SCI_SEARCHANCHOR
: 
6425         case SCI_SEARCHNEXT
: 
6426         case SCI_SEARCHPREV
: 
6427                 return SearchText(iMessage
, wParam
, lParam
); 
6429 #ifdef INCLUDE_DEPRECATED_FEATURES 
6430         case SCI_SETCARETPOLICY
:        // Deprecated 
6431                 caretXPolicy 
= caretYPolicy 
= wParam
; 
6432                 caretXSlop 
= caretYSlop 
= lParam
; 
6436         case SCI_SETXCARETPOLICY
: 
6437                 caretXPolicy 
= wParam
; 
6438                 caretXSlop 
= lParam
; 
6441         case SCI_SETYCARETPOLICY
: 
6442                 caretYPolicy 
= wParam
; 
6443                 caretYSlop 
= lParam
; 
6446         case SCI_SETVISIBLEPOLICY
: 
6447                 visiblePolicy 
= wParam
; 
6448                 visibleSlop 
= lParam
; 
6451         case SCI_LINESONSCREEN
: 
6452                 return LinesOnScreen(); 
6454         case SCI_SETSELFORE
: 
6455                 vs
.selforeset 
= wParam 
!= 0; 
6456                 vs
.selforeground
.desired 
= ColourDesired(lParam
); 
6457                 InvalidateStyleRedraw(); 
6460         case SCI_SETSELBACK
: 
6461                 vs
.selbackset 
= wParam 
!= 0; 
6462                 vs
.selbackground
.desired 
= ColourDesired(lParam
); 
6463                 InvalidateStyleRedraw(); 
6466         case SCI_SETWHITESPACEFORE
: 
6467                 vs
.whitespaceForegroundSet 
= wParam 
!= 0; 
6468                 vs
.whitespaceForeground
.desired 
= ColourDesired(lParam
); 
6469                 InvalidateStyleRedraw(); 
6472         case SCI_SETWHITESPACEBACK
: 
6473                 vs
.whitespaceBackgroundSet 
= wParam 
!= 0; 
6474                 vs
.whitespaceBackground
.desired 
= ColourDesired(lParam
); 
6475                 InvalidateStyleRedraw(); 
6478         case SCI_SETCARETFORE
: 
6479                 vs
.caretcolour
.desired 
= ColourDesired(wParam
); 
6480                 InvalidateStyleRedraw(); 
6483         case SCI_GETCARETFORE
: 
6484                 return vs
.caretcolour
.desired
.AsLong(); 
6486         case SCI_SETCARETWIDTH
: 
6489                 else if (wParam 
>= 3) 
6492                         vs
.caretWidth 
= wParam
; 
6493                 InvalidateStyleRedraw(); 
6496         case SCI_GETCARETWIDTH
: 
6497                 return vs
.caretWidth
; 
6499         case SCI_ASSIGNCMDKEY
: 
6500                 kmap
.AssignCmdKey(Platform::LowShortFromLong(wParam
), 
6501                                   Platform::HighShortFromLong(wParam
), lParam
); 
6504         case SCI_CLEARCMDKEY
: 
6505                 kmap
.AssignCmdKey(Platform::LowShortFromLong(wParam
), 
6506                                   Platform::HighShortFromLong(wParam
), SCI_NULL
); 
6509         case SCI_CLEARALLCMDKEYS
: 
6513         case SCI_INDICSETSTYLE
: 
6514                 if (wParam 
<= INDIC_MAX
) { 
6515                         vs
.indicators
[wParam
].style 
= lParam
; 
6516                         InvalidateStyleRedraw(); 
6520         case SCI_INDICGETSTYLE
: 
6521                 return (wParam 
<= INDIC_MAX
) ? vs
.indicators
[wParam
].style 
: 0; 
6523         case SCI_INDICSETFORE
: 
6524                 if (wParam 
<= INDIC_MAX
) { 
6525                         vs
.indicators
[wParam
].fore
.desired 
= ColourDesired(lParam
); 
6526                         InvalidateStyleRedraw(); 
6530         case SCI_INDICGETFORE
: 
6531                 return (wParam 
<= INDIC_MAX
) ? vs
.indicators
[wParam
].fore
.desired
.AsLong() : 0; 
6534         case SCI_LINEDOWNEXTEND
: 
6536         case SCI_PARADOWNEXTEND
: 
6538         case SCI_LINEUPEXTEND
: 
6540         case SCI_PARAUPEXTEND
: 
6542         case SCI_CHARLEFTEXTEND
: 
6544         case SCI_CHARRIGHTEXTEND
: 
6546         case SCI_WORDLEFTEXTEND
: 
6548         case SCI_WORDRIGHTEXTEND
: 
6549         case SCI_WORDLEFTEND
: 
6550         case SCI_WORDLEFTENDEXTEND
: 
6551         case SCI_WORDRIGHTEND
: 
6552         case SCI_WORDRIGHTENDEXTEND
: 
6554         case SCI_HOMEEXTEND
: 
6556         case SCI_LINEENDEXTEND
: 
6558         case SCI_HOMEWRAPEXTEND
: 
6559         case SCI_LINEENDWRAP
: 
6560         case SCI_LINEENDWRAPEXTEND
: 
6561         case SCI_DOCUMENTSTART
: 
6562         case SCI_DOCUMENTSTARTEXTEND
: 
6563         case SCI_DOCUMENTEND
: 
6564         case SCI_DOCUMENTENDEXTEND
: 
6566         case SCI_STUTTEREDPAGEUP
: 
6567         case SCI_STUTTEREDPAGEUPEXTEND
: 
6568         case SCI_STUTTEREDPAGEDOWN
: 
6569         case SCI_STUTTEREDPAGEDOWNEXTEND
: 
6572         case SCI_PAGEUPEXTEND
: 
6574         case SCI_PAGEDOWNEXTEND
: 
6575         case SCI_EDITTOGGLEOVERTYPE
: 
6577         case SCI_DELETEBACK
: 
6583         case SCI_VCHOMEEXTEND
: 
6584         case SCI_VCHOMEWRAP
: 
6585         case SCI_VCHOMEWRAPEXTEND
: 
6588         case SCI_DELWORDLEFT
: 
6589         case SCI_DELWORDRIGHT
: 
6590         case SCI_DELLINELEFT
: 
6591         case SCI_DELLINERIGHT
: 
6594         case SCI_LINEDELETE
: 
6595         case SCI_LINETRANSPOSE
: 
6596         case SCI_LINEDUPLICATE
: 
6599         case SCI_LINESCROLLDOWN
: 
6600         case SCI_LINESCROLLUP
: 
6601         case SCI_WORDPARTLEFT
: 
6602         case SCI_WORDPARTLEFTEXTEND
: 
6603         case SCI_WORDPARTRIGHT
: 
6604         case SCI_WORDPARTRIGHTEXTEND
: 
6605         case SCI_DELETEBACKNOTLINE
: 
6606         case SCI_HOMEDISPLAY
: 
6607         case SCI_HOMEDISPLAYEXTEND
: 
6608         case SCI_LINEENDDISPLAY
: 
6609         case SCI_LINEENDDISPLAYEXTEND
: 
6610         case SCI_LINEDOWNRECTEXTEND
: 
6611         case SCI_LINEUPRECTEXTEND
: 
6612         case SCI_CHARLEFTRECTEXTEND
: 
6613         case SCI_CHARRIGHTRECTEXTEND
: 
6614         case SCI_HOMERECTEXTEND
: 
6615         case SCI_VCHOMERECTEXTEND
: 
6616         case SCI_LINEENDRECTEXTEND
: 
6617         case SCI_PAGEUPRECTEXTEND
: 
6618         case SCI_PAGEDOWNRECTEXTEND
: 
6619                 return KeyCommand(iMessage
); 
6621         case SCI_BRACEHIGHLIGHT
: 
6622                 SetBraceHighlight(static_cast<int>(wParam
), lParam
, STYLE_BRACELIGHT
); 
6625         case SCI_BRACEBADLIGHT
: 
6626                 SetBraceHighlight(static_cast<int>(wParam
), -1, STYLE_BRACEBAD
); 
6629         case SCI_BRACEMATCH
: 
6630                 // wParam is position of char to find brace for, 
6631                 // lParam is maximum amount of text to restyle to find it 
6632                 return BraceMatch(wParam
, lParam
); 
6634         case SCI_GETVIEWEOL
: 
6637         case SCI_SETVIEWEOL
: 
6638                 vs
.viewEOL 
= wParam 
!= 0; 
6639                 InvalidateStyleRedraw(); 
6643                 vs
.zoomLevel 
= wParam
; 
6644                 InvalidateStyleRedraw(); 
6649                 return vs
.zoomLevel
; 
6651         case SCI_GETEDGECOLUMN
: 
6654         case SCI_SETEDGECOLUMN
: 
6656                 InvalidateStyleRedraw(); 
6659         case SCI_GETEDGEMODE
: 
6660                 return vs
.edgeState
; 
6662         case SCI_SETEDGEMODE
: 
6663                 vs
.edgeState 
= wParam
; 
6664                 InvalidateStyleRedraw(); 
6667         case SCI_GETEDGECOLOUR
: 
6668                 return vs
.edgecolour
.desired
.AsLong(); 
6670         case SCI_SETEDGECOLOUR
: 
6671                 vs
.edgecolour
.desired 
= ColourDesired(wParam
); 
6672                 InvalidateStyleRedraw(); 
6675         case SCI_GETDOCPOINTER
: 
6676                 return reinterpret_cast<sptr_t
>(pdoc
); 
6678         case SCI_SETDOCPOINTER
: 
6680                 SetDocPointer(reinterpret_cast<Document 
*>(lParam
)); 
6683         case SCI_CREATEDOCUMENT
: { 
6684                         Document 
*doc 
= new Document(); 
6688                         return reinterpret_cast<sptr_t
>(doc
); 
6691         case SCI_ADDREFDOCUMENT
: 
6692                 (reinterpret_cast<Document 
*>(lParam
))->AddRef(); 
6695         case SCI_RELEASEDOCUMENT
: 
6696                 (reinterpret_cast<Document 
*>(lParam
))->Release(); 
6699         case SCI_SETMODEVENTMASK
: 
6700                 modEventMask 
= wParam
; 
6703         case SCI_GETMODEVENTMASK
: 
6704                 return modEventMask
; 
6706         case SCI_CONVERTEOLS
: 
6707                 pdoc
->ConvertLineEnds(wParam
); 
6708                 SetSelection(currentPos
, anchor
);       // Ensure selection inside document 
6711         case SCI_SELECTIONISRECTANGLE
: 
6712                 return selType 
== selRectangle 
? 1 : 0; 
6714         case SCI_SETSELECTIONMODE
: { 
6717                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selStream
); 
6718                                 selType 
= selStream
; 
6720                         case SC_SEL_RECTANGLE
: 
6721                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selRectangle
); 
6722                                 selType 
= selRectangle
; 
6725                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selLines
); 
6729                                 moveExtendsSelection 
= !moveExtendsSelection 
|| (selType 
!= selStream
); 
6730                                 selType 
= selStream
; 
6732                         InvalidateSelection(currentPos
, anchor
); 
6734         case SCI_GETSELECTIONMODE
: 
6737                         return SC_SEL_STREAM
; 
6739                         return SC_SEL_RECTANGLE
; 
6741                         return SC_SEL_LINES
; 
6743                         return SC_SEL_STREAM
; 
6745         case SCI_GETLINESELSTARTPOSITION
: { 
6746                         SelectionLineIterator 
lineIterator(this); 
6747                         lineIterator
.SetAt(wParam
); 
6748                         return lineIterator
.startPos
; 
6750         case SCI_GETLINESELENDPOSITION
: { 
6751                         SelectionLineIterator 
lineIterator(this); 
6752                         lineIterator
.SetAt(wParam
); 
6753                         return lineIterator
.endPos
; 
6756         case SCI_SETOVERTYPE
: 
6757                 inOverstrike 
= wParam 
!= 0; 
6760         case SCI_GETOVERTYPE
: 
6761                 return inOverstrike 
? 1 : 0; 
6764                 SetFocusState(wParam 
!= 0); 
6771                 errorStatus 
= wParam
; 
6777         case SCI_SETMOUSEDOWNCAPTURES
: 
6778                 mouseDownCaptures 
= wParam 
!= 0; 
6781         case SCI_GETMOUSEDOWNCAPTURES
: 
6782                 return mouseDownCaptures
; 
6785                 cursorMode 
= wParam
; 
6786                 DisplayCursor(Window::cursorText
); 
6792         case SCI_SETCONTROLCHARSYMBOL
: 
6793                 controlCharSymbol 
= wParam
; 
6796         case SCI_GETCONTROLCHARSYMBOL
: 
6797                 return controlCharSymbol
; 
6799         case SCI_STARTRECORD
: 
6800                 recordingMacro 
= true; 
6803         case SCI_STOPRECORD
: 
6804                 recordingMacro 
= false; 
6807         case SCI_MOVECARETINSIDEVIEW
: 
6808                 MoveCaretInsideView(); 
6811         case SCI_SETFOLDMARGINCOLOUR
: 
6812                 vs
.foldmarginColourSet 
= wParam 
!= 0; 
6813                 vs
.foldmarginColour
.desired 
= ColourDesired(lParam
); 
6814                 InvalidateStyleRedraw(); 
6817         case SCI_SETFOLDMARGINHICOLOUR
: 
6818                 vs
.foldmarginHighlightColourSet 
= wParam 
!= 0; 
6819                 vs
.foldmarginHighlightColour
.desired 
= ColourDesired(lParam
); 
6820                 InvalidateStyleRedraw(); 
6823         case SCI_SETHOTSPOTACTIVEFORE
: 
6824                 vs
.hotspotForegroundSet 
= wParam 
!= 0; 
6825                 vs
.hotspotForeground
.desired 
= ColourDesired(lParam
); 
6826                 InvalidateStyleRedraw(); 
6829         case SCI_SETHOTSPOTACTIVEBACK
: 
6830                 vs
.hotspotBackgroundSet 
= wParam 
!= 0; 
6831                 vs
.hotspotBackground
.desired 
= ColourDesired(lParam
); 
6832                 InvalidateStyleRedraw(); 
6835         case SCI_SETHOTSPOTACTIVEUNDERLINE
: 
6836                 vs
.hotspotUnderline 
= wParam 
!= 0; 
6837                 InvalidateStyleRedraw(); 
6840         case SCI_SETHOTSPOTSINGLELINE
: 
6841                 vs
.hotspotSingleLine 
= wParam 
!= 0; 
6842                 InvalidateStyleRedraw(); 
6846                 return DefWndProc(iMessage
, wParam
, lParam
); 
6848         //Platform::DebugPrintf("end wnd proc\n");