1 // Scintilla source code edit control
2 // Editor.cxx - main code for the edit control
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
13 #include "Scintilla.h"
14 #include "ContractionState.h"
16 #include "CellBuffer.h"
18 #include "Indicator.h"
19 #include "LineMarker.h"
21 #include "ViewStyle.h"
26 active(true), on(true), period(500) {}
29 ticking(false), ticksToWait(0), tickerID(0) {}
36 hideSelection
= false;
46 dropWentOutside
= false;
47 posDrag
= invalidPosition
;
48 posDrop
= invalidPosition
;
49 selectionType
= selChar
;
53 originalAnchorPos
= 0;
57 dragIsRectangle
= false;
62 caretPolicy
= CARET_SLOP
;
67 ucWheelScrollLines
= 0;
68 cWheelDelta
= 0; //wheel delta from roll
80 braces
[0]=invalidPosition
;
81 braces
[1]=invalidPosition
;
82 bracesMatchStyle
= STYLE_BRACEBAD
;
84 edgeState
= EDGE_NONE
;
87 paintState
= notPainting
;
89 modEventMask
= SC_MODEVENTMASKALL
;
91 displayPopupMenu
= true;
93 pdoc
= new Document();
95 pdoc
->AddWatcher(this, 0);
104 pdoc
->RemoveWatcher(this, 0);
114 void Editor::Finalise() {
117 void Editor::DropGraphics() {
118 pixmapLine
.Release();
119 pixmapSelMargin
.Release();
120 pixmapSelPattern
.Release();
123 void Editor::InvalidateStyleData() {
129 void Editor::InvalidateStyleRedraw() {
130 InvalidateStyleData();
134 void Editor::RefreshColourPalette(Palette
&pal
, bool want
) {
135 vs
.RefreshColourPalette(pal
, want
);
138 void Editor::RefreshStyleData() {
144 RefreshColourPalette(palette
, true);
145 palette
.Allocate(wMain
);
146 RefreshColourPalette(palette
, false);
151 PRectangle
Editor::GetClientRectangle() {
152 return wDraw
.GetClientPosition();
155 PRectangle
Editor::GetTextRectangle() {
156 PRectangle rc
= GetClientRectangle();
157 rc
.left
+= vs
.fixedColumnWidth
;
158 rc
.right
-= vs
.rightMarginWidth
;
162 int Editor::LinesOnScreen() {
163 PRectangle rcClient
= GetClientRectangle();
164 int htClient
= rcClient
.bottom
- rcClient
.top
;
165 //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
166 return htClient
/ vs
.lineHeight
;
169 int Editor::LinesToScroll() {
170 int retVal
= LinesOnScreen() - 1;
177 int Editor::MaxScrollPos() {
178 //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
179 //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
180 int retVal
= cs
.LinesDisplayed() - LinesOnScreen();
187 bool IsControlCharacter(char ch
) {
188 // iscntrl returns true for lots of chars > 127 which are displayable
189 return ch
>= 0 && ch
< ' ';
192 const char *ControlCharacterString(char ch
) {
193 const char *reps
[] = {
194 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
195 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
196 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
197 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
199 if (ch
< (sizeof(reps
) / sizeof(reps
[0]))) {
206 Point
Editor::LocationFromPosition(unsigned int pos
) {
208 int line
= pdoc
->LineFromPosition(pos
);
209 int lineVisible
= cs
.DisplayFromDoc(line
);
210 //Platform::DebugPrintf("line=%d\n", line);
214 pt
.y
= (lineVisible
- topLine
) * vs
.lineHeight
; // + half a lineheight?
215 unsigned int posLineStart
= pdoc
->LineStart(line
);
216 if ((pos
- posLineStart
) > LineLayout::maxLineLength
) {
217 // very long line so put x at arbitrary large position
218 pt
.x
= 30000 + vs
.fixedColumnWidth
- xOffset
;
221 LayoutLine(line
, &surface
, vs
, ll
);
222 pt
.x
= ll
.positions
[pos
- posLineStart
] + vs
.fixedColumnWidth
- xOffset
;
227 int Editor::XFromPosition(unsigned int pos
) {
228 Point pt
= LocationFromPosition(pos
);
229 return pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
232 int Editor::LineFromLocation(Point pt
) {
233 return cs
.DocFromDisplay(pt
.y
/ vs
.lineHeight
+ topLine
);
236 void Editor::SetTopLine(int topLineNew
) {
237 topLine
= topLineNew
;
238 posTopLine
= pdoc
->LineStart(topLine
);
241 int Editor::PositionFromLocation(Point pt
) {
243 pt
.x
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
244 int line
= cs
.DocFromDisplay(pt
.y
/ vs
.lineHeight
+ topLine
);
245 if (pt
.y
< 0) { // Division rounds towards 0
246 line
= cs
.DocFromDisplay((pt
.y
- (vs
.lineHeight
- 1)) / vs
.lineHeight
+ topLine
);
250 if (line
>= pdoc
->LinesTotal())
251 return pdoc
->Length();
252 //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
255 unsigned int posLineStart
= pdoc
->LineStart(line
);
258 LayoutLine(line
, &surface
, vs
, ll
);
259 for (int i
= 0; i
< ll
.numCharsInLine
; i
++) {
260 if (pt
.x
< ((ll
.positions
[i
] + ll
.positions
[i
+ 1]) / 2) ||
261 ll
.chars
[i
] == '\r' || ll
.chars
[i
] == '\n') {
262 return i
+ posLineStart
;
266 return ll
.numCharsInLine
+ posLineStart
;
269 int Editor::PositionFromLineX(int line
, int x
) {
271 if (line
>= pdoc
->LinesTotal())
272 return pdoc
->Length();
273 //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
276 unsigned int posLineStart
= pdoc
->LineStart(line
);
279 LayoutLine(line
, &surface
, vs
, ll
);
280 for (int i
= 0; i
< ll
.numCharsInLine
; i
++) {
281 if (x
< ((ll
.positions
[i
] + ll
.positions
[i
+ 1]) / 2) ||
282 ll
.chars
[i
] == '\r' || ll
.chars
[i
] == '\n') {
283 return i
+ posLineStart
;
287 return ll
.numCharsInLine
+ posLineStart
;
290 void Editor::RedrawRect(PRectangle rc
) {
291 //Platform::DebugPrintf("Redraw %d %d - %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
292 wDraw
.InvalidateRectangle(rc
);
295 void Editor::Redraw() {
296 //Platform::DebugPrintf("Redraw all\n");
297 wDraw
.InvalidateAll();
300 void Editor::RedrawSelMargin() {
304 PRectangle rcSelMargin
= GetClientRectangle();
305 rcSelMargin
.right
= vs
.fixedColumnWidth
;
306 wDraw
.InvalidateRectangle(rcSelMargin
);
310 PRectangle
Editor::RectangleFromRange(int start
, int end
) {
317 int minLine
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(minPos
));
318 int maxLine
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(maxPos
));
319 PRectangle rcClient
= GetTextRectangle();
321 rc
.left
= vs
.fixedColumnWidth
;
322 rc
.top
= (minLine
- topLine
) * vs
.lineHeight
;
325 rc
.right
= rcClient
.right
;
326 rc
.bottom
= (maxLine
- topLine
+ 1) * vs
.lineHeight
;
327 // Ensure PRectangle is within 16 bit space
328 rc
.top
= Platform::Clamp(rc
.top
, -32000, 32000);
329 rc
.bottom
= Platform::Clamp(rc
.bottom
, -32000, 32000);
334 void Editor::InvalidateRange(int start
, int end
) {
335 RedrawRect(RectangleFromRange(start
, end
));
338 int Editor::CurrentPosition() {
342 bool Editor::SelectionEmpty() {
343 return anchor
== currentPos
;
346 int Editor::SelectionStart(int line
) {
347 if ((line
== -1) || (selType
== selStream
)) {
348 return Platform::Minimum(currentPos
, anchor
);
349 } else { // selType == selRectangle
350 int selStart
= SelectionStart();
351 int selEnd
= SelectionEnd();
352 int lineStart
= pdoc
->LineFromPosition(selStart
);
353 int lineEnd
= pdoc
->LineFromPosition(selEnd
);
354 if (line
< lineStart
|| line
> lineEnd
) {
357 int minX
= Platform::Minimum(xStartSelect
, xEndSelect
);
358 //return PositionFromLineX(line, minX + vs.fixedColumnWidth - xOffset);
359 return PositionFromLineX(line
, minX
);
364 int Editor::SelectionEnd(int line
) {
365 if ((line
== -1) || (selType
== selStream
)) {
366 return Platform::Maximum(currentPos
, anchor
);
367 } else { // selType == selRectangle
368 int selStart
= SelectionStart();
369 int selEnd
= SelectionEnd();
370 int lineStart
= pdoc
->LineFromPosition(selStart
);
371 int lineEnd
= pdoc
->LineFromPosition(selEnd
);
372 if (line
< lineStart
|| line
> lineEnd
) {
375 int maxX
= Platform::Maximum(xStartSelect
, xEndSelect
);
376 // measure line and return character closest to minx
377 return PositionFromLineX(line
, maxX
);
382 void Editor::SetSelection(int currentPos_
, int anchor_
) {
383 currentPos_
= pdoc
->ClampPositionIntoDocument(currentPos_
);
384 anchor_
= pdoc
->ClampPositionIntoDocument(anchor_
);
385 if ((currentPos
!= currentPos_
) || (anchor
!= anchor_
)) {
386 int firstAffected
= anchor
;
387 if (firstAffected
> currentPos
)
388 firstAffected
= currentPos
;
389 if (firstAffected
> anchor_
)
390 firstAffected
= anchor_
;
391 if (firstAffected
> currentPos_
)
392 firstAffected
= currentPos_
;
393 int lastAffected
= anchor
;
394 if (lastAffected
< currentPos
)
395 lastAffected
= currentPos
;
396 if (lastAffected
< anchor_
)
397 lastAffected
= anchor_
;
398 if (lastAffected
< (currentPos_
+ 1)) // +1 ensures caret repainted
399 lastAffected
= (currentPos_
+ 1);
400 currentPos
= currentPos_
;
403 InvalidateRange(firstAffected
, lastAffected
);
408 void Editor::SetSelection(int currentPos_
) {
409 currentPos_
= pdoc
->ClampPositionIntoDocument(currentPos_
);
410 if (currentPos
!= currentPos_
) {
411 int firstAffected
= anchor
;
412 if (firstAffected
> currentPos
)
413 firstAffected
= currentPos
;
414 if (firstAffected
> currentPos_
)
415 firstAffected
= currentPos_
;
416 int lastAffected
= anchor
;
417 if (lastAffected
< currentPos
)
418 lastAffected
= currentPos
;
419 if (lastAffected
< (currentPos_
+ 1)) // +1 ensures caret repainted
420 lastAffected
= (currentPos_
+ 1);
421 currentPos
= currentPos_
;
423 InvalidateRange(firstAffected
, lastAffected
);
428 void Editor::SetEmptySelection(int currentPos_
) {
429 SetSelection(currentPos_
, currentPos_
);
432 int Editor::MovePositionTo(int newPos
, bool extend
) {
433 int delta
= newPos
- currentPos
;
434 newPos
= pdoc
->ClampPositionIntoDocument(newPos
);
435 newPos
= pdoc
->MovePositionOutsideChar(newPos
, delta
);
437 SetSelection(newPos
);
439 SetEmptySelection(newPos
);
441 EnsureCaretVisible();
442 ShowCaretAtCurrentPosition();
446 int Editor::MovePositionSoVisible(int pos
, int moveDir
) {
447 pos
= pdoc
->ClampPositionIntoDocument(pos
);
448 pos
= pdoc
->MovePositionOutsideChar(pos
, moveDir
);
449 int lineDoc
= pdoc
->LineFromPosition(pos
);
450 if (cs
.GetVisible(lineDoc
)) {
453 int lineDisplay
= cs
.DisplayFromDoc(lineDoc
);
455 lineDisplay
= Platform::Clamp(lineDisplay
+ 1, 0, cs
.LinesDisplayed());
456 return pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
));
458 // lineDisplay is already line before fold as lines in fold use display line of line before fold
459 lineDisplay
= Platform::Clamp(lineDisplay
, 0, cs
.LinesDisplayed());
460 return pdoc
->LineEndPosition(pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
)));
465 // Choose the x position that the caret will try to stick to as it is moves up and down
466 void Editor::SetLastXChosen() {
467 Point pt
= LocationFromPosition(currentPos
);
471 void Editor::ScrollTo(int line
) {
472 int topLineNew
= Platform::Clamp(line
, 0, MaxScrollPos());
473 if (topLineNew
!= topLine
) {
474 // Try to optimise small scrolls
475 int linesToMove
= topLine
- topLineNew
;
476 SetTopLine(topLineNew
);
477 ShowCaretAtCurrentPosition();
478 // Perform redraw rather than scroll if many lines would be redrawn anyway.
479 if (abs(linesToMove
) <= 10) {
480 ScrollText(linesToMove
);
484 SetVerticalScrollPos();
488 void Editor::ScrollText(int linesToMove
) {
489 //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
493 void Editor::HorizontalScrollTo(int xPos
) {
494 //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
498 SetHorizontalScrollPos();
502 void Editor::EnsureCaretVisible(bool useMargin
) {
503 //Platform::DebugPrintf("EnsureCaretVisible %d\n", xOffset);
504 PRectangle rcClient
= GetTextRectangle();
505 int posCaret
= currentPos
;
508 Point pt
= LocationFromPosition(posCaret
);
509 Point ptEOL
= LocationFromPosition(pdoc
->LineEndPosition(posCaret
));
510 Point ptBottomCaret
= pt
;
511 int lineCaret
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(posCaret
));
512 ptBottomCaret
.y
+= vs
.lineHeight
- 1;
514 // Ensure the caret is reasonably visible in context.
515 int xMargin
= Platform::Clamp(xCaretMargin
, 2, Platform::Maximum(rcClient
.Width() - 10, 4) / 2);
519 // Ensure certain amount of text visible on both sides of caretSo move if caret just on edge
520 rcClient
.left
= rcClient
.left
+ xMargin
;
521 rcClient
.right
= rcClient
.right
- xMargin
;
523 if (!rcClient
.Contains(pt
) || !rcClient
.Contains(ptBottomCaret
) || (caretPolicy
& CARET_STRICT
)) {
524 //Platform::DebugPrintf("EnsureCaretVisible move, (%d,%d) (%d,%d)\n", pt.x, pt.y, rcClient.left, rcClient.right);
525 // It should be possible to scroll the window to show the caret,
526 // but this fails to remove the caret on GTK+
527 if (caretPolicy
& CARET_SLOP
) {
528 if ((topLine
> lineCaret
) || ((caretPolicy
& CARET_STRICT
) && (topLine
+ caretSlop
> lineCaret
))) {
529 SetTopLine(Platform::Clamp(lineCaret
- caretSlop
, 0, MaxScrollPos()));
530 SetVerticalScrollPos();
532 } else if ((lineCaret
> topLine
+ LinesOnScreen() - 1) ||
533 ((caretPolicy
& CARET_STRICT
) && (lineCaret
> topLine
+ LinesOnScreen() - 1 - caretSlop
))) {
534 SetTopLine(Platform::Clamp(lineCaret
- LinesOnScreen() + 1 + caretSlop
, 0, MaxScrollPos()));
535 SetVerticalScrollPos();
539 if ((topLine
> lineCaret
) || (lineCaret
> topLine
+ LinesOnScreen() - 1) || (caretPolicy
& CARET_STRICT
)) {
540 SetTopLine(Platform::Clamp(lineCaret
- LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
541 SetVerticalScrollPos();
545 int xOffsetNew
= xOffset
;
546 if (pt
.x
< rcClient
.left
) {
547 xOffsetNew
= xOffset
- (rcClient
.left
- pt
.x
);
548 } else if (pt
.x
>= rcClient
.right
) {
549 xOffsetNew
= xOffset
+ (pt
.x
- rcClient
.right
);
550 int xOffsetEOL
= xOffset
+ (ptEOL
.x
- rcClient
.right
) - xMargin
+ 2;
551 //Platform::DebugPrintf("Margin %d %d\n", xOffsetNew, xOffsetEOL);
552 // Ensure don't scroll out into empty space
553 if (xOffsetNew
> xOffsetEOL
)
554 xOffsetNew
= xOffsetEOL
;
558 if (xOffset
!= xOffsetNew
) {
559 xOffset
= xOffsetNew
;
560 SetHorizontalScrollPos();
566 void Editor::ShowCaretAtCurrentPosition() {
567 if (!wMain
.HasFocus()) {
568 caret
.active
= false;
577 void Editor::DropCaret() {
578 caret
.active
= false;
582 void Editor::InvalidateCaret() {
584 InvalidateRange(posDrag
, posDrag
+ 1);
586 InvalidateRange(currentPos
, currentPos
+ 1);
589 void Editor::PaintSelMargin(Surface
*surfWindow
, PRectangle
&rc
) {
590 if (vs
.fixedColumnWidth
== 0)
593 PRectangle rcMargin
= GetClientRectangle();
594 rcMargin
.right
= vs
.fixedColumnWidth
;
596 if (!rc
.Intersects(rcMargin
))
601 surface
= &pixmapSelMargin
;
603 surface
= surfWindow
;
606 PRectangle rcSelMargin
= rcMargin
;
607 rcSelMargin
.right
= rcMargin
.left
;
609 for (int margin
=0; margin
< vs
.margins
; margin
++) {
610 if (vs
.ms
[margin
].width
> 0) {
612 rcSelMargin
.left
= rcSelMargin
.right
;
613 rcSelMargin
.right
= rcSelMargin
.left
+ vs
.ms
[margin
].width
;
615 if (vs
.ms
[margin
].symbol
) {
617 if (vs.ms[margin].mask & SC_MASK_FOLDERS)
618 surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated);
620 // Required because of special way brush is created for selection margin
621 surface->FillRectangle(rcSelMargin, pixmapSelPattern);
623 if (vs
.ms
[margin
].mask
& SC_MASK_FOLDERS
)
624 // Required because of special way brush is created for selection margin
625 surface
->FillRectangle(rcSelMargin
, pixmapSelPattern
);
627 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
629 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
632 int visibleLine
= topLine
;
633 int line
= cs
.DocFromDisplay(visibleLine
);
636 while ((visibleLine
< cs
.LinesDisplayed()) && yposScreen
< rcMargin
.bottom
) {
637 int marks
= pdoc
->GetMark(line
);
638 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
639 if (cs
.GetExpanded(line
)) {
640 marks
|= 1 << SC_MARKNUM_FOLDEROPEN
;
642 marks
|= 1 << SC_MARKNUM_FOLDER
;
645 marks
&= vs
.ms
[margin
].mask
;
646 PRectangle rcMarker
= rcSelMargin
;
647 rcMarker
.top
= yposScreen
;
648 rcMarker
.bottom
= yposScreen
+ vs
.lineHeight
;
649 if (!vs
.ms
[margin
].symbol
) {
652 sprintf(number
, "%d", line
+ 1);
654 sprintf(number
, "%X", pdoc
->GetLevel(line
));
656 PRectangle rcNumber
=rcMarker
;
658 int width
= surface
->WidthText(vs
.styles
[STYLE_LINENUMBER
].font
, number
, strlen(number
));
659 xpos
= rcNumber
.right
- width
- 3;
660 rcNumber
.left
= xpos
;
661 if ((visibleLine
< cs
.LinesDisplayed()) && cs
.GetVisible(line
)) {
662 surface
->DrawText(rcNumber
, vs
.styles
[STYLE_LINENUMBER
].font
,
663 rcNumber
.top
+ vs
.maxAscent
, number
, strlen(number
),
664 vs
.styles
[STYLE_LINENUMBER
].fore
.allocated
,
665 vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
670 for (int markBit
= 0; (markBit
< 32) && marks
; markBit
++) {
674 vs
.markers
[markBit
].Draw(surface
, rcMarker
);
681 line
= cs
.DocFromDisplay(visibleLine
);
682 yposScreen
+= vs
.lineHeight
;
687 PRectangle rcBlankMargin
= rcMargin
;
688 rcBlankMargin
.left
= rcSelMargin
.right
;
689 surface
->FillRectangle(rcBlankMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
);
692 surfWindow
->Copy(rcMargin
, Point(), pixmapSelMargin
);
696 void DrawTabArrow(Surface
*surface
, PRectangle rcTab
, int ymid
) {
697 int ydiff
= (rcTab
.bottom
- rcTab
.top
) / 2;
698 int xhead
= rcTab
.right
- 1 - ydiff
;
699 if ((rcTab
.left
+ 2) < (rcTab
.right
- 1))
700 surface
->MoveTo(rcTab
.left
+ 2, ymid
);
702 surface
->MoveTo(rcTab
.right
- 1, ymid
);
703 surface
->LineTo(rcTab
.right
- 1, ymid
);
704 surface
->LineTo(xhead
, ymid
- ydiff
);
705 surface
->MoveTo(rcTab
.right
- 1, ymid
);
706 surface
->LineTo(xhead
, ymid
+ ydiff
);
709 void Editor::LayoutLine(int line
, Surface
*surface
, ViewStyle
&vstyle
, LineLayout
&ll
) {
710 int numCharsInLine
= 0;
711 int posLineStart
= pdoc
->LineStart(line
);
712 int posLineEnd
= pdoc
->LineStart(line
+ 1);
713 Font
&ctrlCharsFont
= vstyle
.styles
[STYLE_CONTROLCHAR
].font
;
715 int styleMask
= pdoc
->stylingBitsMask
;
716 for (int charInDoc
= posLineStart
;
717 charInDoc
< posLineEnd
&& numCharsInLine
< LineLayout::maxLineLength
- 1;
719 char chDoc
= pdoc
->CharAt(charInDoc
);
720 styleByte
= pdoc
->StyleAt(charInDoc
);
721 if (vstyle
.viewEOL
|| ((chDoc
!= '\r') && (chDoc
!= '\n'))) {
722 ll
.chars
[numCharsInLine
] = chDoc
;
723 ll
.styles
[numCharsInLine
] = styleByte
& styleMask
;
724 ll
.indicators
[numCharsInLine
] = styleByte
& ~styleMask
;
728 ll
.chars
[numCharsInLine
] = 0;
729 ll
.styles
[numCharsInLine
] = styleByte
; // For eolFilled
730 ll
.indicators
[numCharsInLine
] = 0;
732 // Layout the line, determining the position of each character
736 unsigned int tabWidth
= vstyle
.spaceWidth
* pdoc
->tabInChars
;
738 for (int charInLine
= 0; charInLine
< numCharsInLine
; charInLine
++) {
739 if ((ll
.styles
[charInLine
] != ll
.styles
[charInLine
+ 1]) ||
740 IsControlCharacter(ll
.chars
[charInLine
]) || IsControlCharacter(ll
.chars
[charInLine
+ 1])) {
741 ll
.positions
[startseg
] = 0;
742 if (IsControlCharacter(ll
.chars
[charInLine
])) {
743 if (ll
.chars
[charInLine
] == '\t') {
744 ll
.positions
[charInLine
+ 1] = ((((startsegx
+ 2) /
745 tabWidth
) + 1) * tabWidth
) - startsegx
;
747 const char *ctrlChar
= ControlCharacterString(ll
.chars
[charInLine
]);
748 // +3 For a blank on front and rounded edge each side:
749 ll
.positions
[charInLine
+ 1] = surface
->WidthText(ctrlCharsFont
, ctrlChar
, strlen(ctrlChar
)) + 3;
752 surface
->MeasureWidths(vstyle
.styles
[ll
.styles
[charInLine
]].font
, ll
.chars
+ startseg
,
753 charInLine
- startseg
+ 1, ll
.positions
+ startseg
+ 1);
755 for (int posToIncrease
= startseg
; posToIncrease
<= (charInLine
+ 1); posToIncrease
++) {
756 ll
.positions
[posToIncrease
] += startsegx
;
758 startsegx
= ll
.positions
[charInLine
+ 1];
759 startseg
= charInLine
+ 1;
762 ll
.numCharsInLine
= numCharsInLine
;
765 void Editor::DrawLine(Surface
*surface
, ViewStyle
&vsDraw
, int line
, int xStart
, PRectangle rcLine
, LineLayout
&ll
) {
767 PRectangle rcSegment
= rcLine
;
769 // Using one font for all control characters so it can be controlled independently to ensure
770 // the box goes around the characters tightly. Seems to be no way to work out what height
771 // is taken by an individual character - internal leading gives varying results.
772 Font
&ctrlCharsFont
= vsDraw
.styles
[STYLE_CONTROLCHAR
].font
;
775 Colour markBack
= Colour(0, 0, 0);
776 if (vsDraw
.maskInLine
) {
777 marks
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
;
779 for (int markBit
= 0; (markBit
< 32) && marks
; markBit
++) {
781 markBack
= vsDraw
.markers
[markBit
].back
.allocated
;
786 marks
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
;
789 int posLineStart
= pdoc
->LineStart(line
);
790 int posLineEnd
= pdoc
->LineStart(line
+ 1);
792 int selStart
= SelectionStart(line
);
793 int selEnd
= SelectionEnd(line
);
795 int styleMask
= pdoc
->stylingBitsMask
;
797 for (int i
= 0; i
< ll
.numCharsInLine
; i
++) {
799 int iDoc
= i
+ posLineStart
;
800 // If there is the end of a style run for any reason
801 if ((ll
.styles
[i
] != ll
.styles
[i
+ 1]) ||
802 IsControlCharacter(ll
.chars
[i
]) || IsControlCharacter(ll
.chars
[i
+ 1]) ||
803 ((selStart
!= selEnd
) && ((iDoc
+ 1 == selStart
) || (iDoc
+ 1 == selEnd
))) ||
804 (i
== (theEdge
-1))) {
805 int styleMain
= ll
.styles
[i
];
806 Colour textBack
= vsDraw
.styles
[styleMain
].back
.allocated
;
807 Colour textFore
= vsDraw
.styles
[styleMain
].fore
.allocated
;
808 Font
&textFont
= vsDraw
.styles
[styleMain
].font
;
809 bool inSelection
= (iDoc
>= selStart
) && (iDoc
< selEnd
) && (selStart
!= selEnd
);
810 if (inSelection
&& !hideSelection
) {
811 if (vsDraw
.selbackset
)
812 textBack
= vsDraw
.selbackground
.allocated
;
813 if (vsDraw
.selforeset
)
814 textFore
= vsDraw
.selforeground
.allocated
;
818 if ((edgeState
== EDGE_BACKGROUND
) && (i
>= theEdge
) && (ll
.chars
[i
] != '\n') && (ll
.chars
[i
] != '\r'))
819 textBack
= vs
.edgecolour
.allocated
;
821 // Manage tab display
822 if (ll
.chars
[i
] == '\t') {
823 rcSegment
.left
= ll
.positions
[i
] + xStart
;
824 rcSegment
.right
= ll
.positions
[i
+ 1] + xStart
;
825 surface
->FillRectangle(rcSegment
, textBack
);
826 if (vsDraw
.viewWhitespace
) {
827 surface
->PenColour(textFore
);
828 PRectangle
rcTab(rcSegment
.left
+ 1, rcSegment
.top
+ 4,
829 rcSegment
.right
- 1, rcSegment
.bottom
- vsDraw
.maxDescent
);
830 DrawTabArrow(surface
, rcTab
, rcSegment
.top
+ vsDraw
.lineHeight
/ 2);
832 // Manage control character display
833 } else if (IsControlCharacter(ll
.chars
[i
])) {
834 const char *ctrlChar
= ControlCharacterString(ll
.chars
[i
]);
835 rcSegment
.left
= ll
.positions
[i
] + xStart
;
836 rcSegment
.right
= ll
.positions
[i
+ 1] + xStart
;
837 surface
->FillRectangle(rcSegment
, textBack
);
838 int normalCharHeight
= surface
->Ascent(ctrlCharsFont
) -
839 surface
->InternalLeading(ctrlCharsFont
);
840 PRectangle rcCChar
= rcSegment
;
841 rcCChar
.left
= rcCChar
.left
+ 1;
842 rcCChar
.top
= rcSegment
.top
+ vsDraw
.maxAscent
- normalCharHeight
;
843 rcCChar
.bottom
= rcSegment
.top
+ vsDraw
.maxAscent
+ 1;
844 PRectangle rcCentral
= rcCChar
;
847 surface
->FillRectangle(rcCentral
, textFore
);
848 PRectangle rcChar
= rcCChar
;
851 surface
->DrawTextClipped(rcChar
, ctrlCharsFont
,
852 rcSegment
.top
+ vsDraw
.maxAscent
, ctrlChar
, strlen(ctrlChar
),
854 // Manage normal display
856 rcSegment
.left
= ll
.positions
[startseg
] + xStart
;
857 rcSegment
.right
= ll
.positions
[i
+ 1] + xStart
;
858 // Only try to draw if really visible - enhances performance by not calling environment to
859 // draw strings that are completely past the right side of the window.
860 if (rcSegment
.left
<= rcLine
.right
) {
861 surface
->DrawText(rcSegment
, textFont
,
862 rcSegment
.top
+ vsDraw
.maxAscent
, ll
.chars
+ startseg
,
863 i
- startseg
+ 1, textFore
, textBack
);
864 if (vsDraw
.viewWhitespace
) {
865 for (int cpos
= 0; cpos
<= i
- startseg
; cpos
++) {
866 if (ll
.chars
[cpos
+ startseg
] == ' ') {
867 int xmid
= (ll
.positions
[cpos
+ startseg
] + ll
.positions
[cpos
+ startseg
+ 1]) / 2;
868 PRectangle
rcDot(xmid
+ xStart
, rcSegment
.top
+ vsDraw
.lineHeight
/ 2, 0, 0);
869 rcDot
.right
= rcDot
.left
+ 1;
870 rcDot
.bottom
= rcDot
.top
+ 1;
871 surface
->FillRectangle(rcDot
, textFore
);
882 int indStart
[INDIC_MAX
+ 1] = {0};
883 for (int indica
= 0; indica
<= INDIC_MAX
; indica
++)
884 indStart
[indica
] = 0;
886 for (int indicPos
= 0; indicPos
<= ll
.numCharsInLine
; indicPos
++) {
887 if (ll
.indicators
[indicPos
] != ll
.indicators
[indicPos
+ 1]) {
888 int mask
= 1 << pdoc
->stylingBits
;
889 for (int indicnum
= 0; mask
<= 0x100; indicnum
++) {
890 if ((ll
.indicators
[indicPos
+ 1] & mask
) && !(ll
.indicators
[indicPos
] & mask
)) {
891 indStart
[indicnum
] = ll
.positions
[indicPos
+ 1];
893 if (!(ll
.indicators
[indicPos
+ 1] & mask
) && (ll
.indicators
[indicPos
] & mask
)) {
895 indStart
[indicnum
] + xStart
,
896 rcLine
.top
+ vsDraw
.maxAscent
,
897 ll
.positions
[indicPos
+ 1] + xStart
,
898 rcLine
.top
+ vsDraw
.maxAscent
+ 3);
899 vsDraw
.indicators
[indicnum
].Draw(surface
, rcIndic
);
905 // End of the drawing of the current line
907 // Fill in a PRectangle representing the end of line characters
908 int xEol
= ll
.positions
[ll
.numCharsInLine
];
909 rcSegment
.left
= xEol
+ xStart
;
910 rcSegment
.right
= xEol
+ vsDraw
.aveCharWidth
+ xStart
;
911 bool eolInSelection
= (posLineEnd
> selStart
) && (posLineEnd
<= selEnd
) && (selStart
!= selEnd
);
912 if (eolInSelection
&& !hideSelection
&& vsDraw
.selbackset
&& (line
< pdoc
->LinesTotal()-1)) {
913 surface
->FillRectangle(rcSegment
, vsDraw
.selbackground
.allocated
);
915 surface
->FillRectangle(rcSegment
, markBack
);
917 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
.styles
[ll
.numCharsInLine
] & styleMask
].back
.allocated
);
920 rcSegment
.left
= xEol
+ vsDraw
.aveCharWidth
+ xStart
;
921 rcSegment
.right
= rcLine
.right
;
923 surface
->FillRectangle(rcSegment
, markBack
);
924 } else if (vsDraw
.styles
[ll
.styles
[ll
.numCharsInLine
] & styleMask
].eolFilled
) {
925 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
.styles
[ll
.numCharsInLine
] & styleMask
].back
.allocated
);
927 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[STYLE_DEFAULT
].back
.allocated
);
930 if (edgeState
== EDGE_LINE
) {
931 int edgeX
= theEdge
* vsDraw
.spaceWidth
;
932 rcSegment
.left
= edgeX
+ xStart
;
933 rcSegment
.right
= rcSegment
.left
+ 1;
934 surface
->FillRectangle(rcSegment
, vs
.edgecolour
.allocated
);
938 void Editor::Paint(Surface
*surfaceWindow
, PRectangle rcArea
) {
939 //Platform::DebugPrintf("Paint %d %d - %d %d\n", rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
942 PRectangle rcClient
= GetClientRectangle();
943 //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
944 // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
946 if (!pixmapSelPattern
.Initialised()) {
947 pixmapSelPattern
.InitPixMap(8, 8, surfaceWindow
);
948 // This complex procedure is to reproduce the checker board dithered pattern used by windows
949 // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
950 // way between the chrome colour and the chrome highlight colour making a nice transition
951 // between the window chrome and the content area. And it works in low colour depths.
952 PRectangle
rcPattern(0, 0, 8, 8);
953 if (vs
.selbarlight
.desired
== Colour(0xff, 0xff, 0xff)) {
954 pixmapSelPattern
.FillRectangle(rcPattern
, vs
.selbar
.allocated
);
955 pixmapSelPattern
.PenColour(vs
.selbarlight
.allocated
);
956 for (int stripe
= 0; stripe
< 8; stripe
++) {
957 pixmapSelPattern
.MoveTo(0, stripe
* 2);
958 pixmapSelPattern
.LineTo(8, stripe
* 2 - 8);
961 // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
962 pixmapSelPattern
.FillRectangle(rcPattern
, vs
.selbarlight
.allocated
);
967 if (!pixmapLine
.Initialised()) {
968 pixmapLine
.InitPixMap(rcClient
.Width(), rcClient
.Height(),
970 pixmapSelMargin
.InitPixMap(vs
.fixedColumnWidth
,
971 rcClient
.Height(), surfaceWindow
);
975 surfaceWindow
->SetPalette(&palette
, true);
976 pixmapLine
.SetPalette(&palette
, !wMain
.HasFocus());
978 //Platform::DebugPrintf("Paint: (%3d,%3d) ... (%3d,%3d)\n",
979 // rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
981 int screenLinePaintFirst
= rcArea
.top
/ vs
.lineHeight
;
982 // The area to be painted plus one extra line is styled.
983 // The extra line is to determine when a style change, such as statrting a comment flows on to other lines.
984 int lineStyleLast
= topLine
+ (rcArea
.bottom
-1) / vs
.lineHeight
+ 1;
985 //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast);
986 int endPosPaint
= pdoc
->Length();
987 if (lineStyleLast
< cs
.LinesDisplayed())
988 endPosPaint
= pdoc
->LineStart(cs
.DocFromDisplay(lineStyleLast
+ 1));
990 int xStart
= vs
.fixedColumnWidth
- xOffset
;
993 ypos
+= screenLinePaintFirst
* vs
.lineHeight
;
994 int yposScreen
= screenLinePaintFirst
* vs
.lineHeight
;
996 // Ensure we are styled as far as we are painting.
997 pdoc
->EnsureStyledTo(endPosPaint
);
1001 needUpdateUI
= false;
1004 PaintSelMargin(surfaceWindow
, rcArea
);
1006 PRectangle rcRightMargin
= rcClient
;
1007 rcRightMargin
.left
= rcRightMargin
.right
- vs
.rightMarginWidth
;
1008 if (rcArea
.Intersects(rcRightMargin
)) {
1009 surfaceWindow
->FillRectangle(rcRightMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
);
1012 if (paintState
== paintAbandoned
) {
1013 // Either styling or NotifyUpdateUI noticed that painting is needed
1014 // outside the current painting rectangle
1015 //Platform::DebugPrintf("Abandoning paint\n");
1018 //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
1020 Surface
*surface
= 0;
1021 if (rcArea
.right
> vs
.fixedColumnWidth
) {
1024 surface
= &pixmapLine
;
1026 surface
= surfaceWindow
;
1029 int visibleLine
= topLine
+ screenLinePaintFirst
;
1030 int line
= cs
.DocFromDisplay(visibleLine
);
1032 int posCaret
= currentPos
;
1035 int lineCaret
= pdoc
->LineFromPosition(posCaret
);
1037 // Remove selection margin from drawing area so text will not be drawn
1038 // on it in unbuffered mode.
1039 PRectangle rcTextArea
= rcClient
;
1040 rcTextArea
.left
= vs
.fixedColumnWidth
;
1041 rcTextArea
.right
-= vs
.rightMarginWidth
;
1042 surfaceWindow
->SetClip(rcTextArea
);
1043 //GTimer *tim=g_timer_new();
1044 while (visibleLine
<= cs
.LinesDisplayed() && yposScreen
< rcArea
.bottom
) {
1045 //g_timer_start(tim);
1046 //Platform::DebugPrintf("Painting line %d\n", line);
1048 int posLineStart
= pdoc
->LineStart(line
);
1049 int posLineEnd
= pdoc
->LineStart(line
+ 1);
1050 //Platform::DebugPrintf("line %d %d - %d\n", line, posLineStart, posLineEnd);
1052 PRectangle rcLine
= rcClient
;
1054 rcLine
.bottom
= ypos
+ vs
.lineHeight
;
1056 // Copy this line and its styles from the document into local arrays
1057 // and determine the x position at which each character starts.
1059 LayoutLine(line
, surface
, vs
, ll
);
1061 // Highlight the current braces if any
1062 if ((braces
[0] >= posLineStart
) && (braces
[0] < posLineEnd
))
1063 ll
.styles
[braces
[0] - posLineStart
] = bracesMatchStyle
;
1064 if ((braces
[1] >= posLineStart
) && (braces
[1] < posLineEnd
))
1065 ll
.styles
[braces
[1] - posLineStart
] = bracesMatchStyle
;
1068 if (cs
.GetVisible(line
))
1069 DrawLine(surface
, vs
, line
, xStart
, rcLine
, ll
);
1071 bool expanded
= cs
.GetExpanded(line
);
1072 if ( (expanded
&& (foldFlags
& 2)) || (!expanded
&& (foldFlags
& 4)) ) {
1073 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
1074 PRectangle rcFoldLine
= rcLine
;
1075 rcFoldLine
.bottom
= rcFoldLine
.top
+ 1;
1076 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
);
1079 if ( (expanded
&& (foldFlags
& 8)) || (!expanded
&& (foldFlags
& 16)) ) {
1080 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
1081 PRectangle rcFoldLine
= rcLine
;
1082 rcFoldLine
.top
= rcFoldLine
.bottom
- 1;
1083 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
);
1088 if (line
== lineCaret
) {
1089 int xposCaret
= ll
.positions
[posCaret
- posLineStart
] + xStart
;
1090 int widthOverstrikeCaret
=
1091 ll
.positions
[posCaret
- posLineStart
+ 1] - ll
.positions
[posCaret
- posLineStart
];
1092 if (posCaret
== pdoc
->Length()) // At end of document
1093 widthOverstrikeCaret
= vs
.aveCharWidth
;
1094 if ((posCaret
- posLineStart
) >= ll
.numCharsInLine
) // At end of line
1095 widthOverstrikeCaret
= vs
.aveCharWidth
;
1096 if (widthOverstrikeCaret
< 3) // Make sure its visible
1097 widthOverstrikeCaret
= 3;
1098 if (((caret
.active
&& caret
.on
) || (posDrag
>= 0)) && xposCaret
>= 0) {
1099 PRectangle rcCaret
= rcLine
;
1101 rcCaret
.left
= xposCaret
;
1102 rcCaret
.right
= xposCaret
+ 1;
1105 rcCaret
.top
= rcCaret
.bottom
- 2;
1106 rcCaret
.left
= xposCaret
+ 1;
1107 rcCaret
.right
= rcCaret
.left
+ widthOverstrikeCaret
- 1;
1109 rcCaret
.left
= xposCaret
;
1110 rcCaret
.right
= xposCaret
+ 1;
1113 surface
->FillRectangle(rcCaret
, vs
.caretcolour
.allocated
);
1117 if (cs
.GetVisible(line
)) {
1119 Point
from(vs
.fixedColumnWidth
, 0);
1120 PRectangle
rcCopyArea(vs
.fixedColumnWidth
, yposScreen
,
1121 rcClient
.right
, yposScreen
+ vs
.lineHeight
);
1122 surfaceWindow
->Copy(rcCopyArea
, from
, pixmapLine
);
1126 if (!bufferedDraw
) {
1127 ypos
+= vs
.lineHeight
;
1130 yposScreen
+= vs
.lineHeight
;
1132 line
= cs
.DocFromDisplay(visibleLine
);
1134 //g_timer_stop(tim);
1135 //Platform::DebugPrintf("Paint [%0d] took %g\n", line, g_timer_elapsed(tim, 0));
1137 //g_timer_destroy(tim);
1138 PRectangle rcBeyondEOF
= rcClient
;
1139 rcBeyondEOF
.left
= vs
.fixedColumnWidth
;
1140 rcBeyondEOF
.right
= rcBeyondEOF
.right
;
1141 rcBeyondEOF
.top
= (cs
.LinesDisplayed() - topLine
) * vs
.lineHeight
;
1142 if (rcBeyondEOF
.top
< rcBeyondEOF
.bottom
) {
1143 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
);
1144 if (edgeState
== EDGE_LINE
) {
1145 int edgeX
= theEdge
* vs
.spaceWidth
;
1146 rcBeyondEOF
.left
= edgeX
+ xStart
;
1147 rcBeyondEOF
.right
= rcBeyondEOF
.left
+ 1;
1148 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.edgecolour
.allocated
);
1154 // Space (3 space characters) between line numbers and text when printing.
1155 #define lineNumberPrintSpace " "
1157 // This is mostly copied from the Paint method but with some things omitted
1158 // such as the margin markers, line numbers, selection and caret
1159 // Should be merged back into a combined Draw method.
1160 long Editor::FormatRange(bool draw
, FORMATRANGE
*pfr
) {
1164 Surface
*surface
= new Surface();
1165 surface
->Init(pfr
->hdc
);
1166 Surface
*surfaceMeasure
= new Surface();
1167 surfaceMeasure
->Init(pfr
->hdcTarget
);
1169 ViewStyle
vsPrint(vs
);
1171 // Modify the view style for printing as do not normally want any of the transient features to be printed
1172 // Printing supports only the line number margin.
1173 int lineNumberIndex
= -1;
1174 for (int margin
=0; margin
< ViewStyle::margins
; margin
++) {
1175 if ((!vsPrint
.ms
[margin
].symbol
) && (vsPrint
.ms
[margin
].width
> 0)) {
1176 lineNumberIndex
= margin
;
1178 vsPrint
.ms
[margin
].width
= 0;
1181 vsPrint
.showMarkedLines
= false;
1182 vsPrint
.fixedColumnWidth
= 0;
1183 vsPrint
.zoomLevel
= 0;
1184 // Don't show the selection when printing
1185 vsPrint
.selbackset
= false;
1186 vsPrint
.selforeset
= false;
1187 // White background for the line numbers
1188 vsPrint
.styles
[STYLE_LINENUMBER
].back
.desired
= Colour(0xff,0xff,0xff);
1190 vsPrint
.Refresh(*surfaceMeasure
);
1191 // Ensure colours are set up
1192 vsPrint
.RefreshColourPalette(palette
, true);
1193 vsPrint
.RefreshColourPalette(palette
, false);
1194 // Determining width must hapen after fonts have been realised in Refresh
1195 int lineNumberWidth
= 0;
1196 if (lineNumberIndex
>= 0) {
1197 lineNumberWidth
= surface
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
,
1198 "9999" lineNumberPrintSpace
, 4 + strlen(lineNumberPrintSpace
));
1199 vsPrint
.ms
[lineNumberIndex
].width
= lineNumberWidth
;
1202 int linePrintStart
= pdoc
->LineFromPosition(pfr
->chrg
.cpMin
);
1203 int linePrintLast
= linePrintStart
+ (pfr
->rc
.bottom
- pfr
->rc
.top
) / vsPrint
.lineHeight
- 1;
1204 if (linePrintLast
< linePrintStart
)
1205 linePrintLast
= linePrintStart
;
1206 int linePrintMax
= pdoc
->LineFromPosition(pfr
->chrg
.cpMax
- 1);
1207 if (linePrintLast
> linePrintMax
)
1208 linePrintLast
= linePrintMax
;
1209 //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
1210 // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
1211 // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
1212 int endPosPrint
= pdoc
->Length();
1213 if (linePrintLast
< pdoc
->LinesTotal())
1214 endPosPrint
= pdoc
->LineStart(linePrintLast
+ 1);
1216 // Ensure we are styled to where we are formatting.
1217 pdoc
->EnsureStyledTo(endPosPrint
);
1219 int xStart
= vsPrint
.fixedColumnWidth
+ pfr
->rc
.left
+ lineNumberWidth
;
1220 int ypos
= pfr
->rc
.top
;
1221 int line
= linePrintStart
;
1223 if (draw
) { // Otherwise just measuring
1225 while (line
<= linePrintLast
&& ypos
< pfr
->rc
.bottom
) {
1228 rcLine
.left
= pfr
->rc
.left
+ lineNumberWidth
;
1230 rcLine
.right
= pfr
->rc
.right
;
1231 rcLine
.bottom
= ypos
+ vsPrint
.lineHeight
;
1233 if (lineNumberWidth
) {
1235 sprintf(number
, "%d" lineNumberPrintSpace
, line
+ 1);
1236 PRectangle rcNumber
= rcLine
;
1237 rcNumber
.right
= rcNumber
.left
+ lineNumberWidth
;
1240 surface
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
, number
, strlen(number
));
1241 surface
->DrawText(rcNumber
, vsPrint
.styles
[STYLE_LINENUMBER
].font
,
1242 ypos
+ vsPrint
.maxAscent
, number
, strlen(number
),
1243 vsPrint
.styles
[STYLE_LINENUMBER
].fore
.allocated
,
1244 vsPrint
.styles
[STYLE_LINENUMBER
].back
.allocated
);
1247 // When printing, the hdc and hdcTarget may be the same, so
1248 // changing the state of surfaceMeasure may change the underlying
1249 // state of surface. Therefore, any cached state is discarded before
1250 // using each surface.
1252 // Copy this line and its styles from the document into local arrays
1253 // and determine the x position at which each character starts.
1254 surfaceMeasure
->FlushCachedState();
1256 LayoutLine(line
, surfaceMeasure
, vsPrint
, ll
);
1259 surface
->FlushCachedState();
1260 DrawLine(surface
, vsPrint
, line
, xStart
, rcLine
, ll
);
1262 ypos
+= vsPrint
.lineHeight
;
1268 delete surfaceMeasure
;
1273 void Editor::SetScrollBarsTo(PRectangle
) {
1276 int nMax
= cs
.LinesDisplayed();
1277 int nPage
= cs
.LinesDisplayed() - MaxScrollPos() + 1;
1278 bool modified
= ModifyScrollBars(nMax
, nPage
);
1280 // TODO: ensure always showing as many lines as possible
1281 // May not be, if, for example, window made larger
1282 if (topLine
> MaxScrollPos()) {
1283 SetTopLine(Platform::Clamp(topLine
, 0, MaxScrollPos()));
1284 SetVerticalScrollPos();
1289 //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
1292 void Editor::SetScrollBars() {
1293 PRectangle rsClient
= GetClientRectangle();
1294 SetScrollBarsTo(rsClient
);
1297 void Editor::AddChar(char ch
) {
1298 bool wasSelection
= currentPos
!= anchor
;
1300 if (inOverstrike
&& !wasSelection
) {
1301 if (currentPos
< (pdoc
->Length() - 1)) {
1302 if ((pdoc
->CharAt(currentPos
) != '\r') && (pdoc
->CharAt(currentPos
) != '\n')) {
1303 pdoc
->DelChar(currentPos
);
1307 pdoc
->InsertChar(currentPos
, ch
);
1308 SetEmptySelection(currentPos
+ 1);
1309 EnsureCaretVisible();
1314 void Editor::ClearSelection() {
1315 if (selType
== selRectangle
) {
1316 pdoc
->BeginUndoAction();
1317 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
1318 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
1319 int startPos
= SelectionStart();
1321 for (line
=lineStart
; line
<= lineEnd
; line
++) {
1322 startPos
= SelectionStart(line
);
1323 unsigned int chars
= SelectionEnd(line
) - startPos
;
1325 pdoc
->DeleteChars(startPos
, chars
);
1328 SetEmptySelection(startPos
);
1329 selType
= selStream
;
1330 pdoc
->EndUndoAction();
1332 int startPos
= SelectionStart();
1333 unsigned int chars
= SelectionEnd() - startPos
;
1334 SetEmptySelection(startPos
);
1336 pdoc
->DeleteChars(startPos
, chars
);
1341 void Editor::ClearAll() {
1342 if (0 != pdoc
->Length()) {
1343 pdoc
->DeleteChars(0, pdoc
->Length());
1349 SetVerticalScrollPos();
1352 void Editor::Cut() {
1357 void Editor::PasteRectangular(int pos
, const char *ptr
, int len
) {
1359 int insertPos
= currentPos
;
1360 int xInsert
= XFromPosition(currentPos
);
1361 int line
= pdoc
->LineFromPosition(currentPos
);
1362 bool prevCr
= false;
1363 for (int i
=0; i
<len
; i
++) {
1364 if ((ptr
[i
] == '\r') || (ptr
[i
] == '\n')) {
1365 if ((ptr
[i
] == '\r') || (!prevCr
))
1367 if (line
>= pdoc
->LinesTotal()) {
1368 if (pdoc
->eolMode
!= SC_EOL_LF
)
1369 pdoc
->InsertChar(pdoc
->Length(), '\r');
1370 if (pdoc
->eolMode
!= SC_EOL_CR
)
1371 pdoc
->InsertChar(pdoc
->Length(), '\n');
1373 currentPos
= PositionFromLineX(line
, xInsert
);
1374 prevCr
= ptr
[i
] == '\r';
1376 pdoc
->InsertString(currentPos
, ptr
+i
, 1);
1378 insertPos
= currentPos
;
1382 SetEmptySelection(insertPos
);
1385 void Editor::Clear() {
1386 if (currentPos
== anchor
) {
1391 SetEmptySelection(currentPos
);
1394 void Editor::SelectAll() {
1395 SetSelection(0, pdoc
->Length());
1399 void Editor::Undo() {
1400 if (pdoc
->CanUndo()) {
1401 int newPos
= pdoc
->Undo();
1402 SetEmptySelection(newPos
);
1403 EnsureCaretVisible();
1407 void Editor::Redo() {
1408 if (pdoc
->CanRedo()) {
1409 int newPos
= pdoc
->Redo();
1410 SetEmptySelection(newPos
);
1411 EnsureCaretVisible();
1415 void Editor::DelChar() {
1416 pdoc
->DelChar(currentPos
);
1419 void Editor::DelCharBack() {
1420 if (currentPos
== anchor
) {
1421 int newPos
= pdoc
->DelCharBack(currentPos
);
1422 SetEmptySelection(newPos
);
1425 SetEmptySelection(currentPos
);
1429 void Editor::NotifyFocus(bool) {
1432 void Editor::NotifyStyleNeeded(int endStyleNeeded
) {
1434 scn
.nmhdr
.code
= SCN_STYLENEEDED
;
1435 scn
.position
= endStyleNeeded
;
1439 void Editor::NotifyStyleNeeded(Document
*, void *, int endStyleNeeded
) {
1440 NotifyStyleNeeded(endStyleNeeded
);
1443 void Editor::NotifyChar(char ch
) {
1445 scn
.nmhdr
.code
= SCN_CHARADDED
;
1448 #ifdef MACRO_SUPPORT
1449 if (recordingMacro
) {
1453 NotifyMacroRecord(EM_REPLACESEL
, 0, (LPARAM
) txt
);
1458 void Editor::NotifySavePoint(bool isSavePoint
) {
1461 scn
.nmhdr
.code
= SCN_SAVEPOINTREACHED
;
1463 scn
.nmhdr
.code
= SCN_SAVEPOINTLEFT
;
1468 void Editor::NotifyModifyAttempt() {
1470 scn
.nmhdr
.code
= SCN_MODIFYATTEMPTRO
;
1474 void Editor::NotifyDoubleClick(Point
, bool) {
1476 scn
.nmhdr
.code
= SCN_DOUBLECLICK
;
1480 void Editor::NotifyUpdateUI() {
1482 scn
.nmhdr
.code
= SCN_UPDATEUI
;
1486 bool Editor::NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
) {
1487 int marginClicked
= -1;
1489 for (int margin
=0; margin
< ViewStyle::margins
; margin
++) {
1490 if ((pt
.x
> x
) && (pt
.x
< x
+ vs
.ms
[margin
].width
))
1491 marginClicked
= margin
;
1492 x
+= vs
.ms
[margin
].width
;
1494 if ((marginClicked
>= 0) && vs
.ms
[marginClicked
].sensitive
) {
1496 scn
.nmhdr
.code
= SCN_MARGINCLICK
;
1497 scn
.modifiers
= (shift
? SCI_SHIFT
: 0) | (ctrl
? SCI_CTRL
: 0) |
1498 (alt
? SCI_ALT
: 0);
1499 scn
.position
= pdoc
->LineStart(LineFromLocation(pt
));
1500 scn
.margin
= marginClicked
;
1508 void Editor::NotifyNeedShown(int pos
, int len
) {
1510 scn
.nmhdr
.code
= SCN_NEEDSHOWN
;
1516 // Notifications from document
1517 void Editor::NotifyModifyAttempt(Document
*, void *) {
1518 //Platform::DebugPrintf("** Modify Attempt\n");
1519 NotifyModifyAttempt();
1522 void Editor::NotifySavePoint(Document
*, void *, bool atSavePoint
) {
1523 //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
1524 NotifySavePoint(atSavePoint
);
1527 void Editor::NotifyModified(Document
*, DocModification mh
, void *) {
1528 needUpdateUI
= true;
1529 if (paintState
== painting
) {
1530 CheckForChangeOutsidePaint(Range(mh
.position
, mh
.position
+ mh
.length
));
1531 } else if (paintState
== notPainting
) {
1532 if (mh
.modificationType
& SC_MOD_CHANGESTYLE
) {
1533 if (mh
.position
< pdoc
->LineStart(topLine
)) {
1534 // Styling performed before this view
1537 InvalidateRange(mh
.position
, mh
.position
+ mh
.length
);
1540 // Move selection and brace highlights
1541 if (mh
.modificationType
& SC_MOD_INSERTTEXT
) {
1542 if (currentPos
> mh
.position
) {
1543 currentPos
+= mh
.length
;
1545 if (anchor
> mh
.position
) {
1546 anchor
+= mh
.length
;
1548 if (braces
[0] > mh
.position
) {
1549 braces
[0] += mh
.length
;
1551 if (braces
[1] > mh
.position
) {
1552 braces
[1] += mh
.length
;
1554 } else { // SC_MOD_DELETETEXT
1555 int endPos
= mh
.position
+ mh
.length
;
1556 if (currentPos
> mh
.position
) {
1557 if (currentPos
> endPos
) {
1558 currentPos
-= mh
.length
;
1560 currentPos
= endPos
;
1563 if (anchor
> mh
.position
) {
1564 if (anchor
> endPos
) {
1565 anchor
-= mh
.length
;
1570 if (braces
[0] > mh
.position
) {
1571 if (braces
[0] > endPos
) {
1572 braces
[0] -= mh
.length
;
1577 if (braces
[1] > mh
.position
) {
1578 if (braces
[1] > endPos
) {
1579 braces
[1] -= mh
.length
;
1585 if (mh
.linesAdded
!= 0) {
1587 // Update contraction state for inserted and removed lines
1588 // lineOfPos should be calculated in context of state before modification, shouldn't it
1589 int lineOfPos
= pdoc
->LineFromPosition(mh
.position
);
1590 if (mh
.linesAdded
> 0) {
1591 NotifyNeedShown(mh
.position
, mh
.length
);
1592 cs
.InsertLines(lineOfPos
, mh
.linesAdded
);
1594 cs
.DeleteLines(lineOfPos
, -mh
.linesAdded
);
1596 // Avoid scrolling of display if change before current display
1597 if (mh
.position
< posTopLine
) {
1598 int newTop
= Platform::Clamp(topLine
+ mh
.linesAdded
, 0, MaxScrollPos());
1599 if (newTop
!= topLine
) {
1601 SetVerticalScrollPos();
1605 //Platform::DebugPrintf("** %x Doc Changed\n", this);
1606 // TODO: could invalidate from mh.startModification to end of screen
1607 //InvalidateRange(mh.position, mh.position + mh.length);
1610 //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
1611 // mh.position, mh.position + mh.length);
1612 InvalidateRange(mh
.position
, mh
.position
+ mh
.length
);
1615 } // else paintState == paintAbandoned so no need to do anything
1617 if (mh
.linesAdded
!= 0) {
1621 if (mh
.modificationType
& SC_MOD_CHANGEMARKER
) {
1625 // If client wants to see this modification
1626 if (mh
.modificationType
& modEventMask
) {
1627 if ((mh
.modificationType
& SC_MOD_CHANGESTYLE
) == 0) {
1628 // Real modification made to text of document.
1629 NotifyChange(); // Send EN_CHANGE
1632 scn
.nmhdr
.code
= SCN_MODIFIED
;
1633 scn
.position
= mh
.position
;
1634 scn
.modificationType
= mh
.modificationType
;
1636 scn
.length
= mh
.length
;
1637 scn
.linesAdded
= mh
.linesAdded
;
1639 scn
.foldLevelNow
= mh
.foldLevelNow
;
1640 scn
.foldLevelPrev
= mh
.foldLevelPrev
;
1645 void Editor::NotifyDeleted(Document
*document
, void *userData
) {
1649 #ifdef MACRO_SUPPORT
1650 void Editor::NotifyMacroRecord(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
1652 // Enumerates all macroable messages
1660 case SCI_INSERTTEXT
:
1665 case SCI_SEARCHANCHOR
:
1666 case SCI_SEARCHNEXT
:
1667 case SCI_SEARCHPREV
:
1669 case SCI_LINEDOWNEXTEND
:
1671 case SCI_LINEUPEXTEND
:
1673 case SCI_CHARLEFTEXTEND
:
1675 case SCI_CHARRIGHTEXTEND
:
1677 case SCI_WORDLEFTEXTEND
:
1679 case SCI_WORDRIGHTEXTEND
:
1681 case SCI_HOMEEXTEND
:
1683 case SCI_LINEENDEXTEND
:
1684 case SCI_DOCUMENTSTART
:
1685 case SCI_DOCUMENTSTARTEXTEND
:
1686 case SCI_DOCUMENTEND
:
1687 case SCI_DOCUMENTENDEXTEND
:
1689 case SCI_PAGEUPEXTEND
:
1691 case SCI_PAGEDOWNEXTEND
:
1692 case SCI_EDITTOGGLEOVERTYPE
:
1694 case SCI_DELETEBACK
:
1700 case SCI_VCHOMEEXTEND
:
1701 case SCI_DELWORDLEFT
:
1702 case SCI_DELWORDRIGHT
:
1704 case SCI_LINEDELETE
:
1705 case SCI_LINETRANSPOSE
:
1710 // Filter out all others (display changes, etc)
1712 // printf("Filtered out %ld of macro recording\n", iMessage);
1716 // Send notification
1718 scn
.nmhdr
.code
= SCN_MACRORECORD
;
1719 scn
.message
= iMessage
;
1720 scn
.wParam
= wParam
;
1721 scn
.lParam
= lParam
;
1726 // Force scroll and keep position relative to top of window
1727 void Editor::PageMove(int direction
, bool extend
) {
1728 Point pt
= LocationFromPosition(currentPos
);
1729 int topLineNew
= Platform::Clamp(
1730 topLine
+ direction
* LinesToScroll(), 0, MaxScrollPos());
1731 int newPos
= PositionFromLocation(
1732 Point(lastXChosen
, pt
.y
+ direction
* (vs
.lineHeight
* LinesToScroll())));
1733 if (topLineNew
!= topLine
) {
1734 SetTopLine(topLineNew
);
1735 MovePositionTo(newPos
, extend
);
1737 SetVerticalScrollPos();
1739 MovePositionTo(newPos
, extend
);
1743 void Editor::ChangeCaseOfSelection(bool makeUpperCase
) {
1744 pdoc
->BeginUndoAction();
1745 int startCurrent
= currentPos
;
1746 int startAnchor
= anchor
;
1747 if (selType
== selRectangle
) {
1748 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
1749 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
1750 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
1752 Range(SelectionStart(line
), SelectionEnd(line
)),
1755 // Would be nicer to keep the rectangular selection but this is complex
1756 selType
= selStream
;
1757 SetSelection(startCurrent
, startCurrent
);
1759 pdoc
->ChangeCase(Range(SelectionStart(), SelectionEnd()),
1761 SetSelection(startCurrent
, startAnchor
);
1763 pdoc
->EndUndoAction();
1767 void Editor::LineTranspose() {
1768 int line
= pdoc
->LineFromPosition(currentPos
);
1770 int startPrev
= pdoc
->LineStart(line
-1);
1771 int endPrev
= pdoc
->LineEnd(line
-1);
1772 int start
= pdoc
->LineStart(line
);
1773 int end
= pdoc
->LineEnd(line
);
1774 int startNext
= pdoc
->LineStart(line
+1);
1775 if (end
< pdoc
->Length()) {
1777 char *thisLine
= CopyRange(start
, end
);
1778 pdoc
->DeleteChars(start
, end
-start
);
1779 pdoc
->InsertString(startPrev
, thisLine
, end
-start
);
1780 MovePositionTo(startPrev
+end
-start
);
1783 // Last line so line has no line end
1784 char *thisLine
= CopyRange(start
, end
);
1785 char *prevEnd
= CopyRange(endPrev
, start
);
1786 pdoc
->DeleteChars(endPrev
, end
-endPrev
);
1787 pdoc
->InsertString(startPrev
, thisLine
, end
-start
);
1788 pdoc
->InsertString(startPrev
+ end
-start
, prevEnd
, start
-endPrev
);
1789 MovePositionTo(startPrev
+ end
-endPrev
);
1797 int Editor::KeyCommand(UINT iMessage
) {
1798 Point pt
= LocationFromPosition(currentPos
);
1802 MovePositionTo(PositionFromLocation(
1803 Point(lastXChosen
, pt
.y
+ vs
.lineHeight
)));
1805 case SCI_LINEDOWNEXTEND
:
1806 MovePositionTo(PositionFromLocation(
1807 Point(lastXChosen
, pt
.y
+ vs
.lineHeight
)), true);
1810 MovePositionTo(PositionFromLocation(
1811 Point(lastXChosen
, pt
.y
- vs
.lineHeight
)));
1813 case SCI_LINEUPEXTEND
:
1814 MovePositionTo(PositionFromLocation(
1815 Point(lastXChosen
, pt
.y
- vs
.lineHeight
)), true);
1818 if (SelectionEmpty()) {
1819 MovePositionTo(MovePositionSoVisible(currentPos
- 1, -1));
1821 MovePositionTo(SelectionStart());
1825 case SCI_CHARLEFTEXTEND
:
1826 MovePositionTo(MovePositionSoVisible(currentPos
- 1, -1), true);
1830 if (SelectionEmpty()) {
1831 MovePositionTo(MovePositionSoVisible(currentPos
+ 1, 1));
1833 MovePositionTo(SelectionEnd());
1837 case SCI_CHARRIGHTEXTEND
:
1838 MovePositionTo(MovePositionSoVisible(currentPos
+ 1, 1), true);
1842 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1));
1845 case SCI_WORDLEFTEXTEND
:
1846 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1), true);
1850 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1));
1853 case SCI_WORDRIGHTEXTEND
:
1854 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1), true);
1858 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)));
1861 case SCI_HOMEEXTEND
:
1862 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), true);
1866 MovePositionTo(pdoc
->LineEndPosition(currentPos
));
1869 case SCI_LINEENDEXTEND
:
1870 MovePositionTo(pdoc
->LineEndPosition(currentPos
), true);
1873 case SCI_DOCUMENTSTART
:
1877 case SCI_DOCUMENTSTARTEXTEND
:
1878 MovePositionTo(0, true);
1881 case SCI_DOCUMENTEND
:
1882 MovePositionTo(pdoc
->Length());
1885 case SCI_DOCUMENTENDEXTEND
:
1886 MovePositionTo(pdoc
->Length(), true);
1892 case SCI_PAGEUPEXTEND
:
1893 PageMove( -1, true);
1898 case SCI_PAGEDOWNEXTEND
:
1901 case SCI_EDITTOGGLEOVERTYPE
:
1902 inOverstrike
= !inOverstrike
;
1904 ShowCaretAtCurrentPosition();
1906 case SCI_CANCEL
: // Cancel any modes - handled in subclass
1907 // Also unselect text
1908 SetEmptySelection(currentPos
);
1910 case SCI_DELETEBACK
:
1912 EnsureCaretVisible();
1922 if (pdoc
->eolMode
== SC_EOL_CRLF
) {
1923 pdoc
->InsertString(currentPos
, "\r\n");
1924 SetEmptySelection(currentPos
+ 2);
1927 } else if (pdoc
->eolMode
== SC_EOL_CR
) {
1928 pdoc
->InsertChar(currentPos
, '\r');
1929 SetEmptySelection(currentPos
+ 1);
1931 } else if (pdoc
->eolMode
== SC_EOL_LF
) {
1932 pdoc
->InsertChar(currentPos
, '\n');
1933 SetEmptySelection(currentPos
+ 1);
1937 EnsureCaretVisible();
1943 MovePositionTo(pdoc
->VCHomePosition(currentPos
));
1946 case SCI_VCHOMEEXTEND
:
1947 MovePositionTo(pdoc
->VCHomePosition(currentPos
), true);
1951 if (vs
.zoomLevel
< 20)
1953 InvalidateStyleRedraw();
1956 if (vs
.zoomLevel
> -10)
1958 InvalidateStyleRedraw();
1960 case SCI_DELWORDLEFT
: {
1961 int startWord
= pdoc
->NextWordStart(currentPos
, -1);
1962 pdoc
->DeleteChars(startWord
, currentPos
- startWord
);
1963 MovePositionTo(startWord
);
1966 case SCI_DELWORDRIGHT
: {
1967 int endWord
= pdoc
->NextWordStart(currentPos
, 1);
1968 pdoc
->DeleteChars(currentPos
, endWord
- currentPos
);
1969 MovePositionTo(currentPos
);
1973 int lineStart
= pdoc
->LineFromPosition(currentPos
);
1974 int lineEnd
= pdoc
->LineFromPosition(anchor
);
1975 if (lineStart
> lineEnd
) {
1977 lineEnd
= lineStart
;
1980 int start
= pdoc
->LineStart(lineStart
);
1981 int end
= pdoc
->LineStart(lineEnd
+1);
1982 SetSelection(start
,end
);
1986 case SCI_LINEDELETE
: {
1987 int line
= pdoc
->LineFromPosition(currentPos
);
1988 int start
= pdoc
->LineStart(line
);
1989 int end
= pdoc
->LineStart(line
+1);
1990 pdoc
->DeleteChars(start
, end
-start
);
1991 MovePositionTo(start
);
1994 case SCI_LINETRANSPOSE
:
1998 ChangeCaseOfSelection(false);
2001 ChangeCaseOfSelection(true);
2007 int Editor::KeyDefault(int, int) {
2011 int Editor::KeyDown(int key
, bool shift
, bool ctrl
, bool alt
) {
2012 int modifiers
= (shift
? SCI_SHIFT
: 0) | (ctrl
? SCI_CTRL
: 0) |
2013 (alt
? SCI_ALT
: 0);
2014 int msg
= kmap
.Find(key
, modifiers
);
2016 return WndProc(msg
, 0, 0);
2018 return KeyDefault(key
, modifiers
);
2021 void Editor::SetWhitespaceVisible(bool view
) {
2022 vs
.viewWhitespace
= view
;
2025 bool Editor::GetWhitespaceVisible() {
2026 return vs
.viewWhitespace
;
2029 void Editor::Indent(bool forwards
) {
2030 //Platform::DebugPrintf("INdent %d\n", forwards);
2031 int lineOfAnchor
= pdoc
->LineFromPosition(anchor
);
2032 int lineCurrentPos
= pdoc
->LineFromPosition(currentPos
);
2033 if (lineOfAnchor
== lineCurrentPos
) {
2035 pdoc
->InsertChar(currentPos
, '\t');
2036 //pdoc->InsertChar(currentPos++, '\t');
2037 SetEmptySelection(currentPos
+ 1);
2039 int anchorPosOnLine
= anchor
- pdoc
->LineStart(lineOfAnchor
);
2040 int currentPosPosOnLine
= currentPos
- pdoc
->LineStart(lineCurrentPos
);
2041 // Multiple lines selected so indent / dedent
2042 int lineTopSel
= Platform::Minimum(lineOfAnchor
, lineCurrentPos
);
2043 int lineBottomSel
= Platform::Maximum(lineOfAnchor
, lineCurrentPos
);
2044 if (pdoc
->LineStart(lineBottomSel
) == anchor
|| pdoc
->LineStart(lineBottomSel
) == currentPos
)
2045 lineBottomSel
--; // If not selecting any characters on a line, do not indent
2046 pdoc
->BeginUndoAction();
2047 pdoc
->Indent(forwards
, lineBottomSel
, lineTopSel
);
2048 pdoc
->EndUndoAction();
2049 if (lineOfAnchor
< lineCurrentPos
) {
2050 if (currentPosPosOnLine
== 0)
2051 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
));
2053 SetSelection(pdoc
->LineStart(lineCurrentPos
+ 1), pdoc
->LineStart(lineOfAnchor
));
2055 if (anchorPosOnLine
== 0)
2056 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
));
2058 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
+ 1));
2063 long Editor::FindText(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
2064 FINDTEXTEX
*ft
= reinterpret_cast<FINDTEXTEX
*>(lParam
);
2065 int pos
= pdoc
->FindText(ft
->chrg
.cpMin
, ft
->chrg
.cpMax
, ft
->lpstrText
,
2066 wParam
& FR_MATCHCASE
, wParam
& FR_WHOLEWORD
);
2068 if (iMessage
== EM_FINDTEXTEX
) {
2069 ft
->chrgText
.cpMin
= pos
;
2070 ft
->chrgText
.cpMax
= pos
+ strlen(ft
->lpstrText
);
2076 // Relocatable search support : Searches relative to current selection
2077 // point and sets the selection to the found text range with
2080 // Anchor following searches at current selection start: This allows
2081 // multiple incremental interactive searches to be macro recorded
2082 // while still setting the selection to found text so the find/select
2083 // operation is self-contained.
2084 void Editor::SearchAnchor() {
2085 searchAnchor
= SelectionStart();
2088 // Find text from current search anchor: Must call SearchAnchor first.
2089 // Accepts both SCI_SEARCHNEXT and SCI_SEARCHPREV.
2090 // wParam contains search modes : ORed FR_MATCHCASE and FR_WHOLEWORD.
2091 // lParam contains the text to search for.
2092 long Editor::SearchText(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
2093 const char *txt
= reinterpret_cast<char *>(lParam
);
2096 if (iMessage
== SCI_SEARCHNEXT
) {
2097 pos
= pdoc
->FindText(searchAnchor
, pdoc
->Length(), txt
,
2098 wParam
& FR_MATCHCASE
,
2099 wParam
& FR_WHOLEWORD
);
2101 pos
= pdoc
->FindText(searchAnchor
, 0, txt
,
2102 wParam
& FR_MATCHCASE
,
2103 wParam
& FR_WHOLEWORD
);
2107 SetSelection(pos
, pos
+ strlen(txt
));
2113 void Editor::GoToLine(int lineNo
) {
2114 if (lineNo
> pdoc
->LinesTotal())
2115 lineNo
= pdoc
->LinesTotal();
2118 SetEmptySelection(pdoc
->LineStart(lineNo
));
2119 ShowCaretAtCurrentPosition();
2120 EnsureCaretVisible();
2123 static bool Close(Point pt1
, Point pt2
) {
2124 if (abs(pt1
.x
- pt2
.x
) > 3)
2126 if (abs(pt1
.y
- pt2
.y
) > 3)
2131 char *Editor::CopyRange(int start
, int end
) {
2134 int len
= end
- start
;
2135 text
= new char[len
+ 1];
2137 for (int i
= 0; i
< len
; i
++) {
2138 text
[i
] = pdoc
->CharAt(start
+ i
);
2146 int Editor::SelectionRangeLength() {
2147 if (selType
== selRectangle
) {
2148 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
2149 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
2151 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
2152 totalSize
+= SelectionEnd(line
) - SelectionStart(line
) + 1;
2153 if (pdoc
->eolMode
== SC_EOL_CRLF
)
2158 return SelectionEnd() - SelectionStart();
2162 char *Editor::CopySelectionRange() {
2163 if (selType
== selRectangle
) {
2165 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
2166 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
2167 int totalSize
= SelectionRangeLength();
2168 if (totalSize
> 0) {
2169 text
= new char[totalSize
+ 1];
2172 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
2173 for (int i
=SelectionStart(line
);i
<SelectionEnd(line
);i
++) {
2174 text
[j
++] = pdoc
->CharAt(i
);
2176 if (pdoc
->eolMode
!= SC_EOL_LF
)
2178 if (pdoc
->eolMode
!= SC_EOL_CR
)
2181 text
[totalSize
] = '\0';
2186 return CopyRange(SelectionStart(), SelectionEnd());
2190 void Editor::CopySelectionIntoDrag() {
2193 lenDrag
= SelectionRangeLength();
2194 dragChars
= CopySelectionRange();
2195 dragIsRectangle
= selType
== selRectangle
;
2201 void Editor::SetDragPosition(int newPos
) {
2203 newPos
= pdoc
->MovePositionOutsideChar(newPos
, 1);
2206 if (posDrag
!= newPos
) {
2215 void Editor::StartDrag() {
2216 // Always handled by subclasses
2217 //SetMouseCapture(true);
2218 //wDraw.SetCursor(Window::cursorArrow);
2221 void Editor::DropAt(int position
, const char *value
, bool moving
, bool rectangular
) {
2222 //Platform::DebugPrintf("DropAt %d\n", inDragDrop);
2224 dropWentOutside
= false;
2226 int positionWasInSelection
= PositionInSelection(position
);
2228 bool positionOnEdgeOfSelection
=
2229 (position
== SelectionStart()) || (position
== SelectionEnd());
2231 if ((!inDragDrop
) || !(0 == positionWasInSelection
) ||
2232 (positionOnEdgeOfSelection
&& !moving
)) {
2234 int selStart
= SelectionStart();
2235 int selEnd
= SelectionEnd();
2237 pdoc
->BeginUndoAction();
2239 int positionAfterDeletion
= position
;
2240 if (inDragDrop
&& moving
) {
2241 // Remove dragged out text
2243 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
2244 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
2245 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
2246 int startPos
= SelectionStart(line
);
2247 int endPos
= SelectionEnd(line
);
2248 if (position
>= startPos
) {
2249 if (position
> endPos
) {
2250 positionAfterDeletion
-= endPos
- startPos
;
2252 positionAfterDeletion
-= position
- startPos
;
2257 if (position
> selStart
) {
2258 positionAfterDeletion
-= selEnd
- selStart
;
2263 position
= positionAfterDeletion
;
2266 PasteRectangular(position
, value
, strlen(value
));
2267 pdoc
->EndUndoAction();
2268 // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
2269 SetSelection(position
, position
);
2271 position
= pdoc
->MovePositionOutsideChar(position
, currentPos
- position
);
2272 pdoc
->InsertString(position
, value
);
2273 pdoc
->EndUndoAction();
2274 SetSelection(position
+ strlen(value
), position
);
2276 } else if (inDragDrop
) {
2277 SetSelection(position
, position
);
2281 static int BeforeInOrAfter(int val
, int minim
, int maxim
) {
2284 else if (val
> maxim
)
2290 int Editor::PositionInSelection(int pos
) {
2291 pos
= pdoc
->MovePositionOutsideChar(pos
, currentPos
- pos
);
2292 if (selType
== selRectangle
) {
2293 if (pos
< SelectionStart())
2295 if (pos
> SelectionEnd())
2297 int linePos
= pdoc
->LineFromPosition(pos
);
2298 return BeforeInOrAfter(pos
, SelectionStart(linePos
), SelectionEnd(linePos
));
2300 if (currentPos
> anchor
) {
2301 return BeforeInOrAfter(pos
, anchor
, currentPos
);
2302 } else if (currentPos
< anchor
) {
2303 return BeforeInOrAfter(pos
, currentPos
, anchor
);
2309 bool Editor::PointInSelection(Point pt
) {
2310 // TODO: fix up for rectangular selection
2311 int pos
= PositionFromLocation(pt
);
2312 if (0 == PositionInSelection(pos
)) {
2313 if (pos
== SelectionStart()) {
2314 // see if just before selection
2315 Point locStart
= LocationFromPosition(pos
);
2316 if (pt
.x
< locStart
.x
)
2319 if (pos
== SelectionEnd()) {
2320 // see if just after selection
2321 Point locEnd
= LocationFromPosition(pos
);
2322 if (pt
.x
> locEnd
.x
)
2330 bool Editor::PointInSelMargin(Point pt
) {
2331 // Really means: "Point in a margin"
2332 if (vs
.fixedColumnWidth
> 0) { // There is a margin
2333 PRectangle rcSelMargin
= GetClientRectangle();
2334 rcSelMargin
.right
= vs
.fixedColumnWidth
- vs
.leftMarginWidth
;
2335 return rcSelMargin
.Contains(pt
);
2341 void Editor::ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
) {
2342 //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);
2344 int newPos
= PositionFromLocation(pt
);
2345 newPos
= pdoc
->MovePositionOutsideChar(newPos
, currentPos
- newPos
);
2348 bool processed
= NotifyMarginClick(pt
, shift
, ctrl
, alt
);
2353 SetSelection(newPos
);
2355 if (((curTime
- lastClickTime
) < Platform::DoubleClickTime()) && Close(pt
, lastClick
)) {
2356 //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
2357 SetMouseCapture(true);
2358 SetEmptySelection(newPos
);
2359 bool doubleClick
= false;
2360 // Stop mouse button bounce changing selection type
2361 if (curTime
!= lastClickTime
) {
2362 if (selectionType
== selChar
) {
2363 selectionType
= selWord
;
2365 } else if (selectionType
== selWord
) {
2366 selectionType
= selLine
;
2368 selectionType
= selChar
;
2369 originalAnchorPos
= currentPos
;
2373 if (selectionType
== selWord
) {
2374 if (currentPos
>= originalAnchorPos
) { // Moved forward
2375 SetSelection(pdoc
->ExtendWordSelect(currentPos
, 1),
2376 pdoc
->ExtendWordSelect(originalAnchorPos
, -1));
2377 } else { // Moved backward
2378 SetSelection(pdoc
->ExtendWordSelect(currentPos
, -1),
2379 pdoc
->ExtendWordSelect(originalAnchorPos
, 1));
2381 } else if (selectionType
== selLine
) {
2382 lineAnchor
= LineFromLocation(pt
);
2383 SetSelection(pdoc
->LineStart(lineAnchor
+ 1), pdoc
->LineStart(lineAnchor
));
2384 //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
2387 SetEmptySelection(currentPos
);
2389 //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
2391 NotifyDoubleClick(pt
, shift
);
2392 } else { // Single click
2393 if (PointInSelMargin(pt
)) {
2396 lastClickTime
= curTime
;
2399 lineAnchor
= LineFromLocation(pt
);
2400 // While experimenting with folding turn off line selection
2402 // Single click in margin: select whole line
2403 SetSelection(pdoc
->LineStart(lineAnchor
+ 1), pdoc
->LineStart(lineAnchor
));
2405 // Single shift+click in margin: select from anchor to beginning of clicked line
2406 SetSelection(pdoc
->LineStart(lineAnchor
), anchor
);
2408 SetDragPosition(invalidPosition
);
2409 SetMouseCapture(true);
2410 selectionType
= selLine
;
2413 inDragDrop
= PointInSelection(pt
);
2416 SetMouseCapture(false);
2417 SetDragPosition(newPos
);
2418 CopySelectionIntoDrag();
2421 selType
= alt
? selRectangle
: selStream
;
2422 xStartSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2423 xEndSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2424 SetDragPosition(invalidPosition
);
2425 SetMouseCapture(true);
2427 SetEmptySelection(newPos
);
2428 selectionType
= selChar
;
2429 originalAnchorPos
= currentPos
;
2433 lastClickTime
= curTime
;
2435 ShowCaretAtCurrentPosition();
2438 void Editor::ButtonMove(Point pt
) {
2439 //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
2440 if (HaveMouseCapture()) {
2441 xEndSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2443 int movePos
= PositionFromLocation(pt
);
2444 movePos
= pdoc
->MovePositionOutsideChar(movePos
, currentPos
- movePos
);
2446 SetDragPosition(movePos
);
2448 if (selectionType
== selChar
) {
2449 SetSelection(movePos
);
2450 } else if (selectionType
== selWord
) {
2451 // Continue selecting by word
2452 if (currentPos
> originalAnchorPos
) { // Moved forward
2453 SetSelection(pdoc
->ExtendWordSelect(movePos
, 1),
2454 pdoc
->ExtendWordSelect(originalAnchorPos
, -1));
2455 } else { // Moved backward
2456 SetSelection(pdoc
->ExtendWordSelect(movePos
, -1),
2457 pdoc
->ExtendWordSelect(originalAnchorPos
, 1));
2460 // Continue selecting by line
2461 int lineMove
= LineFromLocation(pt
);
2462 if (lineAnchor
< lineMove
) {
2463 SetSelection(pdoc
->LineStart(lineMove
+ 1),
2464 pdoc
->LineStart(lineAnchor
));
2466 SetSelection(pdoc
->LineStart(lineMove
),
2467 pdoc
->LineStart(lineAnchor
+ 1));
2471 EnsureCaretVisible(false);
2473 if (vs
.fixedColumnWidth
> 0) { // There is a margin
2474 if (PointInSelMargin(pt
)) {
2475 wDraw
.SetCursor(Window::cursorReverseArrow
);
2476 return; // No need to test for selection
2479 // Display regular (drag) cursor over selection
2480 if (PointInSelection(pt
))
2481 wDraw
.SetCursor(Window::cursorArrow
);
2483 wDraw
.SetCursor(Window::cursorText
);
2488 void Editor::ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
) {
2489 //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
2490 if (HaveMouseCapture()) {
2491 if (PointInSelMargin(pt
)) {
2492 wDraw
.SetCursor(Window::cursorReverseArrow
);
2494 wDraw
.SetCursor(Window::cursorText
);
2496 xEndSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2498 SetMouseCapture(false);
2499 int newPos
= PositionFromLocation(pt
);
2500 newPos
= pdoc
->MovePositionOutsideChar(newPos
, currentPos
- newPos
);
2502 int selStart
= SelectionStart();
2503 int selEnd
= SelectionEnd();
2504 if (selStart
< selEnd
) {
2505 if (dragChars
&& lenDrag
) {
2507 pdoc
->InsertString(newPos
, dragChars
, lenDrag
);
2508 SetSelection(newPos
, newPos
+ lenDrag
);
2509 } else if (newPos
< selStart
) {
2510 pdoc
->DeleteChars(selStart
, lenDrag
);
2511 pdoc
->InsertString(newPos
, dragChars
, lenDrag
);
2512 SetSelection(newPos
, newPos
+ lenDrag
);
2513 } else if (newPos
> selEnd
) {
2514 pdoc
->DeleteChars(selStart
, lenDrag
);
2516 pdoc
->InsertString(newPos
, dragChars
, lenDrag
);
2517 SetSelection(newPos
, newPos
+ lenDrag
);
2519 SetEmptySelection(newPos
);
2525 selectionType
= selChar
;
2528 if (selectionType
== selChar
) {
2529 SetSelection(newPos
);
2532 lastClickTime
= curTime
;
2536 EnsureCaretVisible(false);
2540 // Called frequently to perform background UI including
2541 // caret blinking and automatic scrolling.
2542 void Editor::Tick() {
2543 if (HaveMouseCapture()) {
2545 ButtonMove(ptMouseLast
);
2547 if (caret
.period
> 0) {
2548 timer
.ticksToWait
-= timer
.tickSize
;
2549 if (timer
.ticksToWait
<= 0) {
2550 caret
.on
= !caret
.on
;
2551 timer
.ticksToWait
= caret
.period
;
2557 static bool IsIn(int a
, int minimum
, int maximum
) {
2558 return (a
>= minimum
) && (a
<= maximum
);
2561 static bool IsOverlap(int mina
, int maxa
, int minb
, int maxb
) {
2563 IsIn(mina
, minb
, maxb
) ||
2564 IsIn(maxa
, minb
, maxb
) ||
2565 IsIn(minb
, mina
, maxa
) ||
2566 IsIn(maxb
, mina
, maxa
);
2569 void Editor::CheckForChangeOutsidePaint(Range r
) {
2570 if (paintState
== painting
&& !paintingAllText
) {
2571 //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
2575 PRectangle rcText
= GetTextRectangle();
2576 // Determine number of lines displayed including a possible partially displayed last line
2577 int linesDisplayed
= (rcText
.bottom
- rcText
.top
- 1) / vs
.lineHeight
+ 1;
2578 int bottomLine
= topLine
+ linesDisplayed
- 1;
2580 int lineRangeStart
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.start
));
2581 int lineRangeEnd
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.end
));
2582 if (!IsOverlap(topLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) {
2583 //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
2584 // lineRangeStart, lineRangeEnd, topLine, bottomLine);
2588 // Assert rcPaint contained within or equal to rcText
2589 if (rcPaint
.top
> rcText
.top
) {
2590 // does range intersect rcText.top .. rcPaint.top
2591 int paintTopLine
= ((rcPaint
.top
- rcText
.top
-1) / vs
.lineHeight
) + topLine
;
2592 // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
2593 if (IsOverlap(topLine
, paintTopLine
, lineRangeStart
, lineRangeEnd
)) {
2594 //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n",
2595 // lineRangeStart, lineRangeEnd, topLine, paintTopLine);
2596 paintState
= paintAbandoned
;
2600 if (rcPaint
.bottom
< rcText
.bottom
) {
2601 // does range intersect rcPaint.bottom .. rcText.bottom
2602 int paintBottomLine
= ((rcPaint
.bottom
- rcText
.top
-1) / vs
.lineHeight
+ 1) + topLine
;
2603 // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
2604 if (IsOverlap(paintBottomLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) {
2605 //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n",
2606 // lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
2607 paintState
= paintAbandoned
;
2614 char BraceOpposite(char ch
) {
2616 case '(': return ')';
2617 case ')': return '(';
2618 case '[': return ']';
2619 case ']': return '[';
2620 case '{': return '}';
2621 case '}': return '{';
2622 case '<': return '>';
2623 case '>': return '<';
2624 default: return '\0';
2628 // TODO: should be able to extend styled region to find matching brace
2629 // TODO: may need to make DBCS safe
2630 // so should be moved into Document
2631 int Editor::BraceMatch(int position
, int maxReStyle
) {
2632 char chBrace
= pdoc
->CharAt(position
);
2633 char chSeek
= BraceOpposite(chBrace
);
2636 char styBrace
= pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
;
2638 if (chBrace
== '(' || chBrace
== '[' || chBrace
== '{' || chBrace
== '<')
2641 position
= position
+ direction
;
2642 while ((position
>= 0) && (position
< pdoc
->Length())) {
2643 char chAtPos
= pdoc
->CharAt(position
);
2644 char styAtPos
= pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
;
2645 if ((position
> pdoc
->GetEndStyled()) || (styAtPos
== styBrace
)) {
2646 if (chAtPos
== chBrace
)
2648 if (chAtPos
== chSeek
)
2653 position
= position
+ direction
;
2658 void Editor::SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
) {
2659 if ((pos0
!= braces
[0]) || (pos1
!= braces
[1]) || (matchStyle
!= bracesMatchStyle
)) {
2660 if ((braces
[0] != pos0
) || (matchStyle
!= bracesMatchStyle
)) {
2661 CheckForChangeOutsidePaint(Range(braces
[0]));
2662 CheckForChangeOutsidePaint(Range(pos0
));
2665 if ((braces
[1] != pos1
) || (matchStyle
!= bracesMatchStyle
)) {
2666 CheckForChangeOutsidePaint(Range(braces
[1]));
2667 CheckForChangeOutsidePaint(Range(pos1
));
2670 bracesMatchStyle
= matchStyle
;
2671 if (paintState
== notPainting
) {
2677 void Editor::SetDocPointer(Document
*document
) {
2678 //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
2679 pdoc
->RemoveWatcher(this, 0);
2681 if (document
== NULL
) {
2682 pdoc
= new Document();
2687 // Reset the contraction state to fully shown.
2689 cs
.InsertLines(0, pdoc
->LinesTotal()-1);
2691 pdoc
->AddWatcher(this, 0);
2696 // Recursively expand a fold, making lines visible except where they have an unexpanded parent
2697 void Editor::Expand(int &line
, bool doExpand
) {
2698 int lineMaxSubord
= pdoc
->GetLastChild(line
);
2700 while (line
<= lineMaxSubord
) {
2702 cs
.SetVisible(line
, line
, true);
2703 int level
= pdoc
->GetLevel(line
);
2704 if (level
& SC_FOLDLEVELHEADERFLAG
) {
2705 if (doExpand
&& cs
.GetExpanded(line
)) {
2708 Expand(line
, false);
2716 void Editor::ToggleContraction(int line
) {
2717 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
2718 if (cs
.GetExpanded(line
)) {
2719 int lineMaxSubord
= pdoc
->GetLastChild(line
);
2720 cs
.SetExpanded(line
, 0);
2721 if (lineMaxSubord
> line
) {
2722 cs
.SetVisible(line
+1, lineMaxSubord
, false);
2727 cs
.SetExpanded(line
, 1);
2735 // Recurse up from this line to find any folds that prevent this line from being visible
2736 // and unfold them all.
2737 void Editor::EnsureLineVisible(int line
) {
2738 if (!cs
.GetVisible(line
)) {
2739 int lineParent
= pdoc
->GetFoldParent(line
);
2740 if (lineParent
>= 0) {
2741 if (line
!= lineParent
)
2742 EnsureLineVisible(lineParent
);
2743 if (!cs
.GetExpanded(lineParent
)) {
2744 cs
.SetExpanded(lineParent
, 1);
2745 Expand(lineParent
, true);
2753 LRESULT
Editor::WndProc(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
2754 //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
2756 // Optional macro recording hook
2757 #ifdef MACRO_SUPPORT
2759 NotifyMacroRecord(iMessage
, wParam
, lParam
);
2768 char *ptr
= reinterpret_cast<char *>(lParam
);
2769 unsigned int iChar
= 0;
2770 for (; iChar
< wParam
-1; iChar
++)
2771 ptr
[iChar
] = pdoc
->CharAt(iChar
);
2780 pdoc
->DeleteChars(0, pdoc
->Length());
2781 SetEmptySelection(0);
2782 pdoc
->InsertString(0, reinterpret_cast<char *>(lParam
));
2786 case WM_GETTEXTLENGTH
:
2787 return pdoc
->Length();
2790 //Platform::DebugPrintf("S notify %d %d\n", wParam, lParam);
2805 EnsureCaretVisible();
2818 // Edit control mesages
2820 // Not supported (no-ops):
2821 // EM_GETWORDBREAKPROC
2822 // EM_GETWORDBREAKPROCEX
2823 // EM_SETWORDBREAKPROC
2824 // EM_SETWORDBREAKPROCEX
2825 // EM_GETWORDWRAPMODE
2826 // EM_SETWORDWRAPMODE
2834 // EM_GETPASSWORDCHAR
2835 // EM_SETPASSWORDCHAR
2840 // EM_GETOLEINTERFACE
2841 // EM_SETOLEINTERFACE
2842 // EM_SETOLECALLBACK
2857 // EM_GETPUNCTUATION
2858 // EM_SETPUNCTUATION
2861 // Not supported but should be:
2866 // EM_SETTARGETDEVICE
2869 return pdoc
->CanUndo() ? TRUE
: FALSE
;
2875 case EM_EMPTYUNDOBUFFER
:
2876 pdoc
->DeleteUndoHistory();
2879 case EM_GETFIRSTVISIBLELINE
:
2885 int lineStart
= pdoc
->LineStart(wParam
);
2886 int lineEnd
= pdoc
->LineStart(wParam
+ 1);
2887 char *ptr
= reinterpret_cast<char *>(lParam
);
2888 WORD
*pBufSize
= reinterpret_cast<WORD
*>(lParam
);
2889 if (*pBufSize
< lineEnd
- lineStart
) {
2890 ptr
[0] = '\0'; // If no characters copied have to put a NUL into buffer
2894 for (int iChar
= lineStart
; iChar
< lineEnd
; iChar
++)
2895 ptr
[iPlace
++] = pdoc
->CharAt(iChar
);
2899 case EM_GETLINECOUNT
:
2900 if (pdoc
->LinesTotal() == 0)
2903 return pdoc
->LinesTotal();
2906 return !pdoc
->IsSavePoint();
2909 // Not really supported now that there is the save point stuff
2910 //pdoc->isModified = wParam;
2911 //return pdoc->isModified;
2917 *(reinterpret_cast<PRectangle
*>(lParam
)) = GetClientRectangle();
2922 *reinterpret_cast<int *>(wParam
) = SelectionStart();
2924 *reinterpret_cast<int *>(lParam
) = SelectionEnd();
2925 return MAKELONG(SelectionStart(), SelectionEnd());
2930 CHARRANGE
*pCR
= reinterpret_cast<CHARRANGE
*>(lParam
);
2931 pCR
->cpMin
= SelectionStart();
2932 pCR
->cpMax
= SelectionEnd();
2937 int nStart
= static_cast<int>(wParam
);
2938 int nEnd
= static_cast<int>(lParam
);
2940 nEnd
= pdoc
->Length();
2942 nStart
= nEnd
; // Remove selection
2943 SetSelection(nEnd
, nStart
);
2944 EnsureCaretVisible();
2951 CHARRANGE
*pCR
= reinterpret_cast<CHARRANGE
*>(lParam
);
2952 if (pCR
->cpMax
== -1) {
2953 SetSelection(pCR
->cpMin
, pdoc
->Length());
2955 SetSelection(pCR
->cpMin
, pCR
->cpMax
);
2957 EnsureCaretVisible();
2958 return pdoc
->LineFromPosition(SelectionStart());
2961 case EM_GETSELTEXT
: {
2964 char *ptr
= reinterpret_cast<char *>(lParam
);
2965 int selSize
= SelectionRangeLength();
2966 char *text
= CopySelectionRange();
2969 for (; iChar
< selSize
; iChar
++)
2970 ptr
[iChar
] = text
[iChar
];
2977 case EM_GETWORDBREAKPROC
:
2980 case EM_SETWORDBREAKPROC
:
2984 // wParam holds the number of characters control should be limited to
2987 case EM_GETLIMITTEXT
:
2990 case EM_GETOLEINTERFACE
:
2993 case EM_LINEFROMCHAR
:
2994 if (static_cast<int>(wParam
) < 0)
2995 wParam
= SelectionStart();
2996 return pdoc
->LineFromPosition(wParam
);
2998 case EM_EXLINEFROMCHAR
:
2999 if (static_cast<int>(lParam
) < 0)
3000 lParam
= SelectionStart(); // Not specified, but probably OK
3001 return pdoc
->LineFromPosition(lParam
);
3004 if (static_cast<int>(wParam
) < 0)
3005 wParam
= pdoc
->LineFromPosition(SelectionStart());
3007 return 0; // Even if there is no text, there is a first line that starts at 0
3008 if (static_cast<int>(wParam
) > pdoc
->LinesTotal())
3010 //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
3012 return pdoc
->LineStart(wParam
);
3016 if (static_cast<int>(wParam
) < 0) // Who use this anyway?
3017 return 0; // Should be... Too complex to describe here, see MS specs!
3018 if (static_cast<int>(wParam
) > pdoc
->Length()) // Useful test, anyway...
3020 int line
= pdoc
->LineFromPosition(wParam
);
3021 int charsOnLine
= 0;
3022 for (int pos
= pdoc
->LineStart(line
); pos
< pdoc
->LineStart(line
+ 1); pos
++) {
3023 if ((pdoc
->CharAt(pos
) != '\r') && (pdoc
->CharAt(pos
) != '\n'))
3029 // Replacement of the old Scintilla interpretation of EM_LINELENGTH
3030 case SCI_LINELENGTH
:
3031 if ((static_cast<int>(wParam
) < 0) ||
3032 (static_cast<int>(wParam
) > pdoc
->LineFromPosition(pdoc
->Length())))
3034 return pdoc
->LineStart(wParam
+ 1) - pdoc
->LineStart(wParam
);
3036 case EM_REPLACESEL
: {
3039 pdoc
->BeginUndoAction();
3041 char *replacement
= reinterpret_cast<char *>(lParam
);
3042 pdoc
->InsertString(currentPos
, replacement
);
3043 pdoc
->EndUndoAction();
3044 SetEmptySelection(currentPos
+ strlen(replacement
));
3045 EnsureCaretVisible();
3050 ScrollTo(topLine
+ lParam
);
3051 HorizontalScrollTo(xOffset
+ wParam
* vs
.spaceWidth
);
3054 case EM_SCROLLCARET
:
3055 EnsureCaretVisible();
3058 case EM_SETREADONLY
:
3059 pdoc
->SetReadOnly(wParam
);
3068 case EM_CHARFROMPOS
: {
3071 Point
*ppt
= reinterpret_cast<Point
*>(lParam
);
3072 int pos
= PositionFromLocation(*ppt
);
3073 int line
= pdoc
->LineFromPosition(pos
);
3074 return MAKELONG(pos
, line
);
3077 case EM_POSFROMCHAR
: {
3078 // The MS specs for this have changed 3 times: using the RichEdit 3 version
3081 Point
*ppt
= reinterpret_cast<Point
*>(wParam
);
3085 *ppt
= LocationFromPosition(lParam
);
3091 return FindText(iMessage
, wParam
, lParam
);
3094 return FindText(iMessage
, wParam
, lParam
);
3096 case EM_GETTEXTRANGE
: {
3099 TEXTRANGE
*tr
= reinterpret_cast<TEXTRANGE
*>(lParam
);
3100 int cpMax
= tr
->chrg
.cpMax
;
3102 cpMax
= pdoc
->Length();
3103 int len
= cpMax
- tr
->chrg
.cpMin
; // No -1 as cpMin and cpMax are referring to inter character positions
3104 pdoc
->GetCharRange(tr
->lpstrText
, tr
->chrg
.cpMin
, len
);
3105 // Spec says copied text is terminated with a NUL
3106 tr
->lpstrText
[len
] = '\0';
3107 return len
; // Not including NUL
3110 case EM_SELECTIONTYPE
:
3111 if (currentPos
== anchor
)
3116 case EM_HIDESELECTION
:
3117 hideSelection
= wParam
;
3121 case EM_FORMATRANGE
:
3122 return FormatRange(wParam
, reinterpret_cast<FORMATRANGE
*>(lParam
));
3125 return MAKELONG(vs
.leftMarginWidth
, vs
.rightMarginWidth
);
3128 if (wParam
& EC_LEFTMARGIN
) {
3129 vs
.leftMarginWidth
= LOWORD(lParam
);
3131 if (wParam
& EC_RIGHTMARGIN
) {
3132 vs
.rightMarginWidth
= HIWORD(lParam
);
3134 if (wParam
== EC_USEFONTINFO
) {
3135 vs
.leftMarginWidth
= vs
.aveCharWidth
/ 2;
3136 vs
.rightMarginWidth
= vs
.aveCharWidth
/ 2;
3138 InvalidateStyleRedraw();
3141 // Control specific mesages
3146 pdoc
->InsertString(CurrentPosition(), reinterpret_cast<char *>(lParam
), wParam
);
3147 SetEmptySelection(currentPos
+ wParam
);
3151 case SCI_ADDSTYLEDTEXT
: {
3154 pdoc
->InsertStyledString(CurrentPosition() * 2, reinterpret_cast<char *>(lParam
), wParam
);
3155 SetEmptySelection(currentPos
+ wParam
/ 2);
3159 case SCI_INSERTTEXT
: {
3162 int insertPos
= wParam
;
3163 if (static_cast<short>(wParam
) == -1)
3164 insertPos
= CurrentPosition();
3165 int newCurrent
= CurrentPosition();
3166 int newAnchor
= anchor
;
3167 char *sz
= reinterpret_cast<char *>(lParam
);
3168 pdoc
->InsertString(insertPos
, sz
);
3169 if (newCurrent
> insertPos
)
3170 newCurrent
+= strlen(sz
);
3171 if (newAnchor
> insertPos
)
3172 newAnchor
+= strlen(sz
);
3173 SetEmptySelection(newCurrent
);
3181 case SCI_SETUNDOCOLLECTION
:
3182 pdoc
->SetUndoCollection(static_cast<enum undoCollectionType
>(wParam
));
3185 #ifdef INCLUDE_DEPRECATED_FEATURES
3186 case SCI_APPENDUNDOSTARTACTION
:
3187 // Not just deprecated - now dead
3188 //pdoc->AppendUndoStartAction();
3192 case SCI_BEGINUNDOACTION
:
3193 pdoc
->BeginUndoAction();
3196 case SCI_ENDUNDOACTION
:
3197 pdoc
->EndUndoAction();
3200 case SCI_GETCARETPERIOD
:
3201 return caret
.period
;
3203 case SCI_SETCARETPERIOD
:
3204 caret
.period
= wParam
;
3207 case SCI_SETWORDCHARS
: {
3210 pdoc
->SetWordChars(reinterpret_cast<unsigned char *>(lParam
));
3215 return pdoc
->Length();
3218 return pdoc
->CharAt(wParam
);
3220 case SCI_GETCURRENTPOS
:
3226 case SCI_GETSTYLEAT
:
3227 if (static_cast<short>(wParam
) >= pdoc
->Length())
3230 return pdoc
->StyleAt(wParam
);
3240 case SCI_SETSAVEPOINT
:
3241 pdoc
->SetSavePoint();
3242 NotifySavePoint(true);
3245 case SCI_GETSTYLEDTEXT
: {
3248 TEXTRANGE
*tr
= reinterpret_cast<TEXTRANGE
*>(lParam
);
3250 for (int iChar
= tr
->chrg
.cpMin
; iChar
< tr
->chrg
.cpMax
; iChar
++) {
3251 tr
->lpstrText
[iPlace
++] = pdoc
->CharAt(iChar
);
3252 tr
->lpstrText
[iPlace
++] = pdoc
->StyleAt(iChar
);
3254 tr
->lpstrText
[iPlace
] = '\0';
3255 tr
->lpstrText
[iPlace
+ 1] = '\0';
3260 return pdoc
->CanRedo() ? TRUE
: FALSE
;
3262 case SCI_MARKERLINEFROMHANDLE
:
3263 return pdoc
->LineFromHandle(wParam
);
3265 case SCI_MARKERDELETEHANDLE
:
3266 pdoc
->DeleteMarkFromHandle(wParam
);
3270 return vs
.viewWhitespace
;
3273 vs
.viewWhitespace
= wParam
;
3282 SetEmptySelection(wParam
);
3283 EnsureCaretVisible();
3288 SetSelection(currentPos
, wParam
);
3291 case SCI_GETCURLINE
: {
3294 int lineCurrentPos
= pdoc
->LineFromPosition(currentPos
);
3295 int lineStart
= pdoc
->LineStart(lineCurrentPos
);
3296 unsigned int lineEnd
= pdoc
->LineStart(lineCurrentPos
+ 1);
3297 char *ptr
= reinterpret_cast<char *>(lParam
);
3298 unsigned int iPlace
= 0;
3299 for (unsigned int iChar
= lineStart
; iChar
< lineEnd
&& iPlace
< wParam
; iChar
++)
3300 ptr
[iPlace
++] = pdoc
->CharAt(iChar
);
3302 return currentPos
- lineStart
;
3305 case SCI_GETENDSTYLED
:
3306 return pdoc
->GetEndStyled();
3308 case SCI_GETEOLMODE
:
3309 return pdoc
->eolMode
;
3311 case SCI_SETEOLMODE
:
3312 pdoc
->eolMode
= wParam
;
3315 case SCI_STARTSTYLING
:
3316 pdoc
->StartStyling(wParam
, lParam
);
3319 case SCI_SETSTYLING
:
3320 pdoc
->SetStyleFor(wParam
, lParam
);
3323 case SCI_SETSTYLINGEX
: // Specify a complete styling buffer
3326 pdoc
->SetStyles(wParam
, reinterpret_cast<char *>(lParam
));
3329 #ifdef INCLUDE_DEPRECATED_FEATURES
3330 case SCI_SETMARGINWIDTH
:
3332 vs
.ms
[1].width
= wParam
;
3334 InvalidateStyleRedraw();
3338 case SCI_SETBUFFEREDDRAW
:
3339 bufferedDraw
= wParam
;
3342 case SCI_SETTABWIDTH
:
3344 pdoc
->tabInChars
= wParam
;
3345 InvalidateStyleRedraw();
3348 case SCI_SETCODEPAGE
:
3349 pdoc
->dbcsCodePage
= wParam
;
3352 #ifdef INCLUDE_DEPRECATED_FEATURES
3353 case SCI_SETLINENUMBERWIDTH
:
3355 vs
.ms
[0].width
= wParam
;
3357 InvalidateStyleRedraw();
3361 case SCI_SETUSEPALETTE
:
3362 palette
.allowRealization
= wParam
;
3363 InvalidateStyleRedraw();
3366 // Marker definition and setting
3367 case SCI_MARKERDEFINE
:
3368 if (wParam
<= MARKER_MAX
)
3369 vs
.markers
[wParam
].markType
= lParam
;
3370 InvalidateStyleData();
3373 case SCI_MARKERSETFORE
:
3374 if (wParam
<= MARKER_MAX
)
3375 vs
.markers
[wParam
].fore
.desired
= Colour(lParam
);
3376 InvalidateStyleData();
3379 case SCI_MARKERSETBACK
:
3380 if (wParam
<= MARKER_MAX
)
3381 vs
.markers
[wParam
].back
.desired
= Colour(lParam
);
3382 InvalidateStyleData();
3385 case SCI_MARKERADD
: {
3386 int markerID
= pdoc
->AddMark(wParam
, lParam
);
3390 case SCI_MARKERDELETE
:
3391 pdoc
->DeleteMark(wParam
, lParam
);
3394 case SCI_MARKERDELETEALL
:
3395 pdoc
->DeleteAllMarks(static_cast<int>(wParam
));
3399 return pdoc
->GetMark(wParam
);
3401 case SCI_MARKERNEXT
: {
3402 int lt
= pdoc
->LinesTotal();
3403 for (int iLine
= wParam
; iLine
< lt
; iLine
++) {
3404 if ((pdoc
->GetMark(iLine
) & lParam
) != 0)
3410 case SCI_MARKERPREVIOUS
: {
3411 for (int iLine
= wParam
; iLine
>= 0; iLine
--) {
3412 if ((pdoc
->GetMark(iLine
) & lParam
) != 0)
3418 case SCI_SETMARGINTYPEN
:
3419 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3420 vs
.ms
[wParam
].symbol
= (lParam
== SC_MARGIN_SYMBOL
);
3421 InvalidateStyleRedraw();
3425 case SCI_GETMARGINTYPEN
:
3426 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3427 return vs
.ms
[wParam
].symbol
? SC_MARGIN_SYMBOL
: SC_MARGIN_NUMBER
;
3431 case SCI_SETMARGINWIDTHN
:
3432 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3433 vs
.ms
[wParam
].width
= lParam
;
3434 InvalidateStyleRedraw();
3438 case SCI_GETMARGINWIDTHN
:
3439 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3440 return vs
.ms
[wParam
].width
;
3444 case SCI_SETMARGINMASKN
:
3445 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3446 vs
.ms
[wParam
].mask
= lParam
;
3447 InvalidateStyleRedraw();
3451 case SCI_GETMARGINMASKN
:
3452 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3453 return vs
.ms
[wParam
].mask
;
3457 case SCI_SETMARGINSENSITIVEN
:
3458 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3459 vs
.ms
[wParam
].sensitive
= lParam
;
3460 InvalidateStyleRedraw();
3464 case SCI_GETMARGINSENSITIVEN
:
3465 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3466 return vs
.ms
[wParam
].sensitive
? 1 : 0;
3470 case SCI_STYLECLEARALL
:
3472 InvalidateStyleRedraw();
3475 case SCI_STYLESETFORE
:
3476 if (wParam
<= STYLE_MAX
) {
3477 vs
.styles
[wParam
].fore
.desired
= Colour(lParam
);
3478 InvalidateStyleRedraw();
3481 case SCI_STYLESETBACK
:
3482 if (wParam
<= STYLE_MAX
) {
3483 vs
.styles
[wParam
].back
.desired
= Colour(lParam
);
3484 InvalidateStyleRedraw();
3487 case SCI_STYLESETBOLD
:
3488 if (wParam
<= STYLE_MAX
) {
3489 vs
.styles
[wParam
].bold
= lParam
;
3490 InvalidateStyleRedraw();
3493 case SCI_STYLESETITALIC
:
3494 if (wParam
<= STYLE_MAX
) {
3495 vs
.styles
[wParam
].italic
= lParam
;
3496 InvalidateStyleRedraw();
3499 case SCI_STYLESETEOLFILLED
:
3500 if (wParam
<= STYLE_MAX
) {
3501 vs
.styles
[wParam
].eolFilled
= lParam
;
3502 InvalidateStyleRedraw();
3505 case SCI_STYLESETSIZE
:
3506 if (wParam
<= STYLE_MAX
) {
3507 vs
.styles
[wParam
].size
= lParam
;
3508 InvalidateStyleRedraw();
3511 case SCI_STYLESETFONT
:
3514 if (wParam
<= STYLE_MAX
) {
3515 vs
.SetStyleFontName(wParam
, reinterpret_cast<const char *>(lParam
));
3516 InvalidateStyleRedraw();
3520 case SCI_STYLERESETDEFAULT
:
3521 vs
.ResetDefaultStyle();
3522 InvalidateStyleRedraw();
3525 case SCI_SETSTYLEBITS
:
3526 pdoc
->SetStylingBits(wParam
);
3529 case SCI_GETSTYLEBITS
:
3530 return pdoc
->stylingBits
;
3532 case SCI_SETLINESTATE
:
3533 return pdoc
->SetLineState(wParam
, lParam
);
3535 case SCI_GETLINESTATE
:
3536 return pdoc
->GetLineState(wParam
);
3538 case SCI_GETMAXLINESTATE
:
3539 return pdoc
->GetMaxLineState();
3543 case SCI_VISIBLEFROMDOCLINE
:
3544 return cs
.DisplayFromDoc(wParam
);
3546 case SCI_DOCLINEFROMVISIBLE
:
3547 return cs
.DocFromDisplay(wParam
);
3549 case SCI_SETFOLDLEVEL
: {
3550 int prev
= pdoc
->SetLevel(wParam
, lParam
);
3556 case SCI_GETFOLDLEVEL
:
3557 return pdoc
->GetLevel(wParam
);
3559 case SCI_GETLASTCHILD
:
3560 return pdoc
->GetLastChild(wParam
, lParam
);
3562 case SCI_GETFOLDPARENT
:
3563 return pdoc
->GetFoldParent(wParam
);
3566 cs
.SetVisible(wParam
, lParam
, true);
3572 cs
.SetVisible(wParam
, lParam
, false);
3577 case SCI_GETLINEVISIBLE
:
3578 return cs
.GetVisible(wParam
);
3580 case SCI_SETFOLDEXPANDED
:
3581 if (cs
.SetExpanded(wParam
, lParam
)) {
3586 case SCI_GETFOLDEXPANDED
:
3587 return cs
.GetExpanded(wParam
);
3589 case SCI_SETFOLDFLAGS
:
3594 case SCI_TOGGLEFOLD
:
3595 ToggleContraction(wParam
);
3598 case SCI_ENSUREVISIBLE
:
3599 EnsureLineVisible(wParam
);
3602 case SCI_SEARCHANCHOR
:
3606 case SCI_SEARCHNEXT
:
3607 case SCI_SEARCHPREV
:
3608 return SearchText(iMessage
, wParam
, lParam
);
3611 case SCI_SETCARETPOLICY
:
3612 caretPolicy
= wParam
;
3616 case SCI_LINESONSCREEN
:
3617 return LinesOnScreen();
3620 displayPopupMenu
= wParam
;
3623 #ifdef INCLUDE_DEPRECATED_FEATURES
3625 vs
.styles
[STYLE_DEFAULT
].fore
.desired
= Colour(wParam
);
3626 InvalidateStyleRedraw();
3630 vs
.styles
[STYLE_DEFAULT
].back
.desired
= Colour(wParam
);
3631 InvalidateStyleRedraw();
3635 vs
.styles
[STYLE_DEFAULT
].bold
= wParam
;
3636 InvalidateStyleRedraw();
3640 vs
.styles
[STYLE_DEFAULT
].italic
= wParam
;
3641 InvalidateStyleRedraw();
3645 vs
.styles
[STYLE_DEFAULT
].size
= wParam
;
3646 InvalidateStyleRedraw();
3652 strcpy(vs
.styles
[STYLE_DEFAULT
].fontName
, reinterpret_cast<char *>(wParam
));
3653 InvalidateStyleRedraw();
3657 case SCI_SETSELFORE
:
3658 vs
.selforeset
= wParam
;
3659 vs
.selforeground
.desired
= Colour(lParam
);
3660 InvalidateStyleRedraw();
3663 case SCI_SETSELBACK
:
3664 vs
.selbackset
= wParam
;
3665 vs
.selbackground
.desired
= Colour(lParam
);
3666 InvalidateStyleRedraw();
3669 case SCI_SETCARETFORE
:
3670 vs
.caretcolour
.desired
= Colour(wParam
);
3671 InvalidateStyleRedraw();
3674 case SCI_ASSIGNCMDKEY
:
3675 kmap
.AssignCmdKey(LOWORD(wParam
), HIWORD(wParam
), lParam
);
3678 case SCI_CLEARCMDKEY
:
3679 kmap
.AssignCmdKey(LOWORD(wParam
), HIWORD(wParam
), WM_NULL
);
3682 case SCI_CLEARALLCMDKEYS
:
3686 case SCI_INDICSETSTYLE
:
3687 if (wParam
<= INDIC_MAX
) {
3688 vs
.indicators
[wParam
].style
= lParam
;
3689 InvalidateStyleRedraw();
3693 case SCI_INDICGETSTYLE
:
3694 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].style
: 0;
3696 case SCI_INDICSETFORE
:
3697 if (wParam
<= INDIC_MAX
) {
3698 vs
.indicators
[wParam
].fore
.desired
= Colour(lParam
);
3699 InvalidateStyleRedraw();
3703 case SCI_INDICGETFORE
:
3704 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].fore
.desired
.AsLong() : 0;
3707 case SCI_LINEDOWNEXTEND
:
3709 case SCI_LINEUPEXTEND
:
3711 case SCI_CHARLEFTEXTEND
:
3713 case SCI_CHARRIGHTEXTEND
:
3715 case SCI_WORDLEFTEXTEND
:
3717 case SCI_WORDRIGHTEXTEND
:
3719 case SCI_HOMEEXTEND
:
3721 case SCI_LINEENDEXTEND
:
3722 case SCI_DOCUMENTSTART
:
3723 case SCI_DOCUMENTSTARTEXTEND
:
3724 case SCI_DOCUMENTEND
:
3725 case SCI_DOCUMENTENDEXTEND
:
3727 case SCI_PAGEUPEXTEND
:
3729 case SCI_PAGEDOWNEXTEND
:
3730 case SCI_EDITTOGGLEOVERTYPE
:
3732 case SCI_DELETEBACK
:
3738 case SCI_VCHOMEEXTEND
:
3741 case SCI_DELWORDLEFT
:
3742 case SCI_DELWORDRIGHT
:
3744 case SCI_LINEDELETE
:
3745 case SCI_LINETRANSPOSE
:
3748 return KeyCommand(iMessage
);
3750 case SCI_BRACEHIGHLIGHT
:
3751 SetBraceHighlight(static_cast<int>(wParam
), lParam
, STYLE_BRACELIGHT
);
3754 case SCI_BRACEBADLIGHT
:
3755 SetBraceHighlight(static_cast<int>(wParam
), -1, STYLE_BRACEBAD
);
3758 case SCI_BRACEMATCH
:
3759 // wParam is position of char to find brace for,
3760 // lParam is maximum amount of text to restyle to find it
3761 return BraceMatch(wParam
, lParam
);
3763 case SCI_GETVIEWEOL
:
3766 case SCI_SETVIEWEOL
:
3767 vs
.viewEOL
= wParam
;
3771 case SCI_GETEDGECOLUMN
:
3774 case SCI_SETEDGECOLUMN
:
3776 InvalidateStyleRedraw();
3779 case SCI_GETEDGEMODE
:
3782 case SCI_SETEDGEMODE
:
3784 InvalidateStyleRedraw();
3787 case SCI_GETEDGECOLOUR
:
3788 return vs
.edgecolour
.desired
.AsLong();
3790 case SCI_SETEDGECOLOUR
:
3791 vs
.edgecolour
.desired
= Colour(wParam
);
3792 InvalidateStyleRedraw();
3795 case SCI_GETDOCPOINTER
:
3796 return reinterpret_cast<LRESULT
>(pdoc
);
3798 case SCI_SETDOCPOINTER
:
3799 SetDocPointer(reinterpret_cast<Document
*>(lParam
));
3802 case SCI_SETMODEVENTMASK
:
3803 modEventMask
= wParam
;
3806 case SCI_CONVERTEOLS
:
3807 pdoc
->ConvertLineEnds(wParam
);
3808 SetSelection(currentPos
, anchor
); // Ensure selection inside document
3811 #ifdef MACRO_SUPPORT
3812 case SCI_STARTRECORD
:
3816 case SCI_STOPRECORD
:
3822 return DefWndProc(iMessage
, wParam
, lParam
);
3824 //Platform::DebugPrintf("end wnd proc\n");