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 pdoc
= new Document();
93 pdoc
->AddWatcher(this, 0);
102 pdoc
->RemoveWatcher(this, 0);
112 void Editor::Finalise() {
115 void Editor::DropGraphics() {
116 pixmapLine
.Release();
117 pixmapSelMargin
.Release();
118 pixmapSelPattern
.Release();
121 void Editor::InvalidateStyleData() {
127 void Editor::InvalidateStyleRedraw() {
128 InvalidateStyleData();
132 void Editor::RefreshColourPalette(Palette
&pal
, bool want
) {
133 vs
.RefreshColourPalette(pal
, want
);
136 void Editor::RefreshStyleData() {
142 RefreshColourPalette(palette
, true);
143 palette
.Allocate(wMain
);
144 RefreshColourPalette(palette
, false);
149 PRectangle
Editor::GetClientRectangle() {
150 return wDraw
.GetClientPosition();
153 PRectangle
Editor::GetTextRectangle() {
154 PRectangle rc
= GetClientRectangle();
155 rc
.left
+= vs
.fixedColumnWidth
;
156 rc
.right
-= vs
.rightMarginWidth
;
160 int Editor::LinesOnScreen() {
161 PRectangle rcClient
= GetClientRectangle();
162 int htClient
= rcClient
.bottom
- rcClient
.top
;
163 //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
164 return htClient
/ vs
.lineHeight
;
167 int Editor::LinesToScroll() {
168 int retVal
= LinesOnScreen() - 1;
175 int Editor::MaxScrollPos() {
176 //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
177 //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
178 int retVal
= cs
.LinesDisplayed() - LinesOnScreen();
185 bool IsControlCharacter(char ch
) {
186 // iscntrl returns true for lots of chars > 127 which are displayable
187 return ch
>= 0 && ch
< ' ';
190 const char *ControlCharacterString(char ch
) {
191 const char *reps
[] = {
192 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
193 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
194 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
195 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
197 if (ch
< (sizeof(reps
) / sizeof(reps
[0]))) {
204 Point
Editor::LocationFromPosition(unsigned int pos
) {
206 int line
= pdoc
->LineFromPosition(pos
);
207 int lineVisible
= cs
.DisplayFromDoc(line
);
208 //Platform::DebugPrintf("line=%d\n", line);
212 pt
.y
= (lineVisible
- topLine
) * vs
.lineHeight
; // + half a lineheight?
213 unsigned int posLineStart
= pdoc
->LineStart(line
);
214 if ((pos
- posLineStart
) > LineLayout::maxLineLength
) {
215 // very long line so put x at arbitrary large position
216 pt
.x
= 30000 + vs
.fixedColumnWidth
- xOffset
;
219 LayoutLine(line
, &surface
, vs
, ll
);
220 pt
.x
= ll
.positions
[pos
- posLineStart
] + vs
.fixedColumnWidth
- xOffset
;
225 int Editor::XFromPosition(unsigned int pos
) {
226 Point pt
= LocationFromPosition(pos
);
227 return pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
230 int Editor::LineFromLocation(Point pt
) {
231 return cs
.DocFromDisplay(pt
.y
/ vs
.lineHeight
+ topLine
);
234 void Editor::SetTopLine(int topLineNew
) {
235 topLine
= topLineNew
;
236 posTopLine
= pdoc
->LineStart(topLine
);
239 int Editor::PositionFromLocation(Point pt
) {
241 pt
.x
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
242 int line
= cs
.DocFromDisplay(pt
.y
/ vs
.lineHeight
+ topLine
);
243 if (pt
.y
< 0) { // Division rounds towards 0
244 line
= cs
.DocFromDisplay((pt
.y
- (vs
.lineHeight
- 1)) / vs
.lineHeight
+ topLine
);
248 if (line
>= pdoc
->LinesTotal())
249 return pdoc
->Length();
250 //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
253 unsigned int posLineStart
= pdoc
->LineStart(line
);
256 LayoutLine(line
, &surface
, vs
, ll
);
257 for (int i
= 0; i
< ll
.numCharsInLine
; i
++) {
258 if (pt
.x
< ((ll
.positions
[i
] + ll
.positions
[i
+ 1]) / 2) ||
259 ll
.chars
[i
] == '\r' || ll
.chars
[i
] == '\n') {
260 return i
+ posLineStart
;
264 return ll
.numCharsInLine
+ posLineStart
;
267 int Editor::PositionFromLineX(int line
, int x
) {
269 if (line
>= pdoc
->LinesTotal())
270 return pdoc
->Length();
271 //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
274 unsigned int posLineStart
= pdoc
->LineStart(line
);
277 LayoutLine(line
, &surface
, vs
, ll
);
278 for (int i
= 0; i
< ll
.numCharsInLine
; i
++) {
279 if (x
< ((ll
.positions
[i
] + ll
.positions
[i
+ 1]) / 2) ||
280 ll
.chars
[i
] == '\r' || ll
.chars
[i
] == '\n') {
281 return i
+ posLineStart
;
285 return ll
.numCharsInLine
+ posLineStart
;
288 void Editor::RedrawRect(PRectangle rc
) {
289 //Platform::DebugPrintf("Redraw %d %d - %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
290 wDraw
.InvalidateRectangle(rc
);
293 void Editor::Redraw() {
294 //Platform::DebugPrintf("Redraw all\n");
295 wDraw
.InvalidateAll();
298 void Editor::RedrawSelMargin() {
302 PRectangle rcSelMargin
= GetClientRectangle();
303 rcSelMargin
.right
= vs
.fixedColumnWidth
;
304 wDraw
.InvalidateRectangle(rcSelMargin
);
308 PRectangle
Editor::RectangleFromRange(int start
, int end
) {
315 int minLine
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(minPos
));
316 int maxLine
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(maxPos
));
317 PRectangle rcClient
= GetTextRectangle();
319 rc
.left
= vs
.fixedColumnWidth
;
320 rc
.top
= (minLine
- topLine
) * vs
.lineHeight
;
323 rc
.right
= rcClient
.right
;
324 rc
.bottom
= (maxLine
- topLine
+ 1) * vs
.lineHeight
;
325 // Ensure PRectangle is within 16 bit space
326 rc
.top
= Platform::Clamp(rc
.top
, -32000, 32000);
327 rc
.bottom
= Platform::Clamp(rc
.bottom
, -32000, 32000);
332 void Editor::InvalidateRange(int start
, int end
) {
333 RedrawRect(RectangleFromRange(start
, end
));
336 int Editor::CurrentPosition() {
340 bool Editor::SelectionEmpty() {
341 return anchor
== currentPos
;
344 int Editor::SelectionStart(int line
) {
345 if ((line
== -1) || (selType
== selStream
)) {
346 return Platform::Minimum(currentPos
, anchor
);
347 } else { // selType == selRectangle
348 int selStart
= SelectionStart();
349 int selEnd
= SelectionEnd();
350 int lineStart
= pdoc
->LineFromPosition(selStart
);
351 int lineEnd
= pdoc
->LineFromPosition(selEnd
);
352 if (line
< lineStart
|| line
> lineEnd
) {
355 int minX
= Platform::Minimum(xStartSelect
, xEndSelect
);
356 //return PositionFromLineX(line, minX + vs.fixedColumnWidth - xOffset);
357 return PositionFromLineX(line
, minX
);
362 int Editor::SelectionEnd(int line
) {
363 if ((line
== -1) || (selType
== selStream
)) {
364 return Platform::Maximum(currentPos
, anchor
);
365 } else { // selType == selRectangle
366 int selStart
= SelectionStart();
367 int selEnd
= SelectionEnd();
368 int lineStart
= pdoc
->LineFromPosition(selStart
);
369 int lineEnd
= pdoc
->LineFromPosition(selEnd
);
370 if (line
< lineStart
|| line
> lineEnd
) {
373 int maxX
= Platform::Maximum(xStartSelect
, xEndSelect
);
374 // measure line and return character closest to minx
375 return PositionFromLineX(line
, maxX
);
380 void Editor::SetSelection(int currentPos_
, int anchor_
) {
381 currentPos_
= pdoc
->ClampPositionIntoDocument(currentPos_
);
382 anchor_
= pdoc
->ClampPositionIntoDocument(anchor_
);
383 if ((currentPos
!= currentPos_
) || (anchor
!= anchor_
)) {
384 int firstAffected
= anchor
;
385 if (firstAffected
> currentPos
)
386 firstAffected
= currentPos
;
387 if (firstAffected
> anchor_
)
388 firstAffected
= anchor_
;
389 if (firstAffected
> currentPos_
)
390 firstAffected
= currentPos_
;
391 int lastAffected
= anchor
;
392 if (lastAffected
< currentPos
)
393 lastAffected
= currentPos
;
394 if (lastAffected
< anchor_
)
395 lastAffected
= anchor_
;
396 if (lastAffected
< (currentPos_
+ 1)) // +1 ensures caret repainted
397 lastAffected
= (currentPos_
+ 1);
398 currentPos
= currentPos_
;
401 InvalidateRange(firstAffected
, lastAffected
);
406 void Editor::SetSelection(int currentPos_
) {
407 currentPos_
= pdoc
->ClampPositionIntoDocument(currentPos_
);
408 if (currentPos
!= currentPos_
) {
409 int firstAffected
= anchor
;
410 if (firstAffected
> currentPos
)
411 firstAffected
= currentPos
;
412 if (firstAffected
> currentPos_
)
413 firstAffected
= currentPos_
;
414 int lastAffected
= anchor
;
415 if (lastAffected
< currentPos
)
416 lastAffected
= currentPos
;
417 if (lastAffected
< (currentPos_
+ 1)) // +1 ensures caret repainted
418 lastAffected
= (currentPos_
+ 1);
419 currentPos
= currentPos_
;
421 InvalidateRange(firstAffected
, lastAffected
);
426 void Editor::SetEmptySelection(int currentPos_
) {
427 SetSelection(currentPos_
, currentPos_
);
430 int Editor::MovePositionTo(int newPos
, bool extend
) {
431 int delta
= newPos
- currentPos
;
432 newPos
= pdoc
->ClampPositionIntoDocument(newPos
);
433 newPos
= pdoc
->MovePositionOutsideChar(newPos
, delta
);
435 SetSelection(newPos
);
437 SetEmptySelection(newPos
);
439 EnsureCaretVisible();
440 ShowCaretAtCurrentPosition();
444 int Editor::MovePositionSoVisible(int pos
, int moveDir
) {
445 pos
= pdoc
->ClampPositionIntoDocument(pos
);
446 pos
= pdoc
->MovePositionOutsideChar(pos
, moveDir
);
447 int lineDoc
= pdoc
->LineFromPosition(pos
);
448 if (cs
.GetVisible(lineDoc
)) {
451 int lineDisplay
= cs
.DisplayFromDoc(lineDoc
);
453 lineDisplay
= Platform::Clamp(lineDisplay
+ 1, 0, cs
.LinesDisplayed());
454 return pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
));
456 // lineDisplay is already line before fold as lines in fold use display line of line before fold
457 lineDisplay
= Platform::Clamp(lineDisplay
, 0, cs
.LinesDisplayed());
458 return pdoc
->LineEndPosition(pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
)));
463 // Choose the x position that the caret will try to stick to as it is moves up and down
464 void Editor::SetLastXChosen() {
465 Point pt
= LocationFromPosition(currentPos
);
469 void Editor::ScrollTo(int line
) {
470 int topLineNew
= Platform::Clamp(line
, 0, MaxScrollPos());
471 if (topLineNew
!= topLine
) {
472 // Try to optimise small scrolls
473 int linesToMove
= topLine
- topLineNew
;
474 SetTopLine(topLineNew
);
475 ShowCaretAtCurrentPosition();
476 // Perform redraw rather than scroll if many lines would be redrawn anyway.
477 if (abs(linesToMove
) <= 10) {
478 ScrollText(linesToMove
);
482 SetVerticalScrollPos();
486 void Editor::ScrollText(int linesToMove
) {
487 //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
491 void Editor::HorizontalScrollTo(int xPos
) {
492 //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
496 SetHorizontalScrollPos();
500 void Editor::EnsureCaretVisible(bool useMargin
) {
501 //Platform::DebugPrintf("EnsureCaretVisible %d\n", xOffset);
502 PRectangle rcClient
= GetTextRectangle();
503 int posCaret
= currentPos
;
506 Point pt
= LocationFromPosition(posCaret
);
507 Point ptEOL
= LocationFromPosition(pdoc
->LineEndPosition(posCaret
));
508 Point ptBottomCaret
= pt
;
509 int lineCaret
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(posCaret
));
510 ptBottomCaret
.y
+= vs
.lineHeight
- 1;
512 // Ensure the caret is reasonably visible in context.
513 int xMargin
= Platform::Clamp(xCaretMargin
, 2, Platform::Maximum(rcClient
.Width() - 10, 4) / 2);
517 // Ensure certain amount of text visible on both sides of caretSo move if caret just on edge
518 rcClient
.left
= rcClient
.left
+ xMargin
;
519 rcClient
.right
= rcClient
.right
- xMargin
;
521 if (!rcClient
.Contains(pt
) || !rcClient
.Contains(ptBottomCaret
) || (caretPolicy
& CARET_STRICT
)) {
522 //Platform::DebugPrintf("EnsureCaretVisible move, (%d,%d) (%d,%d)\n", pt.x, pt.y, rcClient.left, rcClient.right);
523 // It should be possible to scroll the window to show the caret,
524 // but this fails to remove the caret on GTK+
525 if (caretPolicy
& CARET_SLOP
) {
526 if ((topLine
> lineCaret
) || ((caretPolicy
& CARET_STRICT
) && (topLine
+ caretSlop
> lineCaret
))) {
527 SetTopLine(Platform::Clamp(lineCaret
- caretSlop
, 0, MaxScrollPos()));
528 SetVerticalScrollPos();
530 } else if ((lineCaret
> topLine
+ LinesOnScreen() - 1) ||
531 ((caretPolicy
& CARET_STRICT
) && (lineCaret
> topLine
+ LinesOnScreen() - 1 - caretSlop
))) {
532 SetTopLine(Platform::Clamp(lineCaret
- LinesOnScreen() + 1 + caretSlop
, 0, MaxScrollPos()));
533 SetVerticalScrollPos();
537 if ((topLine
> lineCaret
) || (lineCaret
> topLine
+ LinesOnScreen() - 1) || (caretPolicy
& CARET_STRICT
)) {
538 SetTopLine(Platform::Clamp(lineCaret
- LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
539 SetVerticalScrollPos();
543 int xOffsetNew
= xOffset
;
544 if (pt
.x
< rcClient
.left
) {
545 xOffsetNew
= xOffset
- (rcClient
.left
- pt
.x
);
546 } else if (pt
.x
>= rcClient
.right
) {
547 xOffsetNew
= xOffset
+ (pt
.x
- rcClient
.right
);
548 int xOffsetEOL
= xOffset
+ (ptEOL
.x
- rcClient
.right
) - xMargin
+ 2;
549 //Platform::DebugPrintf("Margin %d %d\n", xOffsetNew, xOffsetEOL);
550 // Ensure don't scroll out into empty space
551 if (xOffsetNew
> xOffsetEOL
)
552 xOffsetNew
= xOffsetEOL
;
556 if (xOffset
!= xOffsetNew
) {
557 xOffset
= xOffsetNew
;
558 SetHorizontalScrollPos();
564 void Editor::ShowCaretAtCurrentPosition() {
565 if (!wMain
.HasFocus()) {
566 caret
.active
= false;
575 void Editor::DropCaret() {
576 caret
.active
= false;
580 void Editor::InvalidateCaret() {
582 InvalidateRange(posDrag
, posDrag
+ 1);
584 InvalidateRange(currentPos
, currentPos
+ 1);
587 void Editor::PaintSelMargin(Surface
*surfWindow
, PRectangle
&rc
) {
588 if (vs
.fixedColumnWidth
== 0)
591 PRectangle rcMargin
= GetClientRectangle();
592 rcMargin
.right
= vs
.fixedColumnWidth
;
594 if (!rc
.Intersects(rcMargin
))
599 surface
= &pixmapSelMargin
;
601 surface
= surfWindow
;
604 PRectangle rcSelMargin
= rcMargin
;
605 rcSelMargin
.right
= rcMargin
.left
;
607 for (int margin
=0; margin
< vs
.margins
; margin
++) {
608 if (vs
.ms
[margin
].width
> 0) {
610 rcSelMargin
.left
= rcSelMargin
.right
;
611 rcSelMargin
.right
= rcSelMargin
.left
+ vs
.ms
[margin
].width
;
613 if (vs
.ms
[margin
].symbol
) {
615 if (vs.ms[margin].mask & SC_MASK_FOLDERS)
616 surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated);
618 // Required because of special way brush is created for selection margin
619 surface->FillRectangle(rcSelMargin, pixmapSelPattern);
621 if (vs
.ms
[margin
].mask
& SC_MASK_FOLDERS
)
622 // Required because of special way brush is created for selection margin
623 surface
->FillRectangle(rcSelMargin
, pixmapSelPattern
);
625 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
627 surface
->FillRectangle(rcSelMargin
, vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
630 int visibleLine
= topLine
;
631 int line
= cs
.DocFromDisplay(visibleLine
);
634 while (line
< pdoc
->LinesTotal() && yposScreen
< rcMargin
.bottom
) {
635 int marks
= pdoc
->GetMark(line
);
636 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
637 if (cs
.GetExpanded(line
)) {
638 marks
|= 1 << SC_MARKNUM_FOLDEROPEN
;
640 marks
|= 1 << SC_MARKNUM_FOLDER
;
643 marks
&= vs
.ms
[margin
].mask
;
644 PRectangle rcMarker
= rcSelMargin
;
645 rcMarker
.top
= yposScreen
;
646 rcMarker
.bottom
= yposScreen
+ vs
.lineHeight
;
647 if (!vs
.ms
[margin
].symbol
) {
650 sprintf(number
, "%d", line
+ 1);
652 sprintf(number
, "%X", pdoc
->GetLevel(line
));
654 PRectangle rcNumber
=rcMarker
;
656 int width
= surface
->WidthText(vs
.styles
[STYLE_LINENUMBER
].font
, number
, strlen(number
));
657 xpos
= rcNumber
.right
- width
- 3;
658 rcNumber
.left
= xpos
;
659 if ((visibleLine
< cs
.LinesDisplayed()) && cs
.GetVisible(line
)) {
660 surface
->DrawText(rcNumber
, vs
.styles
[STYLE_LINENUMBER
].font
,
661 rcNumber
.top
+ vs
.maxAscent
, number
, strlen(number
),
662 vs
.styles
[STYLE_LINENUMBER
].fore
.allocated
,
663 vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
668 for (int markBit
= 0; (markBit
< 32) && marks
; markBit
++) {
672 vs
.markers
[markBit
].Draw(surface
, rcMarker
);
679 line
= cs
.DocFromDisplay(visibleLine
);
680 yposScreen
+= vs
.lineHeight
;
685 PRectangle rcBlankMargin
= rcMargin
;
686 rcBlankMargin
.left
= rcSelMargin
.right
;
687 surface
->FillRectangle(rcBlankMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
);
690 surfWindow
->Copy(rcMargin
, Point(), pixmapSelMargin
);
694 void DrawTabArrow(Surface
*surface
, PRectangle rcTab
, int ymid
) {
695 int ydiff
= (rcTab
.bottom
- rcTab
.top
) / 2;
696 int xhead
= rcTab
.right
- 1 - ydiff
;
697 if ((rcTab
.left
+ 2) < (rcTab
.right
- 1))
698 surface
->MoveTo(rcTab
.left
+ 2, ymid
);
700 surface
->MoveTo(rcTab
.right
- 1, ymid
);
701 surface
->LineTo(rcTab
.right
- 1, ymid
);
702 surface
->LineTo(xhead
, ymid
- ydiff
);
703 surface
->MoveTo(rcTab
.right
- 1, ymid
);
704 surface
->LineTo(xhead
, ymid
+ ydiff
);
707 void Editor::LayoutLine(int line
, Surface
*surface
, ViewStyle
&vstyle
, LineLayout
&ll
) {
708 int numCharsInLine
= 0;
709 int posLineStart
= pdoc
->LineStart(line
);
710 int posLineEnd
= pdoc
->LineStart(line
+ 1);
711 Font
&ctrlCharsFont
= vstyle
.styles
[STYLE_CONTROLCHAR
].font
;
713 int styleMask
= pdoc
->stylingBitsMask
;
714 for (int charInDoc
= posLineStart
;
715 charInDoc
< posLineEnd
&& numCharsInLine
< LineLayout::maxLineLength
- 1;
717 char chDoc
= pdoc
->CharAt(charInDoc
);
718 styleByte
= pdoc
->StyleAt(charInDoc
);
719 if (vstyle
.viewEOL
|| ((chDoc
!= '\r') && (chDoc
!= '\n'))) {
720 ll
.chars
[numCharsInLine
] = chDoc
;
721 ll
.styles
[numCharsInLine
] = styleByte
& styleMask
;
722 ll
.indicators
[numCharsInLine
] = styleByte
& ~styleMask
;
726 ll
.chars
[numCharsInLine
] = 0;
727 ll
.styles
[numCharsInLine
] = styleByte
; // For eolFilled
728 ll
.indicators
[numCharsInLine
] = 0;
730 // Layout the line, determining the position of each character
734 unsigned int tabWidth
= vstyle
.spaceWidth
* pdoc
->tabInChars
;
736 for (int charInLine
= 0; charInLine
< numCharsInLine
; charInLine
++) {
737 if ((ll
.styles
[charInLine
] != ll
.styles
[charInLine
+ 1]) ||
738 IsControlCharacter(ll
.chars
[charInLine
]) || IsControlCharacter(ll
.chars
[charInLine
+ 1])) {
739 ll
.positions
[startseg
] = 0;
740 if (IsControlCharacter(ll
.chars
[charInLine
])) {
741 if (ll
.chars
[charInLine
] == '\t') {
742 ll
.positions
[charInLine
+ 1] = ((((startsegx
+ 2) /
743 tabWidth
) + 1) * tabWidth
) - startsegx
;
745 const char *ctrlChar
= ControlCharacterString(ll
.chars
[charInLine
]);
746 // +3 For a blank on front and rounded edge each side:
747 ll
.positions
[charInLine
+ 1] = surface
->WidthText(ctrlCharsFont
, ctrlChar
, strlen(ctrlChar
)) + 3;
750 surface
->MeasureWidths(vstyle
.styles
[ll
.styles
[charInLine
]].font
, ll
.chars
+ startseg
,
751 charInLine
- startseg
+ 1, ll
.positions
+ startseg
+ 1);
753 for (int posToIncrease
= startseg
; posToIncrease
<= (charInLine
+ 1); posToIncrease
++) {
754 ll
.positions
[posToIncrease
] += startsegx
;
756 startsegx
= ll
.positions
[charInLine
+ 1];
757 startseg
= charInLine
+ 1;
760 ll
.numCharsInLine
= numCharsInLine
;
763 void Editor::DrawLine(Surface
*surface
, ViewStyle
&vsDraw
, int line
, int xStart
, PRectangle rcLine
, LineLayout
&ll
) {
765 PRectangle rcSegment
= rcLine
;
767 // Using one font for all control characters so it can be controlled independently to ensure
768 // the box goes around the characters tightly. Seems to be no way to work out what height
769 // is taken by an individual character - internal leading gives varying results.
770 Font
&ctrlCharsFont
= vsDraw
.styles
[STYLE_CONTROLCHAR
].font
;
773 Colour markBack
= Colour(0, 0, 0);
774 if (vsDraw
.maskInLine
) {
775 marks
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
;
777 for (int markBit
= 0; (markBit
< 32) && marks
; markBit
++) {
779 markBack
= vsDraw
.markers
[markBit
].back
.allocated
;
784 marks
= pdoc
->GetMark(line
) & vsDraw
.maskInLine
;
787 int posLineStart
= pdoc
->LineStart(line
);
788 int posLineEnd
= pdoc
->LineStart(line
+ 1);
790 int selStart
= SelectionStart(line
);
791 int selEnd
= SelectionEnd(line
);
793 int styleMask
= pdoc
->stylingBitsMask
;
795 for (int i
= 0; i
< ll
.numCharsInLine
; i
++) {
797 int iDoc
= i
+ posLineStart
;
798 // If there is the end of a style run for any reason
799 if ((ll
.styles
[i
] != ll
.styles
[i
+ 1]) ||
800 IsControlCharacter(ll
.chars
[i
]) || IsControlCharacter(ll
.chars
[i
+ 1]) ||
801 ((selStart
!= selEnd
) && ((iDoc
+ 1 == selStart
) || (iDoc
+ 1 == selEnd
))) ||
802 (i
== (theEdge
-1))) {
803 int styleMain
= ll
.styles
[i
];
804 Colour textBack
= vsDraw
.styles
[styleMain
].back
.allocated
;
805 Colour textFore
= vsDraw
.styles
[styleMain
].fore
.allocated
;
806 Font
&textFont
= vsDraw
.styles
[styleMain
].font
;
807 bool inSelection
= (iDoc
>= selStart
) && (iDoc
< selEnd
) && (selStart
!= selEnd
);
808 if (inSelection
&& !hideSelection
) {
809 if (vsDraw
.selbackset
)
810 textBack
= vsDraw
.selbackground
.allocated
;
811 if (vsDraw
.selforeset
)
812 textFore
= vsDraw
.selforeground
.allocated
;
816 if ((edgeState
== EDGE_BACKGROUND
) && (i
>= theEdge
) && (ll
.chars
[i
] != '\n') && (ll
.chars
[i
] != '\r'))
817 textBack
= vs
.edgecolour
.allocated
;
819 // Manage tab display
820 if (ll
.chars
[i
] == '\t') {
821 rcSegment
.left
= ll
.positions
[i
] + xStart
;
822 rcSegment
.right
= ll
.positions
[i
+ 1] + xStart
;
823 surface
->FillRectangle(rcSegment
, textBack
);
824 if (vsDraw
.viewWhitespace
) {
825 surface
->PenColour(textFore
);
826 PRectangle
rcTab(rcSegment
.left
+ 1, rcSegment
.top
+ 4,
827 rcSegment
.right
- 1, rcSegment
.bottom
- vsDraw
.maxDescent
);
828 DrawTabArrow(surface
, rcTab
, rcSegment
.top
+ vsDraw
.lineHeight
/ 2);
830 // Manage control character display
831 } else if (IsControlCharacter(ll
.chars
[i
])) {
832 const char *ctrlChar
= ControlCharacterString(ll
.chars
[i
]);
833 rcSegment
.left
= ll
.positions
[i
] + xStart
;
834 rcSegment
.right
= ll
.positions
[i
+ 1] + xStart
;
835 surface
->FillRectangle(rcSegment
, textBack
);
836 int normalCharHeight
= surface
->Ascent(ctrlCharsFont
) -
837 surface
->InternalLeading(ctrlCharsFont
);
838 PRectangle rcCChar
= rcSegment
;
839 rcCChar
.left
= rcCChar
.left
+ 1;
840 rcCChar
.top
= rcSegment
.top
+ vsDraw
.maxAscent
- normalCharHeight
;
841 rcCChar
.bottom
= rcSegment
.top
+ vsDraw
.maxAscent
+ 1;
842 PRectangle rcCentral
= rcCChar
;
845 surface
->FillRectangle(rcCentral
, textFore
);
846 PRectangle rcChar
= rcCChar
;
849 surface
->DrawTextClipped(rcChar
, ctrlCharsFont
,
850 rcSegment
.top
+ vsDraw
.maxAscent
, ctrlChar
, strlen(ctrlChar
),
852 // Manage normal display
854 rcSegment
.left
= ll
.positions
[startseg
] + xStart
;
855 rcSegment
.right
= ll
.positions
[i
+ 1] + xStart
;
856 // Only try do draw if really visible - enhances performance by not calling environment to
857 // draw strings that are completely past the right side of the window.
858 if (rcSegment
.left
<= rcLine
.right
) {
859 surface
->DrawText(rcSegment
, textFont
,
860 rcSegment
.top
+ vsDraw
.maxAscent
, ll
.chars
+ startseg
,
861 i
- startseg
+ 1, textFore
, textBack
);
862 if (vsDraw
.viewWhitespace
) {
863 for (int cpos
= 0; cpos
<= i
- startseg
; cpos
++) {
864 if (ll
.chars
[cpos
+ startseg
] == ' ') {
865 int xmid
= (ll
.positions
[cpos
+ startseg
] + ll
.positions
[cpos
+ startseg
+ 1]) / 2;
866 PRectangle
rcDot(xmid
+ xStart
, rcSegment
.top
+ vsDraw
.lineHeight
/ 2, 0, 0);
867 rcDot
.right
= rcDot
.left
+ 1;
868 rcDot
.bottom
= rcDot
.top
+ 1;
869 surface
->FillRectangle(rcDot
, textFore
);
880 int indStart
[INDIC_MAX
+ 1] = {0};
881 for (int indica
= 0; indica
<= INDIC_MAX
; indica
++)
882 indStart
[indica
] = 0;
884 for (int indicPos
= 0; indicPos
<= ll
.numCharsInLine
; indicPos
++) {
885 if (ll
.indicators
[indicPos
] != ll
.indicators
[indicPos
+ 1]) {
886 int mask
= 1 << pdoc
->stylingBits
;
887 for (int indicnum
= 0; mask
<= 0x100; indicnum
++) {
888 if ((ll
.indicators
[indicPos
+ 1] & mask
) && !(ll
.indicators
[indicPos
] & mask
)) {
889 indStart
[indicnum
] = ll
.positions
[indicPos
+ 1];
891 if (!(ll
.indicators
[indicPos
+ 1] & mask
) && (ll
.indicators
[indicPos
] & mask
)) {
893 indStart
[indicnum
] + xStart
,
894 rcLine
.top
+ vsDraw
.maxAscent
,
895 ll
.positions
[indicPos
+ 1] + xStart
,
896 rcLine
.top
+ vsDraw
.maxAscent
+ 3);
897 vsDraw
.indicators
[indicnum
].Draw(surface
, rcIndic
);
903 // End of the drawing of the current line
905 // Fill in a PRectangle representing the end of line characters
906 int xEol
= ll
.positions
[ll
.numCharsInLine
];
907 rcSegment
.left
= xEol
+ xStart
;
908 rcSegment
.right
= xEol
+ vsDraw
.aveCharWidth
+ xStart
;
909 bool eolInSelection
= (posLineEnd
> selStart
) && (posLineEnd
<= selEnd
) && (selStart
!= selEnd
);
910 if (eolInSelection
&& !hideSelection
&& vsDraw
.selbackset
&& (line
< pdoc
->LinesTotal()-1)) {
911 surface
->FillRectangle(rcSegment
, vsDraw
.selbackground
.allocated
);
913 surface
->FillRectangle(rcSegment
, markBack
);
915 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
.styles
[ll
.numCharsInLine
] & styleMask
].back
.allocated
);
918 rcSegment
.left
= xEol
+ vsDraw
.aveCharWidth
+ xStart
;
919 rcSegment
.right
= rcLine
.right
;
921 surface
->FillRectangle(rcSegment
, markBack
);
922 } else if (vsDraw
.styles
[ll
.styles
[ll
.numCharsInLine
] & styleMask
].eolFilled
) {
923 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[ll
.styles
[ll
.numCharsInLine
] & styleMask
].back
.allocated
);
925 surface
->FillRectangle(rcSegment
, vsDraw
.styles
[STYLE_DEFAULT
].back
.allocated
);
928 if (edgeState
== EDGE_LINE
) {
929 int edgeX
= theEdge
* vsDraw
.spaceWidth
;
930 rcSegment
.left
= edgeX
+ xStart
;
931 rcSegment
.right
= rcSegment
.left
+ 1;
932 surface
->FillRectangle(rcSegment
, vs
.edgecolour
.allocated
);
936 void Editor::Paint(Surface
*surfaceWindow
, PRectangle rcArea
) {
937 //Platform::DebugPrintf("Paint %d %d - %d %d\n", rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
940 PRectangle rcClient
= GetClientRectangle();
941 //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
942 // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
944 if (!pixmapSelPattern
.Initialised()) {
945 pixmapSelPattern
.InitPixMap(8, 8, surfaceWindow
);
946 // This complex procedure is to reproduce the checker board dithered pattern used by windows
947 // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
948 // way between the chrome colour and the chrome highlight colour making a nice transition
949 // between the window chrome and the content area. And it works in low colour depths.
950 PRectangle
rcPattern(0, 0, 8, 8);
951 if (vs
.selbarlight
.desired
== Colour(0xff, 0xff, 0xff)) {
952 pixmapSelPattern
.FillRectangle(rcPattern
, vs
.selbar
.allocated
);
953 pixmapSelPattern
.PenColour(vs
.selbarlight
.allocated
);
954 for (int stripe
= 0; stripe
< 8; stripe
++) {
955 pixmapSelPattern
.MoveTo(0, stripe
* 2);
956 pixmapSelPattern
.LineTo(8, stripe
* 2 - 8);
959 // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
960 pixmapSelPattern
.FillRectangle(rcPattern
, vs
.selbarlight
.allocated
);
965 if (!pixmapLine
.Initialised()) {
966 pixmapLine
.InitPixMap(rcClient
.Width(), rcClient
.Height(),
968 pixmapSelMargin
.InitPixMap(vs
.fixedColumnWidth
,
969 rcClient
.Height(), surfaceWindow
);
973 surfaceWindow
->SetPalette(&palette
, true);
974 pixmapLine
.SetPalette(&palette
, !wMain
.HasFocus());
976 //Platform::DebugPrintf("Paint: (%3d,%3d) ... (%3d,%3d)\n",
977 // rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
979 int screenLinePaintFirst
= rcArea
.top
/ vs
.lineHeight
;
980 // The area to be painted plus one extra line is styled.
981 // The extra line is to determine when a style change, such as statrting a comment flows on to other lines.
982 int lineStyleLast
= topLine
+ (rcArea
.bottom
-1) / vs
.lineHeight
+ 1;
983 //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast);
984 int endPosPaint
= pdoc
->Length();
985 if (lineStyleLast
< cs
.LinesDisplayed())
986 endPosPaint
= pdoc
->LineStart(cs
.DocFromDisplay(lineStyleLast
+ 1));
988 int xStart
= vs
.fixedColumnWidth
- xOffset
;
991 ypos
+= screenLinePaintFirst
* vs
.lineHeight
;
992 int yposScreen
= screenLinePaintFirst
* vs
.lineHeight
;
994 if (endPosPaint
> pdoc
->GetEndStyled()) {
995 // Notify container to do some more styling
996 NotifyStyleNeeded(endPosPaint
);
1000 needUpdateUI
= false;
1003 PaintSelMargin(surfaceWindow
, rcArea
);
1005 PRectangle rcRightMargin
= rcClient
;
1006 rcRightMargin
.left
= rcRightMargin
.right
- vs
.rightMarginWidth
;
1007 if (rcArea
.Intersects(rcRightMargin
)) {
1008 surfaceWindow
->FillRectangle(rcRightMargin
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
);
1011 if (paintState
== paintAbandoned
) {
1012 // Either NotifyStyleNeeded or NotifyUpdateUI noticed that painting is needed
1013 // outside the current painting rectangle
1014 //Platform::DebugPrintf("Abandoning paint\n");
1017 //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
1019 Surface
*surface
= 0;
1020 if (rcArea
.right
> vs
.fixedColumnWidth
) {
1023 surface
= &pixmapLine
;
1025 surface
= surfaceWindow
;
1028 int visibleLine
= topLine
+ screenLinePaintFirst
;
1029 int line
= cs
.DocFromDisplay(visibleLine
);
1031 int posCaret
= currentPos
;
1034 int lineCaret
= pdoc
->LineFromPosition(posCaret
);
1036 // Remove selection margin from drawing area so text will not be drawn
1037 // on it in unbuffered mode.
1038 PRectangle rcTextArea
= rcClient
;
1039 rcTextArea
.left
= vs
.fixedColumnWidth
;
1040 rcTextArea
.right
-= vs
.rightMarginWidth
;
1041 surfaceWindow
->SetClip(rcTextArea
);
1042 //GTimer *tim=g_timer_new();
1043 while (visibleLine
<= cs
.LinesDisplayed() && yposScreen
< rcArea
.bottom
) {
1044 //g_timer_start(tim);
1045 //Platform::DebugPrintf("Painting line %d\n", line);
1047 int posLineStart
= pdoc
->LineStart(line
);
1048 int posLineEnd
= pdoc
->LineStart(line
+ 1);
1049 //Platform::DebugPrintf("line %d %d - %d\n", line, posLineStart, posLineEnd);
1051 PRectangle rcLine
= rcClient
;
1053 rcLine
.bottom
= ypos
+ vs
.lineHeight
;
1055 // Copy this line and its styles from the document into local arrays
1056 // and determine the x position at which each character starts.
1058 LayoutLine(line
, surface
, vs
, ll
);
1060 // Highlight the current braces if any
1061 if ((braces
[0] >= posLineStart
) && (braces
[0] < posLineEnd
))
1062 ll
.styles
[braces
[0] - posLineStart
] = bracesMatchStyle
;
1063 if ((braces
[1] >= posLineStart
) && (braces
[1] < posLineEnd
))
1064 ll
.styles
[braces
[1] - posLineStart
] = bracesMatchStyle
;
1067 if (cs
.GetVisible(line
))
1068 DrawLine(surface
, vs
, line
, xStart
, rcLine
, ll
);
1070 if (foldFlags
& 2) {
1071 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
1072 PRectangle rcFoldLine
= rcLine
;
1073 rcFoldLine
.bottom
= rcFoldLine
.top
+ 1;
1074 surface
->FillRectangle(rcFoldLine
, vs
.styles
[STYLE_DEFAULT
].fore
.allocated
);
1079 if (line
== lineCaret
) {
1080 int xposCaret
= ll
.positions
[posCaret
- posLineStart
] + xStart
;
1081 int widthOverstrikeCaret
=
1082 ll
.positions
[posCaret
- posLineStart
+ 1] - ll
.positions
[posCaret
- posLineStart
];
1083 if (posCaret
== pdoc
->Length()) // At end of document
1084 widthOverstrikeCaret
= vs
.aveCharWidth
;
1085 if ((posCaret
- posLineStart
) >= ll
.numCharsInLine
) // At end of line
1086 widthOverstrikeCaret
= vs
.aveCharWidth
;
1087 if (widthOverstrikeCaret
< 3) // Make sure its visible
1088 widthOverstrikeCaret
= 3;
1089 if (((caret
.active
&& caret
.on
) || (posDrag
>= 0)) && xposCaret
>= 0) {
1090 PRectangle rcCaret
= rcLine
;
1092 rcCaret
.left
= xposCaret
;
1093 rcCaret
.right
= xposCaret
+ 1;
1096 rcCaret
.top
= rcCaret
.bottom
- 2;
1097 rcCaret
.left
= xposCaret
+ 1;
1098 rcCaret
.right
= rcCaret
.left
+ widthOverstrikeCaret
- 1;
1100 rcCaret
.left
= xposCaret
;
1101 rcCaret
.right
= xposCaret
+ 1;
1104 surface
->FillRectangle(rcCaret
, vs
.caretcolour
.allocated
);
1108 if (cs
.GetVisible(line
)) {
1110 Point
from(vs
.fixedColumnWidth
, 0);
1111 PRectangle
rcCopyArea(vs
.fixedColumnWidth
, yposScreen
,
1112 rcClient
.right
, yposScreen
+ vs
.lineHeight
);
1113 surfaceWindow
->Copy(rcCopyArea
, from
, pixmapLine
);
1117 if (!bufferedDraw
) {
1118 ypos
+= vs
.lineHeight
;
1121 yposScreen
+= vs
.lineHeight
;
1123 line
= cs
.DocFromDisplay(visibleLine
);
1125 //g_timer_stop(tim);
1126 //Platform::DebugPrintf("Paint [%0d] took %g\n", line, g_timer_elapsed(tim, 0));
1128 //g_timer_destroy(tim);
1129 PRectangle rcBeyondEOF
= rcClient
;
1130 rcBeyondEOF
.left
= vs
.fixedColumnWidth
;
1131 rcBeyondEOF
.right
= rcBeyondEOF
.right
;
1132 rcBeyondEOF
.top
= (cs
.LinesDisplayed() - topLine
) * vs
.lineHeight
;
1133 if (rcBeyondEOF
.top
< rcBeyondEOF
.bottom
) {
1134 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.styles
[STYLE_DEFAULT
].back
.allocated
);
1135 if (edgeState
== EDGE_LINE
) {
1136 int edgeX
= theEdge
* vs
.spaceWidth
;
1137 rcBeyondEOF
.left
= edgeX
+ xStart
;
1138 rcBeyondEOF
.right
= rcBeyondEOF
.left
+ 1;
1139 surfaceWindow
->FillRectangle(rcBeyondEOF
, vs
.edgecolour
.allocated
);
1145 // Space (3 space characters) between line numbers and text when printing.
1146 #define lineNumberPrintSpace " "
1148 // This is mostly copied from the Paint method but with some things omitted
1149 // such as the margin markers, line numbers, selection and caret
1150 // Should be merged back into a combined Draw method.
1151 long Editor::FormatRange(bool draw
, FORMATRANGE
*pfr
) {
1155 Surface
*surface
= new Surface();
1156 surface
->Init(pfr
->hdc
);
1157 Surface
*surfaceMeasure
= new Surface();
1158 surfaceMeasure
->Init(pfr
->hdcTarget
);
1160 ViewStyle
vsPrint(vs
);
1162 // Modify the view style for printing as do not normally want any of the transient features to be printed
1163 // Printing supports only the line number margin.
1164 int lineNumberIndex
= -1;
1165 for (int margin
=0; margin
< ViewStyle::margins
; margin
++) {
1166 if ((!vsPrint
.ms
[margin
].symbol
) && (vsPrint
.ms
[margin
].width
> 0)) {
1167 lineNumberIndex
= margin
;
1169 vsPrint
.ms
[margin
].width
= 0;
1172 vsPrint
.showMarkedLines
= false;
1173 vsPrint
.fixedColumnWidth
= 0;
1174 vsPrint
.zoomLevel
= 0;
1175 // Don't show the selection when printing
1176 vsPrint
.selbackset
= false;
1177 vsPrint
.selforeset
= false;
1178 // White background for the line numbers
1179 vsPrint
.styles
[STYLE_LINENUMBER
].back
.desired
= Colour(0xff,0xff,0xff);
1181 vsPrint
.Refresh(*surfaceMeasure
);
1182 // Ensure colours are set up
1183 vsPrint
.RefreshColourPalette(palette
, true);
1184 vsPrint
.RefreshColourPalette(palette
, false);
1185 // Determining width must hapen after fonts have been realised in Refresh
1186 int lineNumberWidth
= 0;
1187 if (lineNumberIndex
>= 0) {
1188 lineNumberWidth
= surface
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
,
1189 "9999" lineNumberPrintSpace
, 4 + strlen(lineNumberPrintSpace
));
1190 vsPrint
.ms
[lineNumberIndex
].width
= lineNumberWidth
;
1193 int linePrintStart
= pdoc
->LineFromPosition(pfr
->chrg
.cpMin
);
1194 int linePrintLast
= linePrintStart
+ (pfr
->rc
.bottom
- pfr
->rc
.top
) / vsPrint
.lineHeight
- 1;
1195 if (linePrintLast
< linePrintStart
)
1196 linePrintLast
= linePrintStart
;
1197 int linePrintMax
= pdoc
->LineFromPosition(pfr
->chrg
.cpMax
- 1);
1198 if (linePrintLast
> linePrintMax
)
1199 linePrintLast
= linePrintMax
;
1200 //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
1201 // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
1202 // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
1203 int endPosPrint
= pdoc
->Length();
1204 if (linePrintLast
< pdoc
->LinesTotal())
1205 endPosPrint
= pdoc
->LineStart(linePrintLast
+ 1);
1207 if (endPosPrint
> pdoc
->GetEndStyled()) {
1208 // Notify container to do some more styling
1209 NotifyStyleNeeded(endPosPrint
);
1211 int xStart
= vsPrint
.fixedColumnWidth
+ pfr
->rc
.left
+ lineNumberWidth
;
1212 int ypos
= pfr
->rc
.top
;
1213 int line
= linePrintStart
;
1215 if (draw
) { // Otherwise just measuring
1217 while (line
<= linePrintLast
&& ypos
< pfr
->rc
.bottom
) {
1220 rcLine
.left
= pfr
->rc
.left
+ lineNumberWidth
;
1222 rcLine
.right
= pfr
->rc
.right
;
1223 rcLine
.bottom
= ypos
+ vsPrint
.lineHeight
;
1225 if (lineNumberWidth
) {
1227 sprintf(number
, "%d" lineNumberPrintSpace
, line
+ 1);
1228 PRectangle rcNumber
= rcLine
;
1229 rcNumber
.right
= rcNumber
.left
+ lineNumberWidth
;
1231 rcNumber
.left
+= lineNumberWidth
-
1232 surface
->WidthText(vsPrint
.styles
[STYLE_LINENUMBER
].font
, number
, strlen(number
));
1233 surface
->DrawText(rcNumber
, vsPrint
.styles
[STYLE_LINENUMBER
].font
,
1234 ypos
+ vsPrint
.maxAscent
, number
, strlen(number
),
1235 vsPrint
.styles
[STYLE_LINENUMBER
].fore
.allocated
,
1236 vsPrint
.styles
[STYLE_LINENUMBER
].back
.allocated
);
1239 // Copy this line and its styles from the document into local arrays
1240 // and determine the x position at which each character starts.
1242 LayoutLine(line
, surfaceMeasure
, vsPrint
, ll
);
1245 DrawLine(surface
, vsPrint
, line
, xStart
, rcLine
, ll
);
1247 ypos
+= vsPrint
.lineHeight
;
1253 delete surfaceMeasure
;
1258 void Editor::SetScrollBarsTo(PRectangle
) {
1261 int nMax
= cs
.LinesDisplayed();
1262 int nPage
= cs
.LinesDisplayed() - MaxScrollPos() + 1;
1263 bool modified
= ModifyScrollBars(nMax
, nPage
);
1265 // TODO: ensure always showing as many lines as possible
1266 // May not be, if, for example, window made larger
1267 if (topLine
> MaxScrollPos()) {
1268 SetTopLine(Platform::Clamp(topLine
, 0, MaxScrollPos()));
1269 SetVerticalScrollPos();
1274 //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
1277 void Editor::SetScrollBars() {
1278 PRectangle rsClient
= GetClientRectangle();
1279 SetScrollBarsTo(rsClient
);
1282 void Editor::AddChar(char ch
) {
1283 bool wasSelection
= currentPos
!= anchor
;
1285 if (inOverstrike
&& !wasSelection
) {
1286 if (currentPos
< (pdoc
->Length() - 1)) {
1287 if ((pdoc
->CharAt(currentPos
) != '\r') && (pdoc
->CharAt(currentPos
) != '\n')) {
1288 pdoc
->DelChar(currentPos
);
1292 pdoc
->InsertChar(currentPos
, ch
);
1293 SetEmptySelection(currentPos
+ 1);
1294 EnsureCaretVisible();
1299 void Editor::ClearSelection() {
1300 if (selType
== selRectangle
) {
1301 pdoc
->BeginUndoAction();
1302 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
1303 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
1304 int startPos
= SelectionStart();
1306 for (line
=lineStart
; line
<= lineEnd
; line
++) {
1307 startPos
= SelectionStart(line
);
1308 unsigned int chars
= SelectionEnd(line
) - startPos
;
1310 pdoc
->DeleteChars(startPos
, chars
);
1313 SetEmptySelection(startPos
);
1314 selType
= selStream
;
1315 pdoc
->EndUndoAction();
1317 int startPos
= SelectionStart();
1318 unsigned int chars
= SelectionEnd() - startPos
;
1319 SetEmptySelection(startPos
);
1321 pdoc
->DeleteChars(startPos
, chars
);
1326 void Editor::ClearAll() {
1327 if (0 != pdoc
->Length()) {
1328 pdoc
->DeleteChars(0, pdoc
->Length());
1334 SetVerticalScrollPos();
1337 void Editor::Cut() {
1342 void Editor::PasteRectangular(int pos
, const char *ptr
, int len
) {
1344 int insertPos
= currentPos
;
1345 int xInsert
= XFromPosition(currentPos
);
1346 int line
= pdoc
->LineFromPosition(currentPos
);
1347 bool prevCr
= false;
1348 for (int i
=0; i
<len
; i
++) {
1349 if ((ptr
[i
] == '\r') || (ptr
[i
] == '\n')) {
1350 if ((ptr
[i
] == '\r') || (!prevCr
))
1352 if (line
>= pdoc
->LinesTotal()) {
1353 if (pdoc
->eolMode
!= SC_EOL_LF
)
1354 pdoc
->InsertChar(pdoc
->Length(), '\r');
1355 if (pdoc
->eolMode
!= SC_EOL_CR
)
1356 pdoc
->InsertChar(pdoc
->Length(), '\n');
1358 currentPos
= PositionFromLineX(line
, xInsert
);
1359 prevCr
= ptr
[i
] == '\r';
1361 pdoc
->InsertString(currentPos
, ptr
+i
, 1);
1363 insertPos
= currentPos
;
1367 SetEmptySelection(insertPos
);
1370 void Editor::Clear() {
1371 if (currentPos
== anchor
) {
1376 SetEmptySelection(currentPos
);
1379 void Editor::SelectAll() {
1380 SetSelection(0, pdoc
->Length());
1384 void Editor::Undo() {
1385 if (pdoc
->CanUndo()) {
1386 int newPos
= pdoc
->Undo();
1387 SetEmptySelection(newPos
);
1388 EnsureCaretVisible();
1392 void Editor::Redo() {
1393 if (pdoc
->CanRedo()) {
1394 int newPos
= pdoc
->Redo();
1395 SetEmptySelection(newPos
);
1396 EnsureCaretVisible();
1400 void Editor::DelChar() {
1401 pdoc
->DelChar(currentPos
);
1404 void Editor::DelCharBack() {
1405 if (currentPos
== anchor
) {
1406 int newPos
= pdoc
->DelCharBack(currentPos
);
1407 SetEmptySelection(newPos
);
1410 SetEmptySelection(currentPos
);
1414 void Editor::NotifyFocus(bool) {
1417 void Editor::NotifyStyleNeeded(int endStyleNeeded
) {
1419 scn
.nmhdr
.code
= SCN_STYLENEEDED
;
1420 scn
.position
= endStyleNeeded
;
1424 void Editor::NotifyChar(char ch
) {
1426 scn
.nmhdr
.code
= SCN_CHARADDED
;
1429 #ifdef MACRO_SUPPORT
1430 if (recordingMacro
) {
1434 NotifyMacroRecord(EM_REPLACESEL
, 0, (LPARAM
) txt
);
1439 void Editor::NotifySavePoint(bool isSavePoint
) {
1442 scn
.nmhdr
.code
= SCN_SAVEPOINTREACHED
;
1444 scn
.nmhdr
.code
= SCN_SAVEPOINTLEFT
;
1449 void Editor::NotifyModifyAttempt() {
1451 scn
.nmhdr
.code
= SCN_MODIFYATTEMPTRO
;
1455 void Editor::NotifyDoubleClick(Point
, bool) {
1457 scn
.nmhdr
.code
= SCN_DOUBLECLICK
;
1461 void Editor::NotifyUpdateUI() {
1463 scn
.nmhdr
.code
= SCN_UPDATEUI
;
1467 bool Editor::NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
) {
1468 int marginClicked
= -1;
1470 for (int margin
=0; margin
< ViewStyle::margins
; margin
++) {
1471 if ((pt
.x
> x
) && (pt
.x
< x
+ vs
.ms
[margin
].width
))
1472 marginClicked
= margin
;
1473 x
+= vs
.ms
[margin
].width
;
1475 if ((marginClicked
>= 0) && vs
.ms
[marginClicked
].sensitive
) {
1477 scn
.nmhdr
.code
= SCN_MARGINCLICK
;
1478 scn
.modifiers
= (shift
? SCI_SHIFT
: 0) | (ctrl
? SCI_CTRL
: 0) |
1479 (alt
? SCI_ALT
: 0);
1480 scn
.position
= pdoc
->LineStart(LineFromLocation(pt
));
1481 scn
.margin
= marginClicked
;
1489 void Editor::NotifyNeedShown(int pos
, int len
) {
1491 scn
.nmhdr
.code
= SCN_NEEDSHOWN
;
1497 // Notifications from document
1498 void Editor::NotifyModifyAttempt(Document
*, void *) {
1499 //Platform::DebugPrintf("** Modify Attempt\n");
1500 NotifyModifyAttempt();
1503 void Editor::NotifySavePoint(Document
*, void *, bool atSavePoint
) {
1504 //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
1505 NotifySavePoint(atSavePoint
);
1508 void Editor::NotifyModified(Document
*, DocModification mh
, void *) {
1509 needUpdateUI
= true;
1510 if (paintState
== painting
) {
1511 CheckForChangeOutsidePaint(Range(mh
.position
, mh
.position
+ mh
.length
));
1512 } else if (paintState
== notPainting
) {
1513 if (mh
.modificationType
& SC_MOD_CHANGESTYLE
) {
1514 if (mh
.position
< pdoc
->LineStart(topLine
)) {
1515 // Styling performed before this view
1518 InvalidateRange(mh
.position
, mh
.position
+ mh
.length
);
1521 // Move selection and brace highlights
1522 if (mh
.modificationType
& SC_MOD_INSERTTEXT
) {
1523 if (currentPos
> mh
.position
) {
1524 currentPos
+= mh
.length
;
1526 if (anchor
> mh
.position
) {
1527 anchor
+= mh
.length
;
1529 if (braces
[0] > mh
.position
) {
1530 braces
[0] += mh
.length
;
1532 if (braces
[1] > mh
.position
) {
1533 braces
[1] += mh
.length
;
1535 } else { // SC_MOD_DELETETEXT
1536 int endPos
= mh
.position
+ mh
.length
;
1537 if (currentPos
> mh
.position
) {
1538 if (currentPos
> endPos
) {
1539 currentPos
-= mh
.length
;
1541 currentPos
= endPos
;
1544 if (anchor
> mh
.position
) {
1545 if (anchor
> endPos
) {
1546 anchor
-= mh
.length
;
1551 if (braces
[0] > mh
.position
) {
1552 if (braces
[0] > endPos
) {
1553 braces
[0] -= mh
.length
;
1558 if (braces
[1] > mh
.position
) {
1559 if (braces
[1] > endPos
) {
1560 braces
[1] -= mh
.length
;
1566 if (mh
.linesAdded
!= 0) {
1568 // Update contraction state for inserted and removed lines
1569 // lineOfPos should be calculated in context of state before modification, shouldn't it
1570 int lineOfPos
= pdoc
->LineFromPosition(mh
.position
);
1571 if (mh
.linesAdded
> 0) {
1572 NotifyNeedShown(mh
.position
, mh
.length
);
1573 cs
.InsertLines(lineOfPos
, mh
.linesAdded
);
1575 cs
.DeleteLines(lineOfPos
, -mh
.linesAdded
);
1577 // Avoid scrolling of display if change before current display
1578 if (mh
.position
< posTopLine
) {
1579 int newTop
= Platform::Clamp(topLine
+ mh
.linesAdded
, 0, MaxScrollPos());
1580 if (newTop
!= topLine
) {
1582 SetVerticalScrollPos();
1586 //Platform::DebugPrintf("** %x Doc Changed\n", this);
1587 // TODO: could invalidate from mh.startModification to end of screen
1588 //InvalidateRange(mh.position, mh.position + mh.length);
1591 //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
1592 // mh.position, mh.position + mh.length);
1593 InvalidateRange(mh
.position
, mh
.position
+ mh
.length
);
1596 } // else paintState == paintAbandoned so no need to do anything
1598 if (mh
.linesAdded
!= 0) {
1602 // If client wants to see this modification
1603 if (mh
.modificationType
& modEventMask
) {
1604 if ((mh
.modificationType
& SC_MOD_CHANGESTYLE
) == 0) {
1605 // Real modification made to text of document.
1606 NotifyChange(); // Send EN_CHANGE
1609 scn
.nmhdr
.code
= SCN_MODIFIED
;
1610 scn
.position
= mh
.position
;
1611 scn
.modificationType
= mh
.modificationType
;
1613 scn
.length
= mh
.length
;
1614 scn
.linesAdded
= mh
.linesAdded
;
1616 scn
.foldLevelNow
= mh
.foldLevelNow
;
1617 scn
.foldLevelPrev
= mh
.foldLevelPrev
;
1622 void Editor::NotifyDeleted(Document
*document
, void *userData
) {
1626 #ifdef MACRO_SUPPORT
1627 void Editor::NotifyMacroRecord(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
1629 // Enumerates all macroable messages
1637 case SCI_INSERTTEXT
:
1642 case SCI_SEARCHANCHOR
:
1643 case SCI_SEARCHNEXT
:
1644 case SCI_SEARCHPREV
:
1646 case SCI_LINEDOWNEXTEND
:
1648 case SCI_LINEUPEXTEND
:
1650 case SCI_CHARLEFTEXTEND
:
1652 case SCI_CHARRIGHTEXTEND
:
1654 case SCI_WORDLEFTEXTEND
:
1656 case SCI_WORDRIGHTEXTEND
:
1658 case SCI_HOMEEXTEND
:
1660 case SCI_LINEENDEXTEND
:
1661 case SCI_DOCUMENTSTART
:
1662 case SCI_DOCUMENTSTARTEXTEND
:
1663 case SCI_DOCUMENTEND
:
1664 case SCI_DOCUMENTENDEXTEND
:
1666 case SCI_PAGEUPEXTEND
:
1668 case SCI_PAGEDOWNEXTEND
:
1669 case SCI_EDITTOGGLEOVERTYPE
:
1671 case SCI_DELETEBACK
:
1677 case SCI_VCHOMEEXTEND
:
1678 case SCI_DELWORDLEFT
:
1679 case SCI_DELWORDRIGHT
:
1682 // Filter out all others (display changes, etc)
1684 // printf("Filtered out %ld of macro recording\n", iMessage);
1688 // Send notification
1690 scn
.nmhdr
.code
= SCN_MACRORECORD
;
1691 scn
.message
= iMessage
;
1692 scn
.wParam
= wParam
;
1693 scn
.lParam
= lParam
;
1698 // Force scroll and keep position relative to top of window
1699 void Editor::PageMove(int direction
, bool extend
) {
1700 Point pt
= LocationFromPosition(currentPos
);
1701 int topLineNew
= Platform::Clamp(
1702 topLine
+ direction
* LinesToScroll(), 0, MaxScrollPos());
1703 int newPos
= PositionFromLocation(
1704 Point(lastXChosen
, pt
.y
+ direction
* (vs
.lineHeight
* LinesToScroll())));
1705 if (topLineNew
!= topLine
) {
1706 SetTopLine(topLineNew
);
1707 MovePositionTo(newPos
, extend
);
1709 SetVerticalScrollPos();
1711 MovePositionTo(newPos
, extend
);
1715 int Editor::KeyCommand(UINT iMessage
) {
1716 Point pt
= LocationFromPosition(currentPos
);
1720 MovePositionTo(PositionFromLocation(
1721 Point(lastXChosen
, pt
.y
+ vs
.lineHeight
)));
1723 case SCI_LINEDOWNEXTEND
:
1724 MovePositionTo(PositionFromLocation(
1725 Point(lastXChosen
, pt
.y
+ vs
.lineHeight
)), true);
1728 MovePositionTo(PositionFromLocation(
1729 Point(lastXChosen
, pt
.y
- vs
.lineHeight
)));
1731 case SCI_LINEUPEXTEND
:
1732 MovePositionTo(PositionFromLocation(
1733 Point(lastXChosen
, pt
.y
- vs
.lineHeight
)), true);
1736 if (SelectionEmpty()) {
1737 MovePositionTo(MovePositionSoVisible(currentPos
- 1, -1));
1739 MovePositionTo(SelectionStart());
1743 case SCI_CHARLEFTEXTEND
:
1744 MovePositionTo(MovePositionSoVisible(currentPos
- 1, -1), true);
1748 if (SelectionEmpty()) {
1749 MovePositionTo(MovePositionSoVisible(currentPos
+ 1, 1));
1751 MovePositionTo(SelectionEnd());
1755 case SCI_CHARRIGHTEXTEND
:
1756 MovePositionTo(MovePositionSoVisible(currentPos
+ 1, 1), true);
1760 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1));
1763 case SCI_WORDLEFTEXTEND
:
1764 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, -1), -1), true);
1768 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1));
1771 case SCI_WORDRIGHTEXTEND
:
1772 MovePositionTo(MovePositionSoVisible(pdoc
->NextWordStart(currentPos
, 1), 1), true);
1776 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)));
1779 case SCI_HOMEEXTEND
:
1780 MovePositionTo(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos
)), true);
1784 MovePositionTo(pdoc
->LineEndPosition(currentPos
));
1787 case SCI_LINEENDEXTEND
:
1788 MovePositionTo(pdoc
->LineEndPosition(currentPos
), true);
1791 case SCI_DOCUMENTSTART
:
1795 case SCI_DOCUMENTSTARTEXTEND
:
1796 MovePositionTo(0, true);
1799 case SCI_DOCUMENTEND
:
1800 MovePositionTo(pdoc
->Length());
1803 case SCI_DOCUMENTENDEXTEND
:
1804 MovePositionTo(pdoc
->Length(), true);
1810 case SCI_PAGEUPEXTEND
:
1811 PageMove( -1, true);
1816 case SCI_PAGEDOWNEXTEND
:
1819 case SCI_EDITTOGGLEOVERTYPE
:
1820 inOverstrike
= !inOverstrike
;
1822 ShowCaretAtCurrentPosition();
1824 case SCI_CANCEL
: // Cancel any modes - handled in subclass
1825 // Also unselect text
1826 SetEmptySelection(currentPos
);
1828 case SCI_DELETEBACK
:
1830 EnsureCaretVisible();
1840 if (pdoc
->eolMode
== SC_EOL_CRLF
) {
1841 pdoc
->InsertString(currentPos
, "\r\n");
1842 SetEmptySelection(currentPos
+ 2);
1845 } else if (pdoc
->eolMode
== SC_EOL_CR
) {
1846 pdoc
->InsertChar(currentPos
, '\r');
1847 SetEmptySelection(currentPos
+ 1);
1849 } else if (pdoc
->eolMode
== SC_EOL_LF
) {
1850 pdoc
->InsertChar(currentPos
, '\n');
1851 SetEmptySelection(currentPos
+ 1);
1855 EnsureCaretVisible();
1861 MovePositionTo(pdoc
->VCHomePosition(currentPos
));
1864 case SCI_VCHOMEEXTEND
:
1865 MovePositionTo(pdoc
->VCHomePosition(currentPos
), true);
1869 if (vs
.zoomLevel
< 20)
1871 InvalidateStyleRedraw();
1874 if (vs
.zoomLevel
> -10)
1876 InvalidateStyleRedraw();
1878 case SCI_DELWORDLEFT
: {
1879 int startWord
= pdoc
->NextWordStart(currentPos
, -1);
1880 pdoc
->DeleteChars(startWord
, currentPos
- startWord
);
1881 MovePositionTo(startWord
);
1884 case SCI_DELWORDRIGHT
: {
1885 int endWord
= pdoc
->NextWordStart(currentPos
, 1);
1886 pdoc
->DeleteChars(currentPos
, endWord
- currentPos
);
1893 int Editor::KeyDefault(int, int) {
1897 int Editor::KeyDown(int key
, bool shift
, bool ctrl
, bool alt
) {
1898 int modifiers
= (shift
? SCI_SHIFT
: 0) | (ctrl
? SCI_CTRL
: 0) |
1899 (alt
? SCI_ALT
: 0);
1900 int msg
= kmap
.Find(key
, modifiers
);
1902 return WndProc(msg
, 0, 0);
1904 return KeyDefault(key
, modifiers
);
1907 void Editor::SetWhitespaceVisible(bool view
) {
1908 vs
.viewWhitespace
= view
;
1911 bool Editor::GetWhitespaceVisible() {
1912 return vs
.viewWhitespace
;
1915 void Editor::Indent(bool forwards
) {
1916 //Platform::DebugPrintf("INdent %d\n", forwards);
1917 int lineOfAnchor
= pdoc
->LineFromPosition(anchor
);
1918 int lineCurrentPos
= pdoc
->LineFromPosition(currentPos
);
1919 if (lineOfAnchor
== lineCurrentPos
) {
1921 pdoc
->InsertChar(currentPos
, '\t');
1922 //pdoc->InsertChar(currentPos++, '\t');
1923 SetEmptySelection(currentPos
+ 1);
1925 int anchorPosOnLine
= anchor
- pdoc
->LineStart(lineOfAnchor
);
1926 int currentPosPosOnLine
= currentPos
- pdoc
->LineStart(lineCurrentPos
);
1927 // Multiple lines selected so indent / dedent
1928 int lineTopSel
= Platform::Minimum(lineOfAnchor
, lineCurrentPos
);
1929 int lineBottomSel
= Platform::Maximum(lineOfAnchor
, lineCurrentPos
);
1930 if (pdoc
->LineStart(lineBottomSel
) == anchor
|| pdoc
->LineStart(lineBottomSel
) == currentPos
)
1931 lineBottomSel
--; // If not selecting any characters on a line, do not indent
1932 pdoc
->BeginUndoAction();
1933 pdoc
->Indent(forwards
, lineBottomSel
, lineTopSel
);
1934 pdoc
->EndUndoAction();
1935 if (lineOfAnchor
< lineCurrentPos
) {
1936 if (currentPosPosOnLine
== 0)
1937 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
));
1939 SetSelection(pdoc
->LineStart(lineCurrentPos
+ 1), pdoc
->LineStart(lineOfAnchor
));
1941 if (anchorPosOnLine
== 0)
1942 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
));
1944 SetSelection(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
+ 1));
1949 long Editor::FindText(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
1950 FINDTEXTEX
*ft
= reinterpret_cast<FINDTEXTEX
*>(lParam
);
1951 int pos
= pdoc
->FindText(ft
->chrg
.cpMin
, ft
->chrg
.cpMax
, ft
->lpstrText
,
1952 wParam
& FR_MATCHCASE
, wParam
& FR_WHOLEWORD
);
1954 if (iMessage
== EM_FINDTEXTEX
) {
1955 ft
->chrgText
.cpMin
= pos
;
1956 ft
->chrgText
.cpMax
= pos
+ strlen(ft
->lpstrText
);
1962 // Relocatable search support : Searches relative to current selection
1963 // point and sets the selection to the found text range with
1966 // Anchor following searches at current selection start: This allows
1967 // multiple incremental interactive searches to be macro recorded
1968 // while still setting the selection to found text so the find/select
1969 // operation is self-contained.
1970 void Editor::SearchAnchor() {
1971 searchAnchor
= SelectionStart();
1974 // Find text from current search anchor: Must call SearchAnchor first.
1975 // Accepts both SCI_SEARCHNEXT and SCI_SEARCHPREV.
1976 // wParam contains search modes : ORed FR_MATCHCASE and FR_WHOLEWORD.
1977 // lParam contains the text to search for.
1978 long Editor::SearchText(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
1979 const char *txt
= reinterpret_cast<char *>(lParam
);
1982 if (iMessage
== SCI_SEARCHNEXT
) {
1983 pos
= pdoc
->FindText(searchAnchor
, pdoc
->Length(), txt
,
1984 wParam
& FR_MATCHCASE
,
1985 wParam
& FR_WHOLEWORD
);
1987 pos
= pdoc
->FindText(searchAnchor
, 0, txt
,
1988 wParam
& FR_MATCHCASE
,
1989 wParam
& FR_WHOLEWORD
);
1993 SetSelection(pos
, pos
+ strlen(txt
));
1999 void Editor::GoToLine(int lineNo
) {
2000 if (lineNo
> pdoc
->LinesTotal())
2001 lineNo
= pdoc
->LinesTotal();
2004 SetEmptySelection(pdoc
->LineStart(lineNo
));
2005 ShowCaretAtCurrentPosition();
2006 EnsureCaretVisible();
2009 static bool Close(Point pt1
, Point pt2
) {
2010 if (abs(pt1
.x
- pt2
.x
) > 3)
2012 if (abs(pt1
.y
- pt2
.y
) > 3)
2017 char *Editor::CopyRange(int start
, int end
) {
2020 int len
= end
- start
;
2021 text
= new char[len
+ 1];
2023 for (int i
= 0; i
< len
; i
++) {
2024 text
[i
] = pdoc
->CharAt(start
+ i
);
2032 int Editor::SelectionRangeLength() {
2033 if (selType
== selRectangle
) {
2034 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
2035 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
2037 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
2038 totalSize
+= SelectionEnd(line
) - SelectionStart(line
) + 1;
2039 if (pdoc
->eolMode
== SC_EOL_CRLF
)
2044 return SelectionEnd() - SelectionStart();
2048 char *Editor::CopySelectionRange() {
2049 if (selType
== selRectangle
) {
2051 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
2052 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
2053 int totalSize
= SelectionRangeLength();
2054 if (totalSize
> 0) {
2055 text
= new char[totalSize
+ 1];
2058 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
2059 for (int i
=SelectionStart(line
);i
<SelectionEnd(line
);i
++) {
2060 text
[j
++] = pdoc
->CharAt(i
);
2062 if (pdoc
->eolMode
!= SC_EOL_LF
)
2064 if (pdoc
->eolMode
!= SC_EOL_CR
)
2067 text
[totalSize
] = '\0';
2072 return CopyRange(SelectionStart(), SelectionEnd());
2076 void Editor::CopySelectionIntoDrag() {
2079 lenDrag
= SelectionRangeLength();
2080 dragChars
= CopySelectionRange();
2081 dragIsRectangle
= selType
== selRectangle
;
2087 void Editor::SetDragPosition(int newPos
) {
2089 newPos
= pdoc
->MovePositionOutsideChar(newPos
, 1);
2092 if (posDrag
!= newPos
) {
2101 void Editor::StartDrag() {
2102 // Always handled by subclasses
2103 //SetMouseCapture(true);
2104 //wDraw.SetCursor(Window::cursorArrow);
2107 void Editor::DropAt(int position
, const char *value
, bool moving
, bool rectangular
) {
2108 //Platform::DebugPrintf("DropAt %d\n", inDragDrop);
2110 dropWentOutside
= false;
2112 int positionWasInSelection
= PositionInSelection(position
);
2114 if ((!inDragDrop
) || !(0 == positionWasInSelection
)) {
2116 int selStart
= SelectionStart();
2117 int selEnd
= SelectionEnd();
2119 pdoc
->BeginUndoAction();
2121 int positionAfterDeletion
= position
;
2122 if (inDragDrop
&& moving
) {
2123 // Remove dragged out text
2125 int lineStart
= pdoc
->LineFromPosition(SelectionStart());
2126 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd());
2127 for (int line
=lineStart
; line
<= lineEnd
; line
++) {
2128 int startPos
= SelectionStart(line
);
2129 int endPos
= SelectionEnd(line
);
2130 if (position
>= startPos
) {
2131 if (position
> endPos
) {
2132 positionAfterDeletion
-= endPos
- startPos
;
2134 positionAfterDeletion
-= position
- startPos
;
2139 if (position
> selStart
) {
2140 positionAfterDeletion
-= selEnd
- selStart
;
2145 position
= positionAfterDeletion
;
2148 PasteRectangular(position
, value
, strlen(value
));
2149 pdoc
->EndUndoAction();
2150 // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
2151 SetSelection(position
, position
);
2153 position
= pdoc
->MovePositionOutsideChar(position
, currentPos
- position
);
2154 pdoc
->InsertString(position
, value
);
2155 pdoc
->EndUndoAction();
2156 SetSelection(position
+ strlen(value
), position
);
2158 } else if (inDragDrop
) {
2159 SetSelection(position
, position
);
2163 static int BeforeInOrAfter(int val
, int minim
, int maxim
) {
2166 else if (val
> maxim
)
2172 int Editor::PositionInSelection(int pos
) {
2173 pos
= pdoc
->MovePositionOutsideChar(pos
, currentPos
- pos
);
2174 if (selType
== selRectangle
) {
2175 if (pos
< SelectionStart())
2177 if (pos
> SelectionEnd())
2179 int linePos
= pdoc
->LineFromPosition(pos
);
2180 return BeforeInOrAfter(pos
, SelectionStart(linePos
), SelectionEnd(linePos
));
2182 if (currentPos
> anchor
) {
2183 return BeforeInOrAfter(pos
, anchor
, currentPos
);
2184 } else if (currentPos
< anchor
) {
2185 return BeforeInOrAfter(pos
, currentPos
, anchor
);
2191 bool Editor::PointInSelection(Point pt
) {
2192 // TODO: fix up for rectangular selection
2193 int pos
= PositionFromLocation(pt
);
2194 if (0 == PositionInSelection(pos
)) {
2195 if (pos
== SelectionStart()) {
2196 // see if just before selection
2197 Point locStart
= LocationFromPosition(pos
);
2198 if (pt
.x
< locStart
.x
)
2201 if (pos
== SelectionEnd()) {
2202 // see if just after selection
2203 Point locEnd
= LocationFromPosition(pos
);
2204 if (pt
.x
> locEnd
.x
)
2212 bool Editor::PointInSelMargin(Point pt
) {
2213 // Really means: "Point in a margin"
2214 if (vs
.fixedColumnWidth
> 0) { // There is a margin
2215 PRectangle rcSelMargin
= GetClientRectangle();
2216 rcSelMargin
.right
= vs
.fixedColumnWidth
- vs
.leftMarginWidth
;
2217 return rcSelMargin
.Contains(pt
);
2223 void Editor::ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
) {
2224 //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);
2226 int newPos
= PositionFromLocation(pt
);
2227 newPos
= pdoc
->MovePositionOutsideChar(newPos
, currentPos
- newPos
);
2230 bool processed
= NotifyMarginClick(pt
, shift
, ctrl
, alt
);
2235 SetSelection(newPos
);
2237 if (((curTime
- lastClickTime
) < Platform::DoubleClickTime()) && Close(pt
, lastClick
)) {
2238 //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
2239 SetMouseCapture(true);
2240 SetEmptySelection(newPos
);
2241 bool doubleClick
= false;
2242 // Stop mouse button bounce changing selection type
2243 if (curTime
!= lastClickTime
) {
2244 if (selectionType
== selChar
) {
2245 selectionType
= selWord
;
2247 } else if (selectionType
== selWord
) {
2248 selectionType
= selLine
;
2250 selectionType
= selChar
;
2251 originalAnchorPos
= currentPos
;
2255 if (selectionType
== selWord
) {
2256 if (currentPos
>= originalAnchorPos
) { // Moved forward
2257 SetSelection(pdoc
->ExtendWordSelect(currentPos
, 1),
2258 pdoc
->ExtendWordSelect(originalAnchorPos
, -1));
2259 } else { // Moved backward
2260 SetSelection(pdoc
->ExtendWordSelect(currentPos
, -1),
2261 pdoc
->ExtendWordSelect(originalAnchorPos
, 1));
2263 } else if (selectionType
== selLine
) {
2264 lineAnchor
= LineFromLocation(pt
);
2265 SetSelection(pdoc
->LineStart(lineAnchor
+ 1), pdoc
->LineStart(lineAnchor
));
2266 //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
2269 SetEmptySelection(currentPos
);
2271 //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
2273 NotifyDoubleClick(pt
, shift
);
2274 } else { // Single click
2275 if (PointInSelMargin(pt
)) {
2278 lastClickTime
= curTime
;
2281 lineAnchor
= LineFromLocation(pt
);
2282 // While experimenting with folding turn off line selection
2284 // Single click in margin: select whole line
2285 SetSelection(pdoc
->LineStart(lineAnchor
+ 1), pdoc
->LineStart(lineAnchor
));
2287 // Single shift+click in margin: select from anchor to beginning of clicked line
2288 SetSelection(pdoc
->LineStart(lineAnchor
), anchor
);
2290 SetDragPosition(invalidPosition
);
2291 SetMouseCapture(true);
2292 selectionType
= selLine
;
2295 inDragDrop
= PointInSelection(pt
);
2298 SetMouseCapture(false);
2299 SetDragPosition(newPos
);
2300 CopySelectionIntoDrag();
2303 selType
= alt
? selRectangle
: selStream
;
2304 xStartSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2305 xEndSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2306 SetDragPosition(invalidPosition
);
2307 SetMouseCapture(true);
2309 SetEmptySelection(newPos
);
2310 selectionType
= selChar
;
2311 originalAnchorPos
= currentPos
;
2315 lastClickTime
= curTime
;
2317 ShowCaretAtCurrentPosition();
2320 void Editor::ButtonMove(Point pt
) {
2321 //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
2322 if (HaveMouseCapture()) {
2323 xEndSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2325 int movePos
= PositionFromLocation(pt
);
2326 movePos
= pdoc
->MovePositionOutsideChar(movePos
, currentPos
- movePos
);
2328 SetDragPosition(movePos
);
2330 if (selectionType
== selChar
) {
2331 SetSelection(movePos
);
2332 } else if (selectionType
== selWord
) {
2333 // Continue selecting by word
2334 if (currentPos
> originalAnchorPos
) { // Moved forward
2335 SetSelection(pdoc
->ExtendWordSelect(movePos
, 1),
2336 pdoc
->ExtendWordSelect(originalAnchorPos
, -1));
2337 } else { // Moved backward
2338 SetSelection(pdoc
->ExtendWordSelect(movePos
, -1),
2339 pdoc
->ExtendWordSelect(originalAnchorPos
, 1));
2342 // Continue selecting by line
2343 int lineMove
= LineFromLocation(pt
);
2344 if (lineAnchor
< lineMove
) {
2345 SetSelection(pdoc
->LineStart(lineMove
+ 1),
2346 pdoc
->LineStart(lineAnchor
));
2348 SetSelection(pdoc
->LineStart(lineMove
),
2349 pdoc
->LineStart(lineAnchor
+ 1));
2353 EnsureCaretVisible(false);
2355 if (vs
.fixedColumnWidth
> 0) { // There is a margin
2356 if (PointInSelMargin(pt
)) {
2357 wDraw
.SetCursor(Window::cursorReverseArrow
);
2358 return; // No need to test for selection
2361 // Display regular (drag) cursor over selection
2362 if (PointInSelection(pt
))
2363 wDraw
.SetCursor(Window::cursorArrow
);
2365 wDraw
.SetCursor(Window::cursorText
);
2370 void Editor::ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
) {
2371 //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
2372 if (HaveMouseCapture()) {
2373 if (PointInSelMargin(pt
)) {
2374 wDraw
.SetCursor(Window::cursorReverseArrow
);
2376 wDraw
.SetCursor(Window::cursorText
);
2378 xEndSelect
= pt
.x
- vs
.fixedColumnWidth
+ xOffset
;
2380 SetMouseCapture(false);
2381 int newPos
= PositionFromLocation(pt
);
2382 newPos
= pdoc
->MovePositionOutsideChar(newPos
, currentPos
- newPos
);
2384 int selStart
= SelectionStart();
2385 int selEnd
= SelectionEnd();
2386 if (selStart
< selEnd
) {
2387 if (dragChars
&& lenDrag
) {
2389 pdoc
->InsertString(newPos
, dragChars
, lenDrag
);
2390 SetSelection(newPos
, newPos
+ lenDrag
);
2391 } else if (newPos
< selStart
) {
2392 pdoc
->DeleteChars(selStart
, lenDrag
);
2393 pdoc
->InsertString(newPos
, dragChars
, lenDrag
);
2394 SetSelection(newPos
, newPos
+ lenDrag
);
2395 } else if (newPos
> selEnd
) {
2396 pdoc
->DeleteChars(selStart
, lenDrag
);
2398 pdoc
->InsertString(newPos
, dragChars
, lenDrag
);
2399 SetSelection(newPos
, newPos
+ lenDrag
);
2401 SetEmptySelection(newPos
);
2407 selectionType
= selChar
;
2410 if (selectionType
== selChar
) {
2411 SetSelection(newPos
);
2414 lastClickTime
= curTime
;
2418 EnsureCaretVisible(false);
2422 // Called frequently to perform background UI including
2423 // caret blinking and automatic scrolling.
2424 void Editor::Tick() {
2425 if (HaveMouseCapture()) {
2427 ButtonMove(ptMouseLast
);
2429 if (caret
.period
> 0) {
2430 timer
.ticksToWait
-= timer
.tickSize
;
2431 if (timer
.ticksToWait
<= 0) {
2432 caret
.on
= !caret
.on
;
2433 timer
.ticksToWait
= caret
.period
;
2439 static bool IsIn(int a
, int minimum
, int maximum
) {
2440 return (a
>= minimum
) && (a
<= maximum
);
2443 static bool IsOverlap(int mina
, int maxa
, int minb
, int maxb
) {
2445 IsIn(mina
, minb
, maxb
) ||
2446 IsIn(maxa
, minb
, maxb
) ||
2447 IsIn(minb
, mina
, maxa
) ||
2448 IsIn(maxb
, mina
, maxa
);
2451 void Editor::CheckForChangeOutsidePaint(Range r
) {
2452 if (paintState
== painting
&& !paintingAllText
) {
2453 //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
2457 PRectangle rcText
= GetTextRectangle();
2458 // Determine number of lines displayed including a possible partially displayed last line
2459 int linesDisplayed
= (rcText
.bottom
- rcText
.top
- 1) / vs
.lineHeight
+ 1;
2460 int bottomLine
= topLine
+ linesDisplayed
- 1;
2462 int lineRangeStart
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.start
));
2463 int lineRangeEnd
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.end
));
2464 if (!IsOverlap(topLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) {
2465 //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
2466 // lineRangeStart, lineRangeEnd, topLine, bottomLine);
2470 // Assert rcPaint contained within or equal to rcText
2471 if (rcPaint
.top
> rcText
.top
) {
2472 // does range intersect rcText.top .. rcPaint.top
2473 int paintTopLine
= ((rcPaint
.top
- rcText
.top
-1) / vs
.lineHeight
) + topLine
;
2474 // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
2475 if (IsOverlap(topLine
, paintTopLine
, lineRangeStart
, lineRangeEnd
)) {
2476 //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n",
2477 // lineRangeStart, lineRangeEnd, topLine, paintTopLine);
2478 paintState
= paintAbandoned
;
2482 if (rcPaint
.bottom
< rcText
.bottom
) {
2483 // does range intersect rcPaint.bottom .. rcText.bottom
2484 int paintBottomLine
= ((rcPaint
.bottom
- rcText
.top
-1) / vs
.lineHeight
+ 1) + topLine
;
2485 // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
2486 if (IsOverlap(paintBottomLine
, bottomLine
, lineRangeStart
, lineRangeEnd
)) {
2487 //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n",
2488 // lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
2489 paintState
= paintAbandoned
;
2496 char BraceOpposite(char ch
) {
2498 case '(': return ')';
2499 case ')': return '(';
2500 case '[': return ']';
2501 case ']': return '[';
2502 case '{': return '}';
2503 case '}': return '{';
2504 case '<': return '>';
2505 case '>': return '<';
2506 default: return '\0';
2510 // TODO: should be able to extend styled region to find matching brace
2511 // TODO: may need to make DBCS safe
2512 // so should be moved into Document
2513 int Editor::BraceMatch(int position
, int maxReStyle
) {
2514 char chBrace
= pdoc
->CharAt(position
);
2515 char chSeek
= BraceOpposite(chBrace
);
2518 char styBrace
= pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
;
2520 if (chBrace
== '(' || chBrace
== '[' || chBrace
== '{' || chBrace
== '<')
2523 position
= position
+ direction
;
2524 while ((position
>= 0) && (position
< pdoc
->Length())) {
2525 char chAtPos
= pdoc
->CharAt(position
);
2526 char styAtPos
= pdoc
->StyleAt(position
) & pdoc
->stylingBitsMask
;
2527 if ((position
> pdoc
->GetEndStyled()) || (styAtPos
== styBrace
)) {
2528 if (chAtPos
== chBrace
)
2530 if (chAtPos
== chSeek
)
2535 position
= position
+ direction
;
2540 void Editor::SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
) {
2541 if ((pos0
!= braces
[0]) || (pos1
!= braces
[1]) || (matchStyle
!= bracesMatchStyle
)) {
2542 if ((braces
[0] != pos0
) || (matchStyle
!= bracesMatchStyle
)) {
2543 CheckForChangeOutsidePaint(Range(braces
[0]));
2544 CheckForChangeOutsidePaint(Range(pos0
));
2547 if ((braces
[1] != pos1
) || (matchStyle
!= bracesMatchStyle
)) {
2548 CheckForChangeOutsidePaint(Range(braces
[1]));
2549 CheckForChangeOutsidePaint(Range(pos1
));
2552 bracesMatchStyle
= matchStyle
;
2553 if (paintState
== notPainting
) {
2559 void Editor::SetDocPointer(Document
*document
) {
2560 //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
2561 pdoc
->RemoveWatcher(this, 0);
2563 if (document
== NULL
) {
2564 pdoc
= new Document();
2569 pdoc
->AddWatcher(this, 0);
2574 // Recursively expand a fold, making lines visible except where they have an unexpanded parent
2575 void Editor::Expand(int &line
, bool doExpand
) {
2576 int lineMaxSubord
= pdoc
->GetLastChild(line
);
2578 while (line
<= lineMaxSubord
) {
2580 cs
.SetVisible(line
, line
, true);
2581 int level
= pdoc
->GetLevel(line
);
2582 if (level
& SC_FOLDLEVELHEADERFLAG
) {
2583 if (doExpand
&& cs
.GetExpanded(line
)) {
2586 Expand(line
, false);
2594 void Editor::ToggleContraction(int line
) {
2595 if (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) {
2596 if (cs
.GetExpanded(line
)) {
2597 int lineMaxSubord
= pdoc
->GetLastChild(line
);
2598 cs
.SetExpanded(line
, 0);
2599 if (lineMaxSubord
> line
) {
2600 cs
.SetVisible(line
+1, lineMaxSubord
, false);
2605 cs
.SetExpanded(line
, 1);
2613 // Recurse up from this line to find any folds that prevent this line from being visible
2614 // and unfold them all.
2615 void Editor::EnsureLineVisible(int line
) {
2616 if (!cs
.GetVisible(line
)) {
2617 int lineParent
= pdoc
->GetFoldParent(line
);
2618 if (lineParent
>= 0) {
2619 if (line
!= lineParent
)
2620 EnsureLineVisible(lineParent
);
2621 if (!cs
.GetExpanded(lineParent
)) {
2622 cs
.SetExpanded(lineParent
, 1);
2623 Expand(lineParent
, true);
2631 LRESULT
Editor::WndProc(UINT iMessage
, WPARAM wParam
, LPARAM lParam
) {
2632 //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
2634 // Optional macro recording hook
2635 #ifdef MACRO_SUPPORT
2637 NotifyMacroRecord(iMessage
, wParam
, lParam
);
2646 char *ptr
= reinterpret_cast<char *>(lParam
);
2647 unsigned int iChar
= 0;
2648 for (; iChar
< wParam
-1; iChar
++)
2649 ptr
[iChar
] = pdoc
->CharAt(iChar
);
2658 pdoc
->DeleteChars(0, pdoc
->Length());
2659 SetEmptySelection(0);
2660 pdoc
->InsertString(0, reinterpret_cast<char *>(lParam
));
2664 case WM_GETTEXTLENGTH
:
2665 return pdoc
->Length();
2668 //Platform::DebugPrintf("S notify %d %d\n", wParam, lParam);
2695 // Edit control mesages
2697 // Not supported (no-ops):
2698 // EM_GETWORDBREAKPROC
2699 // EM_GETWORDBREAKPROCEX
2700 // EM_SETWORDBREAKPROC
2701 // EM_SETWORDBREAKPROCEX
2702 // EM_GETWORDWRAPMODE
2703 // EM_SETWORDWRAPMODE
2711 // EM_GETPASSWORDCHAR
2712 // EM_SETPASSWORDCHAR
2717 // EM_GETOLEINTERFACE
2718 // EM_SETOLEINTERFACE
2719 // EM_SETOLECALLBACK
2734 // EM_GETPUNCTUATION
2735 // EM_SETPUNCTUATION
2738 // Not supported but should be:
2743 // EM_SETTARGETDEVICE
2746 return pdoc
->CanUndo() ? TRUE
: FALSE
;
2752 case EM_EMPTYUNDOBUFFER
:
2753 pdoc
->DeleteUndoHistory();
2756 case EM_GETFIRSTVISIBLELINE
:
2762 int lineStart
= pdoc
->LineStart(wParam
);
2763 int lineEnd
= pdoc
->LineStart(wParam
+ 1);
2764 char *ptr
= reinterpret_cast<char *>(lParam
);
2765 WORD
*pBufSize
= reinterpret_cast<WORD
*>(lParam
);
2766 if (*pBufSize
< lineEnd
- lineStart
) {
2767 ptr
[0] = '\0'; // If no characters copied have to put a NUL into buffer
2771 for (int iChar
= lineStart
; iChar
< lineEnd
; iChar
++)
2772 ptr
[iPlace
++] = pdoc
->CharAt(iChar
);
2776 case EM_GETLINECOUNT
:
2777 if (pdoc
->LinesTotal() == 0)
2780 return pdoc
->LinesTotal();
2783 return !pdoc
->IsSavePoint();
2786 // Not really supported now that there is the save point stuff
2787 //pdoc->isModified = wParam;
2788 //return pdoc->isModified;
2794 *(reinterpret_cast<PRectangle
*>(lParam
)) = GetClientRectangle();
2799 *reinterpret_cast<int *>(wParam
) = SelectionStart();
2801 *reinterpret_cast<int *>(lParam
) = SelectionEnd();
2802 return MAKELONG(SelectionStart(), SelectionEnd());
2807 CHARRANGE
*pCR
= reinterpret_cast<CHARRANGE
*>(lParam
);
2808 pCR
->cpMin
= SelectionStart();
2809 pCR
->cpMax
= SelectionEnd();
2814 int nStart
= static_cast<int>(wParam
);
2815 int nEnd
= static_cast<int>(lParam
);
2817 nEnd
= pdoc
->Length();
2819 nStart
= nEnd
; // Remove selection
2820 SetSelection(nEnd
, nStart
);
2821 EnsureCaretVisible();
2828 CHARRANGE
*pCR
= reinterpret_cast<CHARRANGE
*>(lParam
);
2829 if (pCR
->cpMax
== -1) {
2830 SetSelection(pCR
->cpMin
, pdoc
->Length());
2832 SetSelection(pCR
->cpMin
, pCR
->cpMax
);
2834 EnsureCaretVisible();
2835 return pdoc
->LineFromPosition(SelectionStart());
2838 case EM_GETSELTEXT
: {
2841 char *ptr
= reinterpret_cast<char *>(lParam
);
2842 int selSize
= SelectionRangeLength();
2843 char *text
= CopySelectionRange();
2846 for (; iChar
< selSize
; iChar
++)
2847 ptr
[iChar
] = text
[iChar
];
2854 case EM_GETWORDBREAKPROC
:
2857 case EM_SETWORDBREAKPROC
:
2861 // wParam holds the number of characters control should be limited to
2864 case EM_GETLIMITTEXT
:
2867 case EM_GETOLEINTERFACE
:
2870 case EM_LINEFROMCHAR
:
2871 if (static_cast<int>(wParam
) < 0)
2872 wParam
= SelectionStart();
2873 return pdoc
->LineFromPosition(wParam
);
2875 case EM_EXLINEFROMCHAR
:
2876 if (static_cast<int>(lParam
) < 0)
2877 lParam
= SelectionStart(); // Not specified, but probably OK
2878 return pdoc
->LineFromPosition(lParam
);
2881 if (static_cast<int>(wParam
) < 0)
2882 wParam
= pdoc
->LineFromPosition(SelectionStart());
2884 return 0; // Even if there is no text, there is a first line that starts at 0
2885 if (static_cast<int>(wParam
) > pdoc
->LinesTotal())
2887 //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
2889 return pdoc
->LineStart(wParam
);
2893 if (static_cast<int>(wParam
) < 0) // Who use this anyway?
2894 return 0; // Should be... Too complex to describe here, see MS specs!
2895 if (static_cast<int>(wParam
) > pdoc
->Length()) // Useful test, anyway...
2897 int line
= pdoc
->LineFromPosition(wParam
);
2898 int charsOnLine
= 0;
2899 for (int pos
= pdoc
->LineStart(line
); pos
< pdoc
->LineStart(line
+ 1); pos
++) {
2900 if ((pdoc
->CharAt(pos
) != '\r') && (pdoc
->CharAt(pos
) != '\n'))
2906 // Replacement of the old Scintilla interpretation of EM_LINELENGTH
2907 case SCI_LINELENGTH
:
2908 if ((static_cast<int>(wParam
) < 0) ||
2909 (static_cast<int>(wParam
) > pdoc
->LineFromPosition(pdoc
->Length())))
2911 return pdoc
->LineStart(wParam
+ 1) - pdoc
->LineStart(wParam
);
2913 case EM_REPLACESEL
: {
2916 pdoc
->BeginUndoAction();
2918 char *replacement
= reinterpret_cast<char *>(lParam
);
2919 pdoc
->InsertString(currentPos
, replacement
);
2920 pdoc
->EndUndoAction();
2921 SetEmptySelection(currentPos
+ strlen(replacement
));
2922 EnsureCaretVisible();
2927 ScrollTo(topLine
+ lParam
);
2928 HorizontalScrollTo(xOffset
+ wParam
* vs
.spaceWidth
);
2931 case EM_SCROLLCARET
:
2932 EnsureCaretVisible();
2935 case EM_SETREADONLY
:
2936 pdoc
->SetReadOnly(wParam
);
2945 case EM_CHARFROMPOS
: {
2948 Point
*ppt
= reinterpret_cast<Point
*>(lParam
);
2949 int pos
= PositionFromLocation(*ppt
);
2950 int line
= pdoc
->LineFromPosition(pos
);
2951 return MAKELONG(pos
, line
);
2954 case EM_POSFROMCHAR
: {
2955 // The MS specs for this have changed 3 times: using the RichEdit 3 version
2958 Point
*ppt
= reinterpret_cast<Point
*>(wParam
);
2962 *ppt
= LocationFromPosition(lParam
);
2968 return FindText(iMessage
, wParam
, lParam
);
2971 return FindText(iMessage
, wParam
, lParam
);
2973 case EM_GETTEXTRANGE
: {
2976 TEXTRANGE
*tr
= reinterpret_cast<TEXTRANGE
*>(lParam
);
2977 int cpMax
= tr
->chrg
.cpMax
;
2979 cpMax
= pdoc
->Length();
2980 int len
= cpMax
- tr
->chrg
.cpMin
; // No -1 as cpMin and cpMax are referring to inter character positions
2981 pdoc
->GetCharRange(tr
->lpstrText
, tr
->chrg
.cpMin
, len
);
2982 // Spec says copied text is terminated with a NUL
2983 tr
->lpstrText
[len
] = '\0';
2984 return len
; // Not including NUL
2987 case EM_SELECTIONTYPE
:
2988 if (currentPos
== anchor
)
2993 case EM_HIDESELECTION
:
2994 hideSelection
= wParam
;
2998 case EM_FORMATRANGE
:
2999 return FormatRange(wParam
, reinterpret_cast<FORMATRANGE
*>(lParam
));
3002 return MAKELONG(vs
.leftMarginWidth
, vs
.rightMarginWidth
);
3005 if (wParam
& EC_LEFTMARGIN
) {
3006 vs
.leftMarginWidth
= LOWORD(lParam
);
3008 if (wParam
& EC_RIGHTMARGIN
) {
3009 vs
.rightMarginWidth
= HIWORD(lParam
);
3011 if (wParam
== EC_USEFONTINFO
) {
3012 vs
.leftMarginWidth
= vs
.aveCharWidth
/ 2;
3013 vs
.rightMarginWidth
= vs
.aveCharWidth
/ 2;
3015 InvalidateStyleRedraw();
3018 // Control specific mesages
3023 pdoc
->InsertString(CurrentPosition(), reinterpret_cast<char *>(lParam
), wParam
);
3024 SetEmptySelection(currentPos
+ wParam
);
3028 case SCI_ADDSTYLEDTEXT
: {
3031 pdoc
->InsertStyledString(CurrentPosition() * 2, reinterpret_cast<char *>(lParam
), wParam
);
3032 SetEmptySelection(currentPos
+ wParam
/ 2);
3036 case SCI_INSERTTEXT
: {
3039 int insertPos
= wParam
;
3040 if (static_cast<short>(wParam
) == -1)
3041 insertPos
= CurrentPosition();
3042 int newCurrent
= CurrentPosition();
3043 int newAnchor
= anchor
;
3044 char *sz
= reinterpret_cast<char *>(lParam
);
3045 pdoc
->InsertString(insertPos
, sz
);
3046 if (newCurrent
> insertPos
)
3047 newCurrent
+= strlen(sz
);
3048 if (newAnchor
> insertPos
)
3049 newAnchor
+= strlen(sz
);
3050 SetEmptySelection(newCurrent
);
3058 case SCI_SETUNDOCOLLECTION
:
3059 pdoc
->SetUndoCollection(static_cast<enum undoCollectionType
>(wParam
));
3062 #ifdef INCLUDE_DEPRECATED_FEATURES
3063 case SCI_APPENDUNDOSTARTACTION
:
3064 pdoc
->AppendUndoStartAction();
3068 case SCI_BEGINUNDOACTION
:
3069 pdoc
->BeginUndoAction();
3072 case SCI_ENDUNDOACTION
:
3073 pdoc
->EndUndoAction();
3076 case SCI_GETCARETPERIOD
:
3077 return caret
.period
;
3079 case SCI_SETCARETPERIOD
:
3080 caret
.period
= wParam
;
3083 case SCI_SETWORDCHARS
: {
3086 pdoc
->SetWordChars(reinterpret_cast<unsigned char *>(lParam
));
3091 return pdoc
->Length();
3094 return pdoc
->CharAt(wParam
);
3096 case SCI_GETCURRENTPOS
:
3102 case SCI_GETSTYLEAT
:
3103 if (static_cast<short>(wParam
) >= pdoc
->Length())
3106 return pdoc
->StyleAt(wParam
);
3116 case SCI_SETSAVEPOINT
:
3117 pdoc
->SetSavePoint();
3118 NotifySavePoint(true);
3121 case SCI_GETSTYLEDTEXT
: {
3124 TEXTRANGE
*tr
= reinterpret_cast<TEXTRANGE
*>(lParam
);
3126 for (int iChar
= tr
->chrg
.cpMin
; iChar
< tr
->chrg
.cpMax
; iChar
++) {
3127 tr
->lpstrText
[iPlace
++] = pdoc
->CharAt(iChar
);
3128 tr
->lpstrText
[iPlace
++] = pdoc
->StyleAt(iChar
);
3130 tr
->lpstrText
[iPlace
] = '\0';
3131 tr
->lpstrText
[iPlace
+ 1] = '\0';
3136 return pdoc
->CanRedo() ? TRUE
: FALSE
;
3138 case SCI_MARKERLINEFROMHANDLE
:
3139 return pdoc
->LineFromHandle(wParam
);
3141 case SCI_MARKERDELETEHANDLE
:
3142 pdoc
->DeleteMarkFromHandle(wParam
);
3146 return vs
.viewWhitespace
;
3149 vs
.viewWhitespace
= wParam
;
3158 SetEmptySelection(wParam
);
3159 EnsureCaretVisible();
3164 SetSelection(currentPos
, wParam
);
3167 case SCI_GETCURLINE
: {
3170 int lineCurrentPos
= pdoc
->LineFromPosition(currentPos
);
3171 int lineStart
= pdoc
->LineStart(lineCurrentPos
);
3172 unsigned int lineEnd
= pdoc
->LineStart(lineCurrentPos
+ 1);
3173 char *ptr
= reinterpret_cast<char *>(lParam
);
3174 unsigned int iPlace
= 0;
3175 for (unsigned int iChar
= lineStart
; iChar
< lineEnd
&& iPlace
< wParam
; iChar
++)
3176 ptr
[iPlace
++] = pdoc
->CharAt(iChar
);
3178 return currentPos
- lineStart
;
3181 case SCI_GETENDSTYLED
:
3182 return pdoc
->GetEndStyled();
3184 case SCI_GETEOLMODE
:
3185 return pdoc
->eolMode
;
3187 case SCI_SETEOLMODE
:
3188 pdoc
->eolMode
= wParam
;
3191 case SCI_STARTSTYLING
:
3192 pdoc
->StartStyling(wParam
, lParam
);
3195 case SCI_SETSTYLING
:
3196 pdoc
->SetStyleFor(wParam
, lParam
);
3199 case SCI_SETSTYLINGEX
: // Specify a complete styling buffer
3202 pdoc
->SetStyles(wParam
, reinterpret_cast<char *>(lParam
));
3205 #ifdef INCLUDE_DEPRECATED_FEATURES
3206 case SCI_SETMARGINWIDTH
:
3208 vs
.ms
[1].width
= wParam
;
3210 InvalidateStyleRedraw();
3214 case SCI_SETBUFFEREDDRAW
:
3215 bufferedDraw
= wParam
;
3218 case SCI_SETTABWIDTH
:
3220 pdoc
->tabInChars
= wParam
;
3221 InvalidateStyleRedraw();
3224 case SCI_SETCODEPAGE
:
3225 pdoc
->dbcsCodePage
= wParam
;
3228 #ifdef INCLUDE_DEPRECATED_FEATURES
3229 case SCI_SETLINENUMBERWIDTH
:
3231 vs
.ms
[0].width
= wParam
;
3233 InvalidateStyleRedraw();
3237 case SCI_SETUSEPALETTE
:
3238 palette
.allowRealization
= wParam
;
3239 InvalidateStyleRedraw();
3242 // Marker definition and setting
3243 case SCI_MARKERDEFINE
:
3244 if (wParam
<= MARKER_MAX
)
3245 vs
.markers
[wParam
].markType
= lParam
;
3246 InvalidateStyleData();
3249 case SCI_MARKERSETFORE
:
3250 if (wParam
<= MARKER_MAX
)
3251 vs
.markers
[wParam
].fore
.desired
= Colour(lParam
);
3252 InvalidateStyleData();
3255 case SCI_MARKERSETBACK
:
3256 if (wParam
<= MARKER_MAX
)
3257 vs
.markers
[wParam
].back
.desired
= Colour(lParam
);
3258 InvalidateStyleData();
3261 case SCI_MARKERADD
: {
3262 int markerID
= pdoc
->AddMark(wParam
, lParam
);
3267 case SCI_MARKERDELETE
:
3268 pdoc
->DeleteMark(wParam
, lParam
);
3272 case SCI_MARKERDELETEALL
:
3273 pdoc
->DeleteAllMarks(static_cast<int>(wParam
));
3278 return pdoc
->GetMark(wParam
);
3280 case SCI_MARKERNEXT
: {
3281 int lt
= pdoc
->LinesTotal();
3282 for (int iLine
= wParam
; iLine
< lt
; iLine
++) {
3283 if ((pdoc
->GetMark(iLine
) & lParam
) != 0)
3289 case SCI_MARKERPREVIOUS
: {
3290 for (int iLine
= wParam
; iLine
>= 0; iLine
--) {
3291 if ((pdoc
->GetMark(iLine
) & lParam
) != 0)
3297 case SCI_SETMARGINTYPEN
:
3298 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3299 vs
.ms
[wParam
].symbol
= (lParam
== SC_MARGIN_SYMBOL
);
3300 InvalidateStyleRedraw();
3304 case SCI_GETMARGINTYPEN
:
3305 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3306 return vs
.ms
[wParam
].symbol
? SC_MARGIN_SYMBOL
: SC_MARGIN_NUMBER
;
3310 case SCI_SETMARGINWIDTHN
:
3311 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3312 vs
.ms
[wParam
].width
= lParam
;
3313 InvalidateStyleRedraw();
3317 case SCI_GETMARGINWIDTHN
:
3318 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3319 return vs
.ms
[wParam
].width
;
3323 case SCI_SETMARGINMASKN
:
3324 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3325 vs
.ms
[wParam
].mask
= lParam
;
3326 InvalidateStyleRedraw();
3330 case SCI_GETMARGINMASKN
:
3331 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3332 return vs
.ms
[wParam
].mask
;
3336 case SCI_SETMARGINSENSITIVEN
:
3337 if (wParam
>= 0 && wParam
< ViewStyle::margins
) {
3338 vs
.ms
[wParam
].sensitive
= lParam
;
3339 InvalidateStyleRedraw();
3343 case SCI_GETMARGINSENSITIVEN
:
3344 if (wParam
>= 0 && wParam
< ViewStyle::margins
)
3345 return vs
.ms
[wParam
].sensitive
? 1 : 0;
3349 case SCI_STYLECLEARALL
:
3351 InvalidateStyleRedraw();
3354 case SCI_STYLESETFORE
:
3355 if (wParam
<= STYLE_MAX
) {
3356 vs
.styles
[wParam
].fore
.desired
= Colour(lParam
);
3357 InvalidateStyleRedraw();
3360 case SCI_STYLESETBACK
:
3361 if (wParam
<= STYLE_MAX
) {
3362 vs
.styles
[wParam
].back
.desired
= Colour(lParam
);
3363 InvalidateStyleRedraw();
3366 case SCI_STYLESETBOLD
:
3367 if (wParam
<= STYLE_MAX
) {
3368 vs
.styles
[wParam
].bold
= lParam
;
3369 InvalidateStyleRedraw();
3372 case SCI_STYLESETITALIC
:
3373 if (wParam
<= STYLE_MAX
) {
3374 vs
.styles
[wParam
].italic
= lParam
;
3375 InvalidateStyleRedraw();
3378 case SCI_STYLESETEOLFILLED
:
3379 if (wParam
<= STYLE_MAX
) {
3380 vs
.styles
[wParam
].eolFilled
= lParam
;
3381 InvalidateStyleRedraw();
3384 case SCI_STYLESETSIZE
:
3385 if (wParam
<= STYLE_MAX
) {
3386 vs
.styles
[wParam
].size
= lParam
;
3387 InvalidateStyleRedraw();
3390 case SCI_STYLESETFONT
:
3393 if (wParam
<= STYLE_MAX
) {
3394 strcpy(vs
.styles
[wParam
].fontName
, reinterpret_cast<char *>(lParam
));
3395 InvalidateStyleRedraw();
3399 case SCI_STYLERESETDEFAULT
:
3400 vs
.ResetDefaultStyle();
3401 InvalidateStyleRedraw();
3404 case SCI_SETSTYLEBITS
:
3405 pdoc
->SetStylingBits(wParam
);
3408 case SCI_GETSTYLEBITS
:
3409 return pdoc
->stylingBits
;
3411 case SCI_SETLINESTATE
:
3412 return pdoc
->SetLineState(wParam
, lParam
);
3414 case SCI_GETLINESTATE
:
3415 return pdoc
->GetLineState(wParam
);
3417 case SCI_GETMAXLINESTATE
:
3418 return pdoc
->GetMaxLineState();
3422 case SCI_VISIBLEFROMDOCLINE
:
3423 return cs
.DisplayFromDoc(wParam
);
3425 case SCI_DOCLINEFROMVISIBLE
:
3426 return cs
.DocFromDisplay(wParam
);
3428 case SCI_SETFOLDLEVEL
: {
3429 int prev
= pdoc
->SetLevel(wParam
, lParam
);
3435 case SCI_GETFOLDLEVEL
:
3436 return pdoc
->GetLevel(wParam
);
3438 case SCI_GETLASTCHILD
:
3439 return pdoc
->GetLastChild(wParam
, lParam
);
3441 case SCI_GETFOLDPARENT
:
3442 return pdoc
->GetFoldParent(wParam
);
3445 cs
.SetVisible(wParam
, lParam
, true);
3451 cs
.SetVisible(wParam
, lParam
, false);
3456 case SCI_GETLINEVISIBLE
:
3457 return cs
.GetVisible(wParam
);
3459 case SCI_SETFOLDEXPANDED
:
3460 if (cs
.SetExpanded(wParam
, lParam
)) {
3465 case SCI_GETFOLDEXPANDED
:
3466 return cs
.GetExpanded(wParam
);
3468 case SCI_SETFOLDFLAGS
:
3473 case SCI_TOGGLEFOLD
:
3474 ToggleContraction(wParam
);
3477 case SCI_ENSUREVISIBLE
:
3478 EnsureLineVisible(wParam
);
3481 case SCI_SEARCHANCHOR
:
3485 case SCI_SEARCHNEXT
:
3486 case SCI_SEARCHPREV
:
3487 return SearchText(iMessage
, wParam
, lParam
);
3490 case SCI_SETCARETPOLICY
:
3491 caretPolicy
= wParam
;
3495 #ifdef INCLUDE_DEPRECATED_FEATURES
3497 vs
.styles
[STYLE_DEFAULT
].fore
.desired
= Colour(wParam
);
3498 InvalidateStyleRedraw();
3502 vs
.styles
[STYLE_DEFAULT
].back
.desired
= Colour(wParam
);
3503 InvalidateStyleRedraw();
3507 vs
.styles
[STYLE_DEFAULT
].bold
= wParam
;
3508 InvalidateStyleRedraw();
3512 vs
.styles
[STYLE_DEFAULT
].italic
= wParam
;
3513 InvalidateStyleRedraw();
3517 vs
.styles
[STYLE_DEFAULT
].size
= wParam
;
3518 InvalidateStyleRedraw();
3524 strcpy(vs
.styles
[STYLE_DEFAULT
].fontName
, reinterpret_cast<char *>(wParam
));
3525 InvalidateStyleRedraw();
3529 case SCI_SETSELFORE
:
3530 vs
.selforeset
= wParam
;
3531 vs
.selforeground
.desired
= Colour(lParam
);
3532 InvalidateStyleRedraw();
3535 case SCI_SETSELBACK
:
3536 vs
.selbackset
= wParam
;
3537 vs
.selbackground
.desired
= Colour(lParam
);
3538 InvalidateStyleRedraw();
3541 case SCI_SETCARETFORE
:
3542 vs
.caretcolour
.desired
= Colour(wParam
);
3543 InvalidateStyleRedraw();
3546 case SCI_ASSIGNCMDKEY
:
3547 kmap
.AssignCmdKey(LOWORD(wParam
), HIWORD(wParam
), lParam
);
3550 case SCI_CLEARCMDKEY
:
3551 kmap
.AssignCmdKey(LOWORD(wParam
), HIWORD(wParam
), WM_NULL
);
3554 case SCI_CLEARALLCMDKEYS
:
3558 case SCI_INDICSETSTYLE
:
3559 if (wParam
<= INDIC_MAX
) {
3560 vs
.indicators
[wParam
].style
= lParam
;
3561 InvalidateStyleRedraw();
3565 case SCI_INDICGETSTYLE
:
3566 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].style
: 0;
3568 case SCI_INDICSETFORE
:
3569 if (wParam
<= INDIC_MAX
) {
3570 vs
.indicators
[wParam
].fore
.desired
= Colour(lParam
);
3571 InvalidateStyleRedraw();
3575 case SCI_INDICGETFORE
:
3576 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].fore
.desired
.AsLong() : 0;
3579 case SCI_LINEDOWNEXTEND
:
3581 case SCI_LINEUPEXTEND
:
3583 case SCI_CHARLEFTEXTEND
:
3585 case SCI_CHARRIGHTEXTEND
:
3587 case SCI_WORDLEFTEXTEND
:
3589 case SCI_WORDRIGHTEXTEND
:
3591 case SCI_HOMEEXTEND
:
3593 case SCI_LINEENDEXTEND
:
3594 case SCI_DOCUMENTSTART
:
3595 case SCI_DOCUMENTSTARTEXTEND
:
3596 case SCI_DOCUMENTEND
:
3597 case SCI_DOCUMENTENDEXTEND
:
3599 case SCI_PAGEUPEXTEND
:
3601 case SCI_PAGEDOWNEXTEND
:
3602 case SCI_EDITTOGGLEOVERTYPE
:
3604 case SCI_DELETEBACK
:
3610 case SCI_VCHOMEEXTEND
:
3613 case SCI_DELWORDLEFT
:
3614 case SCI_DELWORDRIGHT
:
3615 return KeyCommand(iMessage
);
3617 case SCI_BRACEHIGHLIGHT
:
3618 SetBraceHighlight(static_cast<int>(wParam
), lParam
, STYLE_BRACELIGHT
);
3621 case SCI_BRACEBADLIGHT
:
3622 SetBraceHighlight(static_cast<int>(wParam
), -1, STYLE_BRACEBAD
);
3625 case SCI_BRACEMATCH
:
3626 // wParam is position of char to find brace for,
3627 // lParam is maximum amount of text to restyle to find it
3628 return BraceMatch(wParam
, lParam
);
3630 case SCI_GETVIEWEOL
:
3633 case SCI_SETVIEWEOL
:
3634 vs
.viewEOL
= wParam
;
3638 case SCI_GETEDGECOLUMN
:
3641 case SCI_SETEDGECOLUMN
:
3643 InvalidateStyleRedraw();
3646 case SCI_GETEDGEMODE
:
3649 case SCI_SETEDGEMODE
:
3651 InvalidateStyleRedraw();
3654 case SCI_GETEDGECOLOUR
:
3655 return vs
.edgecolour
.desired
.AsLong();
3657 case SCI_SETEDGECOLOUR
:
3658 vs
.edgecolour
.desired
= Colour(wParam
);
3659 InvalidateStyleRedraw();
3662 case SCI_GETDOCPOINTER
:
3663 return reinterpret_cast<LRESULT
>(pdoc
);
3665 case SCI_SETDOCPOINTER
:
3666 SetDocPointer(reinterpret_cast<Document
*>(lParam
));
3669 case SCI_SETMODEVENTMASK
:
3670 modEventMask
= wParam
;
3673 case SCI_CONVERTEOLS
:
3674 pdoc
->ConvertLineEnds(wParam
);
3675 SetSelection(currentPos
, anchor
); // Ensure selection inside document
3678 #ifdef MACRO_SUPPORT
3679 case SCI_STARTRECORD
:
3683 case SCI_STOPRECORD
:
3689 return DefWndProc(iMessage
, wParam
, lParam
);
3691 //Platform::DebugPrintf("end wnd proc\n");