aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2000-03-08 01:43:56 +0000
committernyamatongwe <unknown>2000-03-08 01:43:56 +0000
commitc196d2fc7c3ece7ccb7d89c425499a75ead7e59b (patch)
tree3ea3c536f04e88499b86ed82e8a9a457f96b4978
parent7fbd8e2a34d2f5084ce26ad95d7c70ae4de6a233 (diff)
downloadscintilla-mirror-c196d2fc7c3ece7ccb7d89c425499a75ead7e59b.tar.gz
Initial revision
-rw-r--r--src/Editor.cxx3705
-rw-r--r--src/Editor.h281
-rw-r--r--src/Indicator.cxx45
-rw-r--r--src/Indicator.h18
-rw-r--r--src/KeyMap.cxx111
-rw-r--r--src/KeyMap.h35
-rw-r--r--src/KeyWords.cxx2648
-rw-r--r--src/LineMarker.cxx125
-rw-r--r--src/LineMarker.h22
-rw-r--r--src/PropSet.cxx399
-rw-r--r--src/SVector.h110
-rw-r--r--src/ScintillaBase.cxx397
-rw-r--r--src/ScintillaBase.h68
-rw-r--r--src/Style.cxx89
-rw-r--r--src/Style.h39
-rw-r--r--src/ViewStyle.cxx226
-rw-r--r--src/ViewStyle.h72
-rw-r--r--win32/Margin.curbin0 -> 326 bytes
-rw-r--r--win32/PlatWin.cxx673
-rw-r--r--win32/PlatformRes.h6
-rw-r--r--win32/ScintRes.rc40
-rw-r--r--win32/ScintillaWin.cxx1349
-rw-r--r--win32/makefile98
-rw-r--r--win32/makefile_bor120
-rw-r--r--win32/makefile_vc125
25 files changed, 10801 insertions, 0 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx
new file mode 100644
index 000000000..1ead18d34
--- /dev/null
+++ b/src/Editor.cxx
@@ -0,0 +1,3705 @@
+// Scintilla source code edit control
+// Editor.cxx - main code for the edit control
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "Document.h"
+#include "Editor.h"
+
+Caret::Caret() :
+active(true), on(true), period(500) {}
+
+Timer::Timer() :
+ticking(false), ticksToWait(0), tickerID(0) {}
+
+Editor::Editor() {
+ ctrlID = 0;
+
+ stylesValid = false;
+
+ hideSelection = false;
+ inOverstrike = false;
+
+ bufferedDraw = true;
+
+ lastClickTime = 0;
+ ptMouseLast.x = 0;
+ ptMouseLast.y = 0;
+ firstExpose = true;
+ inDragDrop = false;
+ dropWentOutside = false;
+ posDrag = invalidPosition;
+ posDrop = invalidPosition;
+ selectionType = selChar;
+
+ lastXChosen = 0;
+ lineAnchor = 0;
+ originalAnchorPos = 0;
+
+ dragChars = 0;
+ lenDrag = 0;
+ dragIsRectangle = false;
+ selType = selStream;
+ xStartSelect = 0;
+ xEndSelect = 0;
+
+ caretPolicy = CARET_SLOP;
+ caretSlop = 0;
+
+ searchAnchor = 0;
+
+ ucWheelScrollLines = 0;
+ cWheelDelta = 0; //wheel delta from roll
+
+ xOffset = 0;
+ xCaretMargin = 50;
+
+ currentPos = 0;
+ anchor = 0;
+
+ topLine = 0;
+ posTopLine = 0;
+
+ needUpdateUI = true;
+ braces[0]=invalidPosition;
+ braces[1]=invalidPosition;
+ bracesMatchStyle = STYLE_BRACEBAD;
+
+ edgeState = EDGE_NONE;
+ theEdge = 0;
+
+ paintState = notPainting;
+
+ modEventMask = SC_MODEVENTMASKALL;
+
+ pdoc = new Document();
+ pdoc ->AddRef();
+ pdoc->AddWatcher(this, 0);
+
+#ifdef MACRO_SUPPORT
+ recordingMacro = 0;
+#endif
+ foldFlags = 0;
+}
+
+Editor::~Editor() {
+ pdoc->RemoveWatcher(this, 0);
+ pdoc->Release();
+ pdoc = 0;
+ DropGraphics();
+
+ delete []dragChars;
+ dragChars = 0;
+ lenDrag = 0;
+}
+
+void Editor::Finalise() {
+}
+
+void Editor::DropGraphics() {
+ pixmapLine.Release();
+ pixmapSelMargin.Release();
+ pixmapSelPattern.Release();
+}
+
+void Editor::InvalidateStyleData() {
+ stylesValid = false;
+ palette.Release();
+ DropGraphics();
+}
+
+void Editor::InvalidateStyleRedraw() {
+ InvalidateStyleData();
+ Redraw();
+}
+
+void Editor::RefreshColourPalette(Palette &pal, bool want) {
+ vs.RefreshColourPalette(pal, want);
+}
+
+void Editor::RefreshStyleData() {
+ if (!stylesValid) {
+ stylesValid = true;
+ Surface surface;
+ surface.Init();
+ vs.Refresh(surface);
+ RefreshColourPalette(palette, true);
+ palette.Allocate(wMain);
+ RefreshColourPalette(palette, false);
+ SetScrollBars();
+ }
+}
+
+PRectangle Editor::GetClientRectangle() {
+ return wDraw.GetClientPosition();
+}
+
+PRectangle Editor::GetTextRectangle() {
+ PRectangle rc = GetClientRectangle();
+ rc.left += vs.fixedColumnWidth;
+ rc.right -= vs.rightMarginWidth;
+ return rc;
+}
+
+int Editor::LinesOnScreen() {
+ PRectangle rcClient = GetClientRectangle();
+ int htClient = rcClient.bottom - rcClient.top;
+ //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
+ return htClient / vs.lineHeight;
+}
+
+int Editor::LinesToScroll() {
+ int retVal = LinesOnScreen() - 1;
+ if (retVal < 1)
+ return 1;
+ else
+ return retVal;
+}
+
+int Editor::MaxScrollPos() {
+ //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
+ //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
+ int retVal = cs.LinesDisplayed() - LinesOnScreen();
+ if (retVal < 0)
+ return 0;
+ else
+ return retVal;
+}
+
+bool IsControlCharacter(char ch) {
+ // iscntrl returns true for lots of chars > 127 which are displayable
+ return ch >= 0 && ch < ' ';
+}
+
+const char *ControlCharacterString(char ch) {
+ const char *reps[] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ if (ch < (sizeof(reps) / sizeof(reps[0]))) {
+ return reps[ch];
+ } else {
+ return "BAD";
+ }
+}
+
+Point Editor::LocationFromPosition(unsigned int pos) {
+ RefreshStyleData();
+ int line = pdoc->LineFromPosition(pos);
+ int lineVisible = cs.DisplayFromDoc(line);
+ //Platform::DebugPrintf("line=%d\n", line);
+ Surface surface;
+ surface.Init();
+ Point pt;
+ pt.y = (lineVisible - topLine) * vs.lineHeight; // + half a lineheight?
+ unsigned int posLineStart = pdoc->LineStart(line);
+ if ((pos - posLineStart) > LineLayout::maxLineLength) {
+ // very long line so put x at arbitrary large position
+ pt.x = 30000 + vs.fixedColumnWidth - xOffset;
+ } else {
+ LineLayout ll;
+ LayoutLine(line, &surface, vs, ll);
+ pt.x = ll.positions[pos - posLineStart] + vs.fixedColumnWidth - xOffset;
+ }
+ return pt;
+}
+
+int Editor::XFromPosition(unsigned int pos) {
+ Point pt = LocationFromPosition(pos);
+ return pt.x - vs.fixedColumnWidth + xOffset;
+}
+
+int Editor::LineFromLocation(Point pt) {
+ return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+}
+
+void Editor::SetTopLine(int topLineNew) {
+ topLine = topLineNew;
+ posTopLine = pdoc->LineStart(topLine);
+}
+
+int Editor::PositionFromLocation(Point pt) {
+ RefreshStyleData();
+ pt.x = pt.x - vs.fixedColumnWidth + xOffset;
+ int line = cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+ if (pt.y < 0) { // Division rounds towards 0
+ line = cs.DocFromDisplay((pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine);
+ }
+ if (line < 0)
+ return 0;
+ if (line >= pdoc->LinesTotal())
+ return pdoc->Length();
+//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+ Surface surface;
+ surface.Init();
+ unsigned int posLineStart = pdoc->LineStart(line);
+
+ LineLayout ll;
+ LayoutLine(line, &surface, vs, ll);
+ for (int i = 0; i < ll.numCharsInLine; i++) {
+ if (pt.x < ((ll.positions[i] + ll.positions[i + 1]) / 2) ||
+ ll.chars[i] == '\r' || ll.chars[i] == '\n') {
+ return i + posLineStart;
+ }
+ }
+
+ return ll.numCharsInLine + posLineStart;
+}
+
+int Editor::PositionFromLineX(int line, int x) {
+ RefreshStyleData();
+ if (line >= pdoc->LinesTotal())
+ return pdoc->Length();
+ //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+ Surface surface;
+ surface.Init();
+ unsigned int posLineStart = pdoc->LineStart(line);
+
+ LineLayout ll;
+ LayoutLine(line, &surface, vs, ll);
+ for (int i = 0; i < ll.numCharsInLine; i++) {
+ if (x < ((ll.positions[i] + ll.positions[i + 1]) / 2) ||
+ ll.chars[i] == '\r' || ll.chars[i] == '\n') {
+ return i + posLineStart;
+ }
+ }
+
+ return ll.numCharsInLine + posLineStart;
+}
+
+void Editor::RedrawRect(PRectangle rc) {
+ //Platform::DebugPrintf("Redraw %d %d - %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
+ wDraw.InvalidateRectangle(rc);
+}
+
+void Editor::Redraw() {
+ //Platform::DebugPrintf("Redraw all\n");
+ wDraw.InvalidateAll();
+}
+
+void Editor::RedrawSelMargin() {
+ if (vs.maskInLine) {
+ Redraw();
+ } else {
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = vs.fixedColumnWidth;
+ wDraw.InvalidateRectangle(rcSelMargin);
+ }
+}
+
+PRectangle Editor::RectangleFromRange(int start, int end) {
+ int minPos = start;
+ if (minPos > end)
+ minPos = end;
+ int maxPos = start;
+ if (maxPos < end)
+ maxPos = end;
+ int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
+ int maxLine = cs.DisplayFromDoc(pdoc->LineFromPosition(maxPos));
+ PRectangle rcClient = GetTextRectangle();
+ PRectangle rc;
+ rc.left = vs.fixedColumnWidth;
+ rc.top = (minLine - topLine) * vs.lineHeight;
+ if (rc.top < 0)
+ rc.top = 0;
+ rc.right = rcClient.right;
+ rc.bottom = (maxLine - topLine + 1) * vs.lineHeight;
+ // Ensure PRectangle is within 16 bit space
+ rc.top = Platform::Clamp(rc.top, -32000, 32000);
+ rc.bottom = Platform::Clamp(rc.bottom, -32000, 32000);
+
+ return rc;
+}
+
+void Editor::InvalidateRange(int start, int end) {
+ RedrawRect(RectangleFromRange(start, end));
+}
+
+int Editor::CurrentPosition() {
+ return currentPos;
+}
+
+bool Editor::SelectionEmpty() {
+ return anchor == currentPos;
+}
+
+int Editor::SelectionStart(int line) {
+ if ((line == -1) || (selType == selStream)) {
+ return Platform::Minimum(currentPos, anchor);
+ } else { // selType == selRectangle
+ int selStart = SelectionStart();
+ int selEnd = SelectionEnd();
+ int lineStart = pdoc->LineFromPosition(selStart);
+ int lineEnd = pdoc->LineFromPosition(selEnd);
+ if (line < lineStart || line > lineEnd) {
+ return -1;
+ } else {
+ int minX = Platform::Minimum(xStartSelect, xEndSelect);
+ //return PositionFromLineX(line, minX + vs.fixedColumnWidth - xOffset);
+ return PositionFromLineX(line, minX);
+ }
+ }
+}
+
+int Editor::SelectionEnd(int line) {
+ if ((line == -1) || (selType == selStream)) {
+ return Platform::Maximum(currentPos, anchor);
+ } else { // selType == selRectangle
+ int selStart = SelectionStart();
+ int selEnd = SelectionEnd();
+ int lineStart = pdoc->LineFromPosition(selStart);
+ int lineEnd = pdoc->LineFromPosition(selEnd);
+ if (line < lineStart || line > lineEnd) {
+ return -1;
+ } else {
+ int maxX = Platform::Maximum(xStartSelect, xEndSelect);
+ // measure line and return character closest to minx
+ return PositionFromLineX(line, maxX);
+ }
+ }
+}
+
+void Editor::SetSelection(int currentPos_, int anchor_) {
+ currentPos_ = pdoc->ClampPositionIntoDocument(currentPos_);
+ anchor_ = pdoc->ClampPositionIntoDocument(anchor_);
+ if ((currentPos != currentPos_) || (anchor != anchor_)) {
+ int firstAffected = anchor;
+ if (firstAffected > currentPos)
+ firstAffected = currentPos;
+ if (firstAffected > anchor_)
+ firstAffected = anchor_;
+ if (firstAffected > currentPos_)
+ firstAffected = currentPos_;
+ int lastAffected = anchor;
+ if (lastAffected < currentPos)
+ lastAffected = currentPos;
+ if (lastAffected < anchor_)
+ lastAffected = anchor_;
+ if (lastAffected < (currentPos_ + 1)) // +1 ensures caret repainted
+ lastAffected = (currentPos_ + 1);
+ currentPos = currentPos_;
+ anchor = anchor_;
+ needUpdateUI = true;
+ InvalidateRange(firstAffected, lastAffected);
+ }
+ ClaimSelection();
+}
+
+void Editor::SetSelection(int currentPos_) {
+ currentPos_ = pdoc->ClampPositionIntoDocument(currentPos_);
+ if (currentPos != currentPos_) {
+ int firstAffected = anchor;
+ if (firstAffected > currentPos)
+ firstAffected = currentPos;
+ if (firstAffected > currentPos_)
+ firstAffected = currentPos_;
+ int lastAffected = anchor;
+ if (lastAffected < currentPos)
+ lastAffected = currentPos;
+ if (lastAffected < (currentPos_ + 1)) // +1 ensures caret repainted
+ lastAffected = (currentPos_ + 1);
+ currentPos = currentPos_;
+ needUpdateUI = true;
+ InvalidateRange(firstAffected, lastAffected);
+ }
+ ClaimSelection();
+}
+
+void Editor::SetEmptySelection(int currentPos_) {
+ SetSelection(currentPos_, currentPos_);
+}
+
+int Editor::MovePositionTo(int newPos, bool extend) {
+ int delta = newPos - currentPos;
+ newPos = pdoc->ClampPositionIntoDocument(newPos);
+ newPos = pdoc->MovePositionOutsideChar(newPos, delta);
+ if (extend) {
+ SetSelection(newPos);
+ } else {
+ SetEmptySelection(newPos);
+ }
+ EnsureCaretVisible();
+ ShowCaretAtCurrentPosition();
+ return 0;
+}
+
+int Editor::MovePositionSoVisible(int pos, int moveDir) {
+ pos = pdoc->ClampPositionIntoDocument(pos);
+ pos = pdoc->MovePositionOutsideChar(pos, moveDir);
+ int lineDoc = pdoc->LineFromPosition(pos);
+ if (cs.GetVisible(lineDoc)) {
+ return pos;
+ } else {
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ if (moveDir > 0) {
+ lineDisplay = Platform::Clamp(lineDisplay + 1, 0, cs.LinesDisplayed());
+ return pdoc->LineStart(cs.DocFromDisplay(lineDisplay));
+ } else {
+ // lineDisplay is already line before fold as lines in fold use display line of line before fold
+ lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
+ return pdoc->LineEndPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
+ }
+ }
+}
+
+// Choose the x position that the caret will try to stick to as it is moves up and down
+void Editor::SetLastXChosen() {
+ Point pt = LocationFromPosition(currentPos);
+ lastXChosen = pt.x;
+}
+
+void Editor::ScrollTo(int line) {
+ int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
+ if (topLineNew != topLine) {
+ // Try to optimise small scrolls
+ int linesToMove = topLine - topLineNew;
+ SetTopLine(topLineNew);
+ ShowCaretAtCurrentPosition();
+ // Perform redraw rather than scroll if many lines would be redrawn anyway.
+ if (abs(linesToMove) <= 10) {
+ ScrollText(linesToMove);
+ } else {
+ Redraw();
+ }
+ SetVerticalScrollPos();
+ }
+}
+
+void Editor::ScrollText(int linesToMove) {
+ //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
+ Redraw();
+}
+
+void Editor::HorizontalScrollTo(int xPos) {
+ //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
+ xOffset = xPos;
+ if (xOffset < 0)
+ xOffset = 0;
+ SetHorizontalScrollPos();
+ Redraw();
+}
+
+void Editor::EnsureCaretVisible(bool useMargin) {
+ //Platform::DebugPrintf("EnsureCaretVisible %d\n", xOffset);
+ PRectangle rcClient = GetTextRectangle();
+ int posCaret = currentPos;
+ if (posDrag >= 0)
+ posCaret = posDrag;
+ Point pt = LocationFromPosition(posCaret);
+ Point ptEOL = LocationFromPosition(pdoc->LineEndPosition(posCaret));
+ Point ptBottomCaret = pt;
+ int lineCaret = cs.DisplayFromDoc(pdoc->LineFromPosition(posCaret));
+ ptBottomCaret.y += vs.lineHeight - 1;
+
+ // Ensure the caret is reasonably visible in context.
+ int xMargin = Platform::Clamp(xCaretMargin, 2, Platform::Maximum(rcClient.Width() - 10, 4) / 2);
+ if (!useMargin)
+ xMargin = 2;
+
+ // Ensure certain amount of text visible on both sides of caretSo move if caret just on edge
+ rcClient.left = rcClient.left + xMargin;
+ rcClient.right = rcClient.right - xMargin;
+
+ if (!rcClient.Contains(pt) || !rcClient.Contains(ptBottomCaret) || (caretPolicy & CARET_STRICT)) {
+ //Platform::DebugPrintf("EnsureCaretVisible move, (%d,%d) (%d,%d)\n", pt.x, pt.y, rcClient.left, rcClient.right);
+ // It should be possible to scroll the window to show the caret,
+ // but this fails to remove the caret on GTK+
+ if (caretPolicy & CARET_SLOP) {
+ if ((topLine > lineCaret) || ((caretPolicy & CARET_STRICT) && (topLine + caretSlop > lineCaret))) {
+ SetTopLine(Platform::Clamp(lineCaret - caretSlop, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ } else if ((lineCaret > topLine + LinesOnScreen() - 1) ||
+ ((caretPolicy & CARET_STRICT) && (lineCaret > topLine + LinesOnScreen() - 1 - caretSlop))) {
+ SetTopLine(Platform::Clamp(lineCaret - LinesOnScreen() + 1 + caretSlop, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ } else {
+ if ((topLine > lineCaret) || (lineCaret > topLine + LinesOnScreen() - 1) || (caretPolicy & CARET_STRICT)) {
+ SetTopLine(Platform::Clamp(lineCaret - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ }
+ int xOffsetNew = xOffset;
+ if (pt.x < rcClient.left) {
+ xOffsetNew = xOffset - (rcClient.left - pt.x);
+ } else if (pt.x >= rcClient.right) {
+ xOffsetNew = xOffset + (pt.x - rcClient.right);
+ int xOffsetEOL = xOffset + (ptEOL.x - rcClient.right) - xMargin + 2;
+ //Platform::DebugPrintf("Margin %d %d\n", xOffsetNew, xOffsetEOL);
+ // Ensure don't scroll out into empty space
+ if (xOffsetNew > xOffsetEOL)
+ xOffsetNew = xOffsetEOL;
+ }
+ if (xOffsetNew < 0)
+ xOffsetNew = 0;
+ if (xOffset != xOffsetNew) {
+ xOffset = xOffsetNew;
+ SetHorizontalScrollPos();
+ Redraw();
+ }
+ }
+}
+
+void Editor::ShowCaretAtCurrentPosition() {
+ if (!wMain.HasFocus()) {
+ caret.active = false;
+ caret.on = false;
+ return;
+ }
+ caret.active = true;
+ caret.on = true;
+ SetTicking(true);
+}
+
+void Editor::DropCaret() {
+ caret.active = false;
+ InvalidateCaret();
+}
+
+void Editor::InvalidateCaret() {
+ if (posDrag >= 0)
+ InvalidateRange(posDrag, posDrag + 1);
+ else
+ InvalidateRange(currentPos, currentPos + 1);
+}
+
+void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
+ if (vs.fixedColumnWidth == 0)
+ return;
+
+ PRectangle rcMargin = GetClientRectangle();
+ rcMargin.right = vs.fixedColumnWidth;
+
+ if (!rc.Intersects(rcMargin))
+ return;
+
+ Surface *surface;
+ if (bufferedDraw) {
+ surface = &pixmapSelMargin;
+ } else {
+ surface = surfWindow;
+ }
+
+ PRectangle rcSelMargin = rcMargin;
+ rcSelMargin.right = rcMargin.left;
+
+ for (int margin=0; margin < vs.margins; margin++) {
+ if (vs.ms[margin].width > 0) {
+
+ rcSelMargin.left = rcSelMargin.right;
+ rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+
+ if (vs.ms[margin].symbol) {
+ /* alternate scheme:
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated);
+ else
+ // Required because of special way brush is created for selection margin
+ surface->FillRectangle(rcSelMargin, pixmapSelPattern);
+ */
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+ // Required because of special way brush is created for selection margin
+ surface->FillRectangle(rcSelMargin, pixmapSelPattern);
+ else
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated);
+ } else {
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated);
+ }
+
+ int visibleLine = topLine;
+ int line = cs.DocFromDisplay(visibleLine);
+ int yposScreen = 0;
+
+ while (line < pdoc->LinesTotal() && yposScreen < rcMargin.bottom) {
+ int marks = pdoc->GetMark(line);
+ if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+ if (cs.GetExpanded(line)) {
+ marks |= 1 << SC_MARKNUM_FOLDEROPEN;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDER;
+ }
+ }
+ marks &= vs.ms[margin].mask;
+ PRectangle rcMarker = rcSelMargin;
+ rcMarker.top = yposScreen;
+ rcMarker.bottom = yposScreen + vs.lineHeight;
+ if (!vs.ms[margin].symbol) {
+ char number[100];
+ number[0] = '\0';
+ sprintf(number, "%d", line + 1);
+ if (foldFlags & 64)
+ sprintf(number, "%X", pdoc->GetLevel(line));
+ int xpos = 0;
+ PRectangle rcNumber=rcMarker;
+ // Right justify
+ int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, strlen(number));
+ xpos = rcNumber.right - width - 3;
+ rcNumber.left = xpos;
+ if ((visibleLine < cs.LinesDisplayed()) && cs.GetVisible(line)) {
+ surface->DrawText(rcNumber, vs.styles[STYLE_LINENUMBER].font,
+ rcNumber.top + vs.maxAscent, number, strlen(number),
+ vs.styles[STYLE_LINENUMBER].fore.allocated,
+ vs.styles[STYLE_LINENUMBER].back.allocated);
+ }
+ }
+
+ if (marks) {
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if (marks & 1) {
+ rcMarker.top++;
+ rcMarker.bottom--;
+ vs.markers[markBit].Draw(surface, rcMarker);
+ }
+ marks >>= 1;
+ }
+ }
+
+ visibleLine++;
+ line = cs.DocFromDisplay(visibleLine);
+ yposScreen += vs.lineHeight;
+ }
+ }
+ }
+
+ PRectangle rcBlankMargin = rcMargin;
+ rcBlankMargin.left = rcSelMargin.right;
+ surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back.allocated);
+
+ if (bufferedDraw) {
+ surfWindow->Copy(rcMargin, Point(), pixmapSelMargin);
+ }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+ int ydiff = (rcTab.bottom - rcTab.top) / 2;
+ int xhead = rcTab.right - 1 - ydiff;
+ if ((rcTab.left + 2) < (rcTab.right - 1))
+ surface->MoveTo(rcTab.left + 2, ymid);
+ else
+ surface->MoveTo(rcTab.right - 1, ymid);
+ surface->LineTo(rcTab.right - 1, ymid);
+ surface->LineTo(xhead, ymid - ydiff);
+ surface->MoveTo(rcTab.right - 1, ymid);
+ surface->LineTo(xhead, ymid + ydiff);
+}
+
+void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll) {
+ int numCharsInLine = 0;
+ int posLineStart = pdoc->LineStart(line);
+ int posLineEnd = pdoc->LineStart(line + 1);
+ Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;
+ char styleByte = 0;
+ int styleMask = pdoc->stylingBitsMask;
+ for (int charInDoc = posLineStart;
+ charInDoc < posLineEnd && numCharsInLine < LineLayout::maxLineLength - 1;
+ charInDoc++) {
+ char chDoc = pdoc->CharAt(charInDoc);
+ styleByte = pdoc->StyleAt(charInDoc);
+ if (vstyle.viewEOL || ((chDoc != '\r') && (chDoc != '\n'))) {
+ ll.chars[numCharsInLine] = chDoc;
+ ll.styles[numCharsInLine] = styleByte & styleMask;
+ ll.indicators[numCharsInLine] = styleByte & ~styleMask;
+ numCharsInLine++;
+ }
+ }
+ ll.chars[numCharsInLine] = 0;
+ ll.styles[numCharsInLine] = styleByte; // For eolFilled
+ ll.indicators[numCharsInLine] = 0;
+
+ // Layout the line, determining the position of each character
+ int startseg = 0;
+ int startsegx = 0;
+ ll.positions[0] = 0;
+ unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
+
+ for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
+ if ((ll.styles[charInLine] != ll.styles[charInLine + 1]) ||
+ IsControlCharacter(ll.chars[charInLine]) || IsControlCharacter(ll.chars[charInLine + 1])) {
+ ll.positions[startseg] = 0;
+ if (IsControlCharacter(ll.chars[charInLine])) {
+ if (ll.chars[charInLine] == '\t') {
+ ll.positions[charInLine + 1] = ((((startsegx + 2) /
+ tabWidth) + 1) * tabWidth) - startsegx;
+ } else {
+ const char *ctrlChar = ControlCharacterString(ll.chars[charInLine]);
+ // +3 For a blank on front and rounded edge each side:
+ ll.positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, strlen(ctrlChar)) + 3;
+ }
+ } else {
+ surface->MeasureWidths(vstyle.styles[ll.styles[charInLine]].font, ll.chars + startseg,
+ charInLine - startseg + 1, ll.positions + startseg + 1);
+ }
+ for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) {
+ ll.positions[posToIncrease] += startsegx;
+ }
+ startsegx = ll.positions[charInLine + 1];
+ startseg = charInLine + 1;
+ }
+ }
+ ll.numCharsInLine = numCharsInLine;
+}
+
+void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout &ll) {
+
+ PRectangle rcSegment = rcLine;
+
+ // Using one font for all control characters so it can be controlled independently to ensure
+ // the box goes around the characters tightly. Seems to be no way to work out what height
+ // is taken by an individual character - internal leading gives varying results.
+ Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+
+ int marks = 0;
+ Colour markBack = Colour(0, 0, 0);
+ if (vsDraw.maskInLine) {
+ marks = pdoc->GetMark(line) & vsDraw.maskInLine;
+ if (marks) {
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if (marks & 1) {
+ markBack = vsDraw.markers[markBit].back.allocated;
+ }
+ marks >>= 1;
+ }
+ }
+ marks = pdoc->GetMark(line) & vsDraw.maskInLine;
+ }
+
+ int posLineStart = pdoc->LineStart(line);
+ int posLineEnd = pdoc->LineStart(line + 1);
+
+ int selStart = SelectionStart(line);
+ int selEnd = SelectionEnd(line);
+
+ int styleMask = pdoc->stylingBitsMask;
+ int startseg = 0;
+ for (int i = 0; i < ll.numCharsInLine; i++) {
+
+ int iDoc = i + posLineStart;
+ // If there is the end of a style run for any reason
+ if ((ll.styles[i] != ll.styles[i + 1]) ||
+ IsControlCharacter(ll.chars[i]) || IsControlCharacter(ll.chars[i + 1]) ||
+ ((selStart != selEnd) && ((iDoc + 1 == selStart) || (iDoc + 1 == selEnd))) ||
+ (i == (theEdge-1))) {
+ int styleMain = ll.styles[i];
+ Colour textBack = vsDraw.styles[styleMain].back.allocated;
+ Colour textFore = vsDraw.styles[styleMain].fore.allocated;
+ Font &textFont = vsDraw.styles[styleMain].font;
+ bool inSelection = (iDoc >= selStart) && (iDoc < selEnd) && (selStart != selEnd);
+ if (inSelection && !hideSelection) {
+ if (vsDraw.selbackset)
+ textBack = vsDraw.selbackground.allocated;
+ if (vsDraw.selforeset)
+ textFore = vsDraw.selforeground.allocated;
+ } else {
+ if (marks)
+ textBack = markBack;
+ if ((edgeState == EDGE_BACKGROUND) && (i >= theEdge) && (ll.chars[i] != '\n') && (ll.chars[i] != '\r'))
+ textBack = vs.edgecolour.allocated;
+ }
+ // Manage tab display
+ if (ll.chars[i] == '\t') {
+ rcSegment.left = ll.positions[i] + xStart;
+ rcSegment.right = ll.positions[i + 1] + xStart;
+ surface->FillRectangle(rcSegment, textBack);
+ if (vsDraw.viewWhitespace) {
+ surface->PenColour(textFore);
+ PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+ rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+ DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
+ }
+ // Manage control character display
+ } else if (IsControlCharacter(ll.chars[i])) {
+ const char *ctrlChar = ControlCharacterString(ll.chars[i]);
+ rcSegment.left = ll.positions[i] + xStart;
+ rcSegment.right = ll.positions[i + 1] + xStart;
+ surface->FillRectangle(rcSegment, textBack);
+ int normalCharHeight = surface->Ascent(ctrlCharsFont) -
+ surface->InternalLeading(ctrlCharsFont);
+ PRectangle rcCChar = rcSegment;
+ rcCChar.left = rcCChar.left + 1;
+ rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+ rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+ PRectangle rcCentral = rcCChar;
+ rcCentral.top++;
+ rcCentral.bottom--;
+ surface->FillRectangle(rcCentral, textFore);
+ PRectangle rcChar = rcCChar;
+ rcChar.left++;
+ rcChar.right--;
+ surface->DrawTextClipped(rcChar, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent, ctrlChar, strlen(ctrlChar),
+ textBack, textFore);
+ // Manage normal display
+ } else {
+ rcSegment.left = ll.positions[startseg] + xStart;
+ rcSegment.right = ll.positions[i + 1] + xStart;
+ // Only try do draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if (rcSegment.left <= rcLine.right) {
+ surface->DrawText(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll.chars + startseg,
+ i - startseg + 1, textFore, textBack);
+ if (vsDraw.viewWhitespace) {
+ for (int cpos = 0; cpos <= i - startseg; cpos++) {
+ if (ll.chars[cpos + startseg] == ' ') {
+ int xmid = (ll.positions[cpos + startseg] + ll.positions[cpos + startseg + 1]) / 2;
+ PRectangle rcDot(xmid + xStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
+ rcDot.right = rcDot.left + 1;
+ rcDot.bottom = rcDot.top + 1;
+ surface->FillRectangle(rcDot, textFore);
+ }
+ }
+ }
+ }
+ }
+ startseg = i + 1;
+ }
+ }
+
+ // Draw indicators
+ int indStart[INDIC_MAX + 1] = {0};
+ for (int indica = 0; indica <= INDIC_MAX; indica++)
+ indStart[indica] = 0;
+
+ for (int indicPos = 0; indicPos <= ll.numCharsInLine; indicPos++) {
+ if (ll.indicators[indicPos] != ll.indicators[indicPos + 1]) {
+ int mask = 1 << pdoc->stylingBits;
+ for (int indicnum = 0; mask <= 0x100; indicnum++) {
+ if ((ll.indicators[indicPos + 1] & mask) && !(ll.indicators[indicPos] & mask)) {
+ indStart[indicnum] = ll.positions[indicPos + 1];
+ }
+ if (!(ll.indicators[indicPos + 1] & mask) && (ll.indicators[indicPos] & mask)) {
+ PRectangle rcIndic(
+ indStart[indicnum] + xStart,
+ rcLine.top + vsDraw.maxAscent,
+ ll.positions[indicPos + 1] + xStart,
+ rcLine.top + vsDraw.maxAscent + 3);
+ vsDraw.indicators[indicnum].Draw(surface, rcIndic);
+ }
+ mask = mask << 1;
+ }
+ }
+ }
+ // End of the drawing of the current line
+
+ // Fill in a PRectangle representing the end of line characters
+ int xEol = ll.positions[ll.numCharsInLine];
+ rcSegment.left = xEol + xStart;
+ rcSegment.right = xEol + vsDraw.aveCharWidth + xStart;
+ bool eolInSelection = (posLineEnd > selStart) && (posLineEnd <= selEnd) && (selStart != selEnd);
+ if (eolInSelection && !hideSelection && vsDraw.selbackset && (line < pdoc->LinesTotal()-1)) {
+ surface->FillRectangle(rcSegment, vsDraw.selbackground.allocated);
+ } else if (marks) {
+ surface->FillRectangle(rcSegment, markBack);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated);
+ }
+
+ rcSegment.left = xEol + vsDraw.aveCharWidth + xStart;
+ rcSegment.right = rcLine.right;
+ if (marks) {
+ surface->FillRectangle(rcSegment, markBack);
+ } else if (vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated);
+ }
+
+ if (edgeState == EDGE_LINE) {
+ int edgeX = theEdge * vsDraw.spaceWidth;
+ rcSegment.left = edgeX + xStart;
+ rcSegment.right = rcSegment.left + 1;
+ surface->FillRectangle(rcSegment, vs.edgecolour.allocated);
+ }
+}
+
+void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+ //Platform::DebugPrintf("Paint %d %d - %d %d\n", rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+ RefreshStyleData();
+
+ PRectangle rcClient = GetClientRectangle();
+ //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
+ // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+ if (!pixmapSelPattern.Initialised()) {
+ pixmapSelPattern.InitPixMap(8, 8, surfaceWindow);
+ // This complex procedure is to reproduce the checker board dithered pattern used by windows
+ // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
+ // way between the chrome colour and the chrome highlight colour making a nice transition
+ // between the window chrome and the content area. And it works in low colour depths.
+ PRectangle rcPattern(0, 0, 8, 8);
+ if (vs.selbarlight.desired == Colour(0xff, 0xff, 0xff)) {
+ pixmapSelPattern.FillRectangle(rcPattern, vs.selbar.allocated);
+ pixmapSelPattern.PenColour(vs.selbarlight.allocated);
+ for (int stripe = 0; stripe < 8; stripe++) {
+ pixmapSelPattern.MoveTo(0, stripe * 2);
+ pixmapSelPattern.LineTo(8, stripe * 2 - 8);
+ }
+ } else {
+ // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
+ pixmapSelPattern.FillRectangle(rcPattern, vs.selbarlight.allocated);
+ }
+ }
+
+ if (bufferedDraw) {
+ if (!pixmapLine.Initialised()) {
+ pixmapLine.InitPixMap(rcClient.Width(), rcClient.Height(),
+ surfaceWindow);
+ pixmapSelMargin.InitPixMap(vs.fixedColumnWidth,
+ rcClient.Height(), surfaceWindow);
+ }
+ }
+
+ surfaceWindow->SetPalette(&palette, true);
+ pixmapLine.SetPalette(&palette, !wMain.HasFocus());
+
+ //Platform::DebugPrintf("Paint: (%3d,%3d) ... (%3d,%3d)\n",
+ // rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+
+ int screenLinePaintFirst = rcArea.top / vs.lineHeight;
+ // The area to be painted plus one extra line is styled.
+ // The extra line is to determine when a style change, such as statrting a comment flows on to other lines.
+ int lineStyleLast = topLine + (rcArea.bottom-1) / vs.lineHeight + 1;
+ //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast);
+ int endPosPaint = pdoc->Length();
+ if (lineStyleLast < cs.LinesDisplayed())
+ endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast + 1));
+
+ int xStart = vs.fixedColumnWidth - xOffset;
+ int ypos = 0;
+ if (!bufferedDraw)
+ ypos += screenLinePaintFirst * vs.lineHeight;
+ int yposScreen = screenLinePaintFirst * vs.lineHeight;
+
+ if (endPosPaint > pdoc->GetEndStyled()) {
+ // Notify container to do some more styling
+ NotifyStyleNeeded(endPosPaint);
+ }
+ if (needUpdateUI) {
+ NotifyUpdateUI();
+ needUpdateUI = false;
+ }
+
+ PaintSelMargin(surfaceWindow, rcArea);
+
+ PRectangle rcRightMargin = rcClient;
+ rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
+ if (rcArea.Intersects(rcRightMargin)) {
+ surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back.allocated);
+ }
+
+ if (paintState == paintAbandoned) {
+ // Either NotifyStyleNeeded or NotifyUpdateUI noticed that painting is needed
+ // outside the current painting rectangle
+ //Platform::DebugPrintf("Abandoning paint\n");
+ return;
+ }
+ //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
+
+ Surface *surface = 0;
+ if (rcArea.right > vs.fixedColumnWidth) {
+
+ if (bufferedDraw) {
+ surface = &pixmapLine;
+ } else {
+ surface = surfaceWindow;
+ }
+
+ int visibleLine = topLine + screenLinePaintFirst;
+ int line = cs.DocFromDisplay(visibleLine);
+
+ int posCaret = currentPos;
+ if (posDrag >= 0)
+ posCaret = posDrag;
+ int lineCaret = pdoc->LineFromPosition(posCaret);
+
+ // Remove selection margin from drawing area so text will not be drawn
+ // on it in unbuffered mode.
+ PRectangle rcTextArea = rcClient;
+ rcTextArea.left = vs.fixedColumnWidth;
+ rcTextArea.right -= vs.rightMarginWidth;
+ surfaceWindow->SetClip(rcTextArea);
+ //GTimer *tim=g_timer_new();
+ while (visibleLine <= cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
+ //g_timer_start(tim);
+ //Platform::DebugPrintf("Painting line %d\n", line);
+
+ int posLineStart = pdoc->LineStart(line);
+ int posLineEnd = pdoc->LineStart(line + 1);
+ //Platform::DebugPrintf("line %d %d - %d\n", line, posLineStart, posLineEnd);
+
+ PRectangle rcLine = rcClient;
+ rcLine.top = ypos;
+ rcLine.bottom = ypos + vs.lineHeight;
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ LineLayout ll;
+ LayoutLine(line, surface, vs, ll);
+
+ // Highlight the current braces if any
+ if ((braces[0] >= posLineStart) && (braces[0] < posLineEnd))
+ ll.styles[braces[0] - posLineStart] = bracesMatchStyle;
+ if ((braces[1] >= posLineStart) && (braces[1] < posLineEnd))
+ ll.styles[braces[1] - posLineStart] = bracesMatchStyle;
+
+ // Draw the line
+ if (cs.GetVisible(line))
+ DrawLine(surface, vs, line, xStart, rcLine, ll);
+
+ bool expanded = cs.GetExpanded(line);
+ if ( (expanded && (foldFlags & 2)) || (!expanded && (foldFlags & 4)) ) {
+ if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.bottom = rcFoldLine.top + 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
+ }
+ if ( (expanded && (foldFlags & 8)) || (!expanded && (foldFlags & 16)) ) {
+ if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.top = rcFoldLine.bottom - 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
+ }
+
+ // Draw the Caret
+ if (line == lineCaret) {
+ int xposCaret = ll.positions[posCaret - posLineStart] + xStart;
+ int widthOverstrikeCaret =
+ ll.positions[posCaret - posLineStart + 1] - ll.positions[posCaret - posLineStart];
+ if (posCaret == pdoc->Length()) // At end of document
+ widthOverstrikeCaret = vs.aveCharWidth;
+ if ((posCaret - posLineStart) >= ll.numCharsInLine) // At end of line
+ widthOverstrikeCaret = vs.aveCharWidth;
+ if (widthOverstrikeCaret < 3) // Make sure its visible
+ widthOverstrikeCaret = 3;
+ if (((caret.active && caret.on) || (posDrag >= 0)) && xposCaret >= 0) {
+ PRectangle rcCaret = rcLine;
+ if (posDrag >= 0) {
+ rcCaret.left = xposCaret;
+ rcCaret.right = xposCaret + 1;
+ } else {
+ if (inOverstrike) {
+ rcCaret.top = rcCaret.bottom - 2;
+ rcCaret.left = xposCaret + 1;
+ rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
+ } else {
+ rcCaret.left = xposCaret;
+ rcCaret.right = xposCaret + 1;
+ }
+ }
+ surface->FillRectangle(rcCaret, vs.caretcolour.allocated);
+ }
+ }
+
+ if (cs.GetVisible(line)) {
+ if (bufferedDraw) {
+ Point from(vs.fixedColumnWidth, 0);
+ PRectangle rcCopyArea(vs.fixedColumnWidth, yposScreen,
+ rcClient.right, yposScreen + vs.lineHeight);
+ surfaceWindow->Copy(rcCopyArea, from, pixmapLine);
+ }
+ }
+
+ if (!bufferedDraw) {
+ ypos += vs.lineHeight;
+ }
+
+ yposScreen += vs.lineHeight;
+ visibleLine++;
+ line = cs.DocFromDisplay(visibleLine);
+ //gdk_flush();
+ //g_timer_stop(tim);
+ //Platform::DebugPrintf("Paint [%0d] took %g\n", line, g_timer_elapsed(tim, 0));
+ }
+ //g_timer_destroy(tim);
+ PRectangle rcBeyondEOF = rcClient;
+ rcBeyondEOF.left = vs.fixedColumnWidth;
+ rcBeyondEOF.right = rcBeyondEOF.right;
+ rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight;
+ if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
+ surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back.allocated);
+ if (edgeState == EDGE_LINE) {
+ int edgeX = theEdge * vs.spaceWidth;
+ rcBeyondEOF.left = edgeX + xStart;
+ rcBeyondEOF.right = rcBeyondEOF.left + 1;
+ surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour.allocated);
+ }
+ }
+ }
+}
+
+// Space (3 space characters) between line numbers and text when printing.
+#define lineNumberPrintSpace " "
+
+// This is mostly copied from the Paint method but with some things omitted
+// such as the margin markers, line numbers, selection and caret
+// Should be merged back into a combined Draw method.
+long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
+ if (!pfr)
+ return 0;
+
+ Surface *surface = new Surface();
+ surface->Init(pfr->hdc);
+ Surface *surfaceMeasure = new Surface();
+ surfaceMeasure->Init(pfr->hdcTarget);
+
+ ViewStyle vsPrint(vs);
+
+ // Modify the view style for printing as do not normally want any of the transient features to be printed
+ // Printing supports only the line number margin.
+ int lineNumberIndex = -1;
+ for (int margin=0; margin < ViewStyle::margins; margin++) {
+ if ((!vsPrint.ms[margin].symbol) && (vsPrint.ms[margin].width > 0)) {
+ lineNumberIndex = margin;
+ } else {
+ vsPrint.ms[margin].width = 0;
+ }
+ }
+ vsPrint.showMarkedLines = false;
+ vsPrint.fixedColumnWidth = 0;
+ vsPrint.zoomLevel = 0;
+ // Don't show the selection when printing
+ vsPrint.selbackset = false;
+ vsPrint.selforeset = false;
+ // White background for the line numbers
+ vsPrint.styles[STYLE_LINENUMBER].back.desired = Colour(0xff,0xff,0xff);
+
+ vsPrint.Refresh(*surfaceMeasure);
+ // Ensure colours are set up
+ vsPrint.RefreshColourPalette(palette, true);
+ vsPrint.RefreshColourPalette(palette, false);
+ // Determining width must hapen after fonts have been realised in Refresh
+ int lineNumberWidth = 0;
+ if (lineNumberIndex >= 0) {
+ lineNumberWidth = surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
+ "9999" lineNumberPrintSpace, 4 + strlen(lineNumberPrintSpace));
+ vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
+ }
+
+ int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
+ int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+ if (linePrintLast < linePrintStart)
+ linePrintLast = linePrintStart;
+ int linePrintMax = pdoc->LineFromPosition(pfr->chrg.cpMax - 1);
+ if (linePrintLast > linePrintMax)
+ linePrintLast = linePrintMax;
+ //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
+ // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+ // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
+ int endPosPrint = pdoc->Length();
+ if (linePrintLast < pdoc->LinesTotal())
+ endPosPrint = pdoc->LineStart(linePrintLast + 1);
+
+ if (endPosPrint > pdoc->GetEndStyled()) {
+ // Notify container to do some more styling
+ NotifyStyleNeeded(endPosPrint);
+ }
+ int xStart = vsPrint.fixedColumnWidth + pfr->rc.left + lineNumberWidth;
+ int ypos = pfr->rc.top;
+ int line = linePrintStart;
+
+ if (draw) { // Otherwise just measuring
+
+ while (line <= linePrintLast && ypos < pfr->rc.bottom) {
+
+ PRectangle rcLine;
+ rcLine.left = pfr->rc.left + lineNumberWidth;
+ rcLine.top = ypos;
+ rcLine.right = pfr->rc.right;
+ rcLine.bottom = ypos + vsPrint.lineHeight;
+
+ if (lineNumberWidth) {
+ char number[100];
+ sprintf(number, "%d" lineNumberPrintSpace, line + 1);
+ PRectangle rcNumber = rcLine;
+ rcNumber.right = rcNumber.left + lineNumberWidth;
+ // Right justify
+ rcNumber.left += lineNumberWidth -
+ surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, number, strlen(number));
+ surface->DrawText(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
+ ypos + vsPrint.maxAscent, number, strlen(number),
+ vsPrint.styles[STYLE_LINENUMBER].fore.allocated,
+ vsPrint.styles[STYLE_LINENUMBER].back.allocated);
+ }
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ LineLayout ll;
+ LayoutLine(line, surfaceMeasure, vsPrint, ll);
+
+ // Draw the line
+ DrawLine(surface, vsPrint, line, xStart, rcLine, ll);
+
+ ypos += vsPrint.lineHeight;
+ line++;
+ }
+ }
+
+ delete surface;
+ delete surfaceMeasure;
+
+ return endPosPrint;
+}
+
+void Editor::SetScrollBarsTo(PRectangle) {
+ RefreshStyleData();
+
+ int nMax = cs.LinesDisplayed();
+ int nPage = cs.LinesDisplayed() - MaxScrollPos() + 1;
+ bool modified = ModifyScrollBars(nMax, nPage);
+
+ // TODO: ensure always showing as many lines as possible
+ // May not be, if, for example, window made larger
+ if (topLine > MaxScrollPos()) {
+ SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ if (modified)
+ Redraw();
+ //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
+}
+
+void Editor::SetScrollBars() {
+ PRectangle rsClient = GetClientRectangle();
+ SetScrollBarsTo(rsClient);
+}
+
+void Editor::AddChar(char ch) {
+ bool wasSelection = currentPos != anchor;
+ ClearSelection();
+ if (inOverstrike && !wasSelection) {
+ if (currentPos < (pdoc->Length() - 1)) {
+ if ((pdoc->CharAt(currentPos) != '\r') && (pdoc->CharAt(currentPos) != '\n')) {
+ pdoc->DelChar(currentPos);
+ }
+ }
+ }
+ pdoc->InsertChar(currentPos, ch);
+ SetEmptySelection(currentPos + 1);
+ EnsureCaretVisible();
+ SetLastXChosen();
+ NotifyChar(ch);
+}
+
+void Editor::ClearSelection() {
+ if (selType == selRectangle) {
+ pdoc->BeginUndoAction();
+ int lineStart = pdoc->LineFromPosition(SelectionStart());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+ int startPos = SelectionStart();
+ int line;
+ for (line=lineStart; line <= lineEnd; line++) {
+ startPos = SelectionStart(line);
+ unsigned int chars = SelectionEnd(line) - startPos;
+ if (0 != chars) {
+ pdoc->DeleteChars(startPos, chars);
+ }
+ }
+ SetEmptySelection(startPos);
+ selType = selStream;
+ pdoc->EndUndoAction();
+ } else {
+ int startPos = SelectionStart();
+ unsigned int chars = SelectionEnd() - startPos;
+ SetEmptySelection(startPos);
+ if (0 != chars) {
+ pdoc->DeleteChars(startPos, chars);
+ }
+ }
+}
+
+void Editor::ClearAll() {
+ if (0 != pdoc->Length()) {
+ pdoc->DeleteChars(0, pdoc->Length());
+ }
+ cs.Clear();
+ anchor = 0;
+ currentPos = 0;
+ SetTopLine(0);
+ SetVerticalScrollPos();
+}
+
+void Editor::Cut() {
+ Copy();
+ ClearSelection();
+}
+
+void Editor::PasteRectangular(int pos, const char *ptr, int len) {
+ currentPos = pos;
+ int insertPos = currentPos;
+ int xInsert = XFromPosition(currentPos);
+ int line = pdoc->LineFromPosition(currentPos);
+ bool prevCr = false;
+ for (int i=0; i<len; i++) {
+ if ((ptr[i] == '\r') || (ptr[i] == '\n')) {
+ if ((ptr[i] == '\r') || (!prevCr))
+ line++;
+ if (line >= pdoc->LinesTotal()) {
+ if (pdoc->eolMode != SC_EOL_LF)
+ pdoc->InsertChar(pdoc->Length(), '\r');
+ if (pdoc->eolMode != SC_EOL_CR)
+ pdoc->InsertChar(pdoc->Length(), '\n');
+ }
+ currentPos = PositionFromLineX(line, xInsert);
+ prevCr = ptr[i] == '\r';
+ } else {
+ pdoc->InsertString(currentPos, ptr+i, 1);
+ currentPos++;
+ insertPos = currentPos;
+ prevCr = false;
+ }
+ }
+ SetEmptySelection(insertPos);
+}
+
+void Editor::Clear() {
+ if (currentPos == anchor) {
+ DelChar();
+ } else {
+ ClearSelection();
+ }
+ SetEmptySelection(currentPos);
+}
+
+void Editor::SelectAll() {
+ SetSelection(0, pdoc->Length());
+ Redraw();
+}
+
+void Editor::Undo() {
+ if (pdoc->CanUndo()) {
+ int newPos = pdoc->Undo();
+ SetEmptySelection(newPos);
+ EnsureCaretVisible();
+ }
+}
+
+void Editor::Redo() {
+ if (pdoc->CanRedo()) {
+ int newPos = pdoc->Redo();
+ SetEmptySelection(newPos);
+ EnsureCaretVisible();
+ }
+}
+
+void Editor::DelChar() {
+ pdoc->DelChar(currentPos);
+}
+
+void Editor::DelCharBack() {
+ if (currentPos == anchor) {
+ int newPos = pdoc->DelCharBack(currentPos);
+ SetEmptySelection(newPos);
+ } else {
+ ClearSelection();
+ SetEmptySelection(currentPos);
+ }
+}
+
+void Editor::NotifyFocus(bool) {
+}
+
+void Editor::NotifyStyleNeeded(int endStyleNeeded) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_STYLENEEDED;
+ scn.position = endStyleNeeded;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyChar(char ch) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_CHARADDED;
+ scn.ch = ch;
+ NotifyParent(scn);
+#ifdef MACRO_SUPPORT
+ if (recordingMacro) {
+ char txt[2];
+ txt[0] = ch;
+ txt[1] = '\0';
+ NotifyMacroRecord(EM_REPLACESEL, 0, (LPARAM) txt);
+ }
+#endif
+}
+
+void Editor::NotifySavePoint(bool isSavePoint) {
+ SCNotification scn;
+ if (isSavePoint) {
+ scn.nmhdr.code = SCN_SAVEPOINTREACHED;
+ } else {
+ scn.nmhdr.code = SCN_SAVEPOINTLEFT;
+ }
+ NotifyParent(scn);
+}
+
+void Editor::NotifyModifyAttempt() {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyDoubleClick(Point, bool) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_DOUBLECLICK;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyUpdateUI() {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_UPDATEUI;
+ NotifyParent(scn);
+}
+
+bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
+ int marginClicked = -1;
+ int x = 0;
+ for (int margin=0; margin < ViewStyle::margins; margin++) {
+ if ((pt.x > x) && (pt.x < x + vs.ms[margin].width))
+ marginClicked = margin;
+ x += vs.ms[margin].width;
+ }
+ if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_MARGINCLICK;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ scn.position = pdoc->LineStart(LineFromLocation(pt));
+ scn.margin = marginClicked;
+ NotifyParent(scn);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Editor::NotifyNeedShown(int pos, int len) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_NEEDSHOWN;
+ scn.position = pos;
+ scn.length = len;
+ NotifyParent(scn);
+}
+
+// Notifications from document
+void Editor::NotifyModifyAttempt(Document*, void *) {
+ //Platform::DebugPrintf("** Modify Attempt\n");
+ NotifyModifyAttempt();
+}
+
+void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) {
+ //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
+ NotifySavePoint(atSavePoint);
+}
+
+void Editor::NotifyModified(Document*, DocModification mh, void *) {
+ needUpdateUI = true;
+ if (paintState == painting) {
+ CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
+ } else if (paintState == notPainting) {
+ if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+ if (mh.position < pdoc->LineStart(topLine)) {
+ // Styling performed before this view
+ Redraw();
+ } else {
+ InvalidateRange(mh.position, mh.position + mh.length);
+ }
+ } else {
+ // Move selection and brace highlights
+ if (mh.modificationType & SC_MOD_INSERTTEXT) {
+ if (currentPos > mh.position) {
+ currentPos += mh.length;
+ }
+ if (anchor > mh.position) {
+ anchor += mh.length;
+ }
+ if (braces[0] > mh.position) {
+ braces[0] += mh.length;
+ }
+ if (braces[1] > mh.position) {
+ braces[1] += mh.length;
+ }
+ } else { // SC_MOD_DELETETEXT
+ int endPos = mh.position + mh.length;
+ if (currentPos > mh.position) {
+ if (currentPos > endPos) {
+ currentPos -= mh.length;
+ } else {
+ currentPos = endPos;
+ }
+ }
+ if (anchor > mh.position) {
+ if (anchor > endPos) {
+ anchor -= mh.length;
+ } else {
+ anchor = endPos;
+ }
+ }
+ if (braces[0] > mh.position) {
+ if (braces[0] > endPos) {
+ braces[0] -= mh.length;
+ } else {
+ braces[0] = endPos;
+ }
+ }
+ if (braces[1] > mh.position) {
+ if (braces[1] > endPos) {
+ braces[1] -= mh.length;
+ } else {
+ braces[1] = endPos;
+ }
+ }
+ }
+ if (mh.linesAdded != 0) {
+
+ // Update contraction state for inserted and removed lines
+ // lineOfPos should be calculated in context of state before modification, shouldn't it
+ int lineOfPos = pdoc->LineFromPosition(mh.position);
+ if (mh.linesAdded > 0) {
+ NotifyNeedShown(mh.position, mh.length);
+ cs.InsertLines(lineOfPos, mh.linesAdded);
+ } else {
+ cs.DeleteLines(lineOfPos, -mh.linesAdded);
+ }
+ // Avoid scrolling of display if change before current display
+ if (mh.position < posTopLine) {
+ int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
+ if (newTop != topLine) {
+ SetTopLine(newTop);
+ SetVerticalScrollPos();
+ }
+ }
+
+ //Platform::DebugPrintf("** %x Doc Changed\n", this);
+ // TODO: could invalidate from mh.startModification to end of screen
+ //InvalidateRange(mh.position, mh.position + mh.length);
+ Redraw();
+ } else {
+ //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
+ // mh.position, mh.position + mh.length);
+ InvalidateRange(mh.position, mh.position + mh.length);
+ }
+ }
+ } // else paintState == paintAbandoned so no need to do anything
+
+ if (mh.linesAdded != 0) {
+ SetScrollBars();
+ }
+
+ // If client wants to see this modification
+ if (mh.modificationType & modEventMask) {
+ if ((mh.modificationType & SC_MOD_CHANGESTYLE) == 0) {
+ // Real modification made to text of document.
+ NotifyChange(); // Send EN_CHANGE
+ }
+ SCNotification scn;
+ scn.nmhdr.code = SCN_MODIFIED;
+ scn.position = mh.position;
+ scn.modificationType = mh.modificationType;
+ scn.text = mh.text;
+ scn.length = mh.length;
+ scn.linesAdded = mh.linesAdded;
+ scn.line = mh.line;
+ scn.foldLevelNow = mh.foldLevelNow;
+ scn.foldLevelPrev = mh.foldLevelPrev;
+ NotifyParent(scn);
+ }
+}
+
+void Editor::NotifyDeleted(Document *document, void *userData) {
+ /* Do nothing */
+}
+
+#ifdef MACRO_SUPPORT
+void Editor::NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+
+ // Enumerates all macroable messages
+ switch (iMessage) {
+ case WM_CUT:
+ case WM_COPY:
+ case WM_PASTE:
+ case WM_CLEAR:
+ case EM_REPLACESEL:
+ case SCI_ADDTEXT:
+ case SCI_INSERTTEXT:
+ case SCI_CLEARALL:
+ case SCI_SELECTALL:
+ case SCI_GOTOLINE:
+ case SCI_GOTOPOS:
+ case SCI_SEARCHANCHOR:
+ case SCI_SEARCHNEXT:
+ case SCI_SEARCHPREV:
+ case SCI_LINEDOWN:
+ case SCI_LINEDOWNEXTEND:
+ case SCI_LINEUP:
+ case SCI_LINEUPEXTEND:
+ case SCI_CHARLEFT:
+ case SCI_CHARLEFTEXTEND:
+ case SCI_CHARRIGHT:
+ case SCI_CHARRIGHTEXTEND:
+ case SCI_WORDLEFT:
+ case SCI_WORDLEFTEXTEND:
+ case SCI_WORDRIGHT:
+ case SCI_WORDRIGHTEXTEND:
+ case SCI_HOME:
+ case SCI_HOMEEXTEND:
+ case SCI_LINEEND:
+ case SCI_LINEENDEXTEND:
+ case SCI_DOCUMENTSTART:
+ case SCI_DOCUMENTSTARTEXTEND:
+ case SCI_DOCUMENTEND:
+ case SCI_DOCUMENTENDEXTEND:
+ case SCI_PAGEUP:
+ case SCI_PAGEUPEXTEND:
+ case SCI_PAGEDOWN:
+ case SCI_PAGEDOWNEXTEND:
+ case SCI_EDITTOGGLEOVERTYPE:
+ case SCI_CANCEL:
+ case SCI_DELETEBACK:
+ case SCI_TAB:
+ case SCI_BACKTAB:
+ case SCI_NEWLINE:
+ case SCI_FORMFEED:
+ case SCI_VCHOME:
+ case SCI_VCHOMEEXTEND:
+ case SCI_DELWORDLEFT:
+ case SCI_DELWORDRIGHT:
+ break;
+
+ // Filter out all others (display changes, etc)
+ default:
+// printf("Filtered out %ld of macro recording\n", iMessage);
+ return;
+ }
+
+ // Send notification
+ SCNotification scn;
+ scn.nmhdr.code = SCN_MACRORECORD;
+ scn.message = iMessage;
+ scn.wParam = wParam;
+ scn.lParam = lParam;
+ NotifyParent(scn);
+}
+#endif
+
+// Force scroll and keep position relative to top of window
+void Editor::PageMove(int direction, bool extend) {
+ Point pt = LocationFromPosition(currentPos);
+ int topLineNew = Platform::Clamp(
+ topLine + direction * LinesToScroll(), 0, MaxScrollPos());
+ int newPos = PositionFromLocation(
+ Point(lastXChosen, pt.y + direction * (vs.lineHeight * LinesToScroll())));
+ if (topLineNew != topLine) {
+ SetTopLine(topLineNew);
+ MovePositionTo(newPos, extend);
+ Redraw();
+ SetVerticalScrollPos();
+ } else {
+ MovePositionTo(newPos, extend);
+ }
+}
+
+int Editor::KeyCommand(UINT iMessage) {
+ Point pt = LocationFromPosition(currentPos);
+
+ switch (iMessage) {
+ case SCI_LINEDOWN:
+ MovePositionTo(PositionFromLocation(
+ Point(lastXChosen, pt.y + vs.lineHeight)));
+ break;
+ case SCI_LINEDOWNEXTEND:
+ MovePositionTo(PositionFromLocation(
+ Point(lastXChosen, pt.y + vs.lineHeight)), true);
+ break;
+ case SCI_LINEUP:
+ MovePositionTo(PositionFromLocation(
+ Point(lastXChosen, pt.y - vs.lineHeight)));
+ break;
+ case SCI_LINEUPEXTEND:
+ MovePositionTo(PositionFromLocation(
+ Point(lastXChosen, pt.y - vs.lineHeight)), true);
+ break;
+ case SCI_CHARLEFT:
+ if (SelectionEmpty()) {
+ MovePositionTo(MovePositionSoVisible(currentPos - 1, -1));
+ } else {
+ MovePositionTo(SelectionStart());
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARLEFTEXTEND:
+ MovePositionTo(MovePositionSoVisible(currentPos - 1, -1), true);
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHT:
+ if (SelectionEmpty()) {
+ MovePositionTo(MovePositionSoVisible(currentPos + 1, 1));
+ } else {
+ MovePositionTo(SelectionEnd());
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHTEXTEND:
+ MovePositionTo(MovePositionSoVisible(currentPos + 1, 1), true);
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFT:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, -1), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, -1), -1), true);
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHT:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, 1), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, 1), 1), true);
+ SetLastXChosen();
+ break;
+ case SCI_HOME:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(currentPos)));
+ SetLastXChosen();
+ break;
+ case SCI_HOMEEXTEND:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(currentPos)), true);
+ SetLastXChosen();
+ break;
+ case SCI_LINEEND:
+ MovePositionTo(pdoc->LineEndPosition(currentPos));
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDEXTEND:
+ MovePositionTo(pdoc->LineEndPosition(currentPos), true);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTSTART:
+ MovePositionTo(0);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTSTARTEXTEND:
+ MovePositionTo(0, true);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTEND:
+ MovePositionTo(pdoc->Length());
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTENDEXTEND:
+ MovePositionTo(pdoc->Length(), true);
+ SetLastXChosen();
+ break;
+ case SCI_PAGEUP:
+ PageMove( -1);
+ break;
+ case SCI_PAGEUPEXTEND:
+ PageMove( -1, true);
+ break;
+ case SCI_PAGEDOWN:
+ PageMove(1);
+ break;
+ case SCI_PAGEDOWNEXTEND:
+ PageMove(1, true);
+ break;
+ case SCI_EDITTOGGLEOVERTYPE:
+ inOverstrike = !inOverstrike;
+ DropCaret();
+ ShowCaretAtCurrentPosition();
+ break;
+ case SCI_CANCEL: // Cancel any modes - handled in subclass
+ // Also unselect text
+ SetEmptySelection(currentPos);
+ break;
+ case SCI_DELETEBACK:
+ DelCharBack();
+ EnsureCaretVisible();
+ break;
+ case SCI_TAB:
+ Indent(true);
+ break;
+ case SCI_BACKTAB:
+ Indent(false);
+ break;
+ case SCI_NEWLINE:
+ ClearSelection();
+ if (pdoc->eolMode == SC_EOL_CRLF) {
+ pdoc->InsertString(currentPos, "\r\n");
+ SetEmptySelection(currentPos + 2);
+ NotifyChar('\r');
+ NotifyChar('\n');
+ } else if (pdoc->eolMode == SC_EOL_CR) {
+ pdoc->InsertChar(currentPos, '\r');
+ SetEmptySelection(currentPos + 1);
+ NotifyChar('\r');
+ } else if (pdoc->eolMode == SC_EOL_LF) {
+ pdoc->InsertChar(currentPos, '\n');
+ SetEmptySelection(currentPos + 1);
+ NotifyChar('\n');
+ }
+ SetLastXChosen();
+ EnsureCaretVisible();
+ break;
+ case SCI_FORMFEED:
+ AddChar('\f');
+ break;
+ case SCI_VCHOME:
+ MovePositionTo(pdoc->VCHomePosition(currentPos));
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEEXTEND:
+ MovePositionTo(pdoc->VCHomePosition(currentPos), true);
+ SetLastXChosen();
+ break;
+ case SCI_ZOOMIN:
+ if (vs.zoomLevel < 20)
+ vs.zoomLevel++;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_ZOOMOUT:
+ if (vs.zoomLevel > -10)
+ vs.zoomLevel--;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_DELWORDLEFT: {
+ int startWord = pdoc->NextWordStart(currentPos, -1);
+ pdoc->DeleteChars(startWord, currentPos - startWord);
+ MovePositionTo(startWord);
+ }
+ break;
+ case SCI_DELWORDRIGHT: {
+ int endWord = pdoc->NextWordStart(currentPos, 1);
+ pdoc->DeleteChars(currentPos, endWord - currentPos);
+ }
+ break;
+ }
+ return 0;
+}
+
+int Editor::KeyDefault(int, int) {
+ return 0;
+}
+
+int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt) {
+ int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ int msg = kmap.Find(key, modifiers);
+ if (msg)
+ return WndProc(msg, 0, 0);
+ else
+ return KeyDefault(key, modifiers);
+}
+
+void Editor::SetWhitespaceVisible(bool view) {
+ vs.viewWhitespace = view;
+}
+
+bool Editor::GetWhitespaceVisible() {
+ return vs.viewWhitespace;
+}
+
+void Editor::Indent(bool forwards) {
+ //Platform::DebugPrintf("INdent %d\n", forwards);
+ int lineOfAnchor = pdoc->LineFromPosition(anchor);
+ int lineCurrentPos = pdoc->LineFromPosition(currentPos);
+ if (lineOfAnchor == lineCurrentPos) {
+ ClearSelection();
+ pdoc->InsertChar(currentPos, '\t');
+ //pdoc->InsertChar(currentPos++, '\t');
+ SetEmptySelection(currentPos + 1);
+ } else {
+ int anchorPosOnLine = anchor - pdoc->LineStart(lineOfAnchor);
+ int currentPosPosOnLine = currentPos - pdoc->LineStart(lineCurrentPos);
+ // Multiple lines selected so indent / dedent
+ int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
+ int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
+ if (pdoc->LineStart(lineBottomSel) == anchor || pdoc->LineStart(lineBottomSel) == currentPos)
+ lineBottomSel--; // If not selecting any characters on a line, do not indent
+ pdoc->BeginUndoAction();
+ pdoc->Indent(forwards, lineBottomSel, lineTopSel);
+ pdoc->EndUndoAction();
+ if (lineOfAnchor < lineCurrentPos) {
+ if (currentPosPosOnLine == 0)
+ SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+ else
+ SetSelection(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
+ } else {
+ if (anchorPosOnLine == 0)
+ SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+ else
+ SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
+ }
+ }
+}
+
+long Editor::FindText(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ FINDTEXTEX *ft = reinterpret_cast<FINDTEXTEX *>(lParam);
+ int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
+ wParam & FR_MATCHCASE, wParam & FR_WHOLEWORD);
+ if (pos != -1) {
+ if (iMessage == EM_FINDTEXTEX) {
+ ft->chrgText.cpMin = pos;
+ ft->chrgText.cpMax = pos + strlen(ft->lpstrText);
+ }
+ }
+ return pos;
+}
+
+// Relocatable search support : Searches relative to current selection
+// point and sets the selection to the found text range with
+// each search.
+
+// Anchor following searches at current selection start: This allows
+// multiple incremental interactive searches to be macro recorded
+// while still setting the selection to found text so the find/select
+// operation is self-contained.
+void Editor::SearchAnchor() {
+ searchAnchor = SelectionStart();
+}
+
+// Find text from current search anchor: Must call SearchAnchor first.
+// Accepts both SCI_SEARCHNEXT and SCI_SEARCHPREV.
+// wParam contains search modes : ORed FR_MATCHCASE and FR_WHOLEWORD.
+// lParam contains the text to search for.
+long Editor::SearchText(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ const char *txt = reinterpret_cast<char *>(lParam);
+ int pos;
+
+ if (iMessage == SCI_SEARCHNEXT) {
+ pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
+ wParam & FR_MATCHCASE,
+ wParam & FR_WHOLEWORD);
+ } else {
+ pos = pdoc->FindText(searchAnchor, 0, txt,
+ wParam & FR_MATCHCASE,
+ wParam & FR_WHOLEWORD);
+ }
+
+ if (pos != -1) {
+ SetSelection(pos, pos + strlen(txt));
+ }
+
+ return pos;
+}
+
+void Editor::GoToLine(int lineNo) {
+ if (lineNo > pdoc->LinesTotal())
+ lineNo = pdoc->LinesTotal();
+ if (lineNo < 0)
+ lineNo = 0;
+ SetEmptySelection(pdoc->LineStart(lineNo));
+ ShowCaretAtCurrentPosition();
+ EnsureCaretVisible();
+}
+
+static bool Close(Point pt1, Point pt2) {
+ if (abs(pt1.x - pt2.x) > 3)
+ return false;
+ if (abs(pt1.y - pt2.y) > 3)
+ return false;
+ return true;
+}
+
+char *Editor::CopyRange(int start, int end) {
+ char *text = 0;
+ if (start < end) {
+ int len = end - start;
+ text = new char[len + 1];
+ if (text) {
+ for (int i = 0; i < len; i++) {
+ text[i] = pdoc->CharAt(start + i);
+ }
+ text[len] = '\0';
+ }
+ }
+ return text;
+}
+
+int Editor::SelectionRangeLength() {
+ if (selType == selRectangle) {
+ int lineStart = pdoc->LineFromPosition(SelectionStart());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+ int totalSize = 0;
+ for (int line=lineStart; line <= lineEnd; line++) {
+ totalSize += SelectionEnd(line) - SelectionStart(line) + 1;
+ if (pdoc->eolMode == SC_EOL_CRLF)
+ totalSize++;
+ }
+ return totalSize;
+ } else {
+ return SelectionEnd() - SelectionStart();
+ }
+}
+
+char *Editor::CopySelectionRange() {
+ if (selType == selRectangle) {
+ char *text = 0;
+ int lineStart = pdoc->LineFromPosition(SelectionStart());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+ int totalSize = SelectionRangeLength();
+ if (totalSize > 0) {
+ text = new char[totalSize + 1];
+ if (text) {
+ int j = 0;
+ for (int line=lineStart; line <= lineEnd; line++) {
+ for (int i=SelectionStart(line);i<SelectionEnd(line);i++) {
+ text[j++] = pdoc->CharAt(i);
+ }
+ if (pdoc->eolMode != SC_EOL_LF)
+ text[j++] = '\r';
+ if (pdoc->eolMode != SC_EOL_CR)
+ text[j++] = '\n';
+ }
+ text[totalSize] = '\0';
+ }
+ }
+ return text;
+ } else {
+ return CopyRange(SelectionStart(), SelectionEnd());
+ }
+}
+
+void Editor::CopySelectionIntoDrag() {
+ delete []dragChars;
+ dragChars = 0;
+ lenDrag = SelectionRangeLength();
+ dragChars = CopySelectionRange();
+ dragIsRectangle = selType == selRectangle;
+ if (!dragChars) {
+ lenDrag = 0;
+ }
+}
+
+void Editor::SetDragPosition(int newPos) {
+ if (newPos >= 0) {
+ newPos = pdoc->MovePositionOutsideChar(newPos, 1);
+ posDrop = newPos;
+ }
+ if (posDrag != newPos) {
+ caret.on = true;
+ SetTicking(true);
+ InvalidateCaret();
+ posDrag = newPos;
+ InvalidateCaret();
+ }
+}
+
+void Editor::StartDrag() {
+ // Always handled by subclasses
+ //SetMouseCapture(true);
+ //wDraw.SetCursor(Window::cursorArrow);
+}
+
+void Editor::DropAt(int position, const char *value, bool moving, bool rectangular) {
+ //Platform::DebugPrintf("DropAt %d\n", inDragDrop);
+ if (inDragDrop)
+ dropWentOutside = false;
+
+ int positionWasInSelection = PositionInSelection(position);
+
+ if ((!inDragDrop) || !(0 == positionWasInSelection)) {
+
+ int selStart = SelectionStart();
+ int selEnd = SelectionEnd();
+
+ pdoc->BeginUndoAction();
+
+ int positionAfterDeletion = position;
+ if (inDragDrop && moving) {
+ // Remove dragged out text
+ if (rectangular) {
+ int lineStart = pdoc->LineFromPosition(SelectionStart());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+ for (int line=lineStart; line <= lineEnd; line++) {
+ int startPos = SelectionStart(line);
+ int endPos = SelectionEnd(line);
+ if (position >= startPos) {
+ if (position > endPos) {
+ positionAfterDeletion -= endPos - startPos;
+ } else {
+ positionAfterDeletion -= position - startPos;
+ }
+ }
+ }
+ } else {
+ if (position > selStart) {
+ positionAfterDeletion -= selEnd - selStart;
+ }
+ }
+ ClearSelection();
+ }
+ position = positionAfterDeletion;
+
+ if (rectangular) {
+ PasteRectangular(position, value, strlen(value));
+ pdoc->EndUndoAction();
+ // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
+ SetSelection(position, position);
+ } else {
+ position = pdoc->MovePositionOutsideChar(position, currentPos - position);
+ pdoc->InsertString(position, value);
+ pdoc->EndUndoAction();
+ SetSelection(position + strlen(value), position);
+ }
+ } else if (inDragDrop) {
+ SetSelection(position, position);
+ }
+}
+
+static int BeforeInOrAfter(int val, int minim, int maxim) {
+ if (val < minim)
+ return -1;
+ else if (val > maxim)
+ return 1;
+ else
+ return 0;
+}
+
+int Editor::PositionInSelection(int pos) {
+ pos = pdoc->MovePositionOutsideChar(pos, currentPos - pos);
+ if (selType == selRectangle) {
+ if (pos < SelectionStart())
+ return -1;
+ if (pos > SelectionEnd())
+ return 1;
+ int linePos = pdoc->LineFromPosition(pos);
+ return BeforeInOrAfter(pos, SelectionStart(linePos), SelectionEnd(linePos));
+ } else {
+ if (currentPos > anchor) {
+ return BeforeInOrAfter(pos, anchor, currentPos);
+ } else if (currentPos < anchor) {
+ return BeforeInOrAfter(pos, currentPos, anchor);
+ }
+ }
+ return 1;
+}
+
+bool Editor::PointInSelection(Point pt) {
+ // TODO: fix up for rectangular selection
+ int pos = PositionFromLocation(pt);
+ if (0 == PositionInSelection(pos)) {
+ if (pos == SelectionStart()) {
+ // see if just before selection
+ Point locStart = LocationFromPosition(pos);
+ if (pt.x < locStart.x)
+ return false;
+ }
+ if (pos == SelectionEnd()) {
+ // see if just after selection
+ Point locEnd = LocationFromPosition(pos);
+ if (pt.x > locEnd.x)
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Editor::PointInSelMargin(Point pt) {
+ // Really means: "Point in a margin"
+ if (vs.fixedColumnWidth > 0) { // There is a margin
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = vs.fixedColumnWidth - vs.leftMarginWidth;
+ return rcSelMargin.Contains(pt);
+ } else {
+ return false;
+ }
+}
+
+void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+ //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);
+ ptMouseLast = pt;
+ int newPos = PositionFromLocation(pt);
+ newPos = pdoc->MovePositionOutsideChar(newPos, currentPos - newPos);
+ inDragDrop = false;
+
+ bool processed = NotifyMarginClick(pt, shift, ctrl, alt);
+ if (processed)
+ return;
+
+ if (shift) {
+ SetSelection(newPos);
+ }
+ if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
+ //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
+ SetMouseCapture(true);
+ SetEmptySelection(newPos);
+ bool doubleClick = false;
+ // Stop mouse button bounce changing selection type
+ if (curTime != lastClickTime) {
+ if (selectionType == selChar) {
+ selectionType = selWord;
+ doubleClick = true;
+ } else if (selectionType == selWord) {
+ selectionType = selLine;
+ } else {
+ selectionType = selChar;
+ originalAnchorPos = currentPos;
+ }
+ }
+
+ if (selectionType == selWord) {
+ if (currentPos >= originalAnchorPos) { // Moved forward
+ SetSelection(pdoc->ExtendWordSelect(currentPos, 1),
+ pdoc->ExtendWordSelect(originalAnchorPos, -1));
+ } else { // Moved backward
+ SetSelection(pdoc->ExtendWordSelect(currentPos, -1),
+ pdoc->ExtendWordSelect(originalAnchorPos, 1));
+ }
+ } else if (selectionType == selLine) {
+ lineAnchor = LineFromLocation(pt);
+ SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+ //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
+ }
+ else {
+ SetEmptySelection(currentPos);
+ }
+ //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
+ if (doubleClick)
+ NotifyDoubleClick(pt, shift);
+ } else { // Single click
+ if (PointInSelMargin(pt)) {
+ if (ctrl) {
+ SelectAll();
+ lastClickTime = curTime;
+ return;
+ }
+ lineAnchor = LineFromLocation(pt);
+ // While experimenting with folding turn off line selection
+ if (!shift) {
+ // Single click in margin: select whole line
+ SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+ } else {
+ // Single shift+click in margin: select from anchor to beginning of clicked line
+ SetSelection(pdoc->LineStart(lineAnchor), anchor);
+ }
+ SetDragPosition(invalidPosition);
+ SetMouseCapture(true);
+ selectionType = selLine;
+ } else {
+ if (!shift) {
+ inDragDrop = PointInSelection(pt);
+ }
+ if (inDragDrop) {
+ SetMouseCapture(false);
+ SetDragPosition(newPos);
+ CopySelectionIntoDrag();
+ StartDrag();
+ } else {
+ selType = alt ? selRectangle : selStream;
+ xStartSelect = pt.x - vs.fixedColumnWidth + xOffset;
+ xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+ SetDragPosition(invalidPosition);
+ SetMouseCapture(true);
+ if (!shift)
+ SetEmptySelection(newPos);
+ selectionType = selChar;
+ originalAnchorPos = currentPos;
+ }
+ }
+ }
+ lastClickTime = curTime;
+ lastXChosen = pt.x;
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::ButtonMove(Point pt) {
+ //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
+ if (HaveMouseCapture()) {
+ xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+ ptMouseLast = pt;
+ int movePos = PositionFromLocation(pt);
+ movePos = pdoc->MovePositionOutsideChar(movePos, currentPos - movePos);
+ if (posDrag >= 0) {
+ SetDragPosition(movePos);
+ } else {
+ if (selectionType == selChar) {
+ SetSelection(movePos);
+ } else if (selectionType == selWord) {
+ // Continue selecting by word
+ if (currentPos > originalAnchorPos) { // Moved forward
+ SetSelection(pdoc->ExtendWordSelect(movePos, 1),
+ pdoc->ExtendWordSelect(originalAnchorPos, -1));
+ } else { // Moved backward
+ SetSelection(pdoc->ExtendWordSelect(movePos, -1),
+ pdoc->ExtendWordSelect(originalAnchorPos, 1));
+ }
+ } else {
+ // Continue selecting by line
+ int lineMove = LineFromLocation(pt);
+ if (lineAnchor < lineMove) {
+ SetSelection(pdoc->LineStart(lineMove + 1),
+ pdoc->LineStart(lineAnchor));
+ } else {
+ SetSelection(pdoc->LineStart(lineMove),
+ pdoc->LineStart(lineAnchor + 1));
+ }
+ }
+ }
+ EnsureCaretVisible(false);
+ } else {
+ if (vs.fixedColumnWidth > 0) { // There is a margin
+ if (PointInSelMargin(pt)) {
+ wDraw.SetCursor(Window::cursorReverseArrow);
+ return; // No need to test for selection
+ }
+ }
+ // Display regular (drag) cursor over selection
+ if (PointInSelection(pt))
+ wDraw.SetCursor(Window::cursorArrow);
+ else
+ wDraw.SetCursor(Window::cursorText);
+ }
+
+}
+
+void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+ //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
+ if (HaveMouseCapture()) {
+ if (PointInSelMargin(pt)) {
+ wDraw.SetCursor(Window::cursorReverseArrow);
+ } else {
+ wDraw.SetCursor(Window::cursorText);
+ }
+ xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+ ptMouseLast = pt;
+ SetMouseCapture(false);
+ int newPos = PositionFromLocation(pt);
+ newPos = pdoc->MovePositionOutsideChar(newPos, currentPos - newPos);
+ if (inDragDrop) {
+ int selStart = SelectionStart();
+ int selEnd = SelectionEnd();
+ if (selStart < selEnd) {
+ if (dragChars && lenDrag) {
+ if (ctrl) {
+ pdoc->InsertString(newPos, dragChars, lenDrag);
+ SetSelection(newPos, newPos + lenDrag);
+ } else if (newPos < selStart) {
+ pdoc->DeleteChars(selStart, lenDrag);
+ pdoc->InsertString(newPos, dragChars, lenDrag);
+ SetSelection(newPos, newPos + lenDrag);
+ } else if (newPos > selEnd) {
+ pdoc->DeleteChars(selStart, lenDrag);
+ newPos -= lenDrag;
+ pdoc->InsertString(newPos, dragChars, lenDrag);
+ SetSelection(newPos, newPos + lenDrag);
+ } else {
+ SetEmptySelection(newPos);
+ }
+ delete []dragChars;
+ dragChars = 0;
+ lenDrag = 0;
+ }
+ selectionType = selChar;
+ }
+ } else {
+ if (selectionType == selChar) {
+ SetSelection(newPos);
+ }
+ }
+ lastClickTime = curTime;
+ lastClick = pt;
+ lastXChosen = pt.x;
+ inDragDrop = false;
+ EnsureCaretVisible(false);
+ }
+}
+
+// Called frequently to perform background UI including
+// caret blinking and automatic scrolling.
+void Editor::Tick() {
+ if (HaveMouseCapture()) {
+ // Auto scroll
+ ButtonMove(ptMouseLast);
+ }
+ if (caret.period > 0) {
+ timer.ticksToWait -= timer.tickSize;
+ if (timer.ticksToWait <= 0) {
+ caret.on = !caret.on;
+ timer.ticksToWait = caret.period;
+ InvalidateCaret();
+ }
+ }
+}
+
+static bool IsIn(int a, int minimum, int maximum) {
+ return (a >= minimum) && (a <= maximum);
+}
+
+static bool IsOverlap(int mina, int maxa, int minb, int maxb) {
+ return
+ IsIn(mina, minb, maxb) ||
+ IsIn(maxa, minb, maxb) ||
+ IsIn(minb, mina, maxa) ||
+ IsIn(maxb, mina, maxa);
+}
+
+void Editor::CheckForChangeOutsidePaint(Range r) {
+ if (paintState == painting && !paintingAllText) {
+ //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
+ if (!r.Valid())
+ return;
+
+ PRectangle rcText = GetTextRectangle();
+ // Determine number of lines displayed including a possible partially displayed last line
+ int linesDisplayed = (rcText.bottom - rcText.top - 1) / vs.lineHeight + 1;
+ int bottomLine = topLine + linesDisplayed - 1;
+
+ int lineRangeStart = cs.DisplayFromDoc(pdoc->LineFromPosition(r.start));
+ int lineRangeEnd = cs.DisplayFromDoc(pdoc->LineFromPosition(r.end));
+ if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) {
+ //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
+ // lineRangeStart, lineRangeEnd, topLine, bottomLine);
+ return;
+ }
+
+ // Assert rcPaint contained within or equal to rcText
+ if (rcPaint.top > rcText.top) {
+ // does range intersect rcText.top .. rcPaint.top
+ int paintTopLine = ((rcPaint.top - rcText.top-1) / vs.lineHeight) + topLine;
+ // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
+ if (IsOverlap(topLine, paintTopLine, lineRangeStart, lineRangeEnd)) {
+ //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n",
+ // lineRangeStart, lineRangeEnd, topLine, paintTopLine);
+ paintState = paintAbandoned;
+ return;
+ }
+ }
+ if (rcPaint.bottom < rcText.bottom) {
+ // does range intersect rcPaint.bottom .. rcText.bottom
+ int paintBottomLine = ((rcPaint.bottom - rcText.top-1) / vs.lineHeight + 1) + topLine;
+ // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
+ if (IsOverlap(paintBottomLine, bottomLine, lineRangeStart, lineRangeEnd)) {
+ //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n",
+ // lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
+ paintState = paintAbandoned;
+ return;
+ }
+ }
+ }
+}
+
+char BraceOpposite(char ch) {
+ switch (ch) {
+ case '(': return ')';
+ case ')': return '(';
+ case '[': return ']';
+ case ']': return '[';
+ case '{': return '}';
+ case '}': return '{';
+ case '<': return '>';
+ case '>': return '<';
+ default: return '\0';
+ }
+}
+
+// TODO: should be able to extend styled region to find matching brace
+// TODO: may need to make DBCS safe
+// so should be moved into Document
+int Editor::BraceMatch(int position, int maxReStyle) {
+ char chBrace = pdoc->CharAt(position);
+ char chSeek = BraceOpposite(chBrace);
+ if (!chSeek)
+ return - 1;
+ char styBrace = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
+ int direction = -1;
+ if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
+ direction = 1;
+ int depth = 1;
+ position = position + direction;
+ while ((position >= 0) && (position < pdoc->Length())) {
+ char chAtPos = pdoc->CharAt(position);
+ char styAtPos = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
+ if ((position > pdoc->GetEndStyled()) || (styAtPos == styBrace)) {
+ if (chAtPos == chBrace)
+ depth++;
+ if (chAtPos == chSeek)
+ depth--;
+ if (depth == 0)
+ return position;
+ }
+ position = position + direction;
+ }
+ return - 1;
+}
+
+void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
+ if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
+ if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
+ CheckForChangeOutsidePaint(Range(braces[0]));
+ CheckForChangeOutsidePaint(Range(pos0));
+ braces[0] = pos0;
+ }
+ if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) {
+ CheckForChangeOutsidePaint(Range(braces[1]));
+ CheckForChangeOutsidePaint(Range(pos1));
+ braces[1] = pos1;
+ }
+ bracesMatchStyle = matchStyle;
+ if (paintState == notPainting) {
+ Redraw();
+ }
+ }
+}
+
+void Editor::SetDocPointer(Document *document) {
+ //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
+ pdoc->RemoveWatcher(this, 0);
+ pdoc->Release();
+ if (document == NULL) {
+ pdoc = new Document();
+ } else {
+ pdoc = document;
+ }
+ pdoc->AddRef();
+ // Reset the contraction state to fully shown.
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal());
+
+ pdoc->AddWatcher(this, 0);
+ Redraw();
+ SetScrollBars();
+}
+
+// Recursively expand a fold, making lines visible except where they have an unexpanded parent
+void Editor::Expand(int &line, bool doExpand) {
+ int lineMaxSubord = pdoc->GetLastChild(line);
+ line++;
+ while (line <= lineMaxSubord) {
+ if (doExpand)
+ cs.SetVisible(line, line, true);
+ int level = pdoc->GetLevel(line);
+ if (level & SC_FOLDLEVELHEADERFLAG) {
+ if (doExpand && cs.GetExpanded(line)) {
+ Expand(line, true);
+ } else {
+ Expand(line, false);
+ }
+ } else {
+ line++;
+ }
+ }
+}
+
+void Editor::ToggleContraction(int line) {
+ if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+ if (cs.GetExpanded(line)) {
+ int lineMaxSubord = pdoc->GetLastChild(line);
+ cs.SetExpanded(line, 0);
+ if (lineMaxSubord > line) {
+ cs.SetVisible(line+1, lineMaxSubord, false);
+ SetScrollBars();
+ Redraw();
+ }
+ } else {
+ cs.SetExpanded(line, 1);
+ Expand(line, true);
+ SetScrollBars();
+ Redraw();
+ }
+ }
+}
+
+// Recurse up from this line to find any folds that prevent this line from being visible
+// and unfold them all.
+void Editor::EnsureLineVisible(int line) {
+ if (!cs.GetVisible(line)) {
+ int lineParent = pdoc->GetFoldParent(line);
+ if (lineParent >= 0) {
+ if (line != lineParent)
+ EnsureLineVisible(lineParent);
+ if (!cs.GetExpanded(lineParent)) {
+ cs.SetExpanded(lineParent, 1);
+ Expand(lineParent, true);
+ }
+ }
+ SetScrollBars();
+ Redraw();
+ }
+}
+
+LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
+
+ // Optional macro recording hook
+#ifdef MACRO_SUPPORT
+ if (recordingMacro)
+ NotifyMacroRecord(iMessage, wParam, lParam);
+#endif
+
+ switch (iMessage) {
+
+ case WM_GETTEXT:
+ {
+ if (lParam == 0)
+ return 0;
+ char *ptr = reinterpret_cast<char *>(lParam);
+ unsigned int iChar = 0;
+ for (; iChar < wParam-1; iChar++)
+ ptr[iChar] = pdoc->CharAt(iChar);
+ ptr[iChar] = '\0';
+ return iChar;
+ }
+
+ case WM_SETTEXT:
+ {
+ if (lParam == 0)
+ return FALSE;
+ pdoc->DeleteChars(0, pdoc->Length());
+ SetEmptySelection(0);
+ pdoc->InsertString(0, reinterpret_cast<char *>(lParam));
+ return TRUE;
+ }
+
+ case WM_GETTEXTLENGTH:
+ return pdoc->Length();
+
+ case WM_NOTIFY:
+ //Platform::DebugPrintf("S notify %d %d\n", wParam, lParam);
+ break;
+
+ case WM_CUT:
+ Cut();
+ SetLastXChosen();
+ break;
+
+ case WM_COPY:
+ Copy();
+ break;
+
+ case WM_PASTE:
+ Paste();
+ SetLastXChosen();
+ break;
+
+ case WM_CLEAR:
+ Clear();
+ SetLastXChosen();
+ break;
+
+ case WM_UNDO:
+ Undo();
+ SetLastXChosen();
+ break;
+
+ // Edit control mesages
+
+ // Not supported (no-ops):
+ // EM_GETWORDBREAKPROC
+ // EM_GETWORDBREAKPROCEX
+ // EM_SETWORDBREAKPROC
+ // EM_SETWORDBREAKPROCEX
+ // EM_GETWORDWRAPMODE
+ // EM_SETWORDWRAPMODE
+ // EM_LIMITTEXT
+ // EM_EXLIMITTEXT
+ // EM_SETRECT
+ // EM_SETRECTNP
+ // EM_FMTLINES
+ // EM_GETHANDLE
+ // EM_SETHANDLE
+ // EM_GETPASSWORDCHAR
+ // EM_SETPASSWORDCHAR
+ // EM_SETTABSTOPS
+ // EM_FINDWORDBREAK
+ // EM_GETCHARFORMAT
+ // EM_SETCHARFORMAT
+ // EM_GETOLEINTERFACE
+ // EM_SETOLEINTERFACE
+ // EM_SETOLECALLBACK
+ // EM_GETPARAFORMAT
+ // EM_SETPARAFORMAT
+ // EM_PASTESPECIAL
+ // EM_REQUESTRESIZE
+ // EM_GETBKGNDCOLOR
+ // EM_SETBKGNDCOLOR
+ // EM_STREAMIN
+ // EM_STREAMOUT
+ // EM_GETIMECOLOR
+ // EM_SETIMECOLOR
+ // EM_GETIMEOPTIONS
+ // EM_SETIMEOPTIONS
+ // EM_GETOPTIONS
+ // EM_SETOPTIONS
+ // EM_GETPUNCTUATION
+ // EM_SETPUNCTUATION
+ // EM_GETTHUMB
+
+ // Not supported but should be:
+ // EM_GETEVENTMASK
+ // EM_SETEVENTMASK
+ // For printing:
+ // EM_DISPLAYBAND
+ // EM_SETTARGETDEVICE
+
+ case EM_CANUNDO:
+ return pdoc->CanUndo() ? TRUE : FALSE;
+
+ case EM_UNDO:
+ Undo();
+ break;
+
+ case EM_EMPTYUNDOBUFFER:
+ pdoc->DeleteUndoHistory();
+ return 0;
+
+ case EM_GETFIRSTVISIBLELINE:
+ return topLine;
+
+ case EM_GETLINE: {
+ if (lParam == 0)
+ return 0;
+ int lineStart = pdoc->LineStart(wParam);
+ int lineEnd = pdoc->LineStart(wParam + 1);
+ char *ptr = reinterpret_cast<char *>(lParam);
+ WORD *pBufSize = reinterpret_cast<WORD *>(lParam);
+ if (*pBufSize < lineEnd - lineStart) {
+ ptr[0] = '\0'; // If no characters copied have to put a NUL into buffer
+ return 0;
+ }
+ int iPlace = 0;
+ for (int iChar = lineStart; iChar < lineEnd; iChar++)
+ ptr[iPlace++] = pdoc->CharAt(iChar);
+ return iPlace;
+ }
+
+ case EM_GETLINECOUNT:
+ if (pdoc->LinesTotal() == 0)
+ return 1;
+ else
+ return pdoc->LinesTotal();
+
+ case EM_GETMODIFY:
+ return !pdoc->IsSavePoint();
+
+ case EM_SETMODIFY:
+ // Not really supported now that there is the save point stuff
+ //pdoc->isModified = wParam;
+ //return pdoc->isModified;
+ return false;
+
+ case EM_GETRECT:
+ if (lParam == 0)
+ return 0;
+ *(reinterpret_cast<PRectangle *>(lParam)) = GetClientRectangle();
+ break;
+
+ case EM_GETSEL:
+ if (wParam)
+ *reinterpret_cast<int *>(wParam) = SelectionStart();
+ if (lParam)
+ *reinterpret_cast<int *>(lParam) = SelectionEnd();
+ return MAKELONG(SelectionStart(), SelectionEnd());
+
+ case EM_EXGETSEL: {
+ if (lParam == 0)
+ return 0;
+ CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
+ pCR->cpMin = SelectionStart();
+ pCR->cpMax = SelectionEnd();
+ }
+ break;
+
+ case EM_SETSEL: {
+ int nStart = static_cast<int>(wParam);
+ int nEnd = static_cast<int>(lParam);
+ if (nEnd < 0)
+ nEnd = pdoc->Length();
+ if (nStart < 0)
+ nStart = nEnd; // Remove selection
+ SetSelection(nEnd, nStart);
+ EnsureCaretVisible();
+ }
+ break;
+
+ case EM_EXSETSEL: {
+ if (lParam == 0)
+ return 0;
+ CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
+ if (pCR->cpMax == -1) {
+ SetSelection(pCR->cpMin, pdoc->Length());
+ } else {
+ SetSelection(pCR->cpMin, pCR->cpMax);
+ }
+ EnsureCaretVisible();
+ return pdoc->LineFromPosition(SelectionStart());
+ }
+
+ case EM_GETSELTEXT: {
+ if (lParam == 0)
+ return 0;
+ char *ptr = reinterpret_cast<char *>(lParam);
+ int selSize = SelectionRangeLength();
+ char *text = CopySelectionRange();
+ int iChar = 0;
+ if (text) {
+ for (; iChar < selSize; iChar++)
+ ptr[iChar] = text[iChar];
+ ptr[iChar] = '\0';
+ delete []text;
+ }
+ return iChar;
+ }
+
+ case EM_GETWORDBREAKPROC:
+ return 0;
+
+ case EM_SETWORDBREAKPROC:
+ break;
+
+ case EM_LIMITTEXT:
+ // wParam holds the number of characters control should be limited to
+ break;
+
+ case EM_GETLIMITTEXT:
+ return 0xffffffff;
+
+ case EM_GETOLEINTERFACE:
+ return 0;
+
+ case EM_LINEFROMCHAR:
+ if (static_cast<int>(wParam) < 0)
+ wParam = SelectionStart();
+ return pdoc->LineFromPosition(wParam);
+
+ case EM_EXLINEFROMCHAR:
+ if (static_cast<int>(lParam) < 0)
+ lParam = SelectionStart(); // Not specified, but probably OK
+ return pdoc->LineFromPosition(lParam);
+
+ case EM_LINEINDEX:
+ if (static_cast<int>(wParam) < 0)
+ wParam = pdoc->LineFromPosition(SelectionStart());
+ if (wParam == 0)
+ return 0; // Even if there is no text, there is a first line that starts at 0
+ if (static_cast<int>(wParam) > pdoc->LinesTotal())
+ return - 1;
+ //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
+ // return -1;
+ return pdoc->LineStart(wParam);
+
+ case EM_LINELENGTH:
+ {
+ if (static_cast<int>(wParam) < 0) // Who use this anyway?
+ return 0; // Should be... Too complex to describe here, see MS specs!
+ if (static_cast<int>(wParam) > pdoc->Length()) // Useful test, anyway...
+ return 0;
+ int line = pdoc->LineFromPosition(wParam);
+ int charsOnLine = 0;
+ for (int pos = pdoc->LineStart(line); pos < pdoc->LineStart(line + 1); pos++) {
+ if ((pdoc->CharAt(pos) != '\r') && (pdoc->CharAt(pos) != '\n'))
+ charsOnLine++;
+ }
+ return charsOnLine;
+ }
+
+ // Replacement of the old Scintilla interpretation of EM_LINELENGTH
+ case SCI_LINELENGTH:
+ if ((static_cast<int>(wParam) < 0) ||
+ (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
+ return 0;
+ return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);
+
+ case EM_REPLACESEL: {
+ if (lParam == 0)
+ return 0;
+ pdoc->BeginUndoAction();
+ ClearSelection();
+ char *replacement = reinterpret_cast<char *>(lParam);
+ pdoc->InsertString(currentPos, replacement);
+ pdoc->EndUndoAction();
+ SetEmptySelection(currentPos + strlen(replacement));
+ EnsureCaretVisible();
+ }
+ break;
+
+ case EM_LINESCROLL:
+ ScrollTo(topLine + lParam);
+ HorizontalScrollTo(xOffset + wParam * vs.spaceWidth);
+ return TRUE;
+
+ case EM_SCROLLCARET:
+ EnsureCaretVisible();
+ break;
+
+ case EM_SETREADONLY:
+ pdoc->SetReadOnly(wParam);
+ return TRUE;
+
+ case EM_SETRECT:
+ break;
+
+ case EM_CANPASTE:
+ return 1;
+
+ case EM_CHARFROMPOS: {
+ if (lParam == 0)
+ return 0;
+ Point *ppt = reinterpret_cast<Point *>(lParam);
+ int pos = PositionFromLocation(*ppt);
+ int line = pdoc->LineFromPosition(pos);
+ return MAKELONG(pos, line);
+ }
+
+ case EM_POSFROMCHAR: {
+ // The MS specs for this have changed 3 times: using the RichEdit 3 version
+ if (wParam == 0)
+ return 0;
+ Point *ppt = reinterpret_cast<Point *>(wParam);
+ if (lParam < 0) {
+ *ppt = Point(0, 0);
+ } else {
+ *ppt = LocationFromPosition(lParam);
+ }
+ return 0;
+ }
+
+ case EM_FINDTEXT:
+ return FindText(iMessage, wParam, lParam);
+
+ case EM_FINDTEXTEX:
+ return FindText(iMessage, wParam, lParam);
+
+ case EM_GETTEXTRANGE: {
+ if (lParam == 0)
+ return 0;
+ TEXTRANGE *tr = reinterpret_cast<TEXTRANGE *>(lParam);
+ int cpMax = tr->chrg.cpMax;
+ if (cpMax == -1)
+ cpMax = pdoc->Length();
+ int len = cpMax - tr->chrg.cpMin; // No -1 as cpMin and cpMax are referring to inter character positions
+ pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
+ // Spec says copied text is terminated with a NUL
+ tr->lpstrText[len] = '\0';
+ return len; // Not including NUL
+ }
+
+ case EM_SELECTIONTYPE:
+ if (currentPos == anchor)
+ return SEL_EMPTY;
+ else
+ return SEL_TEXT;
+
+ case EM_HIDESELECTION:
+ hideSelection = wParam;
+ Redraw();
+ break;
+
+ case EM_FORMATRANGE:
+ return FormatRange(wParam, reinterpret_cast<FORMATRANGE *>(lParam));
+
+ case EM_GETMARGINS:
+ return MAKELONG(vs.leftMarginWidth, vs.rightMarginWidth);
+
+ case EM_SETMARGINS:
+ if (wParam & EC_LEFTMARGIN) {
+ vs.leftMarginWidth = LOWORD(lParam);
+ }
+ if (wParam & EC_RIGHTMARGIN) {
+ vs.rightMarginWidth = HIWORD(lParam);
+ }
+ if (wParam == EC_USEFONTINFO) {
+ vs.leftMarginWidth = vs.aveCharWidth / 2;
+ vs.rightMarginWidth = vs.aveCharWidth / 2;
+ }
+ InvalidateStyleRedraw();
+ break;
+
+ // Control specific mesages
+
+ case SCI_ADDTEXT: {
+ if (lParam == 0)
+ return 0;
+ pdoc->InsertString(CurrentPosition(), reinterpret_cast<char *>(lParam), wParam);
+ SetEmptySelection(currentPos + wParam);
+ return 0;
+ }
+
+ case SCI_ADDSTYLEDTEXT: {
+ if (lParam == 0)
+ return 0;
+ pdoc->InsertStyledString(CurrentPosition() * 2, reinterpret_cast<char *>(lParam), wParam);
+ SetEmptySelection(currentPos + wParam / 2);
+ return 0;
+ }
+
+ case SCI_INSERTTEXT: {
+ if (lParam == 0)
+ return 0;
+ int insertPos = wParam;
+ if (static_cast<short>(wParam) == -1)
+ insertPos = CurrentPosition();
+ int newCurrent = CurrentPosition();
+ int newAnchor = anchor;
+ char *sz = reinterpret_cast<char *>(lParam);
+ pdoc->InsertString(insertPos, sz);
+ if (newCurrent > insertPos)
+ newCurrent += strlen(sz);
+ if (newAnchor > insertPos)
+ newAnchor += strlen(sz);
+ SetEmptySelection(newCurrent);
+ return 0;
+ }
+
+ case SCI_CLEARALL:
+ ClearAll();
+ return 0;
+
+ case SCI_SETUNDOCOLLECTION:
+ pdoc->SetUndoCollection(static_cast<enum undoCollectionType>(wParam));
+ return 0;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+ case SCI_APPENDUNDOSTARTACTION:
+ pdoc->AppendUndoStartAction();
+ return 0;
+#endif
+
+ case SCI_BEGINUNDOACTION:
+ pdoc->BeginUndoAction();
+ return 0;
+
+ case SCI_ENDUNDOACTION:
+ pdoc->EndUndoAction();
+ return 0;
+
+ case SCI_GETCARETPERIOD:
+ return caret.period;
+
+ case SCI_SETCARETPERIOD:
+ caret.period = wParam;
+ break;
+
+ case SCI_SETWORDCHARS: {
+ if (lParam == 0)
+ return 0;
+ pdoc->SetWordChars(reinterpret_cast<unsigned char *>(lParam));
+ }
+ break;
+
+ case SCI_GETLENGTH:
+ return pdoc->Length();
+
+ case SCI_GETCHARAT:
+ return pdoc->CharAt(wParam);
+
+ case SCI_GETCURRENTPOS:
+ return currentPos;
+
+ case SCI_GETANCHOR:
+ return anchor;
+
+ case SCI_GETSTYLEAT:
+ if (static_cast<short>(wParam) >= pdoc->Length())
+ return 0;
+ else
+ return pdoc->StyleAt(wParam);
+
+ case SCI_REDO:
+ Redo();
+ break;
+
+ case SCI_SELECTALL:
+ SelectAll();
+ break;
+
+ case SCI_SETSAVEPOINT:
+ pdoc->SetSavePoint();
+ NotifySavePoint(true);
+ break;
+
+ case SCI_GETSTYLEDTEXT: {
+ if (lParam == 0)
+ return 0;
+ TEXTRANGE *tr = reinterpret_cast<TEXTRANGE *>(lParam);
+ int iPlace = 0;
+ for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
+ tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
+ tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
+ }
+ tr->lpstrText[iPlace] = '\0';
+ tr->lpstrText[iPlace + 1] = '\0';
+ return iPlace;
+ }
+
+ case SCI_CANREDO:
+ return pdoc->CanRedo() ? TRUE : FALSE;
+
+ case SCI_MARKERLINEFROMHANDLE:
+ return pdoc->LineFromHandle(wParam);
+
+ case SCI_MARKERDELETEHANDLE:
+ pdoc->DeleteMarkFromHandle(wParam);
+ break;
+
+ case SCI_GETVIEWWS:
+ return vs.viewWhitespace;
+
+ case SCI_SETVIEWWS:
+ vs.viewWhitespace = wParam;
+ Redraw();
+ break;
+
+ case SCI_GOTOLINE:
+ GoToLine(wParam);
+ break;
+
+ case SCI_GOTOPOS:
+ SetEmptySelection(wParam);
+ EnsureCaretVisible();
+ Redraw();
+ break;
+
+ case SCI_SETANCHOR:
+ SetSelection(currentPos, wParam);
+ break;
+
+ case SCI_GETCURLINE: {
+ if (lParam == 0)
+ return 0;
+ int lineCurrentPos = pdoc->LineFromPosition(currentPos);
+ int lineStart = pdoc->LineStart(lineCurrentPos);
+ unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
+ char *ptr = reinterpret_cast<char *>(lParam);
+ unsigned int iPlace = 0;
+ for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam; iChar++)
+ ptr[iPlace++] = pdoc->CharAt(iChar);
+ ptr[iPlace] = '\0';
+ return currentPos - lineStart;
+ }
+
+ case SCI_GETENDSTYLED:
+ return pdoc->GetEndStyled();
+
+ case SCI_GETEOLMODE:
+ return pdoc->eolMode;
+
+ case SCI_SETEOLMODE:
+ pdoc->eolMode = wParam;
+ break;
+
+ case SCI_STARTSTYLING:
+ pdoc->StartStyling(wParam, lParam);
+ break;
+
+ case SCI_SETSTYLING:
+ pdoc->SetStyleFor(wParam, lParam);
+ break;
+
+ case SCI_SETSTYLINGEX: // Specify a complete styling buffer
+ if (lParam == 0)
+ return 0;
+ pdoc->SetStyles(wParam, reinterpret_cast<char *>(lParam));
+ break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+ case SCI_SETMARGINWIDTH:
+ if (wParam < 100) {
+ vs.ms[1].width = wParam;
+ }
+ InvalidateStyleRedraw();
+ break;
+#endif
+
+ case SCI_SETBUFFEREDDRAW:
+ bufferedDraw = wParam;
+ break;
+
+ case SCI_SETTABWIDTH:
+ if (wParam > 0)
+ pdoc->tabInChars = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETCODEPAGE:
+ pdoc->dbcsCodePage = wParam;
+ break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+ case SCI_SETLINENUMBERWIDTH:
+ if (wParam < 200) {
+ vs.ms[0].width = wParam;
+ }
+ InvalidateStyleRedraw();
+ break;
+#endif
+
+ case SCI_SETUSEPALETTE:
+ palette.allowRealization = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ // Marker definition and setting
+ case SCI_MARKERDEFINE:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].markType = lParam;
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETFORE:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].fore.desired = Colour(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETBACK:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].back.desired = Colour(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERADD: {
+ int markerID = pdoc->AddMark(wParam, lParam);
+ RedrawSelMargin();
+ return markerID;
+ }
+
+ case SCI_MARKERDELETE:
+ pdoc->DeleteMark(wParam, lParam);
+ RedrawSelMargin();
+ break;
+
+ case SCI_MARKERDELETEALL:
+ pdoc->DeleteAllMarks(static_cast<int>(wParam));
+ RedrawSelMargin();
+ break;
+
+ case SCI_MARKERGET:
+ return pdoc->GetMark(wParam);
+
+ case SCI_MARKERNEXT: {
+ int lt = pdoc->LinesTotal();
+ for (int iLine = wParam; iLine < lt; iLine++) {
+ if ((pdoc->GetMark(iLine) & lParam) != 0)
+ return iLine;
+ }
+ }
+ return -1;
+
+ case SCI_MARKERPREVIOUS: {
+ for (int iLine = wParam; iLine >= 0; iLine--) {
+ if ((pdoc->GetMark(iLine) & lParam) != 0)
+ return iLine;
+ }
+ }
+ return -1;
+
+ case SCI_SETMARGINTYPEN:
+ if (wParam >= 0 && wParam < ViewStyle::margins) {
+ vs.ms[wParam].symbol = (lParam == SC_MARGIN_SYMBOL);
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINTYPEN:
+ if (wParam >= 0 && wParam < ViewStyle::margins)
+ return vs.ms[wParam].symbol ? SC_MARGIN_SYMBOL : SC_MARGIN_NUMBER;
+ else
+ return 0;
+
+ case SCI_SETMARGINWIDTHN:
+ if (wParam >= 0 && wParam < ViewStyle::margins) {
+ vs.ms[wParam].width = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINWIDTHN:
+ if (wParam >= 0 && wParam < ViewStyle::margins)
+ return vs.ms[wParam].width;
+ else
+ return 0;
+
+ case SCI_SETMARGINMASKN:
+ if (wParam >= 0 && wParam < ViewStyle::margins) {
+ vs.ms[wParam].mask = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINMASKN:
+ if (wParam >= 0 && wParam < ViewStyle::margins)
+ return vs.ms[wParam].mask;
+ else
+ return 0;
+
+ case SCI_SETMARGINSENSITIVEN:
+ if (wParam >= 0 && wParam < ViewStyle::margins) {
+ vs.ms[wParam].sensitive = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINSENSITIVEN:
+ if (wParam >= 0 && wParam < ViewStyle::margins)
+ return vs.ms[wParam].sensitive ? 1 : 0;
+ else
+ return 0;
+
+ case SCI_STYLECLEARALL:
+ vs.ClearStyles();
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_STYLESETFORE:
+ if (wParam <= STYLE_MAX) {
+ vs.styles[wParam].fore.desired = Colour(lParam);
+ InvalidateStyleRedraw();
+ }
+ break;
+ case SCI_STYLESETBACK:
+ if (wParam <= STYLE_MAX) {
+ vs.styles[wParam].back.desired = Colour(lParam);
+ InvalidateStyleRedraw();
+ }
+ break;
+ case SCI_STYLESETBOLD:
+ if (wParam <= STYLE_MAX) {
+ vs.styles[wParam].bold = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+ case SCI_STYLESETITALIC:
+ if (wParam <= STYLE_MAX) {
+ vs.styles[wParam].italic = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+ case SCI_STYLESETEOLFILLED:
+ if (wParam <= STYLE_MAX) {
+ vs.styles[wParam].eolFilled = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+ case SCI_STYLESETSIZE:
+ if (wParam <= STYLE_MAX) {
+ vs.styles[wParam].size = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+ case SCI_STYLESETFONT:
+ if (lParam == 0)
+ return 0;
+ if (wParam <= STYLE_MAX) {
+ vs.SetStyleFontName(wParam, reinterpret_cast<const char *>(lParam));
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_STYLERESETDEFAULT:
+ vs.ResetDefaultStyle();
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSTYLEBITS:
+ pdoc->SetStylingBits(wParam);
+ break;
+
+ case SCI_GETSTYLEBITS:
+ return pdoc->stylingBits;
+
+ case SCI_SETLINESTATE:
+ return pdoc->SetLineState(wParam, lParam);
+
+ case SCI_GETLINESTATE:
+ return pdoc->GetLineState(wParam);
+
+ case SCI_GETMAXLINESTATE:
+ return pdoc->GetMaxLineState();
+
+ // Folding messages
+
+ case SCI_VISIBLEFROMDOCLINE:
+ return cs.DisplayFromDoc(wParam);
+
+ case SCI_DOCLINEFROMVISIBLE:
+ return cs.DocFromDisplay(wParam);
+
+ case SCI_SETFOLDLEVEL: {
+ int prev = pdoc->SetLevel(wParam, lParam);
+ if (prev != lParam)
+ RedrawSelMargin();
+ return prev;
+ }
+
+ case SCI_GETFOLDLEVEL:
+ return pdoc->GetLevel(wParam);
+
+ case SCI_GETLASTCHILD:
+ return pdoc->GetLastChild(wParam, lParam);
+
+ case SCI_GETFOLDPARENT:
+ return pdoc->GetFoldParent(wParam);
+
+ case SCI_SHOWLINES:
+ cs.SetVisible(wParam, lParam, true);
+ SetScrollBars();
+ Redraw();
+ break;
+
+ case SCI_HIDELINES:
+ cs.SetVisible(wParam, lParam, false);
+ SetScrollBars();
+ Redraw();
+ break;
+
+ case SCI_GETLINEVISIBLE:
+ return cs.GetVisible(wParam);
+
+ case SCI_SETFOLDEXPANDED:
+ if (cs.SetExpanded(wParam, lParam)) {
+ RedrawSelMargin();
+ }
+ break;
+
+ case SCI_GETFOLDEXPANDED:
+ return cs.GetExpanded(wParam);
+
+ case SCI_SETFOLDFLAGS:
+ foldFlags = wParam;
+ Redraw();
+ break;
+
+ case SCI_TOGGLEFOLD:
+ ToggleContraction(wParam);
+ break;
+
+ case SCI_ENSUREVISIBLE:
+ EnsureLineVisible(wParam);
+ break;
+
+ case SCI_SEARCHANCHOR:
+ SearchAnchor();
+ break;
+
+ case SCI_SEARCHNEXT:
+ case SCI_SEARCHPREV:
+ return SearchText(iMessage, wParam, lParam);
+ break;
+
+ case SCI_SETCARETPOLICY:
+ caretPolicy = wParam;
+ caretSlop = lParam;
+ break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+ case SCI_SETFORE:
+ vs.styles[STYLE_DEFAULT].fore.desired = Colour(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETBACK:
+ vs.styles[STYLE_DEFAULT].back.desired = Colour(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETBOLD:
+ vs.styles[STYLE_DEFAULT].bold = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETITALIC:
+ vs.styles[STYLE_DEFAULT].italic = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSIZE:
+ vs.styles[STYLE_DEFAULT].size = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETFONT:
+ if (wParam == 0)
+ return 0;
+ strcpy(vs.styles[STYLE_DEFAULT].fontName, reinterpret_cast<char *>(wParam));
+ InvalidateStyleRedraw();
+ break;
+#endif
+
+ case SCI_SETSELFORE:
+ vs.selforeset = wParam;
+ vs.selforeground.desired = Colour(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSELBACK:
+ vs.selbackset = wParam;
+ vs.selbackground.desired = Colour(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETCARETFORE:
+ vs.caretcolour.desired = Colour(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_ASSIGNCMDKEY:
+ kmap.AssignCmdKey(LOWORD(wParam), HIWORD(wParam), lParam);
+ break;
+
+ case SCI_CLEARCMDKEY:
+ kmap.AssignCmdKey(LOWORD(wParam), HIWORD(wParam), WM_NULL);
+ break;
+
+ case SCI_CLEARALLCMDKEYS:
+ kmap.Clear();
+ break;
+
+ case SCI_INDICSETSTYLE:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].style = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETSTYLE:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;
+
+ case SCI_INDICSETFORE:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].fore.desired = Colour(lParam);
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETFORE:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.desired.AsLong() : 0;
+
+ case SCI_LINEDOWN:
+ case SCI_LINEDOWNEXTEND:
+ case SCI_LINEUP:
+ case SCI_LINEUPEXTEND:
+ case SCI_CHARLEFT:
+ case SCI_CHARLEFTEXTEND:
+ case SCI_CHARRIGHT:
+ case SCI_CHARRIGHTEXTEND:
+ case SCI_WORDLEFT:
+ case SCI_WORDLEFTEXTEND:
+ case SCI_WORDRIGHT:
+ case SCI_WORDRIGHTEXTEND:
+ case SCI_HOME:
+ case SCI_HOMEEXTEND:
+ case SCI_LINEEND:
+ case SCI_LINEENDEXTEND:
+ case SCI_DOCUMENTSTART:
+ case SCI_DOCUMENTSTARTEXTEND:
+ case SCI_DOCUMENTEND:
+ case SCI_DOCUMENTENDEXTEND:
+ case SCI_PAGEUP:
+ case SCI_PAGEUPEXTEND:
+ case SCI_PAGEDOWN:
+ case SCI_PAGEDOWNEXTEND:
+ case SCI_EDITTOGGLEOVERTYPE:
+ case SCI_CANCEL:
+ case SCI_DELETEBACK:
+ case SCI_TAB:
+ case SCI_BACKTAB:
+ case SCI_NEWLINE:
+ case SCI_FORMFEED:
+ case SCI_VCHOME:
+ case SCI_VCHOMEEXTEND:
+ case SCI_ZOOMIN:
+ case SCI_ZOOMOUT:
+ case SCI_DELWORDLEFT:
+ case SCI_DELWORDRIGHT:
+ return KeyCommand(iMessage);
+
+ case SCI_BRACEHIGHLIGHT:
+ SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
+ break;
+
+ case SCI_BRACEBADLIGHT:
+ SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
+ break;
+
+ case SCI_BRACEMATCH:
+ // wParam is position of char to find brace for,
+ // lParam is maximum amount of text to restyle to find it
+ return BraceMatch(wParam, lParam);
+
+ case SCI_GETVIEWEOL:
+ return vs.viewEOL;
+
+ case SCI_SETVIEWEOL:
+ vs.viewEOL = wParam;
+ Redraw();
+ break;
+
+ case SCI_GETEDGECOLUMN:
+ return theEdge;
+
+ case SCI_SETEDGECOLUMN:
+ theEdge = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEDGEMODE:
+ return edgeState;
+
+ case SCI_SETEDGEMODE:
+ edgeState = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEDGECOLOUR:
+ return vs.edgecolour.desired.AsLong();
+
+ case SCI_SETEDGECOLOUR:
+ vs.edgecolour.desired = Colour(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETDOCPOINTER:
+ return reinterpret_cast<LRESULT>(pdoc);
+
+ case SCI_SETDOCPOINTER:
+ SetDocPointer(reinterpret_cast<Document *>(lParam));
+ return 0;
+
+ case SCI_SETMODEVENTMASK:
+ modEventMask = wParam;
+ return 0;
+
+ case SCI_CONVERTEOLS:
+ pdoc->ConvertLineEnds(wParam);
+ SetSelection(currentPos, anchor); // Ensure selection inside document
+ return 0;
+
+#ifdef MACRO_SUPPORT
+ case SCI_STARTRECORD:
+ recordingMacro = 1;
+ return 0;
+
+ case SCI_STOPRECORD:
+ recordingMacro = 0;
+ return 0;
+#endif
+
+ default:
+ return DefWndProc(iMessage, wParam, lParam);
+ }
+ //Platform::DebugPrintf("end wnd proc\n");
+ return 0l;
+}
diff --git a/src/Editor.h b/src/Editor.h
new file mode 100644
index 000000000..4ff334767
--- /dev/null
+++ b/src/Editor.h
@@ -0,0 +1,281 @@
+// Scintilla source code edit control
+// Editor.h - defines the main editor class
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef EDITOR_H
+#define EDITOR_H
+
+class Caret {
+public:
+ bool active;
+ bool on;
+ int period;
+
+ Caret();
+};
+
+class Timer {
+
+public:
+ bool ticking;
+ int ticksToWait;
+ enum {tickSize = 100};
+ int tickerID;
+
+ Timer();
+};
+
+class LineLayout {
+public:
+ // Drawing is only performed for maxLineLength characters on each line.
+ enum {maxLineLength = 4000};
+ int numCharsInLine;
+ char chars[maxLineLength];
+ char styles[maxLineLength];
+ char indicators[maxLineLength];
+ int positions[maxLineLength];
+};
+
+class Editor : public DocWatcher {
+protected: // ScintillaBase subclass needs access to much of Editor
+
+ // On GTK+, Scintilla is a container widget holding two scroll bars and a drawing area
+ // whereas on Windows there is just one window with both scroll bars turned on.
+ // Therefore, on GTK+ the following are separate windows but only one window on Windows.
+ Window wMain; // The Scintilla parent window
+ Window wDraw; // The text drawing area
+
+ // Style resources may be expensive to allocate so are cached between uses.
+ // When a style attribute is changed, this cache is flushed.
+ bool stylesValid;
+ ViewStyle vs;
+ Palette palette;
+
+ bool hideSelection;
+ bool inOverstrike;
+
+ // In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
+ // the screen. This avoids flashing but is about 30% slower.
+ bool bufferedDraw;
+
+ int xOffset; // Horizontal scrolled amount in pixels
+ int xCaretMargin; // Ensure this many pixels visible on both sides of caret
+
+ Surface pixmapLine;
+ Surface pixmapSelMargin;
+ Surface pixmapSelPattern;
+ // Intellimouse support - currently only implemented for Windows
+ unsigned int ucWheelScrollLines;
+ short cWheelDelta; //wheel delta from roll
+
+ KeyMap kmap;
+
+ Caret caret;
+ Timer timer;
+
+ Point lastClick;
+ unsigned int lastClickTime;
+ enum { selChar, selWord, selLine } selectionType;
+ Point ptMouseLast;
+ bool firstExpose;
+ bool inDragDrop;
+ bool dropWentOutside;
+ int posDrag;
+ int posDrop;
+ int lastXChosen;
+ int lineAnchor;
+ int originalAnchorPos;
+ int currentPos;
+ int anchor;
+ int topLine;
+ int posTopLine;
+
+ bool needUpdateUI;
+ Position braces[2];
+ int bracesMatchStyle;
+
+ int edgeState;
+ int theEdge;
+
+ enum { notPainting, painting, paintAbandoned } paintState;
+ PRectangle rcPaint;
+ bool paintingAllText;
+
+ int modEventMask;
+
+ char *dragChars;
+ int lenDrag;
+ bool dragIsRectangle;
+ enum { selStream, selRectangle, selRectangleFixed } selType;
+ int xStartSelect;
+ int xEndSelect;
+
+ int caretPolicy;
+ int caretSlop;
+
+ int searchAnchor;
+
+#ifdef MACRO_SUPPORT
+ int recordingMacro;
+#endif
+
+ int foldFlags;
+ ContractionState cs;
+
+ Document *pdoc;
+
+ Editor();
+ virtual ~Editor();
+ virtual void Initialise() = 0;
+ virtual void Finalise();
+
+ void InvalidateStyleData();
+ void InvalidateStyleRedraw();
+ virtual void RefreshColourPalette(Palette &pal, bool want);
+ void RefreshStyleData();
+ void DropGraphics();
+
+ PRectangle GetClientRectangle();
+ PRectangle GetTextRectangle();
+
+ int LinesOnScreen();
+ int LinesToScroll();
+ int MaxScrollPos();
+ Point LocationFromPosition(unsigned int pos);
+ int XFromPosition(unsigned int pos);
+ int PositionFromLocation(Point pt);
+ int PositionFromLineX(int line, int x);
+ int LineFromLocation(Point pt);
+ void SetTopLine(int topLineNew);
+
+ void RedrawRect(PRectangle rc);
+ void Redraw();
+ void RedrawSelMargin();
+ PRectangle RectangleFromRange(int start, int end);
+ void InvalidateRange(int start, int end);
+
+ int CurrentPosition();
+ bool SelectionEmpty();
+ int SelectionStart(int line=-1);
+ int SelectionEnd(int line=-1);
+ void SetSelection(int currentPos_, int anchor_);
+ void SetSelection(int currentPos_);
+ void SetEmptySelection(int currentPos_);
+ int MovePositionTo(int newPos, bool extend = false);
+ int MovePositionSoVisible(int pos, int moveDir);
+ void SetLastXChosen();
+
+ void ScrollTo(int line);
+ virtual void ScrollText(int linesToMove);
+ void HorizontalScrollTo(int xPos);
+ void EnsureCaretVisible(bool useMargin=true);
+ void ShowCaretAtCurrentPosition();
+ void DropCaret();
+ void InvalidateCaret();
+
+ void PaintSelMargin(Surface *surface, PRectangle &rc);
+ void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll);
+ void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout &ll);
+ void Paint(Surface *surfaceWindow, PRectangle rcArea);
+ long FormatRange(bool draw, FORMATRANGE *pfr);
+
+ virtual void SetVerticalScrollPos() = 0;
+ virtual void SetHorizontalScrollPos() = 0;
+ virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
+ void SetScrollBarsTo(PRectangle rsClient);
+ void SetScrollBars();
+
+ virtual void AddChar(char ch);
+ void ClearSelection();
+ void ClearAll();
+ void Cut();
+ void PasteRectangular(int pos, const char *ptr, int len);
+ virtual void Copy() = 0;
+ virtual void Paste() = 0;
+ void Clear();
+ void SelectAll();
+ void Undo();
+ void Redo();
+ void DelChar();
+ void DelCharBack();
+ virtual void ClaimSelection() = 0;
+
+ virtual void NotifyChange() = 0;
+ virtual void NotifyFocus(bool focus);
+ virtual void NotifyParent(SCNotification scn) = 0;
+ virtual void NotifyStyleNeeded(int endStyleNeeded);
+ void NotifyChar(char ch);
+ void NotifySavePoint(bool isSavePoint);
+ void NotifyModifyAttempt();
+ virtual void NotifyDoubleClick(Point pt, bool shift);
+ void NotifyUpdateUI();
+ bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
+ void NotifyNeedShown(int pos, int len);
+
+ void NotifyModifyAttempt(Document *document, void *userData);
+ void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
+ void NotifyModified(Document *document, DocModification mh, void *userData);
+ void NotifyDeleted(Document *document, void *userData);
+
+#ifdef MACRO_SUPPORT
+ void NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam);
+#endif
+
+ void PageMove(int direction, bool extend=false);
+ virtual int KeyCommand(UINT iMessage);
+ virtual int KeyDefault(int /* key */, int /*modifiers*/);
+ int KeyDown(int key, bool shift, bool ctrl, bool alt);
+
+ bool GetWhitespaceVisible();
+ void SetWhitespaceVisible(bool view);
+
+ void Indent(bool forwards);
+
+ long FindText(UINT iMessage,WPARAM wParam,LPARAM lParam);
+ void SearchAnchor();
+ long SearchText(UINT iMessage,WPARAM wParam,LPARAM lParam);
+ void GoToLine(int lineNo);
+
+ char *CopyRange(int start, int end);
+ int SelectionRangeLength();
+ char *CopySelectionRange();
+ void CopySelectionIntoDrag();
+ void SetDragPosition(int newPos);
+ virtual void StartDrag();
+ void DropAt(int position, const char *value, bool moving, bool rectangular);
+ // PositionInSelection returns 0 if position in selection, -1 if position before selection, and 1 if after.
+ // Before means either before any line of selection or before selection on its line, with a similar meaning to after
+ int PositionInSelection(int pos);
+ bool PointInSelection(Point pt);
+ bool PointInSelMargin(Point pt);
+ virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
+ void ButtonMove(Point pt);
+ void ButtonUp(Point pt, unsigned int curTime, bool ctrl);
+
+ void Tick();
+ virtual void SetTicking(bool on) = 0;
+ virtual void SetMouseCapture(bool on) = 0;
+ virtual bool HaveMouseCapture() = 0;
+
+ void CheckForChangeOutsidePaint(Range r);
+ int BraceMatch(int position, int maxReStyle);
+ void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
+
+ void SetDocPointer(Document *document);
+
+ void Expand(int &line, bool doExpand);
+ void ToggleContraction(int line);
+ void EnsureLineVisible(int line);
+
+ virtual LRESULT DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) = 0;
+
+public:
+ // Public so scintilla_send_message can use it
+ virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+ // Public so scintilla_set_id can use it
+ int ctrlID;
+};
+
+#endif
diff --git a/src/Indicator.cxx b/src/Indicator.cxx
new file mode 100644
index 000000000..fb6ad0915
--- /dev/null
+++ b/src/Indicator.cxx
@@ -0,0 +1,45 @@
+// Scintilla source code edit control
+// Indicator.cxx - defines the style of indicators which are text decorations such as underlining
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "Indicator.h"
+
+void Indicator::Draw(Surface *surface, PRectangle &rc) {
+ surface->PenColour(fore.allocated);
+ int ymid = (rc.bottom + rc.top) / 2;
+ if (style == INDIC_SQUIGGLE) {
+ surface->MoveTo(rc.left, rc.top);
+ int x = rc.left + 2;
+ int y = 2;
+ while (x < rc.right) {
+ surface->LineTo(x, rc.top + y);
+ x += 2;
+ y = 2 - y;
+ }
+ surface->LineTo(rc.right, rc.top + y); // Finish the line
+ } else if (style == INDIC_TT) {
+ surface->MoveTo(rc.left, ymid);
+ int x = rc.left + 5;
+ while (x < rc.right) {
+ surface->LineTo(x, ymid);
+ surface->MoveTo(x-3, ymid);
+ surface->LineTo(x-3, ymid+2);
+ x++;
+ surface->MoveTo(x, ymid);
+ x += 5;
+ }
+ surface->LineTo(rc.right, ymid); // Finish the line
+ if (x - 3 <= rc.right) {
+ surface->MoveTo(x-3, ymid);
+ surface->LineTo(x-3, ymid+2);
+ }
+ } else { // Either INDIC_PLAIN or unknown
+ surface->MoveTo(rc.left, ymid);
+ surface->LineTo(rc.right, ymid);
+ }
+}
+
diff --git a/src/Indicator.h b/src/Indicator.h
new file mode 100644
index 000000000..2472cedc1
--- /dev/null
+++ b/src/Indicator.h
@@ -0,0 +1,18 @@
+// Scintilla source code edit control
+// Indicator.h - defines the style of indicators which are text decorations such as underlining
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef INDICATOR_H
+#define INDICATOR_H
+
+class Indicator {
+public:
+ int style;
+ ColourPair fore;
+ Indicator() : style(INDIC_PLAIN), fore(Colour(0,0,0)) {
+ }
+ void Draw(Surface *surface, PRectangle &rc);
+};
+
+#endif
diff --git a/src/KeyMap.cxx b/src/KeyMap.cxx
new file mode 100644
index 000000000..f339cd275
--- /dev/null
+++ b/src/KeyMap.cxx
@@ -0,0 +1,111 @@
+// Scintilla source code edit control
+// KeyMap.cxx - defines a mapping between keystrokes and commands
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+
+#include "KeyMap.h"
+
+KeyMap::KeyMap() : kmap(0), len(0), alloc(0) {
+ for (int i = 0; MapDefault[i].key; i++) {
+ AssignCmdKey(MapDefault[i].key,
+ MapDefault[i].modifiers,
+ MapDefault[i].msg);
+ }
+}
+
+KeyMap::~KeyMap() {
+ Clear();
+}
+
+void KeyMap::Clear() {
+ delete []kmap;
+ kmap = 0;
+ len = 0;
+ alloc = 0;
+}
+
+void KeyMap::AssignCmdKey(int key, int modifiers, UINT msg) {
+ if ((len+1) >= alloc) {
+ KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
+ if (!ktcNew)
+ return;
+ for (int k=0;k<len;k++)
+ ktcNew[k] = kmap[k];
+ alloc += 5;
+ delete []kmap;
+ kmap = ktcNew;
+ }
+ for (int keyIndex = 0; keyIndex < len; keyIndex++) {
+ if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
+ kmap[keyIndex].msg = msg;
+ return;
+ }
+ }
+ kmap[len].key = key;
+ kmap[len].modifiers = modifiers;
+ kmap[len].msg = msg;
+ len++;
+}
+
+UINT KeyMap::Find(int key, int modifiers) {
+ for (int i=0; i < len; i++) {
+ if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
+ return kmap[i].msg;
+ }
+ }
+ return 0;
+}
+
+KeyToCommand KeyMap::MapDefault[] = {
+ VK_DOWN, SCI_NORM, SCI_LINEDOWN,
+ VK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND,
+ VK_UP, SCI_NORM, SCI_LINEUP,
+ VK_UP, SCI_SHIFT, SCI_LINEUPEXTEND,
+ VK_LEFT, SCI_NORM, SCI_CHARLEFT,
+ VK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND,
+ VK_LEFT, SCI_CTRL, SCI_WORDLEFT,
+ VK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND,
+ VK_RIGHT, SCI_NORM, SCI_CHARRIGHT,
+ VK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND,
+ VK_RIGHT, SCI_CTRL, SCI_WORDRIGHT,
+ VK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND,
+ VK_HOME, SCI_NORM, SCI_VCHOME,
+ VK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND,
+ VK_HOME, SCI_CTRL, SCI_DOCUMENTSTART,
+ VK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND,
+ VK_END, SCI_NORM, SCI_LINEEND,
+ VK_END, SCI_SHIFT, SCI_LINEENDEXTEND,
+ VK_END, SCI_CTRL, SCI_DOCUMENTEND,
+ VK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND,
+ VK_PRIOR, SCI_NORM, SCI_PAGEUP,
+ VK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND,
+ VK_NEXT, SCI_NORM, SCI_PAGEDOWN,
+ VK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND,
+ VK_DELETE, SCI_NORM, WM_CLEAR,
+ VK_DELETE, SCI_SHIFT, WM_CUT,
+ VK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT,
+ VK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE,
+ VK_INSERT, SCI_SHIFT, WM_PASTE,
+ VK_INSERT, SCI_CTRL, WM_COPY,
+ VK_ESCAPE, SCI_NORM, SCI_CANCEL,
+ VK_BACK, SCI_NORM, SCI_DELETEBACK,
+ VK_BACK, SCI_CTRL, SCI_DELWORDLEFT,
+ 'Z', SCI_CTRL, WM_UNDO,
+ 'Y', SCI_CTRL, SCI_REDO,
+ 'X', SCI_CTRL, WM_CUT,
+ 'C', SCI_CTRL, WM_COPY,
+ 'V', SCI_CTRL, WM_PASTE,
+ 'A', SCI_CTRL, SCI_SELECTALL,
+ VK_TAB, SCI_NORM, SCI_TAB,
+ VK_TAB, SCI_SHIFT, SCI_BACKTAB,
+ VK_RETURN, SCI_NORM, SCI_NEWLINE,
+ 'L', SCI_CTRL, SCI_FORMFEED,
+ VK_ADD, SCI_CTRL, SCI_ZOOMIN,
+ VK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT,
+ 0,0,0,
+};
+
diff --git a/src/KeyMap.h b/src/KeyMap.h
new file mode 100644
index 000000000..814f3aa3b
--- /dev/null
+++ b/src/KeyMap.h
@@ -0,0 +1,35 @@
+// Scintilla source code edit control
+// KeyMap.h - defines a mapping between keystrokes and commands
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef KEYTOCOMMAND_H
+#define KEYTOCOMMAND_H
+
+#define SCI_NORM 0
+#define SCI_SHIFT SHIFT_PRESSED
+#define SCI_CTRL LEFT_CTRL_PRESSED
+#define SCI_ALT LEFT_ALT_PRESSED
+#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
+
+class KeyToCommand {
+public:
+ int key;
+ int modifiers;
+ UINT msg;
+};
+
+class KeyMap {
+ KeyToCommand *kmap;
+ int len;
+ int alloc;
+ static KeyToCommand MapDefault[];
+public:
+ KeyMap();
+ ~KeyMap();
+ void Clear();
+ void AssignCmdKey(int key, int modifiers, UINT msg);
+ UINT Find(int key, int modifiers); // 0 returned on failure
+};
+
+#endif
diff --git a/src/KeyWords.cxx b/src/KeyWords.cxx
new file mode 100644
index 000000000..7a6784f73
--- /dev/null
+++ b/src/KeyWords.cxx
@@ -0,0 +1,2648 @@
+// SciTE - Scintilla based Text Editor
+// KeyWords.cxx - colourise for particular languages
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+inline bool IsLeadByte(int codePage, char ch) {
+#if PLAT_GTK
+ // TODO: support DBCS under GTK+
+ return false;
+#elif PLAT_WIN
+ return codePage && IsDBCSLeadByteEx(codePage, ch);
+#elif PLAT_WX
+ return false;
+#endif
+}
+
+inline bool iswordchar(char ch) {
+ return isalnum(ch) || ch == '.' || ch == '_';
+}
+
+inline bool iswordstart(char ch) {
+ return isalnum(ch) || ch == '_';
+}
+
+enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
+
+typedef bool (*PFNIsCommentLeader)(StylingContext &styler, int pos, int len);
+
+static int IndentAmount(StylingContext &styler, int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0) {
+ int end = styler.Length();
+ int spaceFlags = 0;
+
+ // Determines the indentation level of the current line and also checks for consistent
+ // indentation compared to the previous line.
+ // Indentation is judged consistent when the indentation whitespace of each line lines
+ // the same or the indentation of one line is a prefix of the other.
+
+ int pos = styler.LineStart(line);
+ char ch = styler[pos];
+ int indent = 0;
+ bool inPrevPrefix = line > 0;
+ int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
+ while ((ch == ' ' || ch == '\t') && (pos < end)) {
+ if (inPrevPrefix) {
+ char chPrev = styler[posPrev++];
+ if (chPrev == ' ' || chPrev == '\t') {
+ if (chPrev != ch)
+ spaceFlags |= wsInconsistent;
+ } else {
+ inPrevPrefix = false;
+ }
+ }
+ if (ch == ' ') {
+ spaceFlags |= wsSpace;
+ indent++;
+ } else { // Tab
+ spaceFlags |= wsTab;
+ if (spaceFlags & wsSpace)
+ spaceFlags |= wsSpaceTab;
+ indent = (indent / 8 + 1) * 8;
+ }
+ ch = styler[++pos];
+ }
+
+ *flags = spaceFlags;
+ indent += SC_FOLDLEVELBASE;
+ // if completely empty line or the start of a comment...
+ if ( isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(styler, pos, end-pos)) )
+ return indent | SC_FOLDLEVELWHITEFLAG;
+ else
+ return indent;
+}
+
+inline bool isoperator(char ch) {
+ if (isalnum(ch))
+ return false;
+ // '.' left out as it is used to make up numbers
+ if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
+ ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
+ ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
+ ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
+ ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
+ ch == '?' || ch == '!' || ch == '.' || ch == '~')
+ return true;
+ return false;
+}
+
+static void classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_C_IDENTIFIER;
+ if (wordIsNumber)
+ chAttr = SCE_C_NUMBER;
+ else {
+ if (keywords.InList(s))
+ chAttr = SCE_C_WORD;
+ }
+ styler.ColourSegment(start, end, chAttr);
+}
+
+static void ColouriseCppDoc(int codePage, int startPos, int length,
+ int initStyle, WordList &keywords, StylingContext &styler) {
+
+ bool fold = styler.GetPropSet().GetInt("fold");
+ int lineCurrent = styler.GetLine(startPos);
+ int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+ int levelCurrent = levelPrev;
+
+ int state = initStyle;
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ int startSeg = startPos;
+ int lengthDoc = startPos + length;
+ int visChars = 0;
+ for (unsigned int i = startPos; i <= lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((fold) && ((ch == '\r' && chNext != '\n') || (ch == '\n'))) {
+ int lev = levelPrev;
+ if (visChars == 0)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if ((levelCurrent > levelPrev) && (visChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ visChars = 0;
+ levelPrev = levelCurrent;
+ }
+ if (!isspace(ch))
+ visChars++;
+
+ if (IsLeadByte(codePage, ch)) { // dbcs
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_STRINGEOL) {
+ if (ch != '\r' && ch != '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ }
+ }
+ if (state == SCE_C_DEFAULT) {
+ if (iswordstart(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_WORD;
+ startSeg = i;
+ } else if (ch == '/' && chNext == '*') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ if (styler.SafeGetCharAt(i + 2) == '*')
+ state = SCE_C_COMMENTDOC;
+ else
+ state = SCE_C_COMMENT;
+ startSeg = i;
+ } else if (ch == '/' && chNext == '/') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_COMMENTLINE;
+ startSeg = i;
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_STRING;
+ startSeg = i;
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_CHARACTER;
+ startSeg = i;
+ } else if (ch == '#') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_PREPROCESSOR;
+ startSeg = i;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ styler.ColourSegment(i, i, SCE_C_OPERATOR);
+ startSeg = i + 1;
+ if ((ch == '{') || (ch == '}')) {
+ levelCurrent += (ch == '{') ? 1 : -1;
+ }
+ }
+ } else if (state == SCE_C_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordCpp(startSeg, i - 1, keywords, styler);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ if (ch == '/' && chNext == '*') {
+ if (styler.SafeGetCharAt(i + 2) == '*')
+ state = SCE_C_COMMENTDOC;
+ else
+ state = SCE_C_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_C_STRING;
+ } else if (ch == '\'') {
+ state = SCE_C_CHARACTER;
+ } else if (ch == '#') {
+ state = SCE_C_PREPROCESSOR;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+ startSeg = i + 1;
+ if ((ch == '{') || (ch == '}')) {
+ levelCurrent += (ch == '{') ? 1 : -1;
+ }
+ }
+ }
+ } else {
+ if (state == SCE_C_PREPROCESSOR) {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ }
+ } else if (state == SCE_C_COMMENT) {
+ if (ch == '/' && chPrev == '*' && (
+ (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_C_COMMENTDOC) {
+ if (ch == '/' && chPrev == '*' && (
+ (i > startSeg + 3) || ((initStyle == SCE_C_COMMENTDOC) && (startSeg == startPos)))) {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ }
+ } else if (state == SCE_C_STRING) {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_STRINGEOL;
+ startSeg = i;
+ } else if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_C_DEFAULT;
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ startSeg = i;
+ }
+ } else if (state == SCE_C_CHARACTER) {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_STRINGEOL;
+ startSeg = i;
+ } else if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_C_DEFAULT;
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ startSeg = i;
+ }
+ }
+ if (state == SCE_C_DEFAULT) { // One of the above succeeded
+ if (ch == '/' && chNext == '*') {
+ if (styler.SafeGetCharAt(i + 2) == '*')
+ state = SCE_C_COMMENTDOC;
+ else
+ state = SCE_C_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_C_STRING;
+ } else if (ch == '\'') {
+ state = SCE_C_CHARACTER;
+ } else if (ch == '#') {
+ state = SCE_C_PREPROCESSOR;
+ } else if (iswordstart(ch)) {
+ state = SCE_C_WORD;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+ startSeg = i + 1;
+ if ((ch == '{') || (ch == '}')) {
+ levelCurrent += (ch == '{') ? 1 : -1;
+ }
+ }
+ }
+ }
+ chPrev = ch;
+ }
+ if (startSeg < lengthDoc)
+ styler.ColourSegment(startSeg, lengthDoc - 1, state);
+ // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+ if (fold) {
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ //styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+
+ }
+}
+
+inline bool isPerlOperator(char ch) {
+ if (isalnum(ch))
+ return false;
+ // '.' left out as it is used to make up numbers
+ if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || ch == '\\' ||
+ ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
+ ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
+ ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
+ ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
+ ch == '?' || ch == '!' || ch == '.' || ch == '~')
+ return true;
+ return false;
+}
+
+static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_PL_IDENTIFIER;
+ if (wordIsNumber)
+ chAttr = SCE_PL_NUMBER;
+ else {
+ if (keywords.InList(s))
+ chAttr = SCE_PL_WORD;
+ }
+ styler.ColourSegment(start, end, chAttr);
+ return chAttr;
+}
+
+static bool isEndVar(char ch) {
+ return !isalnum(ch) && ch != '#' && ch != '$' &&
+ ch != '_' && ch != '\'';
+}
+
+static bool isMatch(StylingContext &styler, int lengthDoc, int pos, const char *val) {
+ if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
+ return false;
+ }
+ while (*val) {
+ if (*val != styler[pos++]) {
+ return false;
+ }
+ val++;
+ }
+ return true;
+}
+
+static bool isOKQuote(char ch) {
+ if (isalnum(ch))
+ return false;
+ if (isspace(ch))
+ return false;
+ if (iscntrl(ch))
+ return false;
+ return true;
+}
+
+static char opposite(char ch) {
+ if (ch == '(')
+ return ')';
+ if (ch == '[')
+ return ']';
+ if (ch == '{')
+ return '}';
+ if (ch == '<')
+ return '>';
+ return ch;
+}
+
+static void ColourisePerlDoc(int codePage, int startPos, int length, int initStyle,
+ WordList &keywords, StylingContext &styler) {
+ char sooked[100];
+ int quotes = 0;
+ char quoteDown = 'd';
+ char quoteUp = 'd';
+ int quoteRep = 1;
+ int sookedpos = 0;
+ bool preferRE = true;
+ sooked[sookedpos] = '\0';
+ int state = initStyle;
+ int lengthDoc = startPos + length;
+ // If in a long distance lexical state, seek to the beginning to find quote characters
+ if (state == SCE_PL_HERE || state == SCE_PL_REGEX ||
+ state == SCE_PL_REGSUBST || state == SCE_PL_LONGQUOTE) {
+ while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
+ startPos--;
+ }
+ state = SCE_PL_DEFAULT;
+ }
+ styler.StartAt(startPos);
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ int startSeg = startPos;
+ for (int i = startPos; i <= lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+
+ if (IsLeadByte(codePage, ch)) { // dbcs
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_PL_DEFAULT) {
+ if (iswordstart(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ if (ch == 's' && !isalnum(chNext)) {
+ state = SCE_PL_REGSUBST;
+ quotes = 0;
+ quoteUp = '\0';
+ quoteDown = '\0';
+ quoteRep = 2;
+ startSeg = i;
+ } else if (ch == 'm' && !isalnum(chNext)) {
+ state = SCE_PL_REGEX;
+ quotes = 0;
+ quoteUp = '\0';
+ quoteDown = '\0';
+ quoteRep = 1;
+ startSeg = i;
+ } else if (ch == 't' && chNext == 'r' && !isalnum(chNext2)) {
+ state = SCE_PL_REGSUBST;
+ quotes = 0;
+ quoteUp = '\0';
+ quoteDown = '\0';
+ quoteRep = 2;
+ startSeg = i;
+ i++;
+ chNext = chNext2;
+ } else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isalnum(chNext2)) {
+ state = SCE_PL_LONGQUOTE;
+ startSeg = i;
+ i++;
+ chNext = chNext2;
+ quotes = 0;
+ quoteUp = '\0';
+ quoteDown = '\0';
+ quoteRep = 1;
+ } else {
+ state = SCE_PL_WORD;
+ startSeg = i;
+ preferRE = false;
+ }
+ } else if (ch == '#') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_COMMENTLINE;
+ startSeg = i;
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_STRING;
+ startSeg = i;
+ } else if (ch == '\'') {
+ if (chPrev == '&') {
+ // Archaic call
+ styler.ColourSegment(i, i, state);
+ startSeg = i + 1;
+ } else {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_CHARACTER;
+ startSeg = i;
+ }
+ } else if (ch == '`') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_BACKTICKS;
+ startSeg = i;
+ } else if (ch == '$') {
+ preferRE = false;
+ styler.ColourSegment(startSeg, i - 1, state);
+ if (isalnum(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+ state = SCE_PL_SCALAR;
+ startSeg = i;
+ } else if (chNext != '{' && chNext != '[') {
+ styler.ColourSegment(i - 1, i, SCE_PL_SCALAR);
+ i++;
+ startSeg = i + 1;
+ ch = ' ';
+ chNext = ' ';
+ } else {
+ styler.ColourSegment(i, i, SCE_PL_SCALAR);
+ startSeg = i + 1;
+ }
+ } else if (ch == '@') {
+ preferRE = false;
+ styler.ColourSegment(startSeg, i - 1, state);
+ if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+ state = SCE_PL_ARRAY;
+ startSeg = i;
+ } else if (chNext != '{' && chNext != '[') {
+ styler.ColourSegment(i - 1, i, SCE_PL_ARRAY);
+ i++;
+ startSeg = i + 1;
+ ch = ' ';
+ } else {
+ styler.ColourSegment(i, i, SCE_PL_ARRAY);
+ startSeg = i + 1;
+ }
+ } else if (ch == '%') {
+ preferRE = false;
+ styler.ColourSegment(startSeg, i - 1, state);
+ if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+ state = SCE_PL_HASH;
+ startSeg = i;
+ } else if (chNext != '{' && chNext != '[') {
+ styler.ColourSegment(i - 1, i, SCE_PL_HASH);
+ i++;
+ startSeg = i + 1;
+ ch = ' ';
+ } else {
+ styler.ColourSegment(i, i, SCE_PL_HASH);
+ startSeg = i + 1;
+ }
+ } else if (ch == '*') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_SYMBOLTABLE;
+ startSeg = i;
+ } else if (ch == '/' && preferRE) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_REGEX;
+ quoteUp = '/';
+ quoteDown = '/';
+ quotes = 1;
+ quoteRep = 1;
+ startSeg = i;
+ } else if (ch == '<' && chNext == '<') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_HERE;
+ startSeg = i;
+ i++;
+ ch = chNext;
+ chNext = chNext2;
+ quotes = 0;
+ sookedpos = 0;
+ sooked[sookedpos] = '\0';
+ } else if (ch == '=' && isalpha(chNext)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_POD;
+ startSeg = i;
+ quotes = 0;
+ sookedpos = 0;
+ sooked[sookedpos] = '\0';
+ } else if (isPerlOperator(ch)) {
+ if (ch == ')' || ch == ']')
+ preferRE = false;
+ else
+ preferRE = true;
+ styler.ColourSegment(startSeg, i - 1, state);
+ styler.ColourSegment(i, i, SCE_PL_OPERATOR);
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_PL_WORD) {
+ if (!iswordchar(ch) && ch != '\'') { // Archaic Perl has quotes inside names
+ if (isMatch(styler, lengthDoc, startSeg, "__DATA__")) {
+ styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
+ state = SCE_PL_DATASECTION;
+ } else if (isMatch(styler, lengthDoc, startSeg, "__END__")) {
+ styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
+ state = SCE_PL_DATASECTION;
+ } else {
+ if (classifyWordPerl(startSeg, i - 1, keywords, styler) == SCE_PL_WORD)
+ preferRE = true;
+ state = SCE_PL_DEFAULT;
+ startSeg = i;
+ if (ch == '#') {
+ state = SCE_PL_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_PL_STRING;
+ } else if (ch == '\'') {
+ state = SCE_PL_CHARACTER;
+ } else if (ch == '<' && chNext == '<') {
+ state = SCE_PL_HERE;
+ quotes = 0;
+ startSeg = i;
+ sookedpos = 0;
+ sooked[sookedpos] = '\0';
+ } else if (isPerlOperator(ch)) {
+ if (ch == ')' || ch == ']')
+ preferRE = false;
+ else
+ preferRE = true;
+ styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
+ state = SCE_PL_DEFAULT;
+ startSeg = i + 1;
+ }
+ }
+ }
+ } else {
+ if (state == SCE_PL_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_PL_DEFAULT;
+ startSeg = i;
+ }
+ } else if (state == SCE_PL_HERE) {
+ if (isalnum(ch) && quotes < 2) {
+ sooked[sookedpos++] = ch;
+ sooked[sookedpos] = '\0';
+ if (quotes == 0)
+ quotes = 1;
+ } else {
+ quotes++;
+ }
+
+ if (quotes > 1 && isMatch(styler, lengthDoc, i, sooked)) {
+ styler.ColourSegment(startSeg, i + sookedpos - 1, SCE_PL_HERE);
+ state = SCE_PL_DEFAULT;
+ i += sookedpos;
+ startSeg = i;
+ chNext = ' ';
+ }
+ } else if (state == SCE_PL_STRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_PL_DEFAULT;
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ startSeg = i;
+ }
+ } else if (state == SCE_PL_CHARACTER) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_PL_DEFAULT;
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ startSeg = i;
+ }
+ } else if (state == SCE_PL_BACKTICKS) {
+ if (ch == '`') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_PL_DEFAULT;
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ startSeg = i;
+ }
+ } else if (state == SCE_PL_POD) {
+ if (ch == '=') {
+ if (isMatch(styler, lengthDoc, i, "=cut")) {
+ styler.ColourSegment(startSeg, i - 1 + 4, state);
+ i += 4;
+ startSeg = i;
+ state = SCE_PL_DEFAULT;
+ chNext = ' ';
+ ch = ' ';
+ }
+ }
+ } else if (state == SCE_PL_SCALAR) {
+ if (isEndVar(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ state = SCE_PL_DEFAULT;
+ }
+ } else if (state == SCE_PL_ARRAY) {
+ if (isEndVar(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ state = SCE_PL_DEFAULT;
+ }
+ } else if (state == SCE_PL_HASH) {
+ if (isEndVar(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ state = SCE_PL_DEFAULT;
+ }
+ } else if (state == SCE_PL_SYMBOLTABLE) {
+ if (isEndVar(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ state = SCE_PL_DEFAULT;
+ }
+ } else if (state == SCE_PL_REF) {
+ if (isEndVar(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ state = SCE_PL_DEFAULT;
+ }
+ } else if (state == SCE_PL_REGEX) {
+ if (!quoteUp && !isspace(ch)) {
+ quoteUp = ch;
+ quoteDown = opposite(ch);
+ quotes++;
+ } else {
+ if (ch == quoteDown && chPrev != '\\') {
+ quotes--;
+ if (quotes == 0) {
+ quoteRep--;
+ if (quoteUp == quoteDown) {
+ quotes++;
+ }
+ }
+ if (!isalpha(chNext)) {
+ if (quoteRep <= 0) {
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ state = SCE_PL_DEFAULT;
+ ch = ' ';
+ }
+ }
+ } else if (ch == quoteUp && chPrev != '\\') {
+ quotes++;
+ } else if (!isalpha(chNext)) {
+ if (quoteRep <= 0) {
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ state = SCE_PL_DEFAULT;
+ ch = ' ';
+ }
+ }
+ }
+ } else if (state == SCE_PL_REGSUBST) {
+ if (!quoteUp && !isspace(ch)) {
+ quoteUp = ch;
+ quoteDown = opposite(ch);
+ quotes++;
+ } else {
+ if (ch == quoteDown && chPrev != '\\') {
+ quotes--;
+ if (quotes == 0) {
+ quoteRep--;
+ }
+ if (!isalpha(chNext)) {
+ if (quoteRep <= 0) {
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ state = SCE_PL_DEFAULT;
+ ch = ' ';
+ }
+ }
+ if (quoteUp == quoteDown) {
+ quotes++;
+ }
+ } else if (ch == quoteUp && chPrev != '\\') {
+ quotes++;
+ } else if (!isalpha(chNext)) {
+ if (quoteRep <= 0) {
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ state = SCE_PL_DEFAULT;
+ ch = ' ';
+ }
+ }
+ }
+ } else if (state == SCE_PL_LONGQUOTE) {
+ if (!quoteDown && !isspace(ch)) {
+ quoteUp = ch;
+ quoteDown = opposite(quoteUp);
+ quotes++;
+ } else if (ch == quoteDown) {
+ quotes--;
+ if (quotes == 0) {
+ quoteRep--;
+ if (quoteRep <= 0) {
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ state = SCE_PL_DEFAULT;
+ ch = ' ';
+ }
+ if (quoteUp == quoteDown) {
+ quotes++;
+ }
+ }
+ } else if (ch == quoteUp) {
+ quotes++;
+ }
+ }
+
+ if (state == SCE_PL_DEFAULT) { // One of the above succeeded
+ if (ch == '#') {
+ state = SCE_PL_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_PL_STRING;
+ } else if (ch == '\'') {
+ state = SCE_PL_CHARACTER;
+ } else if (iswordstart(ch)) {
+ state = SCE_PL_WORD;
+ preferRE = false;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
+ startSeg = i + 1;
+ }
+ }
+ }
+ chPrev = ch;
+ }
+ if (startSeg < lengthDoc)
+ styler.ColourSegment(startSeg, lengthDoc, state);
+}
+
+
+static int classifyWordVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = tolower(styler[start + i]);
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_C_DEFAULT;
+ if (wordIsNumber)
+ chAttr = SCE_C_NUMBER;
+ else {
+ if (keywords.InList(s)) {
+ chAttr = SCE_C_WORD;
+ if (strcmp(s, "rem") == 0)
+ chAttr = SCE_C_COMMENTLINE;
+ }
+ }
+ styler.ColourSegment(start, end, chAttr);
+ if (chAttr == SCE_C_COMMENTLINE)
+ return SCE_C_COMMENTLINE;
+ else
+ return SCE_C_DEFAULT;
+}
+
+static void ColouriseVBDoc(int codePage, int startPos, int length, int initStyle,
+ WordList &keywords, StylingContext &styler) {
+ int state = initStyle;
+ char chNext = styler[startPos];
+ int startSeg = startPos;
+ int lengthDoc = startPos + length;
+ for (int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (IsLeadByte(codePage, ch)) { // dbcs
+ chNext = styler.SafeGetCharAt(i + 2);
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_DEFAULT) {
+ if (iswordstart(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_WORD;
+ startSeg = i;
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_COMMENTLINE;
+ startSeg = i;
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_STRING;
+ startSeg = i;
+ }
+ } else if (state == SCE_C_WORD) {
+ if (!iswordchar(ch)) {
+ state = classifyWordVB(startSeg, i - 1, keywords, styler);
+ if (state == SCE_C_DEFAULT) {
+ startSeg = i;
+ if (ch == '\'') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_C_STRING;
+ }
+ }
+ }
+ } else {
+ if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ }
+ } else if (state == SCE_C_STRING) {
+ // VB doubles quotes to preserve them
+ if (ch == '\"') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_C_DEFAULT;
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ startSeg = i;
+ }
+ }
+ if (state == SCE_C_DEFAULT) { // One of the above succeeded
+ if (ch == '\'') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_C_STRING;
+ } else if (iswordstart(ch)) {
+ state = SCE_C_WORD;
+ }
+ }
+ }
+ }
+ if (startSeg < lengthDoc)
+ styler.ColourSegment(startSeg, lengthDoc, state);
+}
+
+static void classifyWordPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]);
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_P_IDENTIFIER;
+ if (0 == strcmp(prevWord, "class"))
+ chAttr = SCE_P_CLASSNAME;
+ else if (0 == strcmp(prevWord, "def"))
+ chAttr = SCE_P_DEFNAME;
+ else if (wordIsNumber)
+ chAttr = SCE_P_NUMBER;
+ else if (keywords.InList(s))
+ chAttr = SCE_P_WORD;
+ styler.ColourSegment(start, end, chAttr);
+ strcpy(prevWord, s);
+}
+
+static bool IsPyComment(StylingContext &styler, int pos, int len) {
+ return len>0 && styler[pos]=='#';
+}
+
+static void ColourisePyDoc(int codePage, int startPos, int length, int initStyle, WordList &keywords, StylingContext &styler) {
+ //Platform::DebugPrintf("Python coloured\n");
+ bool fold = styler.GetPropSet().GetInt("fold");
+ int whingeLevel = styler.GetPropSet().GetInt("tab.timmy.whinge.level");
+ char prevWord[200];
+ prevWord[0] = '\0';
+ if (length == 0)
+ return ;
+ int lineCurrent = styler.GetLine(startPos);
+ int spaceFlags = 0;
+ // TODO: Need to check previous line for indentation for both folding and bad indentation
+ int indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags, IsPyComment);
+
+ int state = initStyle & 31;
+ char chPrev = ' ';
+ char chPrev2 = ' ';
+ char chNext = styler[startPos];
+ char chNext2 = styler[startPos];
+ int startSeg = startPos;
+ int lengthDoc = startPos + length;
+ bool atStartLine = true;
+ for (int i = startPos; i <= lengthDoc; i++) {
+
+ if (atStartLine) {
+ if (whingeLevel == 1) {
+ styler.SetFlags((spaceFlags & wsInconsistent) ? 64 : 0, state);
+ } else if (whingeLevel == 2) {
+ styler.SetFlags((spaceFlags & wsSpaceTab) ? 64 : 0, state);
+ } else if (whingeLevel == 3) {
+ styler.SetFlags((spaceFlags & wsSpace) ? 64 : 0, state);
+ } else if (whingeLevel == 4) {
+ styler.SetFlags((spaceFlags & wsTab) ? 64 : 0, state);
+ }
+ atStartLine = false;
+ }
+
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ chNext2 = styler.SafeGetCharAt(i + 2);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
+ // Perform colourisation of white space and triple quoted strings at end of each line to allow
+ // tab marking to work inside white space and triple quoted strings
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ }
+
+ int lev = indentCurrent;
+ int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags, IsPyComment);
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+ // Only non whitespace lines can be headers
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ indentCurrent = indentNext;
+ if (fold) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ atStartLine = true;
+ }
+
+ if (IsLeadByte(codePage, ch)) { // dbcs
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ chPrev2 = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_P_STRINGEOL) {
+ if (ch != '\r' && ch != '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_P_DEFAULT;
+ startSeg = i;
+ }
+ }
+ if (state == SCE_P_DEFAULT) {
+ if (iswordstart(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_P_WORD;
+ startSeg = i;
+ } else if (ch == '#') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
+ startSeg = i;
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_P_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_P_STRING;
+ }
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ startSeg = i;
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_P_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_P_CHARACTER;
+ }
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ styler.ColourSegment(i, i, SCE_P_OPERATOR);
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_P_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordPy(startSeg, i - 1, keywords, styler, prevWord);
+ state = SCE_P_DEFAULT;
+ startSeg = i;
+ if (ch == '#') {
+ state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
+ } else if (ch == '\"') {
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_P_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_P_STRING;
+ }
+ } else if (ch == '\'') {
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_P_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_P_CHARACTER;
+ }
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i, SCE_P_OPERATOR);
+ startSeg = i + 1;
+ }
+ }
+ } else {
+ if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_P_DEFAULT;
+ startSeg = i;
+ }
+ } else if (state == SCE_P_STRING) {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_P_STRINGEOL;
+ startSeg = i;
+ } else if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_P_DEFAULT;
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_P_CHARACTER) {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_P_STRINGEOL;
+ startSeg = i;
+ } else if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_P_DEFAULT;
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_P_TRIPLE) {
+ if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_P_DEFAULT;
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_P_TRIPLEDOUBLE) {
+ if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_P_DEFAULT;
+ startSeg = i + 1;
+ }
+ }
+ }
+ chPrev2 = chPrev;
+ chPrev = ch;
+ }
+ if (startSeg <= lengthDoc) {
+ if (state == SCE_P_DEFAULT) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ } else if (state == SCE_P_WORD) {
+ classifyWordPy(startSeg, lengthDoc, keywords, styler, prevWord);
+ } else if (state == SCE_P_COMMENTLINE) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ } else if (state == SCE_P_COMMENTBLOCK) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ } else if (state == SCE_P_STRING) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ } else if (state == SCE_P_CHARACTER) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ } else if (state == SCE_P_TRIPLE) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ } else if (state == SCE_P_TRIPLEDOUBLE) {
+ styler.ColourSegment(startSeg, lengthDoc, state);
+ }
+ }
+}
+
+static void ColouriseBatchLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+ if (0 == strncmp(lineBuffer, "REM", 3)) {
+ styler.ColourSegment(0, lengthLine - 1, 1);
+ } else if (0 == strncmp(lineBuffer, "rem", 3)) {
+ styler.ColourSegment(0, lengthLine - 1, 1);
+ } else if (0 == strncmp(lineBuffer, "SET", 3)) {
+ styler.ColourSegment(0, lengthLine - 1, 2);
+ } else if (0 == strncmp(lineBuffer, "set", 3)) {
+ styler.ColourSegment(0, lengthLine - 1, 2);
+ } else if (lineBuffer[0] == ':') {
+ styler.ColourSegment(0, lengthLine - 1, 3);
+ } else {
+ styler.ColourSegment(0, lengthLine - 1, 0);
+ }
+}
+
+static void ColouriseBatchDoc(int startPos, int length, int, StylingContext &styler) {
+ char lineBuffer[1024];
+ unsigned int linePos = 0;
+ for (int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+ ColouriseBatchLine(lineBuffer, linePos, styler);
+ linePos = 0;
+ }
+ }
+ if (linePos > 0)
+ ColouriseBatchLine(lineBuffer, linePos, styler);
+}
+
+enum { eScriptNone, eScriptJS, eScriptVBS, eScriptPython };
+static int segIsScriptingIndicator(StylingContext &styler, unsigned int start, unsigned int end, int prevValue) {
+ char s[100];
+ s[0] = '\0';
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = tolower(styler[start + i]);
+ s[i + 1] = '\0';
+ }
+Platform::DebugPrintf("Scripting indicator [%s]\n", s);
+ if (strstr(s, "vbs"))
+ return eScriptVBS;
+ if (strstr(s, "pyth"))
+ return eScriptPython;
+ if (strstr(s, "javas"))
+ return eScriptJS;
+ if (strstr(s, "jscr"))
+ return eScriptJS;
+
+ return prevValue;
+}
+
+static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.') ||
+ (styler[start] == '-') || (styler[start] == '#');
+ char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
+ if (wordIsNumber) {
+ chAttr = SCE_H_NUMBER;
+ } else {
+ char s[100];
+ s[0] = '\0';
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = tolower(styler[start + i]);
+ s[i + 1] = '\0';
+ }
+ if (keywords.InList(s))
+ chAttr = SCE_H_ATTRIBUTE;
+ }
+ styler.ColourTo(end, chAttr);
+}
+
+static int classifyTagHTML(unsigned int start, unsigned int end,
+ WordList &keywords, StylingContext &styler) {
+ char s[100];
+ // Copy after the '<'
+ unsigned int i = 0;
+ for (int cPos=start; cPos <= end && i < 30; cPos++) {
+ char ch = styler[cPos];
+ if (ch != '<')
+ s[i++] = tolower(ch);
+ }
+ s[i] = '\0';
+ char chAttr = SCE_H_TAGUNKNOWN;
+ if (s[0] == '!' && s[1] == '-' && s[2] == '-') { //Comment
+ chAttr = SCE_H_COMMENT;
+ } else if (s[0] == '/') { // Closing tag
+ if (keywords.InList(s + 1))
+ chAttr = SCE_H_TAG;
+ } else {
+ if (keywords.InList(s)) {
+ chAttr = SCE_H_TAG;
+ if (0 == strcmp(s, "script"))
+ chAttr = SCE_H_SCRIPT;
+ }
+ }
+ styler.ColourTo(end, chAttr);
+ return chAttr;
+}
+
+static void classifyWordHTJS(unsigned int start, unsigned int end,
+ WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_HJ_WORD;
+ if (wordIsNumber)
+ chAttr = SCE_HJ_NUMBER;
+ else {
+ if (keywords.InList(s))
+ chAttr = SCE_HJ_KEYWORD;
+ }
+ styler.ColourTo(end, chAttr);
+}
+
+static void classifyWordHTJSA(unsigned int start, unsigned int end,
+ WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_HJA_WORD;
+ if (wordIsNumber)
+ chAttr = SCE_HJA_NUMBER;
+ else {
+ if (keywords.InList(s))
+ chAttr = SCE_HJA_KEYWORD;
+ }
+ styler.ColourTo(end, chAttr);
+}
+
+static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = tolower(styler[start + i]);
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_HB_IDENTIFIER;
+ if (wordIsNumber)
+ chAttr = SCE_HB_NUMBER;
+ else {
+ if (keywords.InList(s)) {
+ chAttr = SCE_HB_WORD;
+ if (strcmp(s, "rem") == 0)
+ chAttr = SCE_HB_COMMENTLINE;
+ }
+ }
+ styler.ColourTo(end, chAttr);
+ if (chAttr == SCE_HB_COMMENTLINE)
+ return SCE_HB_COMMENTLINE;
+ else
+ return SCE_HB_DEFAULT;
+}
+
+static int classifyWordHTVBA(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = tolower(styler[start + i]);
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_HBA_IDENTIFIER;
+ if (wordIsNumber)
+ chAttr = SCE_HBA_NUMBER;
+ else {
+ if (keywords.InList(s)) {
+ chAttr = SCE_HBA_WORD;
+ if (strcmp(s, "rem") == 0)
+ chAttr = SCE_HBA_COMMENTLINE;
+ }
+ }
+ styler.ColourTo(end, chAttr);
+ if (chAttr == SCE_HBA_COMMENTLINE)
+ return SCE_HBA_COMMENTLINE;
+ else
+ return SCE_HBA_DEFAULT;
+}
+
+static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]);
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_HP_IDENTIFIER;
+ if (0 == strcmp(prevWord, "class"))
+ chAttr = SCE_HP_CLASSNAME;
+ else if (0 == strcmp(prevWord, "def"))
+ chAttr = SCE_HP_DEFNAME;
+ else if (wordIsNumber)
+ chAttr = SCE_HP_NUMBER;
+ else if (keywords.InList(s))
+ chAttr = SCE_HP_WORD;
+ styler.ColourTo(end, chAttr);
+ strcpy(prevWord, s);
+}
+
+static void classifyWordHTPyA(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]);
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_HPA_IDENTIFIER;
+ if (0 == strcmp(prevWord, "class"))
+ chAttr = SCE_HPA_CLASSNAME;
+ else if (0 == strcmp(prevWord, "def"))
+ chAttr = SCE_HPA_DEFNAME;
+ else if (wordIsNumber)
+ chAttr = SCE_HPA_NUMBER;
+ else if (keywords.InList(s))
+ chAttr = SCE_HPA_WORD;
+ styler.ColourTo(end, chAttr);
+ strcpy(prevWord, s);
+}
+
+inline bool ishtmlwordchar(char ch) {
+ return isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#';
+}
+
+static bool InTagState(int state) {
+ return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||
+ state == SCE_H_SCRIPT ||
+ state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN ||
+ state == SCE_H_NUMBER || state == SCE_H_OTHER ||
+ state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING;
+}
+
+static bool isLineEnd(char ch) {
+ return ch == '\r' || ch == '\n';
+}
+
+static void ColouriseHyperTextDoc(int codePage, int startPos, int length,
+ int initStyle, WordList &keywords, WordList &keywords2, WordList &keywords3, WordList &keywords4,
+ StylingContext &styler) {
+
+ styler.StartAt(startPos, 127);
+ bool lastTagWasScript = false;
+ char prevWord[200];
+ prevWord[0] = '\0';
+ int scriptLanguage = eScriptJS;
+ int state = initStyle;
+ // If inside a tag, it may be a script tage, so reread from the start to ensure any language tas are seen
+ if (InTagState(state)) {
+ while ((startPos > 1) && (InTagState(styler.StyleAt(startPos - 1)))) {
+ startPos--;
+ }
+ state = SCE_H_DEFAULT;
+ }
+ styler.StartAt(startPos, 127);
+
+ int lineState = eScriptVBS;
+ int lineCurrent = styler.GetLine(startPos);
+ if (lineCurrent > 0)
+ lineState = styler.GetLineState(lineCurrent);
+ int defaultScript = lineState &0xff;
+ int beforeASP = (lineState >> 8) &0xff;
+ int inASP = (lineState >> 16) &0xff;
+
+ char chPrev = ' ';
+ char chPrev2 = ' ';
+ styler.StartSegment(startPos);
+ int lengthDoc = startPos + length;
+ for (int i = startPos; i <= lengthDoc; i++) {
+ char ch = styler[i];
+ char chNext = styler.SafeGetCharAt(i + 1);
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+
+ if (IsLeadByte(codePage, ch)) { // dbcs
+ chPrev2 = ' ';
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ // New line -> record any line state onto /next/ line
+ lineCurrent++;
+ styler.SetLineState(lineCurrent,
+ defaultScript | (beforeASP << 8) | (inASP << 16));
+ }
+
+ // Handle ASP even within other constructs as it is a preprocessor
+ if ((ch == '<') && (chNext == '%')) {
+ beforeASP = state;
+ styler.ColourTo(i - 1, state);
+ if (chNext2 == '@') {
+ styler.ColourTo(i + 2, SCE_H_ASP);
+ state = SCE_H_ASPAT;
+ i+=2;
+ } else {
+ if (defaultScript == eScriptVBS)
+ state = SCE_HBA_START;
+ else if (defaultScript == eScriptPython)
+ state = SCE_HPA_START;
+ else
+ state = SCE_HJA_START;
+ if (chNext2 == '=') {
+ styler.ColourTo(i + 2, SCE_H_ASP);
+ i+=2;
+ } else {
+ styler.ColourTo(i + 1, SCE_H_ASP);
+ i++;
+ }
+ }
+ inASP = 1;
+ continue;
+ }
+ if (inASP && (ch == '%') && (chNext == '>')) {
+ if (state == SCE_H_ASPAT)
+ defaultScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, defaultScript);
+ // Bounce out of any ASP mode
+ if (state == SCE_HJA_WORD) {
+ classifyWordHTJSA(styler.GetStartSegment(), i - 1, keywords2, styler);
+ } else if (state == SCE_HBA_WORD) {
+ classifyWordHTVBA(styler.GetStartSegment(), i - 1, keywords3, styler);
+ } else if (state == SCE_HPA_WORD) {
+ classifyWordHTPyA(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord);
+ } else {
+ styler.ColourTo(i - 1, state);
+ }
+ //if (state == SCE_H_ASPAT)
+ // styler.ColourTo(i+1, SCE_H_ASPAT);
+ //else
+ styler.ColourTo(i+1, SCE_H_ASP);
+ i++;
+ state = beforeASP;
+ beforeASP = SCE_H_DEFAULT;
+ inASP = 0;
+ continue;
+ }
+
+ if (state == SCE_H_DEFAULT) {
+ if (ch == '<') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ if (chNext == '?') {
+ styler.ColourTo(i + 1, SCE_H_XMLSTART);
+ i++;
+ ch = chNext;
+ }
+ } else if (ch == '&') {
+ styler.ColourTo(i - 1, SCE_H_DEFAULT);
+ state = SCE_H_ENTITY;
+ }
+ } else if (state == SCE_H_COMMENT) {
+ if ((ch == '>') && (chPrev == '-')) {
+ styler.ColourTo(i, state);
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_H_ENTITY) {
+ if (ch == ';') {
+ styler.ColourTo(i, state);
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_H_TAGUNKNOWN) {
+ if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
+ int eClass = classifyTagHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+ lastTagWasScript = eClass == SCE_H_SCRIPT;
+ if (lastTagWasScript) {
+ scriptLanguage = eScriptJS;
+ eClass = SCE_H_TAG;
+ }
+ if (ch == '>') {
+ styler.ColourTo(i, SCE_H_TAG);
+ if (lastTagWasScript) {
+ if (scriptLanguage == eScriptVBS)
+ state = SCE_HB_START;
+ else if (scriptLanguage == eScriptPython)
+ state = SCE_HP_START;
+ else
+ state = SCE_HJ_START;
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ } else {
+ if (eClass == SCE_H_COMMENT) {
+ state = SCE_H_COMMENT;
+ } else {
+ state = SCE_H_OTHER;
+ }
+ }
+ }
+ } else if (state == SCE_H_ATTRIBUTE) {
+ if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
+ if (lastTagWasScript)
+ scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, scriptLanguage);
+ classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+ if (ch == '>') {
+ styler.ColourTo(i, SCE_H_TAG);
+ if (lastTagWasScript) {
+ if (scriptLanguage == eScriptVBS)
+ state = SCE_HB_START;
+ else if (scriptLanguage == eScriptPython)
+ state = SCE_HP_START;
+ else
+ state = SCE_HJ_START;
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ } else {
+ state = SCE_H_OTHER;
+ }
+ }
+ } else if (state == SCE_H_ASP) {
+ if ((ch == '>') && (chPrev == '%')) {
+ styler.ColourTo(i, state);
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_H_ASPAT) {
+ if ((ch == '>') && (chPrev == '%')) {
+ styler.ColourTo(i, state);
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_H_OTHER) {
+ if (ch == '>') {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_H_TAG);
+ if (lastTagWasScript) {
+ if (scriptLanguage == eScriptVBS)
+ state = SCE_HB_START;
+ else if (scriptLanguage == eScriptPython)
+ state = SCE_HP_START;
+ else
+ state = SCE_HJ_START;
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_DOUBLESTRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_SINGLESTRING;
+ } else if (ch == '/' && chNext == '>') {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ } else if (ch == '?' && chNext == '>') {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_H_XMLEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ } else if (ishtmlwordchar(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_ATTRIBUTE;
+ }
+ } else if (state == SCE_H_DOUBLESTRING) {
+ if (ch == '\"') {
+ if (lastTagWasScript)
+ scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+ styler.ColourTo(i, SCE_H_DOUBLESTRING);
+ state = SCE_H_OTHER;
+ }
+ } else if (state == SCE_H_SINGLESTRING) {
+ if (ch == '\'') {
+ if (lastTagWasScript)
+ scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+ styler.ColourTo(i, SCE_H_SINGLESTRING);
+ state = SCE_H_OTHER;
+ }
+ } else if (state == SCE_HJ_DEFAULT || state == SCE_HJ_START) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_WORD;
+ } else if (ch == '/' && chNext == '*') {
+ styler.ColourTo(i - 1, state);
+ if (chNext2 == '*')
+ state = SCE_HJ_COMMENTDOC;
+ else
+ state = SCE_HJ_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_DOUBLESTRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_SINGLESTRING;
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_COMMENTLINE;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_HJ_SYMBOLS);
+ state = SCE_HJ_DEFAULT;
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HJ_START) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HJ_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler);
+ //styler.ColourTo(i - 1, eHTJSKeyword);
+ state = SCE_HJ_DEFAULT;
+ if (ch == '/' && chNext == '*') {
+ if (chNext2 == '*')
+ state = SCE_HJ_COMMENTDOC;
+ else
+ state = SCE_HJ_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_HJ_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HJ_DOUBLESTRING;
+ } else if (ch == '\'') {
+ state = SCE_HJ_SINGLESTRING;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HJ_SYMBOLS);
+ state = SCE_HJ_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HJ_COMMENT) {
+ if (ch == '/' && chPrev == '*') {
+ state = SCE_HJ_DEFAULT;
+ styler.ColourTo(i, SCE_HJ_COMMENT);
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_HJ_COMMENTDOC) {
+ if (ch == '/' && chPrev == '*') {
+ state = SCE_HJ_DEFAULT;
+ styler.ColourTo(i, SCE_HJ_COMMENTDOC);
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_HJ_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
+ state = SCE_HJ_DEFAULT;
+ } else if ((ch == '<') && (chNext == '/')) {
+ // Common to hide end script tag in comment
+ styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
+ state = SCE_H_TAGUNKNOWN;
+ }
+ } else if (state == SCE_HJ_DOUBLESTRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, SCE_HJ_DOUBLESTRING);
+ state = SCE_HJ_DEFAULT;
+ i++;
+ ch = chNext;
+ } else if (isLineEnd(ch)) {
+ styler.ColourTo(i-1, state);
+ state = SCE_HJ_STRINGEOL;
+ }
+ } else if (state == SCE_HJ_SINGLESTRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i, SCE_HJ_SINGLESTRING);
+ state = SCE_HJ_DEFAULT;
+ i++;
+ ch = chNext;
+ } else if (isLineEnd(ch)) {
+ styler.ColourTo(i-1, state);
+ state = SCE_HJ_STRINGEOL;
+ }
+ } else if (state == SCE_HJ_STRINGEOL) {
+ if (!isLineEnd(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJ_DEFAULT;
+ } else if (!isLineEnd(chNext)) {
+ styler.ColourTo(i, state);
+ state = SCE_HJ_DEFAULT;
+ }
+ } else if (state == SCE_HJA_DEFAULT || state == SCE_HJA_START) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_WORD;
+ } else if (ch == '/' && chNext == '*') {
+ styler.ColourTo(i - 1, state);
+ if (chNext2 == '*')
+ state = SCE_HJA_COMMENTDOC;
+ else
+ state = SCE_HJA_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_DOUBLESTRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_SINGLESTRING;
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_COMMENTLINE;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_HJA_SYMBOLS);
+ state = SCE_HJA_DEFAULT;
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HJA_START) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HJA_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordHTJSA(styler.GetStartSegment(), i - 1, keywords2, styler);
+ //styler.ColourTo(i - 1, eHTJSKeyword);
+ state = SCE_HJA_DEFAULT;
+ if (ch == '/' && chNext == '*') {
+ if (chNext2 == '*')
+ state = SCE_HJA_COMMENTDOC;
+ else
+ state = SCE_HJA_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_HJA_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HJA_DOUBLESTRING;
+ } else if (ch == '\'') {
+ state = SCE_HJA_SINGLESTRING;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HJA_SYMBOLS);
+ state = SCE_HJA_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HJA_COMMENT) {
+ if (ch == '/' && chPrev == '*') {
+ state = SCE_HJA_DEFAULT;
+ styler.ColourTo(i, SCE_HJA_COMMENT);
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_HJA_COMMENTDOC) {
+ if (ch == '/' && chPrev == '*') {
+ state = SCE_HJA_DEFAULT;
+ styler.ColourTo(i, SCE_HJA_COMMENTDOC);
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ }
+ } else if (state == SCE_HJA_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, SCE_HJA_COMMENTLINE);
+ state = SCE_HJA_DEFAULT;
+ } else if ((ch == '<') && (chNext == '/')) {
+ // Common to hide end script tag in comment
+ styler.ColourTo(i - 1, SCE_HJA_COMMENTLINE);
+ state = SCE_H_TAGUNKNOWN;
+ }
+ } else if (state == SCE_HJA_DOUBLESTRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, SCE_HJA_DOUBLESTRING);
+ state = SCE_HJA_DEFAULT;
+ i++;
+ ch = chNext;
+ } else if (isLineEnd(ch)) {
+ styler.ColourTo(i-1, state);
+ state = SCE_HJA_STRINGEOL;
+ }
+ } else if (state == SCE_HJA_SINGLESTRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i, SCE_HJA_SINGLESTRING);
+ state = SCE_HJA_DEFAULT;
+ i++;
+ ch = chNext;
+ } else if (isLineEnd(ch)) {
+ styler.ColourTo(i-1, state);
+ state = SCE_HJA_STRINGEOL;
+ }
+ } else if (state == SCE_HJA_STRINGEOL) {
+ if (!isLineEnd(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HJA_DEFAULT;
+ } else if (!isLineEnd(chNext)) {
+ styler.ColourTo(i, state);
+ state = SCE_HJA_DEFAULT;
+ }
+ } else if (state == SCE_HB_DEFAULT || state == SCE_HB_START) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_WORD;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_STRING;
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_COMMENTLINE;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_HB_DEFAULT);
+ state = SCE_HB_DEFAULT;
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HB_START) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HB_WORD) {
+ if (!iswordchar(ch)) {
+ state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler);
+ if (state == SCE_HB_DEFAULT) {
+ if (ch == '\"') {
+ state = SCE_HB_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HB_COMMENTLINE;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HB_DEFAULT);
+ state = SCE_HB_DEFAULT;
+ }
+ }
+ }
+ } else if (state == SCE_HB_STRING) {
+ if (ch == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_HB_DEFAULT;
+ i++;
+ ch = chNext;
+ } else if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i-1, state);
+ state = SCE_HB_STRINGEOL;
+ }
+ } else if (state == SCE_HB_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_DEFAULT;
+ } else if ((ch == '<') && (chNext == '/')) {
+ // Common to hide end script tag in comment
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ }
+ } else if (state == SCE_HB_STRINGEOL) {
+ if (!isLineEnd(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HB_DEFAULT;
+ } else if (!isLineEnd(chNext)) {
+ styler.ColourTo(i, state);
+ state = SCE_HB_DEFAULT;
+ }
+ } else if (state == SCE_HBA_DEFAULT || state == SCE_HBA_START) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_WORD;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_STRING;
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_COMMENTLINE;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_HBA_DEFAULT);
+ state = SCE_HBA_DEFAULT;
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HBA_START) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HBA_WORD) {
+ if (!iswordchar(ch)) {
+ state = classifyWordHTVBA(styler.GetStartSegment(), i - 1, keywords3, styler);
+ if (state == SCE_HBA_DEFAULT) {
+ if (ch == '\"') {
+ state = SCE_HBA_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HBA_COMMENTLINE;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HBA_DEFAULT);
+ state = SCE_HBA_DEFAULT;
+ }
+ }
+ }
+ } else if (state == SCE_HBA_STRING) {
+ if (ch == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_HBA_DEFAULT;
+ i++;
+ ch = chNext;
+ } else if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i-1, state);
+ state = SCE_HBA_STRINGEOL;
+ }
+ } else if (state == SCE_HBA_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_DEFAULT;
+ } else if ((ch == '<') && (chNext == '/')) {
+ // Common to hide end script tag in comment
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ }
+ } else if (state == SCE_HBA_STRINGEOL) {
+ if (!isLineEnd(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HBA_DEFAULT;
+ } else if (!isLineEnd(chNext)) {
+ styler.ColourTo(i, state);
+ state = SCE_HBA_DEFAULT;
+ }
+ } else if (state == SCE_HP_DEFAULT || state == SCE_HP_START) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HP_WORD;
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HP_COMMENTLINE;
+ } else if (ch == '#') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HP_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_HP_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HP_STRING;
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_HP_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HP_CHARACTER;
+ }
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_HP_OPERATOR);
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HP_START) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HP_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HP_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord);
+ state = SCE_HP_DEFAULT;
+ if (ch == '#') {
+ state = SCE_HP_COMMENTLINE;
+ } else if (ch == '\"') {
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_HP_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HP_STRING;
+ }
+ } else if (ch == '\'') {
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_HP_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HP_CHARACTER;
+ }
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HP_OPERATOR);
+ }
+ }
+ } else if (state == SCE_HP_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HP_DEFAULT;
+ }
+ } else if (state == SCE_HP_STRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_HP_DEFAULT;
+ }
+ } else if (state == SCE_HP_CHARACTER) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i, state);
+ state = SCE_HP_DEFAULT;
+ }
+ } else if (state == SCE_HP_TRIPLE) {
+ if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+ styler.ColourTo(i, state);
+ state = SCE_HP_DEFAULT;
+ }
+ } else if (state == SCE_HP_TRIPLEDOUBLE) {
+ if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_HP_DEFAULT;
+ }
+ } else if (state == SCE_HPA_DEFAULT || state == SCE_HPA_START) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HPA_WORD;
+ } else if ((ch == '<') && (chNext == '/')) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_H_TAGUNKNOWN;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HPA_COMMENTLINE;
+ } else if (ch == '#') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HPA_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, state);
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_HPA_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HPA_STRING;
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_HPA_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HPA_CHARACTER;
+ }
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_HPA_OPERATOR);
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HPA_START) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HPA_DEFAULT;
+ }
+ }
+ } else if (state == SCE_HPA_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordHTPyA(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord);
+ state = SCE_HPA_DEFAULT;
+ if (ch == '#') {
+ state = SCE_HPA_COMMENTLINE;
+ } else if (ch == '\"') {
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_HPA_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HPA_STRING;
+ }
+ } else if (ch == '\'') {
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_HPA_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ state = SCE_HPA_CHARACTER;
+ }
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HPA_OPERATOR);
+ }
+ }
+ } else if (state == SCE_HPA_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_HPA_DEFAULT;
+ }
+ } else if (state == SCE_HPA_STRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_HPA_DEFAULT;
+ }
+ } else if (state == SCE_HPA_CHARACTER) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i, state);
+ state = SCE_HPA_DEFAULT;
+ }
+ } else if (state == SCE_HPA_TRIPLE) {
+ if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+ styler.ColourTo(i, state);
+ state = SCE_HPA_DEFAULT;
+ }
+ } else if (state == SCE_HPA_TRIPLEDOUBLE) {
+ if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_HPA_DEFAULT;
+ }
+ }
+ if (state == SCE_HB_DEFAULT) { // One of the above succeeded
+ if (ch == '\"') {
+ state = SCE_HB_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HB_COMMENTLINE;
+ } else if (iswordstart(ch)) {
+ state = SCE_HB_WORD;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HB_DEFAULT);
+ }
+ }
+ if (state == SCE_HBA_DEFAULT) { // One of the above succeeded
+ if (ch == '\"') {
+ state = SCE_HBA_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HBA_COMMENTLINE;
+ } else if (iswordstart(ch)) {
+ state = SCE_HBA_WORD;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HBA_DEFAULT);
+ }
+ }
+ if (state == SCE_HJ_DEFAULT) { // One of the above succeeded
+ if (ch == '/' && chNext == '*') {
+ if (styler.SafeGetCharAt(i + 2) == '*')
+ state = SCE_HJ_COMMENTDOC;
+ else
+ state = SCE_HJ_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_HJ_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HJ_DOUBLESTRING;
+ } else if (ch == '\'') {
+ state = SCE_HJ_SINGLESTRING;
+ } else if (iswordstart(ch)) {
+ state = SCE_HJ_WORD;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HJ_SYMBOLS);
+ }
+ }
+ if (state == SCE_HJA_DEFAULT) { // One of the above succeeded
+ if (ch == '/' && chNext == '*') {
+ if (styler.SafeGetCharAt(i + 2) == '*')
+ state = SCE_HJA_COMMENTDOC;
+ else
+ state = SCE_HJA_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_HJA_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HJA_DOUBLESTRING;
+ } else if (ch == '\'') {
+ state = SCE_HJA_SINGLESTRING;
+ } else if (iswordstart(ch)) {
+ state = SCE_HJA_WORD;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_HJA_SYMBOLS);
+ }
+ }
+ chPrev2 = chPrev;
+ chPrev = ch;
+ }
+ styler.ColourTo(lengthDoc - 1, state);
+}
+
+static void ColourisePropsLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+ int i = 0;
+ while (isspace(lineBuffer[i]) && (i < lengthLine)) // Skip initial spaces
+ i++;
+ if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
+ styler.ColourSegment(0, lengthLine - 1, 1);
+ } else if (lineBuffer[i] == '[') {
+ styler.ColourSegment(0, lengthLine - 1, 2);
+ } else if (lineBuffer[i] == '@') {
+ styler.ColourSegment(0, i, 4);
+ if (lineBuffer[++i] == '=')
+ styler.ColourSegment(i, i, 3);
+ if (++i < lengthLine)
+ styler.ColourSegment(i, lengthLine - 1, 0);
+ } else {
+ while (lineBuffer[i] != '=' && (i < lengthLine)) // Search the '=' character
+ i++;
+ if (lineBuffer[i] == '=') {
+ styler.ColourSegment(0, i - 1, 0);
+ styler.ColourSegment(i, i, 3);
+ if (++i < lengthLine)
+ styler.ColourSegment(i, lengthLine - 1, 0);
+ } else
+ styler.ColourSegment(0, lengthLine - 1, 0);
+ }
+}
+
+static void ColourisePropsDoc(int startPos, int length, int, StylingContext &styler) {
+ char lineBuffer[1024];
+ unsigned int linePos = 0;
+ for (int i = startPos; i <= startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+ lineBuffer[linePos] = '\0';
+ ColourisePropsLine(lineBuffer, linePos, styler);
+ linePos = 0;
+ }
+ }
+ if (linePos > 0)
+ ColourisePropsLine(lineBuffer, linePos, styler);
+}
+
+static void ColouriseMakeLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+ int i = 0;
+ while (isspace(lineBuffer[i]) && (i < lengthLine))
+ i++;
+ if (lineBuffer[i] == '#' || lineBuffer[i] == '!') {
+ styler.ColourSegment(0, lengthLine - 1, 1);
+ } else {
+ styler.ColourSegment(0, lengthLine - 1, 0);
+ }
+}
+
+static void ColouriseMakeDoc(int startPos, int length, int, StylingContext &styler) {
+ char lineBuffer[1024];
+ unsigned int linePos = 0;
+ for (int i = startPos; i <= startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+ ColouriseMakeLine(lineBuffer, linePos, styler);
+ linePos = 0;
+ }
+ }
+ if (linePos > 0)
+ ColouriseMakeLine(lineBuffer, linePos, styler);
+}
+
+static void ColouriseErrorListLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+ if (lineBuffer[0] == '>') {
+ // Command or return status
+ styler.ColourSegment(0, lengthLine - 1, 4);
+ } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
+ styler.ColourSegment(0, lengthLine - 1, 1);
+ } else if (0 == strncmp(lineBuffer, "Error ", strlen("Error "))) {
+ // Borland error message
+ styler.ColourSegment(0, lengthLine - 1, 5);
+ } else if (0 == strncmp(lineBuffer, "Warning ", strlen("Warning "))) {
+ // Borland warning message
+ styler.ColourSegment(0, lengthLine - 1, 5);
+ } else {
+ // Look for <filename>:<line>:message
+ // Look for <filename>(line)message
+ // Look for <filename>(line,pos)message
+ int state = 0;
+ for (int i = 0; i < lengthLine; i++) {
+ if (state == 0 && lineBuffer[i] == ':' && isdigit(lineBuffer[i + 1])) {
+ state = 1;
+ } else if (state == 0 && lineBuffer[i] == '(') {
+ state = 10;
+ } else if (state == 1 && isdigit(lineBuffer[i])) {
+ state = 2;
+ } else if (state == 2 && lineBuffer[i] == ':') {
+ state = 3;
+ break;
+ } else if (state == 2 && !isdigit(lineBuffer[i])) {
+ state = 99;
+ } else if (state == 10 && isdigit(lineBuffer[i])) {
+ state = 11;
+ } else if (state == 11 && lineBuffer[i] == ',') {
+ state = 14;
+ } else if (state == 11 && lineBuffer[i] == ')') {
+ state = 12;
+ break;
+ } else if (state == 12 && lineBuffer[i] == ':') {
+ state = 13;
+ } else if (state == 14 && lineBuffer[i] == ')') {
+ state = 15;
+ break;
+ } else if (((state == 11) || (state == 14)) && !((lineBuffer[i] == ' ') || isdigit(lineBuffer[i]))) {
+ state = 99;
+ }
+ }
+ if (state == 3) {
+ styler.ColourSegment(0, lengthLine - 1, 2);
+ } else if ((state == 14) || (state == 15)) {
+ styler.ColourSegment(0, lengthLine - 1, 3);
+ } else {
+ styler.ColourSegment(0, lengthLine - 1, 0);
+ }
+ }
+}
+
+static void ColouriseErrorListDoc(int startPos, int length, int, StylingContext &styler) {
+ char lineBuffer[1024];
+ unsigned int linePos = 0;
+ for (int i = startPos; i <= startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+ ColouriseErrorListLine(lineBuffer, linePos, styler);
+ linePos = 0;
+ }
+ }
+ if (linePos > 0)
+ ColouriseErrorListLine(lineBuffer, linePos, styler);
+}
+
+static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+ char s[100];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+ for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+ s[i] = toupper(styler[start + i]);
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_C_IDENTIFIER;
+ if (wordIsNumber)
+ chAttr = SCE_C_NUMBER;
+ else {
+ if (keywords.InList(s))
+ chAttr = SCE_C_WORD;
+ }
+ styler.ColourSegment(start, end, chAttr);
+}
+
+static void ColouriseSQLDoc(int codePage, int startPos, int length,
+ int initStyle, WordList &keywords, StylingContext &styler) {
+
+ bool fold = styler.GetPropSet().GetInt("fold");
+ int lineCurrent = styler.GetLine(startPos);
+ int spaceFlags = 0;
+ int indentCurrent = 0;
+
+ int state = initStyle;
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ int startSeg = startPos;
+ int lengthDoc = startPos + length;
+ bool prevCr = false;
+ for (int i = startPos; i <= lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
+ int lev = indentCurrent;
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+ // Only non whitespace lines can be headers
+ int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
+ if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ if (fold) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ }
+
+ if (IsLeadByte(codePage, ch)) { // dbcs
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_DEFAULT) {
+ if (iswordstart(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_WORD;
+ startSeg = i;
+ } else if (ch == '/' && chNext == '*') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_COMMENT;
+ startSeg = i;
+ } else if (ch == '-' && chNext == '-') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_COMMENTLINE;
+ startSeg = i;
+ } else if (ch == '\'') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_STRING;
+ startSeg = i;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i - 1, state);
+ styler.ColourSegment(i, i, SCE_C_OPERATOR);
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_C_WORD) {
+ if (!iswordchar(ch)) {
+ classifyWordSQL(startSeg, i - 1, keywords, styler);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ if (ch == '/' && chNext == '*') {
+ state = SCE_C_COMMENT;
+ } else if (ch == '-' && chNext == '-') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\'') {
+ state = SCE_C_STRING;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+ startSeg = i + 1;
+ }
+ }
+ } else {
+ if (state == SCE_C_COMMENT) {
+ if (ch == '/' && chPrev == '*' && (
+ (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
+ state = SCE_C_DEFAULT;
+ styler.ColourSegment(startSeg, i, state);
+ startSeg = i + 1;
+ }
+ } else if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourSegment(startSeg, i - 1, state);
+ state = SCE_C_DEFAULT;
+ startSeg = i;
+ }
+ } else if (state == SCE_C_STRING) {
+ if (ch == '\'') {
+ if ( chNext == '\'' ) {
+ i++;
+ } else {
+ styler.ColourSegment(startSeg, i, state);
+ state = SCE_C_DEFAULT;
+ i++;
+ startSeg = i;
+ }
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ }
+ if (state == SCE_C_DEFAULT) { // One of the above succeeded
+ if (ch == '/' && chNext == '*') {
+ state = SCE_C_COMMENT;
+ } else if (ch == '-' && chNext == '-') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\'') {
+ state = SCE_C_STRING;
+ } else if (iswordstart(ch)) {
+ state = SCE_C_WORD;
+ } else if (isoperator(ch)) {
+ styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+ startSeg = i + 1;
+ }
+ }
+ }
+ chPrev = ch;
+ }
+ if (startSeg < lengthDoc)
+ styler.ColourSegment(startSeg, lengthDoc - 1, state);
+}
+
+void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle,
+ int language, WordList *keywordlists[], StylingContext &styler) {
+ //Platform::DebugPrintf("ColouriseDoc <%s>\n", language);
+ if (language == SCLEX_PYTHON) {
+ // Python uses a different mask because bad indentation is marked by oring with 32
+ styler.StartAt(startPos, 127);
+ ColourisePyDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+ } else if (language == SCLEX_PERL) {
+ // Lexer for perl often has to backtrack to start of current style to determine
+ // which characters are being used as quotes, how deeply nested is the
+ // start position and what the termination string is for here documents
+ ColourisePerlDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+ } else if ((language == SCLEX_HTML) || (language == SCLEX_XML)) {
+ // Lexer for HTML requires more lexical states (6 bits worth) than most lexers
+ ColouriseHyperTextDoc(codePage, startPos, lengthDoc, initStyle,
+ *keywordlists[0], *keywordlists[1], *keywordlists[2], *keywordlists[3], styler);
+ } else {
+ styler.StartAt(startPos);
+ if (language == SCLEX_CPP) {
+ ColouriseCppDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+ } else if (language == SCLEX_SQL) {
+ ColouriseSQLDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+ } else if (language == SCLEX_VB) {
+ ColouriseVBDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+ } else if (language == SCLEX_PROPERTIES) {
+ ColourisePropsDoc(startPos, lengthDoc, initStyle, styler);
+ } else if (language == SCLEX_ERRORLIST) {
+ ColouriseErrorListDoc(startPos, lengthDoc, initStyle, styler);
+ } else if (language == SCLEX_MAKEFILE) {
+ ColouriseMakeDoc(startPos, lengthDoc, initStyle, styler);
+ } else if (language == SCLEX_BATCH) {
+ ColouriseBatchDoc(startPos, lengthDoc, initStyle, styler);
+ } else {
+ // Null language means all style bytes are 0 so just mark the end - no need to fill in.
+ styler.StartAt(startPos + lengthDoc - 1);
+ styler.ColourSegment(0, 0, 0);
+ }
+ }
+}
diff --git a/src/LineMarker.cxx b/src/LineMarker.cxx
new file mode 100644
index 000000000..9afccb822
--- /dev/null
+++ b/src/LineMarker.cxx
@@ -0,0 +1,125 @@
+// Scintilla source code edit control
+// LineMarker.cxx - defines the look of a line marker in the margin
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "LineMarker.h"
+
+void LineMarker::Draw(Surface *surface, PRectangle &rc) {
+ int minDim = Platform::Minimum(rc.Width(), rc.Height());
+ minDim--; // Ensure does not go beyond edge
+ int centreX = (rc.right + rc.left) / 2;
+ int centreY = (rc.bottom + rc.top) / 2;
+ int dimOn2 = minDim / 2;
+ int dimOn4 = minDim / 4;
+ if (rc.Width() > (rc.Height() * 2)) {
+ // Wide column is line number so move to left to try to avoid overlapping number
+ centreX = rc.left + dimOn2 + 1;
+ }
+ if (markType == SC_MARK_ROUNDRECT) {
+ PRectangle rcRounded = rc;
+ rcRounded.left = rc.left + 1;
+ rcRounded.right = rc.right - 1;
+ surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated);
+ } else if (markType == SC_MARK_CIRCLE) {
+ PRectangle rcCircle;
+ rcCircle.left = centreX - dimOn2;
+ rcCircle.top = centreY - dimOn2;
+ rcCircle.right = centreX + dimOn2;
+ rcCircle.bottom = centreY + dimOn2;
+ surface->Ellipse(rcCircle, fore.allocated, back.allocated);
+ } else if (markType == SC_MARK_ARROW) {
+ Point pts[] = {
+ Point(centreX - dimOn4, centreY - dimOn2),
+ Point(centreX - dimOn4, centreY + dimOn2),
+ Point(centreX + dimOn2 - dimOn4, centreY),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_ARROWDOWN) {
+ Point pts[] = {
+ Point(centreX - dimOn2, centreY - dimOn4),
+ Point(centreX + dimOn2, centreY - dimOn4),
+ Point(centreX, centreY + dimOn2 - dimOn4),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_PLUS) {
+ int armSize = dimOn2-2;
+ Point xpts[] = {
+ Point(centreX - armSize, centreY),
+ Point(centreX, centreY),
+ Point(centreX, centreY - armSize),
+ Point(centreX, centreY - armSize),
+ Point(centreX, centreY),
+ Point(centreX + armSize, centreY),
+ Point(centreX + armSize, centreY),
+ Point(centreX, centreY),
+ Point(centreX, centreY + armSize),
+ Point(centreX, centreY + armSize),
+ Point(centreX, centreY),
+ Point(centreX - armSize, centreY),
+ };
+ Point pts[] = {
+ Point(centreX - armSize, centreY - 1),
+ Point(centreX - 1, centreY - 1),
+ Point(centreX - 1, centreY - armSize),
+ Point(centreX + 1, centreY - armSize),
+ Point(centreX + 1, centreY - 1),
+ Point(centreX + armSize, centreY -1),
+ Point(centreX + armSize, centreY +1),
+ Point(centreX + 1, centreY + 1),
+ Point(centreX + 1, centreY + armSize),
+ Point(centreX - 1, centreY + armSize),
+ Point(centreX - 1, centreY + 1),
+ Point(centreX - armSize, centreY + 1),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_MINUS) {
+ int armSize = dimOn2-2;
+ Point pts[] = {
+ Point(centreX - armSize, centreY - 1),
+ Point(centreX + armSize, centreY -1),
+ Point(centreX + armSize, centreY +1),
+ Point(centreX - armSize, centreY + 1),
+ };
+ Point xpts[] = {
+ Point(centreX - armSize, centreY),
+ Point(centreX + armSize, centreY),
+ Point(centreX + armSize, centreY),
+ Point(centreX - armSize, centreY),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_SMALLRECT) {
+ PRectangle rcSmall;
+ rcSmall.left = rc.left + 1;
+ rcSmall.top = rc.top + 2;
+ rcSmall.right = rc.right - 1;
+ rcSmall.bottom = rc.bottom - 2;
+ surface->RectangleDraw(rcSmall, fore.allocated, back.allocated);
+ } else if (markType == SC_MARK_EMPTY) {
+ // An invisible marker so don't draw anything
+ } else { // SC_MARK_SHORTARROW
+ Point pts[] = {
+ Point(centreX, centreY + dimOn2),
+ Point(centreX + dimOn2, centreY),
+ Point(centreX, centreY - dimOn2),
+ Point(centreX, centreY - dimOn4),
+ Point(centreX - dimOn4, centreY - dimOn4),
+ Point(centreX - dimOn4, centreY + dimOn4),
+ Point(centreX, centreY + dimOn4),
+ Point(centreX, centreY + dimOn2),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+ }
+}
diff --git a/src/LineMarker.h b/src/LineMarker.h
new file mode 100644
index 000000000..f22241bb1
--- /dev/null
+++ b/src/LineMarker.h
@@ -0,0 +1,22 @@
+// Scintilla source code edit control
+// LineMarker.h - defines the look of a line marker in the margin
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef LINEMARKER_H
+#define LINEMARKER_H
+
+class LineMarker {
+public:
+ int markType;
+ ColourPair fore;
+ ColourPair back;
+ LineMarker() {
+ markType = SC_MARK_CIRCLE;
+ fore = Colour(0,0,0);
+ back = Colour(0xff,0xff,0xff);
+ }
+ void Draw(Surface *surface, PRectangle &rc);
+};
+
+#endif
diff --git a/src/PropSet.cxx b/src/PropSet.cxx
new file mode 100644
index 000000000..7e2a906a4
--- /dev/null
+++ b/src/PropSet.cxx
@@ -0,0 +1,399 @@
+// SciTE - Scintilla based Text Editor
+// PropSet.cxx - a java style properties file module
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// Maintain a dictionary of properties
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+
+bool EqualCaseInsensitive(const char *a, const char *b) {
+#if PLAT_GTK
+ return 0 == strcasecmp(a, b);
+#elif PLAT_WIN
+ return 0 == stricmp(a, b);
+#elif PLAT_WX
+ return 0 == wxStricmp(a, b);
+#endif
+}
+
+// Get a line of input. If end of line escaped with '\\' then continue reading.
+static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
+ bool continuation = true;
+ while ((len > 1) && lenData > 0) {
+ char ch = *fpc;
+ fpc++;
+ lenData--;
+ if ((ch == '\r') || (ch == '\n')) {
+ if (!continuation) {
+ if ((lenData > 0) && (ch == '\r') && ((*fpc) == '\n')) {
+ // munch the second half of a crlf
+ fpc++;
+ lenData--;
+ }
+ *s++ = '\0';
+ return true;
+ }
+ } else if ((ch == '\\') && (lenData > 0) && ((*fpc == '\r') || (*fpc == '\n'))) {
+ continuation = true;
+ } else {
+ continuation = false;
+ *s++ = ch;
+ len--;
+ }
+ }
+ return false;
+}
+
+PropSet::PropSet() {
+ superPS = 0;
+ size = 10;
+ used = 0;
+ vals = new char * [size];
+}
+
+PropSet::~PropSet() {
+ superPS = 0;
+ Clear();
+ delete []vals;
+}
+
+void PropSet::EnsureCanAddEntry() {
+ if (used >= size - 2) {
+ int newsize = size + 10;
+ char **newvals = new char * [newsize];
+
+ for (int i = 0; i < used; i++) {
+ newvals[i] = vals[i];
+ }
+ delete []vals;
+ vals = newvals;
+ size = newsize;
+ }
+}
+
+void PropSet::Set(const char *key, const char *val) {
+ EnsureCanAddEntry();
+ for (int i = 0; i < used; i += 2) {
+ if (EqualCaseInsensitive(vals[i], key)) {
+ // Replace current value
+ delete [](vals[i + 1]);
+ vals[i + 1] = StringDup(val);
+ return;
+ }
+ }
+ // Not found
+ vals[used++] = StringDup(key);
+ vals[used++] = StringDup(val);
+}
+
+void PropSet::Set(char *keyval) {
+ char *eqat = strchr(keyval, '=');
+ if (eqat) {
+ *eqat = '\0';
+ Set(keyval, eqat + 1);
+ *eqat = '=';
+ }
+}
+
+SString PropSet::Get(const char *key) {
+ for (int i = 0; i < used; i += 2) {
+ if (EqualCaseInsensitive(vals[i], key)) {
+ return vals[i + 1];
+ }
+ }
+ if (superPS) {
+ // Failed here, so try in base property set
+ return superPS->Get(key);
+ } else {
+ return "";
+ }
+}
+
+int PropSet::GetInt(const char *key, int defaultValue) {
+ SString val = Get(key);
+ if (val.length())
+ return Get(key).value();
+ else
+ return defaultValue;
+}
+
+bool isprefix(const char *target, const char *prefix) {
+ while (*target && *prefix) {
+ if (toupper(*target) != toupper(*prefix))
+ return false;
+ target++;
+ prefix++;
+ }
+ if (*prefix)
+ return false;
+ else
+ return true;
+}
+
+bool issuffix(const char *target, const char *suffix) {
+ int lentarget = strlen(target);
+ int lensuffix = strlen(suffix);
+ if (lensuffix > lentarget)
+ return false;
+ for (int i = lensuffix - 1; i >= 0; i--) {
+ if (toupper(target[i + lentarget - lensuffix]) != toupper(suffix[i]))
+ return false;
+ }
+ return true;
+}
+
+SString PropSet::GetWild(const char *keybase, const char *filename) {
+ for (int i = 0; i < used; i += 2) {
+ if (isprefix(vals[i], keybase)) {
+ char *orgkeyfile = vals[i] + strlen(keybase);
+ char *keyfile = NULL;
+
+ if (strstr(orgkeyfile, "$(") == orgkeyfile) {
+ char *cpendvar = strchr(orgkeyfile, ')');
+ if (cpendvar) {
+ int lenvar = cpendvar - orgkeyfile - 2; // Subtract the $()
+ char *var = static_cast<char *>(malloc(lenvar + 1));
+ strncpy(var, orgkeyfile + 2, lenvar);
+ var[lenvar] = '\0';
+ SString s = Get(var);
+ free(var);
+ keyfile = strdup(s.c_str());
+ }
+ }
+ char *keyptr = keyfile;
+
+ if (keyfile == NULL)
+ keyfile = orgkeyfile;
+
+ for (; ; ) {
+ char *del = strchr(keyfile, ';');
+ if (del == NULL)
+ del = keyfile + strlen(keyfile);
+ char delchr = *del;
+ *del = '\0';
+ if (*keyfile == '*') {
+ if (issuffix(filename, keyfile + 1)) {
+ *del = delchr;
+ free(keyptr);
+ return vals[i + 1];
+ }
+ } else if (EqualCaseInsensitive(keyfile, filename)) {
+ *del = delchr;
+ free(keyptr);
+ return vals[i + 1];
+ }
+ if (delchr == '\0')
+ break;
+ *del = delchr;
+ keyfile = del + 1;
+ }
+ free(keyptr);
+
+ if (EqualCaseInsensitive(vals[i], keybase)) {
+ return vals[i + 1];
+ }
+ }
+ }
+ if (superPS) {
+ // Failed here, so try in base property set
+ return superPS->GetWild(keybase, filename);
+ } else {
+ return "";
+ }
+}
+
+SString PropSet::GetNewExpand(const char *keybase, const char *filename) {
+ char *base = StringDup(GetWild(keybase, filename).c_str());
+ char *cpvar = strstr(base, "$(");
+ while (cpvar) {
+ char *cpendvar = strchr(cpvar, ')');
+ if (cpendvar) {
+ int lenvar = cpendvar - cpvar - 2; // Subtract the $()
+ char *var = new char[lenvar + 1];
+ strncpy(var, cpvar + 2, lenvar);
+ var[lenvar] = '\0';
+ SString val = GetWild(var, filename);
+ int newlenbase = strlen(base) + val.length() - lenvar;
+ char *newbase = new char[newlenbase];
+ strncpy(newbase, base, cpvar - base);
+ strcpy(newbase + (cpvar - base), val.c_str());
+ strcpy(newbase + (cpvar - base) + val.length(), cpendvar + 1);
+ delete []var;
+ delete []base;
+ base = newbase;
+ }
+ cpvar = strstr(base, "$(");
+ }
+ SString sret = base;
+ delete []base;
+ return sret;
+}
+
+void PropSet::Clear() {
+ for (int i = 0; i < used; i++) {
+ delete [](vals[i]);
+ vals[i] = 0;
+ }
+ used = 0;
+}
+
+void PropSet::ReadFromMemory(const char *data, int len) {
+ if (len > 0) {
+ const char *pd = data;
+ char linebuf[60000];
+ while (GetFullLine(pd, len, linebuf, sizeof(linebuf))) {
+ if (isalpha(linebuf[0]))
+ Set(linebuf);
+ }
+ }
+}
+
+void PropSet::Read(const char *filename) {
+ //printf("Opening properties <%s>\n", filename);
+ Clear();
+ char propsData[60000];
+ FILE *rcfile = fopen(filename, "rb");
+ if (rcfile) {
+ int lenFile = fread(propsData, 1, sizeof(propsData), rcfile);
+ fclose(rcfile);
+ ReadFromMemory(propsData, lenFile);
+ } else {
+ //printf("Could not open <%s>\n", filename);
+ }
+}
+
+static bool iswordsep(char ch, bool onlyLineEnds) {
+ if (!isspace(ch))
+ return false;
+ if (!onlyLineEnds)
+ return true;
+ return ch == '\r' || ch == '\n';
+}
+
+// Creates an array that points into each word in the string and puts \0 terminators
+// after each word.
+static char **ArrayFromWordList(char *wordlist, bool onlyLineEnds = false) {
+ char prev = '\n';
+ int words = 0;
+ for (int j = 0; wordlist[j]; j++) {
+ if (!iswordsep(wordlist[j], onlyLineEnds) && iswordsep(prev, onlyLineEnds))
+ words++;
+ prev = wordlist[j];
+ }
+ char **keywords = new char * [words + 1];
+ if (keywords) {
+ words = 0;
+ prev = '\0';
+ int len = strlen(wordlist);
+ for (int k = 0; k < len; k++) {
+ if (!iswordsep(wordlist[k], onlyLineEnds)) {
+ if (!prev) {
+ keywords[words] = &wordlist[k];
+ words++;
+ }
+ } else {
+ wordlist[k] = '\0';
+ }
+ prev = wordlist[k];
+ }
+ keywords[words] = &wordlist[len];
+ }
+ return keywords;
+}
+
+void WordList::Clear() {
+ if (words) {
+ delete []words;
+ delete []list;
+ }
+ words = 0;
+ list = 0;
+ len = 0;
+}
+
+void WordList::Set(const char *s) {
+ len = 0;
+ list = StringDup(s);
+ words = ArrayFromWordList(list, onlyLineEnds);
+}
+
+char *WordList::Allocate(int size) {
+ list = new char[size + 1];
+ list[size] = '\0';
+ return list;
+}
+
+void WordList::SetFromAllocated() {
+ len = 0;
+ words = ArrayFromWordList(list, onlyLineEnds);
+}
+
+// Shell sort based upon public domain C implementation by Raymond Gardner 1991
+// Used here because of problems with mingw qsort.
+static void SortWordList(char **words, unsigned int len) {
+ unsigned int gap = len / 2;
+
+ while (gap > 0) {
+ unsigned int i = gap;
+ while (i < len) {
+ unsigned int j = i;
+ char **a = words + j;
+ do {
+ j -= gap;
+ char **b = a;
+ a -= gap;
+ if (strcmp(*a, *b) > 0) {
+ char *tmp = *a;
+ *a = *b;
+ *b = tmp;
+ } else {
+ break;
+ }
+ } while (j >= gap);
+ i++;
+ }
+ gap = gap / 2;
+ }
+}
+
+bool WordList::InList(const char *s) {
+ if (0 == words)
+ return false;
+ if (len == 0) {
+ for (int i = 0; words[i][0]; i++)
+ len++;
+ SortWordList(words, len);
+ for (int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
+ starts[k] = -1;
+ for (int l = len - 1; l >= 0; l--) {
+ unsigned char indexChar = words[l][0];
+ starts[indexChar] = l;
+ }
+ }
+ unsigned char firstChar = s[0];
+ int j = starts[firstChar];
+ if (j >= 0) {
+ while (words[j][0] == firstChar) {
+ if (s[1] == words[j][1]) {
+ const char *a = words[j] + 1;
+ const char *b = s + 1;
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ if (!*a && !*b)
+ return true;
+ }
+ j++;
+ }
+ }
+ return false;
+}
diff --git a/src/SVector.h b/src/SVector.h
new file mode 100644
index 000000000..7bc948738
--- /dev/null
+++ b/src/SVector.h
@@ -0,0 +1,110 @@
+// Scintilla source code edit control
+// SVector.h - a simple expandable vector
+// Copyright 1998-1999 by Neil Hodgson <neilh@hare.net.au>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SVECTOR_H
+#define SVECTOR_H
+
+// A simple expandable vector.
+// T must support assignment.
+// Storage not allocated for elements until an element is used.
+// This makes it very lightweight unless used so is a good match for optional features.
+template<class T, int sizeIncrement>
+class SVector {
+ T *v;
+ unsigned int size; // Number of elements allocated
+ unsigned int len; // Number of elements in vector
+ bool allocFailure; // A memory allocation call has failed
+
+ // Internally allocate more elements than the user wants to avoid
+ // thrashng the memory allocator
+ void SizeTo(int newSize) {
+ if (newSize < sizeIncrement)
+ newSize += sizeIncrement;
+ else
+ newSize = (newSize * 3) / 2;
+ T* newv = new T[newSize];
+ if (!newv) {
+ allocFailure = true;
+ return;
+ }
+ size = newSize;
+ for (int i=0; i<len; i++) {
+ newv[i] = v[i];
+ }
+ delete []v;
+ v = newv;
+ }
+
+public:
+ SVector() {
+ allocFailure = false;
+ v = 0;
+ len = 0;
+ size = 0;
+ }
+ ~SVector() {
+ Free();
+ }
+ SVector(const SVector &other) {
+ allocFailure = false;
+ v = 0;
+ len = 0;
+ size = 0;
+ if (other.Length() > 0) {
+ SizeTo(other.Length());
+ if (!allocFailure) {
+ for (int i=0;i<other.Length();i++)
+ v[i] = other.v[i];
+ len = other.Length();
+ }
+ }
+ }
+ SVector &operator=(const SVector &other) {
+ if (this != &other) {
+ delete []v;
+ allocFailure = false;
+ v = 0;
+ len = 0;
+ size = 0;
+ if (other.Length() > 0) {
+ SizeTo(other.Length());
+ if (!allocFailure) {
+ for (int i=0;i<other.Length();i++)
+ v[i] = other.v[i];
+ }
+ len = other.Length();
+ }
+ }
+ return *this;
+ }
+ T &operator[](unsigned int i) {
+ if (i >= len) {
+ if (i >= size) {
+ SizeTo(i);
+ }
+ len = i+1;
+ }
+ return v[i];
+ }
+ void Free() {
+ delete []v;
+ v = 0;
+ size = 0;
+ len = 0;
+ }
+ void SetLength(int newLen) {
+ if (newLength > len) {
+ if (newLength >= size) {
+ SizeTo(newLength);
+ }
+ }
+ len = newLen;
+ }
+ int Length() const {
+ return len;
+ }
+};
+
+#endif
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
new file mode 100644
index 000000000..0ca299bd2
--- /dev/null
+++ b/src/ScintillaBase.cxx
@@ -0,0 +1,397 @@
+// Scintilla source code edit control
+// ScintillaBase.cxx - an enhanced subclass of Editor with calltips, autocomplete and context menu
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "AutoComplete.h"
+#include "Document.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+ScintillaBase::ScintillaBase() {
+#ifdef SCI_LEXER
+ lexLanguage = SCLEX_CONTAINER;
+ for (int wl=0;wl<numWordLists;wl++)
+ keyWordLists[wl] = new WordList;
+#endif
+}
+
+ScintillaBase::~ScintillaBase() {}
+
+void ScintillaBase::Finalise() {
+ popup.Destroy();
+}
+
+void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
+ Editor::RefreshColourPalette(pal, want);
+ ct.RefreshColourPalette(pal, want);
+}
+
+void ScintillaBase::AddChar(char ch) {
+ bool acActiveBeforeCharAdded = ac.Active();
+ Editor::AddChar(ch);
+ if (acActiveBeforeCharAdded)
+ AutoCompleteChanged(ch);
+}
+
+void ScintillaBase::Command(int cmdId) {
+
+ switch (cmdId) {
+
+ case idAutoComplete: // Nothing to do
+ break;
+
+ case idCallTip: // Nothing to do
+ break;
+
+ case idcmdUndo:
+ WndProc(WM_UNDO, 0, 0);
+ break;
+
+ case idcmdRedo:
+ WndProc(SCI_REDO, 0, 0);
+ break;
+
+ case idcmdCut:
+ WndProc(WM_CUT, 0, 0);
+ break;
+
+ case idcmdCopy:
+ WndProc(WM_COPY, 0, 0);
+ break;
+
+ case idcmdPaste:
+ WndProc(WM_PASTE, 0, 0);
+ break;
+
+ case idcmdDelete:
+ WndProc(WM_CLEAR, 0, 0);
+ break;
+
+ case idcmdSelectAll:
+ WndProc(SCI_SELECTALL, 0, 0);
+ break;
+ }
+}
+
+int ScintillaBase::KeyCommand(UINT iMessage) {
+ // Most key commands cancel autocompletion mode
+ if (ac.Active()) {
+ switch (iMessage) {
+ // Except for these
+ case SCI_LINEDOWN:
+ AutoCompleteMove(1);
+ return 0;
+ case SCI_LINEUP:
+ AutoCompleteMove( -1);
+ return 0;
+ case SCI_PAGEDOWN:
+ AutoCompleteMove(5);
+ return 0;
+ case SCI_PAGEUP:
+ AutoCompleteMove( -5);
+ return 0;
+ case SCI_VCHOME:
+ AutoCompleteMove( -5000);
+ return 0;
+ case SCI_LINEEND:
+ AutoCompleteMove(5000);
+ return 0;
+ case SCI_DELETEBACK:
+ DelCharBack();
+ AutoCompleteChanged();
+ EnsureCaretVisible();
+ return 0;
+ case SCI_TAB:
+ AutoCompleteCompleted();
+ return 0;
+
+ default:
+ ac.Cancel();
+ }
+ }
+
+ if (ct.inCallTipMode) {
+ if (
+ (iMessage != SCI_CHARLEFT) &&
+ (iMessage != SCI_CHARLEFTEXTEND) &&
+ (iMessage != SCI_CHARRIGHT) &&
+ (iMessage != SCI_CHARLEFTEXTEND) &&
+ (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
+ (iMessage != SCI_DELETEBACK)
+ ) {
+ ct.CallTipCancel();
+ }
+ if (iMessage == SCI_DELETEBACK) {
+ if (currentPos <= ct.posStartCallTip) {
+ ct.CallTipCancel();
+ }
+ }
+ }
+ return Editor::KeyCommand(iMessage);
+}
+
+void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
+ //Platform::DebugPrintf("AutoCOmplete %s\n", list);
+ ct.CallTipCancel();
+
+ ac.Start(wDraw, idAutoComplete, currentPos, lenEntered);
+
+ PRectangle rcClient = GetClientRectangle();
+ Point pt = LocationFromPosition(currentPos-lenEntered);
+
+ //Platform::DebugPrintf("Auto complete %x\n", lbAutoComplete);
+ int heightLB = 100;
+ int widthLB = 100;
+ if (pt.x >= rcClient.right - widthLB) {
+ HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB);
+ Redraw();
+ pt = LocationFromPosition(currentPos);
+ }
+ PRectangle rcac;
+ rcac.left = pt.x - 5;
+ if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
+ pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above.
+ rcac.top = pt.y - heightLB;
+ if (rcac.top < 0) {
+ heightLB += rcac.top;
+ rcac.top = 0;
+ }
+ } else {
+ rcac.top = pt.y + vs.lineHeight;
+ }
+ rcac.right = rcac.left + widthLB;
+ rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
+ ac.lb.SetPositionRelative(rcac, wMain);
+ ac.lb.SetFont(vs.styles[0].font);
+
+ int maxStrLen = ac.SetList(list);
+
+ // Fiddle the position of the list so it is right next to the target and wide enough for all its strings
+ PRectangle rcList = ac.lb.GetPosition();
+ int heightAlloced = rcList.bottom - rcList.top;
+ // Make an allowance for large strings in list
+ rcList.left = pt.x - 5;
+ rcList.right = rcList.left + Platform::Maximum(widthLB, maxStrLen * 8 + 16);
+ if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
+ pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above.
+ rcList.top = pt.y - heightAlloced;
+ } else {
+ rcList.top = pt.y + vs.lineHeight;
+ }
+ rcList.bottom = rcList.top + heightAlloced;
+ ac.lb.SetPositionRelative(rcList, wMain);
+ //lbAutoComplete.SetPosition(rcList);
+ ac.Show();
+}
+
+void ScintillaBase::AutoCompleteCancel() {
+ ac.Cancel();
+}
+
+void ScintillaBase::AutoCompleteMove(int delta) {
+ ac.Move(delta);
+}
+
+void ScintillaBase::AutoCompleteChanged(char ch) {
+ if (currentPos <= ac.posStart) {
+ ac.Cancel();
+ } else if (ac.IsStopChar(ch)) {
+ ac.Cancel();
+ } else {
+ char wordCurrent[1000];
+ int i;
+ int startWord = ac.posStart - ac.startLen;
+ for (i = startWord; i < currentPos; i++)
+ wordCurrent[i - startWord] = pdoc->CharAt(i);
+ wordCurrent[i - startWord] = '\0';
+ ac.Select(wordCurrent);
+ }
+}
+
+void ScintillaBase::AutoCompleteCompleted() {
+ int item = ac.lb.GetSelection();
+ char selected[200];
+ if (item != -1) {
+ ac.lb.GetValue(item, selected, sizeof(selected));
+ }
+ ac.Cancel();
+ if (currentPos != ac.posStart) {
+ pdoc->DeleteChars(ac.posStart, currentPos - ac.posStart);
+ }
+ SetEmptySelection(ac.posStart);
+ if (item != -1) {
+ pdoc->InsertString(currentPos, selected + ac.startLen);
+ SetEmptySelection(currentPos + strlen(selected + ac.startLen));
+ }
+}
+
+void ScintillaBase::ContextMenu(Point pt) {
+ popup.CreatePopUp();
+ AddToPopUp("Undo", idcmdUndo, pdoc->CanUndo());
+ AddToPopUp("Redo", idcmdRedo, pdoc->CanRedo());
+ AddToPopUp("");
+ AddToPopUp("Cut", idcmdCut, currentPos != anchor);
+ AddToPopUp("Copy", idcmdCopy, currentPos != anchor);
+ AddToPopUp("Paste", idcmdPaste, WndProc(EM_CANPASTE, 0, 0));
+ AddToPopUp("Delete", idcmdDelete, currentPos != anchor);
+ AddToPopUp("");
+ AddToPopUp("Select All", idcmdSelectAll);
+ popup.Show(pt, wMain);
+}
+
+void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+ AutoCompleteCancel();
+ ct.CallTipCancel();
+ Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
+}
+
+#ifdef SCI_LEXER
+void ScintillaBase::Colourise(int start, int end) {
+ int lengthDoc = Platform::SendScintilla(wMain.GetID(), SCI_GETLENGTH, 0, 0);
+ if (end == -1)
+ end = lengthDoc;
+ int len = end - start;
+
+ StylingContext styler(wMain.GetID(), props);
+
+ int styleStart = 0;
+ if (start > 0)
+ styleStart = styler.StyleAt(start - 1);
+
+ ColouriseDoc(pdoc->dbcsCodePage, start, len, styleStart, lexLanguage, keyWordLists, styler);
+ styler.Flush();
+}
+#endif
+
+void ScintillaBase::NotifyStyleNeeded(int endStyleNeeded) {
+#ifdef SCI_LEXER
+ if (lexLanguage != SCLEX_CONTAINER) {
+ int endStyled = Platform::SendScintilla(wMain.GetID(), SCI_GETENDSTYLED, 0, 0);
+ int lineEndStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEFROMCHAR, endStyled, 0);
+ endStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEINDEX, lineEndStyled, 0);
+ Colourise(endStyled, endStyleNeeded);
+ return;
+ }
+#endif
+ Editor::NotifyStyleNeeded(endStyleNeeded);
+}
+
+LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ switch (iMessage) {
+ case SCI_AUTOCSHOW:
+ AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_AUTOCCANCEL:
+ AutoCompleteCancel();
+ break;
+
+ case SCI_AUTOCACTIVE:
+ return ac.Active();
+
+ case SCI_AUTOCPOSSTART:
+ return ac.posStart;
+
+ case SCI_AUTOCCOMPLETE:
+ AutoCompleteCompleted();
+ break;
+
+ case SCI_AUTOCSTOPS:
+ ac.SetStopChars(reinterpret_cast<char *>(lParam));
+ break;
+
+ case SCI_CALLTIPSHOW: {
+ AutoCompleteCancel();
+ if (!ct.wCallTip.Created()) {
+ PRectangle rc = ct.CallTipStart(currentPos, LocationFromPosition(wParam),
+ reinterpret_cast<char *>(lParam),
+ vs.styles[0].fontName, vs.styles[0].size);
+ // If the call-tip window would be out of the client
+ // space, adjust so it displays above the text.
+ PRectangle rcClient = GetClientRectangle();
+ if (rc.bottom > rcClient.bottom) {
+ int offset = vs.lineHeight + rc.Height();
+ rc.top -= offset;
+ rc.bottom -= offset;
+ }
+ // Now display the window.
+ CreateCallTipWindow(rc);
+ ct.wCallTip.SetPositionRelative(rc, wDraw);
+ ct.wCallTip.Show();
+ }
+ }
+ break;
+
+ case SCI_CALLTIPCANCEL:
+ ct.CallTipCancel();
+ break;
+
+ case SCI_CALLTIPACTIVE:
+ return ct.inCallTipMode;
+
+ case SCI_CALLTIPPOSSTART:
+ return ct.posStartCallTip;
+
+ case SCI_CALLTIPSETHLT:
+ ct.SetHighlight(wParam, lParam);
+ break;
+
+ case SCI_CALLTIPSETBACK:
+ ct.colourBG = Colour(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+#ifdef SCI_LEXER
+ case SCI_SETLEXER:
+ lexLanguage = wParam;
+ break;
+
+ case SCI_GETLEXER:
+ return lexLanguage;
+
+ case SCI_COLOURISE:
+ Colourise(wParam, lParam);
+ break;
+
+ case SCI_SETPROPERTY:
+ props.Set(reinterpret_cast<const char *>(wParam),
+ reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_SETKEYWORDS:
+ if ((wParam >= 0) && (wParam < numWordLists)) {
+ keyWordLists[wParam]->Clear();
+ keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
+ }
+ break;
+#endif
+
+ default:
+ return Editor::WndProc(iMessage, wParam, lParam);
+ }
+ return 0l;
+}
diff --git a/src/ScintillaBase.h b/src/ScintillaBase.h
new file mode 100644
index 000000000..e9f8f28d0
--- /dev/null
+++ b/src/ScintillaBase.h
@@ -0,0 +1,68 @@
+// Scintilla source code edit control
+// ScintillaBase.h - defines an enhanced subclass of Editor with calltips, autocomplete and context menu
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SCINTILLABASE_H
+#define SCINTILLABASE_H
+
+class ScintillaBase : public Editor {
+protected:
+ // Enumeration of commands and child windows
+ enum {
+ idCallTip=1,
+ idAutoComplete=2,
+
+ idcmdUndo=10,
+ idcmdRedo=11,
+ idcmdCut=12,
+ idcmdCopy=13,
+ idcmdPaste=14,
+ idcmdDelete=15,
+ idcmdSelectAll=16
+ };
+
+ Menu popup;
+ AutoComplete ac;
+
+ CallTip ct;
+
+#ifdef SCI_LEXER
+ int lexLanguage;
+ PropSet props;
+ enum {numWordLists=5};
+ WordList *keyWordLists[numWordLists];
+ void Colourise(int start, int end);
+#endif
+
+ ScintillaBase();
+ virtual ~ScintillaBase();
+ virtual void Initialise() = 0;
+ virtual void Finalise() = 0;
+
+ virtual void RefreshColourPalette(Palette &pal, bool want);
+
+ virtual void AddChar(char ch);
+ void Command(int cmdId);
+ virtual int KeyCommand(UINT iMessage);
+
+ void AutoCompleteStart(int lenEntered, const char *list);
+ void AutoCompleteCancel();
+ void AutoCompleteMove(int delta);
+ void AutoCompleteChanged(char ch=0);
+ void AutoCompleteCompleted();
+
+ virtual void CreateCallTipWindow(PRectangle rc) = 0;
+
+ virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true) = 0;
+ void ContextMenu(Point pt);
+
+ virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
+
+ virtual void NotifyStyleNeeded(int endStyleNeeded);
+public:
+ // Public so scintilla_send_message can use it
+ virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+};
+
+#endif
diff --git a/src/Style.cxx b/src/Style.cxx
new file mode 100644
index 000000000..271d98fc2
--- /dev/null
+++ b/src/Style.cxx
@@ -0,0 +1,89 @@
+// Scintilla source code edit control
+// Style.cxx - defines the font and colour style for a class of text
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Style.h"
+
+Style::Style() {
+ Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
+ Platform::DefaultFontSize(), 0,
+ false, false, false);
+}
+
+Style::~Style() {
+ if (!aliasOfDefaultFont)
+ font.Release();
+}
+
+Style &Style::operator=(const Style &source) {
+ if (this == &source)
+ return *this;
+ Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
+ Platform::DefaultFontSize(), 0,
+ false, false, false);
+ fore.desired = source.fore.desired;
+ back.desired = source.back.desired;
+ bold = source.bold;
+ italic = source.italic;
+ size = source.size;
+ fontName = source.fontName;
+ eolFilled = source.eolFilled;
+ return *this;
+}
+
+void Style::Clear(Colour fore_, Colour back_, int size_, const char *fontName_,
+ bool bold_, bool italic_, bool eolFilled_) {
+ fore.desired = fore_;
+ back.desired = back_;
+ bold = bold_;
+ italic = italic_;
+ size = size_;
+ fontName = fontName_;
+ eolFilled = eolFilled_;
+ if (!aliasOfDefaultFont)
+ font.Release();
+ aliasOfDefaultFont = false;
+}
+
+bool Style::EquivalentFontTo(const Style *other) const {
+ if (bold != other->bold ||
+ italic != other->italic ||
+ size != other->size)
+ return false;
+ if (fontName == other->fontName)
+ return true;
+ if (!fontName)
+ return false;
+ if (!other->fontName)
+ return false;
+ return strcmp(fontName, other->fontName) == 0;
+}
+
+void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle) {
+ int sizeZoomed = size + zoomLevel;
+ if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2;
+
+ int deviceHeight = (sizeZoomed * surface.LogPixelsY()) / 72;
+ aliasOfDefaultFont = defaultStyle && EquivalentFontTo(defaultStyle);
+ if (aliasOfDefaultFont) {
+ font.SetID(defaultStyle->font.GetID());
+ } else if (fontName) {
+ font.Create(fontName, deviceHeight, bold, italic);
+ }
+
+ ascent = surface.Ascent(font);
+ descent = surface.Descent(font);
+ // Probably more typographically correct to include leading
+ // but that means more complex drawing as leading must be erased
+ //lineHeight = surface.ExternalLeading() + surface.Height();
+ externalLeading = surface.ExternalLeading(font);
+ lineHeight = surface.Height(font);
+ aveCharWidth = surface.AverageCharWidth(font);
+ spaceWidth = surface.WidthChar(font, ' ');
+}
diff --git a/src/Style.h b/src/Style.h
new file mode 100644
index 000000000..a610ff8ba
--- /dev/null
+++ b/src/Style.h
@@ -0,0 +1,39 @@
+// Scintilla source code edit control
+// Style.h - defines the font and colour style for a class of text
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef STYLE_H
+#define STYLE_H
+
+class Style {
+public:
+ ColourPair fore;
+ ColourPair back;
+ bool aliasOfDefaultFont;
+ bool bold;
+ bool italic;
+ int size;
+ const char *fontName;
+ bool eolFilled;
+
+ Font font;
+ unsigned int lineHeight;
+ unsigned int ascent;
+ unsigned int descent;
+ unsigned int externalLeading;
+ unsigned int aveCharWidth;
+ unsigned int spaceWidth;
+
+ Style();
+ ~Style();
+ Style &operator=(const Style &source);
+ void Clear(Colour fore_, Colour back_,
+ int size_,
+ const char *fontName_,
+ bool bold_, bool italic_, bool eolFilled_);
+ bool EquivalentFontTo(const Style *other) const;
+ void Realise(Surface &surface, int zoomLevel, Style *defaultStyle=0);
+};
+
+#endif
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
new file mode 100644
index 000000000..122db6a00
--- /dev/null
+++ b/src/ViewStyle.cxx
@@ -0,0 +1,226 @@
+// Scintilla source code edit control
+// ViewStyle.cxx - store information on how the document is to be viewed
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+
+MarginStyle::MarginStyle() :
+ symbol(false), width(16), mask(0xffffffff), sensitive(false) {
+}
+
+// A list of the fontnames - avoids wasting space in each style
+FontNames::FontNames() {
+ max = 0;
+}
+
+FontNames::~FontNames() {
+ Clear();
+}
+
+void FontNames::Clear() {
+ for (int i=0;i<max;i++) {
+ delete []names[i];
+ }
+ max = 0;
+}
+
+const char *FontNames::Save(const char *name) {
+ for (int i=0;i<max;i++) {
+ if (strcmp(names[i], name) == 0) {
+ return names[i];
+ }
+ }
+ names[max] = new char[strlen(name) + 1];
+ strcpy(names[max], name);
+ max++;
+ return names[max-1];
+}
+
+ViewStyle::ViewStyle() {
+ Init();
+}
+
+ViewStyle::ViewStyle(const ViewStyle &source) {
+ Init();
+ for (int sty=0;sty<=STYLE_MAX;sty++) {
+ styles[sty] = source.styles[sty];
+ }
+ for (int mrk=0;mrk<=MARKER_MAX;mrk++) {
+ markers[mrk] = source.markers[mrk];
+ }
+ for (int ind=0;ind<=INDIC_MAX;ind++) {
+ indicators[ind] = source.indicators[ind];
+ }
+
+ selforeset = source.selforeset;
+ selforeground.desired = source.selforeground.desired;
+ selbackset = source.selbackset;
+ selbackground.desired = source.selbackground.desired;
+ selbar.desired = source.selbar.desired;
+ selbarlight.desired = source.selbarlight.desired;
+ caretcolour.desired = source.caretcolour.desired;
+ edgecolour.desired = source.edgecolour.desired;
+ leftMarginWidth = source.leftMarginWidth;
+ rightMarginWidth = source.rightMarginWidth;
+ for (int i=0;i < margins; i++) {
+ ms[i] = source.ms[i];
+ }
+ symbolMargin = source.symbolMargin;
+ maskInLine = source.maskInLine;
+ fixedColumnWidth = source.fixedColumnWidth;
+ zoomLevel = source.zoomLevel;
+ viewWhitespace = source.viewWhitespace;
+ viewEOL = source.viewEOL;
+ showMarkedLines = source.showMarkedLines;
+}
+
+ViewStyle::~ViewStyle() {
+}
+
+void ViewStyle::Init() {
+ fontNames.Clear();
+
+ indicators[0].style = INDIC_SQUIGGLE;
+ indicators[0].fore = Colour(0, 0x7f, 0);
+ indicators[1].style = INDIC_TT;
+ indicators[1].fore = Colour(0, 0, 0xff);
+ indicators[2].style = INDIC_PLAIN;
+ indicators[2].fore = Colour(0xff, 0, 0);
+
+ lineHeight = 1;
+ maxAscent = 1;
+ maxDescent = 1;
+ aveCharWidth = 8;
+ spaceWidth = 8;
+
+ selforeset = false;
+ selforeground.desired = Colour(0xff, 0, 0);
+ selbackset = true;
+ selbackground.desired = Colour(0xc0, 0xc0, 0xc0);
+ selbar.desired = Platform::Chrome();
+ selbarlight.desired = Platform::ChromeHighlight();
+ styles[STYLE_LINENUMBER].fore.desired = Colour(0, 0, 0);
+ styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+ //caretcolour.desired = Colour(0xff, 0, 0);
+ caretcolour.desired = Colour(0, 0, 0);
+ edgecolour.desired = Colour(0xc0, 0xc0, 0xc0);
+
+ leftMarginWidth = 1;
+ rightMarginWidth = 1;
+ ms[0].symbol = false;
+ ms[0].width = 0;
+ ms[0].mask = 0;
+ ms[1].symbol = true;
+ ms[1].width = 16;
+ ms[1].mask = ~SC_MASK_FOLDERS;
+ ms[2].symbol = true;
+ ms[2].width = 14; // Nice width for arrows
+ ms[2].mask = SC_MASK_FOLDERS;
+ ms[2].width = 0; // Nice width for arrows
+ ms[2].mask = 0;
+ fixedColumnWidth = leftMarginWidth;
+ symbolMargin = false;
+ maskInLine = 0xffffffff;
+ for (int margin=0; margin < margins; margin++) {
+ fixedColumnWidth += ms[margin].width;
+ symbolMargin = symbolMargin || ms[margin].symbol;
+ if (ms[margin].width > 0)
+ maskInLine &= ~ms[margin].mask;
+ }
+ zoomLevel = 0;
+ viewWhitespace = false;
+ viewEOL = false;
+ showMarkedLines = true;
+}
+
+void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
+ unsigned int i;
+ for (i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
+ pal.WantFind(styles[i].fore, want);
+ pal.WantFind(styles[i].back, want);
+ }
+ for (i=0;i<(sizeof(indicators)/sizeof(indicators[0]));i++) {
+ pal.WantFind(indicators[i].fore, want);
+ }
+ for (i=0;i<(sizeof(markers)/sizeof(markers[0]));i++) {
+ pal.WantFind(markers[i].fore, want);
+ pal.WantFind(markers[i].back, want);
+ }
+ pal.WantFind(selforeground, want);
+ pal.WantFind(selbackground, want);
+ pal.WantFind(selbar, want);
+ pal.WantFind(selbarlight, want);
+ pal.WantFind(caretcolour, want);
+ pal.WantFind(edgecolour, want);
+}
+
+#include <mmsystem.h>
+void ViewStyle::Refresh(Surface &surface) {
+DWORD dwStart = timeGetTime();
+ selbar.desired = Platform::Chrome();
+ selbarlight.desired = Platform::ChromeHighlight();
+ maxAscent = 1;
+ maxDescent = 1;
+ styles[STYLE_DEFAULT].Realise(surface, zoomLevel);
+ for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
+ if (i != STYLE_DEFAULT) {
+ styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT]);
+ if (maxAscent < styles[i].ascent)
+ maxAscent = styles[i].ascent;
+ if (maxDescent < styles[i].descent)
+ maxDescent = styles[i].descent;
+ }
+ }
+
+ lineHeight = maxAscent + maxDescent;
+ aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
+ spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
+
+ fixedColumnWidth = leftMarginWidth;
+ symbolMargin = false;
+ maskInLine = 0xffffffff;
+ for (int margin=0; margin < margins; margin++) {
+ fixedColumnWidth += ms[margin].width;
+ symbolMargin = symbolMargin || ms[margin].symbol;
+ if (ms[margin].width > 0)
+ maskInLine &= ~ms[margin].mask;
+ }
+DWORD dwEnd = timeGetTime();
+Platform::DebugPrintf("Refresh took %d\n", dwEnd - dwStart);
+}
+
+void ViewStyle::ResetDefaultStyle() {
+ styles[STYLE_DEFAULT].Clear(Colour(0,0,0), Colour(0xff,0xff,0xff),
+ Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
+ false, false, false);
+}
+
+void ViewStyle::ClearStyles() {
+ // Reset all styles to be like the default style
+ for (int i=0; i<=STYLE_MAX; i++) {
+ if (i != STYLE_DEFAULT) {
+ styles[i].Clear(
+ styles[STYLE_DEFAULT].fore.desired,
+ styles[STYLE_DEFAULT].back.desired,
+ styles[STYLE_DEFAULT].size,
+ styles[STYLE_DEFAULT].fontName,
+ styles[STYLE_DEFAULT].bold,
+ styles[STYLE_DEFAULT].italic,
+ styles[STYLE_DEFAULT].eolFilled);
+ }
+ }
+ styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+}
+
+void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
+ styles[styleIndex].fontName = fontNames.Save(name);
+}
diff --git a/src/ViewStyle.h b/src/ViewStyle.h
new file mode 100644
index 000000000..4436e83ff
--- /dev/null
+++ b/src/ViewStyle.h
@@ -0,0 +1,72 @@
+// Scintilla source code edit control
+// ViewStyle.h - store information on how the document is to be viewed
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef VIEWSTYLE_H
+#define VIEWSTYLE_H
+
+class MarginStyle {
+public:
+ bool symbol;
+ int width;
+ int mask;
+ bool sensitive;
+ MarginStyle();
+};
+
+class FontNames {
+private:
+ char *names[STYLE_MAX + 1];
+ int max;
+public:
+ FontNames();
+ ~FontNames();
+ void Clear();
+ const char *Save(const char *name);
+};
+
+class ViewStyle {
+public:
+ FontNames fontNames;
+ Style styles[STYLE_MAX + 1];
+ LineMarker markers[MARKER_MAX + 1];
+ Indicator indicators[INDIC_MAX + 1];
+ int lineHeight;
+ unsigned int maxAscent;
+ unsigned int maxDescent;
+ unsigned int aveCharWidth;
+ unsigned int spaceWidth;
+ bool selforeset;
+ ColourPair selforeground;
+ bool selbackset;
+ ColourPair selbackground;
+ ColourPair selbar;
+ ColourPair selbarlight;
+ // Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
+ int leftMarginWidth; // Spacing margin on left of text
+ int rightMarginWidth; // Spacing margin on left of text
+ enum { margins=3 };
+ bool symbolMargin;
+ int maskInLine; // Mask for markers to be put into text because there is nowhere for them to go in margin
+ MarginStyle ms[margins];
+ int fixedColumnWidth;
+ int zoomLevel;
+ bool viewWhitespace;
+ bool viewEOL;
+ bool showMarkedLines;
+ ColourPair caretcolour;
+ ColourPair edgecolour;
+
+ ViewStyle();
+ ViewStyle(const ViewStyle &source);
+ ~ViewStyle();
+ void Init();
+ void RefreshColourPalette(Palette &pal, bool want);
+ void Refresh(Surface &surface);
+ void ResetDefaultStyle();
+ void ClearStyles();
+ void SetStyleFontName(int styleIndex, const char *name);
+};
+
+#endif
diff --git a/win32/Margin.cur b/win32/Margin.cur
new file mode 100644
index 000000000..9e0e79066
--- /dev/null
+++ b/win32/Margin.cur
Binary files differ
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
new file mode 100644
index 000000000..9fde8a272
--- /dev/null
+++ b/win32/PlatWin.cxx
@@ -0,0 +1,673 @@
+// Scintilla source code edit control
+// PlatWin.cxx - implementation of platform facilities on Windows
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "Platform.h"
+#include "PlatformRes.h"
+
+Point Point::FromLong(long lpoint) {
+ return Point(static_cast<short>(LOWORD(lpoint)), static_cast<short>(HIWORD(lpoint)));
+}
+
+static RECT RectFromPRectangle(PRectangle prc) {
+ RECT rc = {prc.left, prc.top, prc.right, prc.bottom};
+ return rc;
+}
+
+Colour::Colour(long lcol) {
+ co = lcol;
+}
+
+Colour::Colour(unsigned int red, unsigned int green, unsigned int blue) {
+ co = RGB(red, green, blue);
+}
+
+bool Colour::operator==(const Colour &other) const {
+ return co == other.co;
+}
+
+long Colour::AsLong() const {
+ return co;
+}
+
+unsigned int Colour::GetRed() {
+ return co & 0xff;
+}
+
+unsigned int Colour::GetGreen() {
+ return (co >> 8) & 0xff;
+}
+
+unsigned int Colour::GetBlue() {
+ return (co >> 16) & 0xff;
+}
+
+Palette::Palette() {
+ used = 0;
+ allowRealization = false;
+ hpal = 0;
+}
+
+Palette::~Palette() {
+ Release();
+}
+
+void Palette::Release() {
+ used = 0;
+ if (hpal)
+ ::DeleteObject(hpal);
+ hpal = 0;
+}
+
+// This method either adds a colour to the list of wanted colours (want==true)
+// or retrieves the allocated colour back to the ColourPair.
+// This is one method to make it easier to keep the code for wanting and retrieving in sync.
+void Palette::WantFind(ColourPair &cp, bool want) {
+ if (want) {
+ for (int i=0; i < used; i++) {
+ if (entries[i].desired == cp.desired)
+ return;
+ }
+
+ if (used < numEntries) {
+ entries[used].desired = cp.desired;
+ entries[used].allocated = cp.desired;
+ used++;
+ }
+ } else {
+ for (int i=0; i < used; i++) {
+ if (entries[i].desired == cp.desired) {
+ cp.allocated = entries[i].allocated;
+ return;
+ }
+ }
+ cp.allocated = cp.desired;
+ }
+}
+
+void Palette::Allocate(Window &) {
+ if (hpal)
+ ::DeleteObject(hpal);
+ hpal = 0;
+
+ if (allowRealization) {
+ char *pal = new char[sizeof(LOGPALETTE) + (used-1) * sizeof(PALETTEENTRY)];
+ LOGPALETTE *logpal = reinterpret_cast<LOGPALETTE *>(pal);
+ logpal->palVersion = 0x300;
+ logpal->palNumEntries = used;
+ for (int iPal=0;iPal<used;iPal++) {
+ Colour desired = entries[iPal].desired;
+ logpal->palPalEntry[iPal].peRed = desired.GetRed();
+ logpal->palPalEntry[iPal].peGreen = desired.GetGreen();
+ logpal->palPalEntry[iPal].peBlue = desired.GetBlue();
+ entries[iPal].allocated =
+ PALETTERGB(desired.GetRed(), desired.GetGreen(), desired.GetBlue());
+ // PC_NOCOLLAPSE means exact colours allocated even when in background this means other windows
+ // are less likely to get their colours and also flashes more when switching windows
+ logpal->palPalEntry[iPal].peFlags = PC_NOCOLLAPSE;
+ // 0 allows approximate colours when in background, yielding moe colours to other windows
+ //logpal->palPalEntry[iPal].peFlags = 0;
+ }
+ hpal = ::CreatePalette(logpal);
+ delete []pal;
+ }
+}
+
+Font::Font() {
+ id = 0;
+}
+
+Font::~Font() {
+}
+
+void Font::Create(const char *faceName, int size, bool bold, bool italic) {
+ Release();
+
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(lf));
+ // The negative is to allow for leading
+ lf.lfHeight = -(abs(size));
+ lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = italic ? 1 : 0;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ strcpy(lf.lfFaceName, faceName);
+
+ id = ::CreateFontIndirect(&lf);
+}
+
+void Font::Release() {
+ if (id)
+ ::DeleteObject(id);
+ id = 0;
+}
+
+Surface::Surface() :
+ hdc(0), hdcOwned(false),
+ pen(0), penOld(0),
+ brush(0), brushOld(0),
+ font(0), fontOld(0),
+ bitmap(0), bitmapOld(0),
+ paletteOld(0) {
+}
+
+Surface::~Surface() {
+ Release();
+}
+
+void Surface::Release() {
+ if (penOld) {
+ ::SelectObject(hdc, penOld);
+ ::DeleteObject(pen);
+ penOld = 0;
+ }
+ pen = 0;
+ if (brushOld) {
+ ::SelectObject(hdc, brushOld);
+ ::DeleteObject(brush);
+ brushOld = 0;
+ }
+ brush = 0;
+ if (fontOld) {
+ // Fonts are not deleted as they are owned by a Font object
+ ::SelectObject(hdc, fontOld);
+ fontOld = 0;
+ }
+ font =0;
+ if (bitmapOld) {
+ ::SelectObject(hdc, bitmapOld);
+ ::DeleteObject(bitmap);
+ bitmapOld = 0;
+ }
+ bitmap = 0;
+ if (paletteOld) {
+ // Fonts are not deleted as they are owned by a Palette object
+ ::SelectPalette(hdc, paletteOld, TRUE);
+ paletteOld = 0;
+ }
+ if (hdcOwned) {
+ ::DeleteDC(hdc);
+ hdc = 0;
+ hdcOwned = false;
+ }
+}
+
+bool Surface::Initialised() {
+ return hdc;
+}
+
+void Surface::Init() {
+ Release();
+ hdc = ::CreateCompatibleDC(NULL);
+ hdcOwned = true;
+ ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::Init(HDC hdc_) {
+ Release();
+ hdc = hdc_;
+ ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::InitPixMap(int width, int height, Surface *surface_) {
+ Release();
+ hdc = ::CreateCompatibleDC(surface_->hdc);
+ hdcOwned = true;
+ bitmap = ::CreateCompatibleBitmap(surface_->hdc, width, height);
+ bitmapOld = static_cast<HBITMAP>(::SelectObject(hdc, bitmap));
+ ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::PenColour(Colour fore) {
+ if (pen) {
+ ::SelectObject(hdc, penOld);
+ ::DeleteObject(pen);
+ pen = 0;
+ penOld = 0;
+ }
+ pen = ::CreatePen(0,1,fore.AsLong());
+ penOld = static_cast<HPEN>(::SelectObject(hdc, pen));
+}
+
+void Surface::BrushColor(Colour back) {
+ if (brush) {
+ ::SelectObject(hdc, brushOld);
+ ::DeleteObject(brush);
+ brush = 0;
+ brushOld = 0;
+ }
+ // Only ever want pure, non-dithered brushes
+ Colour colourNearest = ::GetNearestColor(hdc, back.AsLong());
+ brush = ::CreateSolidBrush(colourNearest.AsLong());
+ brushOld = static_cast<HBRUSH>(::SelectObject(hdc, brush));
+}
+
+void Surface::SetFont(Font &font_) {
+ if (font_.GetID() != font) {
+ if (fontOld) {
+ ::SelectObject(hdc, font_.GetID());
+ } else {
+ fontOld = static_cast<HFONT>(::SelectObject(hdc, font_.GetID()));
+ }
+ font = font_.GetID();
+ }
+}
+
+int Surface::LogPixelsY() {
+ return ::GetDeviceCaps(hdc, LOGPIXELSY);
+}
+
+void Surface::MoveTo(int x_, int y_) {
+ ::MoveToEx(hdc, x_, y_, 0);
+}
+
+void Surface::LineTo(int x_, int y_) {
+ ::LineTo(hdc, x_, y_);
+}
+
+void Surface::Polygon(Point *pts, int npts, Colour fore,
+ Colour back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::Polygon(hdc, reinterpret_cast<POINT *>(pts), npts);
+}
+
+void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void Surface::FillRectangle(PRectangle rc, Colour back) {
+ // Using ExtTextOut rather than a FillRect ensures that no dithering occurs.
+ // There is no need to allocate a brush either.
+ RECT rcw = RectFromPRectangle(rc);
+ ::SetBkColor(hdc, back.AsLong());
+ ::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, "", 0, NULL);
+}
+
+void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+ HBRUSH br = 0;
+ if (surfacePattern.bitmap)
+ br = ::CreatePatternBrush(surfacePattern.bitmap);
+ else // Something is wrong so display in red
+ br = ::CreateSolidBrush(RGB(0xff, 0, 0));
+ RECT rcw = RectFromPRectangle(rc);
+ ::FillRect(hdc, &rcw, br);
+ ::DeleteObject(br);
+}
+
+void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::RoundRect(hdc,
+ rc.left + 1, rc.top,
+ rc.right - 1, rc.bottom,
+ 8, 8 );
+}
+
+void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+ ::BitBlt(hdc, rc.left, rc.top, rc.Width(), rc.Height(),
+ surfaceSource.hdc, from.x, from.y, SRCCOPY);
+}
+
+void Surface::DrawText(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back) {
+ SetFont(font_);
+ ::SetTextColor(hdc, fore.AsLong());
+ ::SetBkColor(hdc, back.AsLong());
+ RECT rcw = RectFromPRectangle(rc);
+ ::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, s, len, NULL);
+}
+
+void Surface::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back) {
+ SetFont(font_);
+ ::SetTextColor(hdc, fore.AsLong());
+ ::SetBkColor(hdc, back.AsLong());
+ RECT rcw = RectFromPRectangle(rc);
+ ::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, s, len, NULL);
+}
+
+int Surface::WidthText(Font &font_, const char *s, int len) {
+ SetFont(font_);
+ SIZE sz;
+ ::GetTextExtentPoint32(hdc, s, len, &sz);
+ return sz.cx;
+}
+
+void Surface::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+ SetFont(font_);
+ SIZE sz;
+ int fit = 0;
+ ::GetTextExtentExPoint(hdc, s, len, 30000, &fit, positions, &sz);
+}
+
+int Surface::WidthChar(Font &font_, char ch) {
+ SetFont(font_);
+ SIZE sz;
+ ::GetTextExtentPoint32(hdc, &ch, 1, &sz);
+ return sz.cx;
+}
+
+int Surface::Ascent(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmAscent;
+}
+
+int Surface::Descent(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmDescent;
+}
+
+int Surface::InternalLeading(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmInternalLeading;
+}
+
+int Surface::ExternalLeading(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmExternalLeading;
+}
+
+int Surface::Height(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmHeight;
+}
+
+int Surface::AverageCharWidth(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmAveCharWidth;
+}
+
+int Surface::SetPalette(Palette *pal, bool inBackGround) {
+ if (paletteOld) {
+ ::SelectPalette(hdc,paletteOld,TRUE);
+ }
+ paletteOld = 0;
+ int changes = 0;
+ if (pal->allowRealization) {
+ paletteOld = ::SelectPalette(hdc, pal->hpal, inBackGround);
+ changes = ::RealizePalette(hdc);
+ }
+ return changes;
+}
+
+void Surface::SetClip(PRectangle rc) {
+ ::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
+}
+
+Window::~Window() {
+}
+
+void Window::Destroy() {
+ if (id)
+ ::DestroyWindow(id);
+ id = 0;
+}
+
+bool Window::HasFocus() {
+ return ::GetFocus() == id;
+}
+
+PRectangle Window::GetPosition() {
+ RECT rc;
+ ::GetWindowRect(id, &rc);
+ return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void Window::SetPosition(PRectangle rc) {
+ ::SetWindowPos(id, 0, rc.left, rc.top, rc.Width(), rc.Height(), 0);
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window) {
+ SetPosition(rc);
+}
+
+PRectangle Window::GetClientPosition() {
+ RECT rc;
+ ::GetClientRect(id, &rc);
+ return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void Window::Show(bool show) {
+ if (show)
+ ::ShowWindow(id, SW_SHOWNORMAL);
+ else
+ ::ShowWindow(id, SW_HIDE);
+}
+
+void Window::InvalidateAll() {
+ ::InvalidateRect(id, NULL, FALSE);
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+ RECT rcw = RectFromPRectangle(rc);
+ ::InvalidateRect(id, &rcw, FALSE);
+}
+
+void Window::SetFont(Font &font) {
+ SendMessage(WM_SETFONT,
+ reinterpret_cast<WPARAM>(font.GetID()), 0);
+}
+
+static HINSTANCE hinstPlatformRes = 0;
+
+void Window::SetCursor(Cursor curs) {
+ switch (curs) {
+ case cursorText:
+ ::SetCursor(::LoadCursor(NULL,IDC_IBEAM));
+ break;
+ case cursorArrow:
+ ::SetCursor(::LoadCursor(NULL,IDC_ARROW));
+ break;
+ case cursorUp:
+ ::SetCursor(::LoadCursor(NULL,IDC_UPARROW));
+ break;
+ case cursorWait:
+ ::SetCursor(::LoadCursor(NULL,IDC_WAIT));
+ break;
+ case cursorHoriz:
+ ::SetCursor(::LoadCursor(NULL,IDC_SIZEWE));
+ break;
+ case cursorVert:
+ ::SetCursor(::LoadCursor(NULL,IDC_SIZENS));
+ break;
+ case cursorReverseArrow: {
+ if (!hinstPlatformRes)
+ hinstPlatformRes = GetModuleHandle("Scintilla");
+ if (!hinstPlatformRes)
+ hinstPlatformRes = GetModuleHandle("SciLexer");
+ if (!hinstPlatformRes)
+ hinstPlatformRes = GetModuleHandle(NULL);
+ ::SetCursor(::LoadCursor(hinstPlatformRes, MAKEINTRESOURCE(IDC_MARGIN)));
+ }
+ break;
+ }
+}
+
+void Window::SetTitle(const char *s) {
+ ::SetWindowText(id, s);
+}
+
+LRESULT Window::SendMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
+ return ::SendMessage(id, msg, wParam, lParam);
+}
+
+int Window::GetDlgCtrlID() {
+ return ::GetDlgCtrlID(id);
+}
+
+HINSTANCE Window::GetInstance() {
+ return reinterpret_cast<HINSTANCE>(
+ ::GetWindowLong(id,GWL_HINSTANCE));
+}
+
+ListBox::ListBox() {
+}
+
+ListBox::~ListBox() {
+}
+
+void ListBox::Create(Window &parent, int ctrlID) {
+ id = ::CreateWindowEx(
+ WS_EX_CLIENTEDGE, "listbox", "",
+ WS_CHILD|WS_BORDER|WS_VSCROLL|LBS_SORT|LBS_NOTIFY,
+ 100,100, 150,80, parent.GetID(), reinterpret_cast<HMENU>(ctrlID),
+ parent.GetInstance(), 0);
+}
+
+void ListBox::Clear() {
+ SendMessage(LB_RESETCONTENT);
+}
+
+void ListBox::Append(char *s) {
+ SendMessage(LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(s));
+}
+
+int ListBox::Length() {
+ return SendMessage(LB_GETCOUNT);
+}
+
+void ListBox::Select(int n) {
+ SendMessage(LB_SETCURSEL, n);
+}
+
+int ListBox::GetSelection() {
+ return SendMessage(LB_GETCURSEL);
+}
+
+int ListBox::Find(const char *prefix) {
+ return SendMessage(LB_FINDSTRING, 0, reinterpret_cast<LPARAM>(prefix));
+}
+
+void ListBox::GetValue(int n, char *value, int len) {
+ int lenText = SendMessage(LB_GETTEXTLEN, n);
+ if ((len > 0) && (lenText > 0)){
+ char *text = new char[len+1];
+ if (text) {
+ SendMessage(LB_GETTEXT, n, reinterpret_cast<LPARAM>(text));
+ strncpy(value, text, len);
+ value[len-1] = '\0';
+ delete []text;
+ } else {
+ value[0] = '\0';
+ }
+ } else {
+ value[0] = '\0';
+ }
+}
+
+void ListBox::Sort() {
+ // Windows keeps sorted so no need to sort
+}
+
+Menu::Menu() : id(0) {
+}
+
+void Menu::CreatePopUp() {
+ Destroy();
+ id = ::CreatePopupMenu();
+}
+
+void Menu::Destroy() {
+ if (id)
+ ::DestroyMenu(id);
+ id = 0;
+}
+
+void Menu::Show(Point pt, Window &w) {
+ ::TrackPopupMenu(id, 0, pt.x - 4, pt.y, 0, w.GetID(), NULL);
+ Destroy();
+}
+
+Colour Platform::Chrome() {
+ return ::GetSysColor(COLOR_3DFACE);
+}
+
+Colour Platform::ChromeHighlight() {
+ return ::GetSysColor(COLOR_3DHIGHLIGHT);
+}
+
+const char *Platform::DefaultFont() {
+ return "Verdana";
+}
+
+int Platform::DefaultFontSize() {
+ return 8;
+}
+
+unsigned int Platform::DoubleClickTime() {
+ return ::GetDoubleClickTime();
+}
+
+void Platform::DebugDisplay(const char *s) {
+ ::OutputDebugString(s);
+}
+
+bool Platform::IsKeyDown(int key) {
+ return ::GetKeyState(key) & 0x80000000;
+}
+
+long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
+ return ::SendMessage(w, msg, wParam, lParam);
+}
+
+// These are utility functions not really tied to a platform
+
+int Platform::Minimum(int a, int b) {
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+int Platform::Maximum(int a, int b) {
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+#define TRACE
+
+void Platform::DebugPrintf(const char *format, ...) {
+#ifdef TRACE
+ char buffer[2000];
+ va_list pArguments;
+ va_start(pArguments, format);
+ vsprintf(buffer,format,pArguments);
+ va_end(pArguments);
+ Platform::DebugDisplay(buffer);
+#endif
+}
+
+int Platform::Clamp(int val, int minVal, int maxVal) {
+ if (val > maxVal)
+ val = maxVal;
+ if (val < minVal)
+ val = minVal;
+ return val;
+}
diff --git a/win32/PlatformRes.h b/win32/PlatformRes.h
new file mode 100644
index 000000000..a4361dcaa
--- /dev/null
+++ b/win32/PlatformRes.h
@@ -0,0 +1,6 @@
+// Scintilla source code edit control
+// PlatformRes.h - defines IDs of resources used by Scintilla on Windows platform
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#define IDC_MARGIN 400
diff --git a/win32/ScintRes.rc b/win32/ScintRes.rc
new file mode 100644
index 000000000..96c93751e
--- /dev/null
+++ b/win32/ScintRes.rc
@@ -0,0 +1,40 @@
+// Resource file for Scintilla
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef __BORLANDC__
+#include <windows.h>
+#endif
+
+#include "PlatformRes.h"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION 1, 2, 2, 0
+PRODUCTVERSION 1, 2, 2, 0
+FILEFLAGSMASK 0x3fL
+FILEFLAGS 0
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Neil Hodgson neilh@scintilla.org\0"
+ VALUE "FileDescription", "Scintilla.DLL - a Source Editing Component\0"
+ VALUE "FileVersion", "1.22\0"
+ VALUE "InternalName", "Scintilla\0"
+ VALUE "LegalCopyright", "Copyright 1998-2000 by Neil Hodgson\0"
+ VALUE "OriginalFilename", "Scintilla.DLL\0"
+ VALUE "ProductName", "Scintilla\0"
+ VALUE "ProductVersion", "1.22\0"
+ END
+ END
+END
+
+IDC_MARGIN CURSOR DISCARDABLE "Margin.cur"
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
new file mode 100644
index 000000000..fd4126249
--- /dev/null
+++ b/win32/ScintillaWin.cxx
@@ -0,0 +1,1349 @@
+// Scintilla source code edit control
+// ScintillaWin.cxx - Windows specific subclass of ScintillaBase
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "AutoComplete.h"
+#include "ViewStyle.h"
+#include "Document.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+//#include "CElapsed.h"
+
+#ifndef SPI_GETWHEELSCROLLLINES
+#define SPI_GETWHEELSCROLLLINES 104
+#endif
+
+#ifndef WM_IME_STARTCOMPOSITION
+#include <imm.h>
+#endif
+
+#include <commctrl.h>
+#ifndef __BORLANDC__
+#include <zmouse.h>
+#endif
+#include <ole2.h>
+
+#ifndef MK_ALT
+#define MK_ALT 32
+#endif
+
+// TOTAL_CONTROL ifdef surrounds code that will only work when ScintillaWin
+// is derived from ScintillaBase (all features) rather than directly from Editor (lightweight editor).
+#define TOTAL_CONTROL
+
+// GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables.
+
+class ScintillaWin; // Forward declaration for COM interface subobjects
+
+class FormatEnumerator {
+public:
+ void **vtbl;
+ int ref;
+ int pos;
+ FormatEnumerator(int pos_);
+};
+
+class DropSource {
+public:
+ void **vtbl;
+ ScintillaWin *sci;
+ DropSource();
+};
+
+class DataObject {
+public:
+ void **vtbl;
+ ScintillaWin *sci;
+ DataObject();
+};
+
+class DropTarget {
+public:
+ void **vtbl;
+ ScintillaWin *sci;
+ DropTarget();
+};
+
+class ScintillaWin :
+ public ScintillaBase {
+
+ bool capturedMouse;
+
+ UINT cfColumnSelect;
+
+ DropSource ds;
+ DataObject dob;
+ DropTarget dt;
+
+ static HINSTANCE hInstance;
+
+ ScintillaWin(HWND hwnd);
+ virtual ~ScintillaWin();
+
+ virtual void Initialise();
+ virtual void Finalise();
+
+ static LRESULT PASCAL SWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+ static LRESULT PASCAL CTWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+
+ virtual void StartDrag();
+ virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+ virtual void SetTicking(bool on);
+ virtual void SetMouseCapture(bool on);
+ virtual bool HaveMouseCapture();
+ virtual void ScrollText(int linesToMove);
+ virtual void SetVerticalScrollPos();
+ virtual void SetHorizontalScrollPos();
+ virtual bool ModifyScrollBars(int nMax, int nPage);
+ virtual void NotifyChange();
+ virtual void NotifyFocus(bool focus);
+ virtual void NotifyParent(SCNotification scn);
+ virtual void NotifyDoubleClick(Point pt, bool shift);
+ virtual void Copy();
+ virtual void Paste();
+ virtual void CreateCallTipWindow(PRectangle rc);
+ virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+ virtual void ClaimSelection();
+
+ // DBCS
+ void ImeStartComposition();
+ void ImeEndComposition();
+
+ void GetIntelliMouseParameters();
+ HGLOBAL GetSelText();
+ void ScrollMessage(WPARAM wParam);
+ void HorizontalScrollMessage(WPARAM wParam);
+ void RealizeWindowPalette(bool inBackGround);
+ void FullPaint();
+
+public:
+ // Implement IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
+ STDMETHODIMP_(ULONG)AddRef();
+ STDMETHODIMP_(ULONG)Release();
+
+ // Implement IDropTarget
+ STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect);
+ STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect);
+ STDMETHODIMP DragLeave();
+ STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect);
+
+ // Implement important part of IDataObject
+ STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM);
+
+ static void Register(HINSTANCE hInstance_);
+ friend class DropSource;
+ friend class DataObject;
+ friend class DropTarget;
+ bool DragIsRectangularOK(UINT fmt) {
+ return dragIsRectangle && (fmt == cfColumnSelect);
+ }
+};
+
+HINSTANCE ScintillaWin::hInstance = 0;
+
+ScintillaWin::ScintillaWin(HWND hwnd) {
+
+ capturedMouse = false;
+
+ // There does not seem to be a real standard for indicating that the clipboard contains a rectangular
+ // selection, so copy Developer Studio.
+ cfColumnSelect = ::RegisterClipboardFormat("MSDEVColumnSelect");
+
+ wMain = hwnd;
+ wDraw = hwnd;
+
+ dob.sci = this;
+ ds.sci = this;
+ dt.sci = this;
+
+ Initialise();
+}
+
+ScintillaWin::~ScintillaWin() {}
+
+void ScintillaWin::Initialise() {
+ // Initialize COM. If the app has already done this it will have
+ // no effect. If the app hasnt, we really shouldnt ask them to call
+ // it just so this internal feature works.
+ OleInitialize(NULL);
+}
+
+void ScintillaWin::Finalise() {
+ ScintillaBase::Finalise();
+ SetTicking(false);
+ RevokeDragDrop(wMain.GetID());
+ OleUninitialize();
+}
+
+void ScintillaWin::StartDrag() {
+ DWORD dwEffect = 0;
+ dropWentOutside = true;
+ IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob);
+ IDropSource *pDropSource = reinterpret_cast<IDropSource *>(&ds);
+ //Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource);
+ HRESULT hr = DoDragDrop(
+ pDataObject,
+ pDropSource,
+ DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
+ //Platform::DebugPrintf("DoDragDrop = %x\n", hr);
+ if (SUCCEEDED(hr)) {
+ if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) {
+ // Remove dragged out text
+ ClearSelection();
+ }
+ }
+ inDragDrop = false;
+ SetDragPosition(invalidPosition);
+}
+
+// Avoid warnings everywhere for old style casts by conecntrating them here
+static WORD LoWord(DWORD l) {
+ return LOWORD(l);
+}
+
+static WORD HiWord(DWORD l) {
+ return HIWORD(l);
+}
+
+LRESULT ScintillaWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ switch (iMessage) {
+
+ case WM_CREATE:
+ ctrlID = wMain.GetDlgCtrlID();
+ // Get Intellimouse scroll line parameters
+ GetIntelliMouseParameters();
+ RegisterDragDrop(wMain.GetID(), reinterpret_cast<IDropTarget *>(&dt));
+ break;
+
+ case WM_COMMAND:
+#ifdef TOTAL_CONTROL
+ if (LoWord(wParam) == idAutoComplete) {
+ int cmd = HiWord(wParam);
+ if (cmd == LBN_DBLCLK) {
+ AutoCompleteCompleted();
+ } else {
+ if (cmd != LBN_SETFOCUS)
+ SetFocus(wMain.GetID());
+ }
+ }
+ Command(LoWord(wParam));
+#endif
+ break;
+
+ case WM_PAINT: {
+ //CElapsed ce; ce.Begin();
+ paintState = painting;
+ PAINTSTRUCT ps;
+ BeginPaint(wMain.GetID(), &ps);
+ Surface surfaceWindow;
+ surfaceWindow.Init(ps.hdc);
+ rcPaint = PRectangle(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+ PRectangle rcText = GetTextRectangle();
+ paintingAllText = rcPaint.Contains(rcText);
+ if (paintingAllText) {
+ //Platform::DebugPrintf("Performing full text paint\n");
+ } else {
+ //Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom);
+ }
+ Paint(&surfaceWindow, rcPaint);
+ surfaceWindow.Release();
+ EndPaint(wMain.GetID(), &ps);
+ if (paintState == paintAbandoned) {
+ // Painting area was insufficient to cover new styling or brace highlight positions
+ FullPaint();
+ }
+ paintState = notPainting;
+ //Platform::DebugPrintf("Paint took %g\n", ce.End());
+ }
+ break;
+
+ case WM_VSCROLL:
+ ScrollMessage(wParam);
+ break;
+
+ case WM_HSCROLL:
+ HorizontalScrollMessage(wParam);
+ break;
+
+ case WM_SIZE: {
+ //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
+ PRectangle rsClient(0, 0, LoWord(lParam), HiWord(lParam));
+ SetScrollBarsTo(rsClient);
+ DropGraphics();
+ }
+ break;
+
+ case WM_MOUSEWHEEL:
+ // Don't handle datazoom.
+ // (A good idea for datazoom would be to "fold" or "unfold" details.
+ // i.e. if datazoomed out only class structures are visible, when datazooming in the control
+ // structures appear, then eventually the individual statements...)
+ if (wParam & MK_SHIFT) {
+ return DefWindowProc(wMain.GetID(), iMessage, wParam, lParam);
+ }
+
+ // Either SCROLL or ZOOM. We handle the wheel steppings calculation
+ cWheelDelta -= static_cast<short>(HiWord(wParam));
+ if (abs(cWheelDelta) >= WHEEL_DELTA && ucWheelScrollLines > 0) {
+ int cLineScroll;
+ cLineScroll = ucWheelScrollLines;
+ if (cLineScroll == 0) {
+ cLineScroll++;
+ }
+ cLineScroll *= (cWheelDelta / WHEEL_DELTA);
+ cWheelDelta = cWheelDelta % WHEEL_DELTA;
+
+ if (wParam & MK_CONTROL) {
+ // Zoom! We play with the font sizes in the styles.
+ // Number of steps/line is ignored, we just care if sizing up or down
+ if (cLineScroll < 0) {
+ KeyCommand(SCI_ZOOMIN);
+ } else {
+ KeyCommand(SCI_ZOOMOUT);
+ }
+ } else {
+ // Scroll
+ ScrollTo(topLine + cLineScroll);
+ }
+ }
+ return 0;
+
+ case WM_TIMER:
+ Tick();
+ break;
+
+ case WM_GETMINMAXINFO:
+ return DefWindowProc(wMain.GetID(), iMessage, wParam, lParam);
+
+ case WM_LBUTTONDOWN:
+ //Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam,
+ // Platform::IsKeyDown(VK_SHIFT),
+ // Platform::IsKeyDown(VK_CONTROL),
+ // Platform::IsKeyDown(VK_MENU));
+ ButtonDown(Point::FromLong(lParam), GetTickCount(),
+ wParam & MK_SHIFT, wParam & MK_CONTROL, Platform::IsKeyDown(VK_MENU));
+ SetFocus(wMain.GetID());
+ break;
+
+ case WM_MOUSEMOVE:
+ ButtonMove(Point::FromLong(lParam));
+ break;
+
+ case WM_LBUTTONUP:
+ ButtonUp(Point::FromLong(lParam), GetTickCount(), wParam & MK_CONTROL);
+ break;
+
+ case WM_SETCURSOR:
+ if (LoWord(lParam) == HTCLIENT) {
+ if (inDragDrop) {
+ wDraw.SetCursor(Window::cursorUp);
+ } else {
+ // Display regular (drag) cursor over selection
+ POINT pt;
+ ::GetCursorPos(&pt);
+ ::ScreenToClient(wMain.GetID(), &pt);
+ if (PointInSelMargin(Point(pt.x, pt.y))) {
+ wDraw.SetCursor(Window::cursorReverseArrow);
+ } else if (PointInSelection(Point(pt.x, pt.y))) {
+ wDraw.SetCursor(Window::cursorArrow);
+ } else {
+ wDraw.SetCursor(Window::cursorText);
+ }
+ }
+ return TRUE;
+ } else
+ return DefWindowProc(wMain.GetID(), iMessage, wParam, lParam);
+
+ case WM_CHAR:
+ //Platform::DebugPrintf("S char proc %d %x %x\n",iMessage, wParam, lParam);
+ if (!iscntrl(wParam&0xff))
+ AddChar(static_cast<char>(wParam&0xff));
+ return 1;
+
+ case WM_KEYDOWN:
+ //Platform::DebugPrintf("S keydown %d %x %x %x %x\n",iMessage, wParam, lParam, ::IsKeyDown(VK_SHIFT), ::IsKeyDown(VK_CONTROL));
+ return KeyDown(wParam, Platform::IsKeyDown(VK_SHIFT),
+ Platform::IsKeyDown(VK_CONTROL), false);
+
+ case WM_KEYUP:
+ //Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam);
+ break;
+
+ case WM_SETTINGCHANGE:
+ //Platform::DebugPrintf("Setting Changed\n");
+ InvalidateStyleData();
+ // Get Intellimouse scroll line parameters
+ GetIntelliMouseParameters();
+ break;
+
+ case WM_GETDLGCODE:
+ return DLGC_HASSETSEL | DLGC_WANTALLKEYS;
+
+ case WM_KILLFOCUS:
+ NotifyFocus(false);
+ DropCaret();
+ //RealizeWindowPalette(true);
+ break;
+
+ case WM_SETFOCUS:
+ NotifyFocus(true);
+ ShowCaretAtCurrentPosition();
+ RealizeWindowPalette(false);
+ break;
+
+ case WM_SYSCOLORCHANGE:
+ //Platform::DebugPrintf("Setting Changed\n");
+ InvalidateStyleData();
+ break;
+
+ case WM_PALETTECHANGED:
+ if (wParam != reinterpret_cast<unsigned int>(wMain.GetID())) {
+ //Platform::DebugPrintf("** Palette Changed\n");
+ RealizeWindowPalette(true);
+ }
+ break;
+
+ case WM_QUERYNEWPALETTE:
+ //Platform::DebugPrintf("** Query palette\n");
+ RealizeWindowPalette(false);
+ break;
+
+ case WM_IME_STARTCOMPOSITION: // dbcs
+ ImeStartComposition();
+ return DefWindowProc(wMain.GetID(), iMessage, wParam, lParam);
+
+ case WM_IME_ENDCOMPOSITION: // dbcs
+ ImeEndComposition();
+ return DefWindowProc(wMain.GetID(), iMessage, wParam, lParam);
+
+ case WM_CONTEXTMENU:
+#ifdef TOTAL_CONTROL
+ ContextMenu(Point::FromLong(lParam));
+#endif
+ break;
+
+ case EM_CANPASTE: {
+ OpenClipboard(wMain.GetID());
+ HGLOBAL hmemSelection = GetClipboardData(CF_TEXT);
+ if (hmemSelection)
+ GlobalUnlock(hmemSelection);
+ CloseClipboard();
+ return hmemSelection != 0;
+ }
+
+ case EM_SCROLL: {
+ int topStart = topLine;
+ ScrollMessage(wParam);
+ return MAKELONG(topLine - topStart, TRUE);
+ }
+
+ default:
+ return ScintillaBase::WndProc(iMessage, wParam, lParam);
+ }
+ return 0l;
+}
+
+LRESULT ScintillaWin::DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ return ::DefWindowProc(wMain.GetID(), iMessage, wParam, lParam);
+}
+
+void ScintillaWin::SetTicking(bool on) {
+ if (timer.ticking != on) {
+ timer.ticking = on;
+ if (timer.ticking) {
+ timer.tickerID = ::SetTimer(wMain.GetID(), 1, timer.tickSize, NULL);
+ } else {
+ ::KillTimer(wMain.GetID(), timer.tickerID);
+ timer.tickerID = 0;
+ }
+ }
+ timer.ticksToWait = caret.period;
+}
+
+void ScintillaWin::SetMouseCapture(bool on) {
+ if (on) {
+ ::SetCapture(wMain.GetID());
+ } else {
+ ::ReleaseCapture();
+ }
+ capturedMouse = on;
+}
+
+bool ScintillaWin::HaveMouseCapture() {
+ // Cannot just see if GetCapture is this window as the scroll bar also sets capture for the window
+ return capturedMouse && (::GetCapture() == wMain.GetID());
+}
+
+void ScintillaWin::ScrollText(int linesToMove) {
+ //Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove);
+ ::ScrollWindow(wMain.GetID(), 0,
+ vs.lineHeight * (linesToMove), 0, 0);
+ ::UpdateWindow(wMain.GetID());
+}
+
+void ScintillaWin::SetVerticalScrollPos() {
+ ::SetScrollPos(wMain.GetID(), SB_VERT, topLine, TRUE);
+}
+
+void ScintillaWin::SetHorizontalScrollPos() {
+ ::SetScrollPos(wMain.GetID(), SB_HORZ, xOffset, TRUE);
+}
+
+bool ScintillaWin::ModifyScrollBars(int nMax, int nPage) {
+ bool modified = false;
+ SCROLLINFO sci = {
+ sizeof(sci)
+ };
+ sci.fMask = SIF_PAGE | SIF_RANGE;
+ BOOL bz = ::GetScrollInfo(wMain.GetID(), SB_VERT, &sci);
+ if ((sci.nMin != 0) || (sci.nMax != pdoc->LinesTotal()) ||
+ (sci.nPage != (pdoc->LinesTotal() - MaxScrollPos() + 1)) ||
+ (sci.nPos != 0)) {
+ //Platform::DebugPrintf("Scroll info changed %d %d %d %d %d\n",
+ // sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
+ sci.fMask = SIF_PAGE | SIF_RANGE;
+ sci.nMin = 0;
+ sci.nMax = nMax;
+ sci.nPage = nPage;
+ sci.nPos = 0;
+ sci.nTrackPos = 1;
+ ::SetScrollInfo(wMain.GetID(), SB_VERT, &sci, TRUE);
+ modified = true;
+ }
+ int horizStart = 0;
+ int horizEnd = 2000;
+ if (!::GetScrollRange(wMain.GetID(), SB_HORZ, &horizStart, &horizEnd) ||
+ horizStart != 0 || horizEnd != 2000) {
+ ::SetScrollRange(wMain.GetID(), SB_HORZ, 0, 2000, TRUE);
+ //Platform::DebugPrintf("Horiz Scroll info changed\n");
+ modified = true;
+ }
+ return modified;
+}
+
+void ScintillaWin::NotifyChange() {
+ ::SendMessage(GetParent(wMain.GetID()), WM_COMMAND,
+ MAKELONG(wMain.GetDlgCtrlID(), EN_CHANGE),
+ reinterpret_cast<LPARAM>(wMain.GetID()));
+}
+
+void ScintillaWin::NotifyFocus(bool focus) {
+ ::SendMessage(GetParent(wMain.GetID()), WM_COMMAND,
+ MAKELONG(wMain.GetDlgCtrlID(), focus ? EN_SETFOCUS : EN_KILLFOCUS),
+ reinterpret_cast<LPARAM>(wMain.GetID()));
+}
+
+void ScintillaWin::NotifyParent(SCNotification scn) {
+ scn.nmhdr.hwndFrom = wMain.GetID();
+ scn.nmhdr.idFrom = ctrlID;
+ ::SendMessage(GetParent(wMain.GetID()), WM_NOTIFY,
+ wMain.GetDlgCtrlID(), reinterpret_cast<LPARAM>(&scn));
+}
+
+void ScintillaWin::NotifyDoubleClick(Point pt, bool shift) {
+ //Platform::DebugPrintf("ScintillaWin Double click 0\n");
+ ScintillaBase::NotifyDoubleClick(pt, shift);
+ // Send myself a WM_LBUTTONDBLCLK, so the container can handle it too.
+ wMain.SendMessage(WM_LBUTTONDBLCLK,
+ shift ? MK_SHIFT : 0,
+ MAKELPARAM(pt.x, pt.y));
+}
+
+void ScintillaWin::Copy() {
+ //Platform::DebugPrintf("Copy\n");
+ if (currentPos != anchor) {
+ HGLOBAL hmemSelection = GetSelText();
+ ::OpenClipboard(wMain.GetID());
+ ::EmptyClipboard();
+ ::SetClipboardData(CF_TEXT, hmemSelection);
+ if (selType == selRectangle) {
+ ::SetClipboardData(cfColumnSelect, 0);
+ }
+ ::CloseClipboard();
+ }
+}
+
+void ScintillaWin::Paste() {
+ pdoc->BeginUndoAction();
+ int selStart = SelectionStart();
+ ClearSelection();
+ ::OpenClipboard(wMain.GetID());
+ bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect);
+ HGLOBAL hmemSelection = ::GetClipboardData(CF_TEXT);
+ if (hmemSelection) {
+ char *ptr = static_cast<char *>(
+ ::GlobalLock(hmemSelection));
+ if (ptr) {
+ unsigned int bytes = ::GlobalSize(hmemSelection);
+ unsigned int len = bytes;
+ for (unsigned int i = 0; i < bytes; i++) {
+ if ((len == bytes) && (0 == ptr[i]))
+ len = i;
+ }
+ if (isRectangular) {
+ PasteRectangular(selStart, ptr, len);
+ } else {
+ pdoc->InsertString(currentPos, ptr, len);
+ SetEmptySelection(currentPos + len);
+ }
+ }
+ ::GlobalUnlock(hmemSelection);
+ }
+ ::CloseClipboard();
+ pdoc->EndUndoAction();
+ NotifyChange();
+ Redraw();
+}
+
+void ScintillaWin::CreateCallTipWindow(PRectangle) {
+#ifdef TOTAL_CONTROL
+ ct.wCallTip = ::CreateWindow(callClassName, "ACallTip",
+ WS_VISIBLE | WS_CHILD, 100, 100, 150, 20,
+ wDraw.GetID(), reinterpret_cast<HMENU>(idCallTip), wDraw.GetInstance(), &ct);
+ ct.wDraw = ct.wCallTip;
+#endif
+}
+
+void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) {
+#ifdef TOTAL_CONTROL
+ if (!label[0])
+ ::AppendMenu(popup.GetID(), MF_SEPARATOR, 0, "");
+ else if (enabled)
+ ::AppendMenu(popup.GetID(), MF_STRING, cmd, label);
+ else
+ ::AppendMenu(popup.GetID(), MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label);
+#endif
+}
+
+void ScintillaWin::ClaimSelection() {
+ // Windows does not have a primary selection
+}
+
+// Implement IUnknown
+
+STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
+STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
+ //Platform::DebugPrintf("EFE QI");
+ *ppv = NULL;
+ if (riid == IID_IUnknown)
+ *ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
+ if (riid == IID_IEnumFORMATETC)
+ *ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
+ if (!*ppv)
+ return E_NOINTERFACE;
+ FormatEnumerator_AddRef(fe);
+ return S_OK;
+}
+STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) {
+ return ++fe->ref;
+}
+STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) {
+ fe->ref--;
+ if (fe->ref > 0)
+ return fe->ref;
+ delete fe;
+ return 0;
+}
+// Implement IEnumFORMATETC
+STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
+ //Platform::DebugPrintf("EFE Next %d %d", fe->pos, celt);
+ if (rgelt == NULL) return E_POINTER;
+ // We only support one format, so this is simple.
+ unsigned int putPos = 0;
+ while ((fe->pos < 1) && (putPos < celt)) {
+ rgelt->cfFormat = CF_TEXT;
+ rgelt->ptd = 0;
+ rgelt->dwAspect = DVASPECT_CONTENT;
+ rgelt->lindex = -1;
+ rgelt->tymed = TYMED_HGLOBAL;
+ fe->pos++;
+ putPos++;
+ }
+ if (pceltFetched)
+ *pceltFetched = putPos;
+ return putPos ? S_OK : S_FALSE;
+}
+STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) {
+ fe->pos += celt;
+ return S_OK;
+}
+STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) {
+ fe->pos = 0;
+ return S_OK;
+}
+STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) {
+ FormatEnumerator *pfe = new FormatEnumerator(fe->pos);
+ return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
+ reinterpret_cast<void **>(ppenum));
+}
+
+static void *vtFormatEnumerator[] = {
+ FormatEnumerator_QueryInterface,
+ FormatEnumerator_AddRef,
+ FormatEnumerator_Release,
+ FormatEnumerator_Next,
+ FormatEnumerator_Skip,
+ FormatEnumerator_Reset,
+ FormatEnumerator_Clone
+};
+
+FormatEnumerator::FormatEnumerator(int pos_) {
+ vtbl = vtFormatEnumerator;
+ ref = 0; // First QI adds first reference...
+ pos = pos_;
+}
+
+// Implement IUnknown
+STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) {
+ return ds->sci->QueryInterface(riid, ppv);
+}
+STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) {
+ return ds->sci->AddRef();
+}
+STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) {
+ return ds->sci->Release();
+}
+
+// Implement IDropSource
+STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) {
+ if (fEsc)
+ return DRAGDROP_S_CANCEL;
+ if (!(grfKeyState & MK_LBUTTON))
+ return DRAGDROP_S_DROP;
+ return S_OK;
+}
+
+STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) {
+ return DRAGDROP_S_USEDEFAULTCURSORS;
+}
+
+static void *vtDropSource[] = {
+ DropSource_QueryInterface,
+ DropSource_AddRef,
+ DropSource_Release,
+ DropSource_QueryContinueDrag,
+ DropSource_GiveFeedback
+ };
+
+DropSource::DropSource() {
+ vtbl = vtDropSource;
+ sci = 0;
+}
+
+// Implement IUnkown
+STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) {
+ //Platform::DebugPrintf("DO QI %x\n", pd);
+ return pd->sci->QueryInterface(riid, ppv);
+}
+STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) {
+ return pd->sci->AddRef();
+}
+STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) {
+ return pd->sci->Release();
+}
+// Implement IDataObject
+STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) {
+ return pd->sci->GetData(pFEIn, pSTM);
+}
+
+STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) {
+ //Platform::DebugPrintf("DOB GetDataHere\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
+ if (pd->sci->DragIsRectangularOK(pFE->cfFormat) &&
+ pFE->ptd == 0 &&
+ (pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
+ pFE->lindex == -1 &&
+ (pFE->tymed & TYMED_HGLOBAL) != 0
+ ) {
+ return S_OK;
+ }
+
+ if (
+ ((pFE->cfFormat != CF_TEXT) && (pFE->cfFormat != CF_HDROP)) ||
+ pFE->ptd != 0 ||
+ (pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
+ pFE->lindex != -1 ||
+ (pFE->tymed & TYMED_HGLOBAL) == 0
+ ) {
+ //Platform::DebugPrintf("DOB QueryGetData No %x\n",pFE->cfFormat);
+ //return DATA_E_FORMATETC;
+ return S_FALSE;
+ }
+ //Platform::DebugPrintf("DOB QueryGetData OK %x\n",pFE->cfFormat);
+ return S_OK;
+}
+
+STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *, FORMATETC *, FORMATETC *pFEOut) {
+ //Platform::DebugPrintf("DOB GetCanon\n");
+ pFEOut->cfFormat = CF_TEXT;
+ pFEOut->ptd = 0;
+ pFEOut->dwAspect = DVASPECT_CONTENT;
+ pFEOut->lindex = -1;
+ pFEOut->tymed = TYMED_HGLOBAL;
+ return S_OK;
+}
+
+STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) {
+ //Platform::DebugPrintf("DOB SetData\n");
+ return E_FAIL;
+}
+
+STDMETHODIMP DataObject_EnumFormatEtc(DataObject *, DWORD dwDirection, IEnumFORMATETC **ppEnum) {
+ //Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
+ if (dwDirection != DATADIR_GET) {
+ *ppEnum = 0;
+ return E_FAIL;
+ }
+ FormatEnumerator *pfe = new FormatEnumerator(0);
+ return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
+ reinterpret_cast<void **>(ppEnum));
+}
+
+STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
+ //Platform::DebugPrintf("DOB DAdvise\n");
+ return E_FAIL;
+}
+
+STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) {
+ //Platform::DebugPrintf("DOB DUnadvise\n");
+ return E_FAIL;
+}
+
+STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) {
+ //Platform::DebugPrintf("DOB EnumDAdvise\n");
+ return E_FAIL;
+}
+
+static void *vtDataObject[] = {
+ DataObject_QueryInterface,
+ DataObject_AddRef,
+ DataObject_Release,
+ DataObject_GetData,
+ DataObject_GetDataHere,
+ DataObject_QueryGetData,
+ DataObject_GetCanonicalFormatEtc,
+ DataObject_SetData,
+ DataObject_EnumFormatEtc,
+ DataObject_DAdvise,
+ DataObject_DUnadvise,
+ DataObject_EnumDAdvise
+};
+
+DataObject::DataObject() {
+ vtbl = vtDataObject;
+ sci = 0;
+}
+
+// Implement IUnknown
+STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) {
+ //Platform::DebugPrintf("DT QI %x\n", dt);
+ return dt->sci->QueryInterface(riid, ppv);
+}
+STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) {
+ return dt->sci->AddRef();
+}
+STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) {
+ return dt->sci->Release();
+}
+
+// Implement IDropTarget by forwarding to Scintilla
+STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect) {
+ return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
+}
+STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
+ return dt->sci->DragOver(grfKeyState, pt, pdwEffect);
+}
+STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) {
+ return dt->sci->DragLeave();
+}
+STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect) {
+ return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
+}
+
+static void *vtDropTarget[] = {
+ DropTarget_QueryInterface,
+ DropTarget_AddRef,
+ DropTarget_Release,
+ DropTarget_DragEnter,
+ DropTarget_DragOver,
+ DropTarget_DragLeave,
+ DropTarget_Drop
+};
+
+DropTarget::DropTarget() {
+ vtbl = vtDropTarget;
+ sci = 0;
+}
+
+// DBCS: support Input Method Editor (IME)
+// Called when IME Window opened.
+void ScintillaWin::ImeStartComposition() {
+ if (caret.active) {
+ // Move IME Window to current caret position
+ HIMC hIMC = ::ImmGetContext(wMain.GetID());
+ Point pos = LocationFromPosition(currentPos);
+ COMPOSITIONFORM CompForm;
+ CompForm.dwStyle = CFS_POINT;
+ CompForm.ptCurrentPos.x = pos.x;
+ CompForm.ptCurrentPos.y = pos.y;
+
+ ::ImmSetCompositionWindow(hIMC, &CompForm);
+
+ // Set font of IME window to same as surrounded text.
+ if (stylesValid) {
+ // Since the style creation code has been made platform independent,
+ // The logfont for the IME is recreated here.
+ int styleHere = (pdoc->StyleAt(currentPos)) & 31;
+ LOGFONT lf = {0};
+ int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel;
+ if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2;
+ Surface surface;
+ int deviceHeight = (sizeZoomed * surface.LogPixelsY()) / 72;
+ // The negative is to allow for leading
+ lf.lfHeight = -(abs(deviceHeight));
+ lf.lfWeight = vs.styles[styleHere].bold ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = vs.styles[styleHere].italic ? 1 : 0;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ strcpy(lf.lfFaceName, vs.styles[styleHere].fontName);
+
+ ::ImmSetCompositionFont(hIMC, &lf);
+ ::ImmReleaseContext(wMain.GetID(), hIMC);
+ }
+ // Caret is displayed in IME window. So, caret in Scintilla is useless.
+ DropCaret();
+ }
+}
+
+// Called when IME Window closed.
+void ScintillaWin::ImeEndComposition() {
+ ShowCaretAtCurrentPosition();
+}
+
+void ScintillaWin::GetIntelliMouseParameters() {
+ // This retrieves the number of lines per scroll as configured inthe Mouse Properties sheet in Control Panel
+ ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &ucWheelScrollLines, 0);
+}
+
+HGLOBAL ScintillaWin::GetSelText() {
+ int bytes = SelectionRangeLength();
+
+ HGLOBAL hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
+ bytes + 1);
+ if (hand) {
+ char *ptr = static_cast<char *>(::GlobalLock(hand));
+ char *selChars = CopySelectionRange();
+ if (selChars) {
+ memcpy(ptr, selChars, bytes);
+ delete []selChars;
+ //for (int i = 0; i < bytes; i++) {
+ // ptr[i] = pdoc->CharAt(startPos + i);
+ //}
+ }
+ ptr[bytes] = '\0';
+ ::GlobalUnlock(hand);
+ }
+ return hand;
+}
+
+void ScintillaWin::ScrollMessage(WPARAM wParam) {
+ //DWORD dwStart = timeGetTime();
+ //Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);
+
+ SCROLLINFO sci;
+ memset(&sci, 0, sizeof(sci));
+ sci.cbSize = sizeof(sci);
+ sci.fMask = SIF_ALL;
+
+ BOOL b = ::GetScrollInfo(wMain.GetID(), SB_VERT, &sci);
+
+ //Platform::DebugPrintf("ScrollInfo %d mask=%x min=%d max=%d page=%d pos=%d track=%d\n", b,sci.fMask,
+ //sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
+
+ int topLineNew = topLine;
+ switch (LoWord(wParam)) {
+ case SB_LINEUP:
+ topLineNew -= 1;
+ break;
+ case SB_LINEDOWN:
+ topLineNew += 1;
+ break;
+ case SB_PAGEUP:
+ topLineNew -= LinesToScroll(); break;
+ case SB_PAGEDOWN: topLineNew += LinesToScroll(); break;
+ case SB_TOP: topLineNew = 0; break;
+ case SB_BOTTOM: topLineNew = MaxScrollPos(); break;
+ case SB_THUMBPOSITION: topLineNew = sci.nTrackPos; break;
+ case SB_THUMBTRACK: topLineNew = sci.nTrackPos; break;
+ }
+ ScrollTo(topLineNew);
+}
+
+void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
+ int xPos = xOffset;
+ switch (LoWord(wParam)) {
+ case SB_LINEUP:
+ xPos -= 20;
+ break;
+ case SB_LINEDOWN:
+ xPos += 20;
+ break;
+ case SB_PAGEUP:
+ xPos -= 200;
+ break;
+ case SB_PAGEDOWN:
+ xPos += 200;
+ break;
+ case SB_TOP:
+ xPos = 0;
+ break;
+ case SB_BOTTOM:
+ xPos = 2000;
+ break;
+ case SB_THUMBPOSITION:
+ xPos = HiWord(wParam);
+ break;
+ case SB_THUMBTRACK:
+ xPos = HiWord(wParam);
+ break;
+ }
+ HorizontalScrollTo(xPos);
+}
+
+void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
+ RefreshStyleData();
+ Surface surfaceWindow;
+ HDC hdc = ::GetDC(wMain.GetID());
+ surfaceWindow.Init(hdc);
+ int changes = surfaceWindow.SetPalette(&palette, inBackGround);
+ if (changes > 0)
+ Redraw();
+ surfaceWindow.Release();
+ ::ReleaseDC(wMain.GetID(), hdc);
+}
+
+// Redraw all of text area. This paint will not be abandoned.
+void ScintillaWin::FullPaint() {
+ paintState = painting;
+ rcPaint = GetTextRectangle();
+ paintingAllText = true;
+ HDC hdc = ::GetDC(wMain.GetID());
+ Surface surfaceWindow;
+ surfaceWindow.Init(hdc);
+ Paint(&surfaceWindow, rcPaint);
+ surfaceWindow.Release();
+ ::ReleaseDC(wMain.GetID(), hdc);
+ paintState = notPainting;
+}
+
+// Implement IUnknown
+STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
+ *ppv = NULL;
+ if (riid == IID_IUnknown)
+ *ppv = reinterpret_cast<IDropTarget *>(&dt);
+ if (riid == IID_IDropSource)
+ *ppv = reinterpret_cast<IDropSource *>(&ds);
+ if (riid == IID_IDropTarget)
+ *ppv = reinterpret_cast<IDropTarget *>(&dt);
+ if (riid == IID_IDataObject)
+ *ppv = reinterpret_cast<IDataObject *>(&dob);
+ if (!*ppv)
+ return E_NOINTERFACE;
+ return S_OK;
+}
+
+STDMETHODIMP_(ULONG) ScintillaWin::AddRef() {
+ return 1;
+}
+
+STDMETHODIMP_(ULONG) ScintillaWin::Release() {
+ return 1;
+}
+
+// Implement IDropTarget
+STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT, DWORD grfKeyState,
+ POINTL, PDWORD pdwEffect) {
+ if (inDragDrop) // Internal defaults to move
+ *pdwEffect = DROPEFFECT_MOVE;
+ else
+ *pdwEffect = DROPEFFECT_COPY;
+ if (grfKeyState & MK_ALT)
+ *pdwEffect = DROPEFFECT_MOVE;
+ if (grfKeyState & MK_CONTROL)
+ *pdwEffect = DROPEFFECT_COPY;
+ return S_OK;
+}
+
+STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
+ // These are the Wordpad semantics.
+ if (inDragDrop) // Internal defaults to move
+ *pdwEffect = DROPEFFECT_MOVE;
+ else
+ *pdwEffect = DROPEFFECT_COPY;
+ if (grfKeyState & MK_ALT)
+ *pdwEffect = DROPEFFECT_MOVE;
+ if (grfKeyState & MK_CONTROL)
+ *pdwEffect = DROPEFFECT_COPY;
+ // Update the cursor.
+ POINT rpt = {pt.x, pt.y};
+ ::ScreenToClient(wMain.GetID(), &rpt);
+ SetDragPosition(PositionFromLocation(Point(rpt.x, rpt.y)));
+
+ return S_OK;
+}
+
+STDMETHODIMP ScintillaWin::DragLeave() {
+ SetDragPosition(invalidPosition);
+ return S_OK;
+}
+
+STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect) {
+ if (inDragDrop) // Internal defaults to move
+ *pdwEffect = DROPEFFECT_MOVE;
+ else
+ *pdwEffect = DROPEFFECT_COPY;
+ if (grfKeyState & MK_ALT)
+ *pdwEffect = DROPEFFECT_MOVE;
+ if (grfKeyState & MK_CONTROL)
+ *pdwEffect = DROPEFFECT_COPY;
+
+ if (pIDataSource == NULL)
+ return E_POINTER;
+
+ SetDragPosition(invalidPosition);
+
+ FORMATETC fmte = {CF_TEXT,
+ NULL,
+ DVASPECT_CONTENT,
+ -1,
+ TYMED_HGLOBAL
+ };
+ STGMEDIUM medium;
+
+ HRESULT hres = pIDataSource->GetData(&fmte, &medium);
+ if (FAILED(hres)) {
+ //Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
+ return hres;
+ }
+ if (medium.hGlobal == 0) {
+ return E_OUTOFMEMORY;
+ }
+ char *data = static_cast<char *>(::GlobalLock(medium.hGlobal));
+
+ FORMATETC fmtr = {cfColumnSelect,
+ NULL,
+ DVASPECT_CONTENT,
+ -1,
+ TYMED_HGLOBAL
+ };
+ HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);
+
+ POINT rpt = {pt.x, pt.y};
+ ::ScreenToClient(wMain.GetID(), &rpt);
+ Point npt(rpt.x, rpt.y);
+ int movePos = PositionFromLocation(Point(rpt.x, rpt.y));
+
+ DropAt(movePos, data, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK);
+
+ ::GlobalUnlock(medium.hGlobal);
+
+ // Free data
+ if (medium.pUnkForRelease != NULL)
+ medium.pUnkForRelease->Release();
+
+ return S_OK;
+}
+
+// Implement important part of IDataObject
+STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
+ if (
+ ((pFEIn->cfFormat != CF_TEXT) && (pFEIn->cfFormat != CF_HDROP)) ||
+ pFEIn->ptd != 0 ||
+ (pFEIn->dwAspect & DVASPECT_CONTENT) == 0 ||
+ pFEIn->lindex != -1 ||
+ (pFEIn->tymed & TYMED_HGLOBAL) == 0
+ ) {
+ //Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
+ return DATA_E_FORMATETC;
+ }
+ pSTM->tymed = TYMED_HGLOBAL;
+ if (pFEIn->cfFormat == CF_HDROP) {
+ pSTM->hGlobal = 0;
+ pSTM->pUnkForRelease = 0;
+ return S_OK;
+ }
+ //Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);
+
+ HGLOBAL hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
+ lenDrag + 1);
+ if (hand) {
+ char *ptr = static_cast<char *>(::GlobalLock(hand));
+ for (int i = 0; i < lenDrag; i++) {
+ ptr[i] = dragChars[i];
+ }
+ ptr[lenDrag] = '\0';
+ ::GlobalUnlock(hand);
+ }
+ pSTM->hGlobal = hand;
+ pSTM->pUnkForRelease = 0;
+ return S_OK;
+}
+
+const char scintillaClassName[] = "Scintilla";
+
+void ScintillaWin::Register(HINSTANCE hInstance_) {
+
+ hInstance = hInstance_;
+
+ InitCommonControls();
+
+ WNDCLASS wndclass;
+
+ // Register the Scintilla class
+
+ wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
+ wndclass.cbClsExtra = 0;
+ // Reserve extra bytes for each instance of the window;
+ // we will use these bytes to store a pointer to the C++
+ // (ScintillaWin) object corresponding to the window.
+ wndclass.cbWndExtra = sizeof(ScintillaWin *);
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = NULL;
+ //wndclass.hCursor = LoadCursor(NULL,IDC_IBEAM);
+ wndclass.hCursor = NULL;
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = scintillaClassName;
+
+ if (!RegisterClass(&wndclass)) {
+ //Platform::DebugPrintf("Could not register class\n");
+ // TODO: fail nicely
+ return;
+ }
+
+ // Register the CallTip class
+
+ wndclass.lpfnWndProc = ScintillaWin::CTWndProc;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.lpszClassName = callClassName;
+
+ if (!RegisterClass(&wndclass)) {
+ //Platform::DebugPrintf("Could not register class\n");
+ return;
+ }
+}
+
+LRESULT PASCAL ScintillaWin::CTWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
+
+ // Find C++ object associated with window.
+ CallTip *ctp = reinterpret_cast<CallTip *>(GetWindowLong(hWnd, 0));
+ // ctp will be zero if WM_CREATE not seen yet
+ if (ctp == 0) {
+ if (iMessage == WM_CREATE) {
+ // Associate CallTip object with window
+ CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
+ SetWindowLong(hWnd, 0,
+ reinterpret_cast<LONG>(pCreate->lpCreateParams));
+ return 0;
+ } else {
+ return DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+ } else {
+ if (iMessage == WM_DESTROY) {
+ SetWindowLong(hWnd, 0, 0);
+ return DefWindowProc(hWnd, iMessage, wParam, lParam);
+ } else if (iMessage == WM_PAINT) {
+ PAINTSTRUCT ps;
+ ::BeginPaint(hWnd, &ps);
+ Surface surfaceWindow;
+ surfaceWindow.Init(ps.hdc);
+ ctp->PaintCT(&surfaceWindow);
+ surfaceWindow.Release();
+ ::EndPaint(hWnd, &ps);
+ return 0;
+ } else {
+ return DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+ }
+}
+
+LRESULT PASCAL ScintillaWin::SWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ //Platform::DebugPrintf("S W:%x M:%d WP:%x L:%x\n", hWnd, iMessage, wParam, lParam);
+
+ // Find C++ object associated with window.
+ ScintillaWin *sci = reinterpret_cast<ScintillaWin *>(GetWindowLong(hWnd, 0));
+ // sci will be zero if WM_CREATE not seen yet
+ if (sci == 0) {
+ if (iMessage == WM_CREATE) {
+ // Create C++ object associated with window
+ sci = new ScintillaWin(hWnd);
+ SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(sci));
+ return sci->WndProc(iMessage, wParam, lParam);
+ } else {
+ return DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+ } else {
+ if (iMessage == WM_DESTROY) {
+ sci->Finalise();
+ delete sci;
+ SetWindowLong(hWnd, 0, 0);
+ return DefWindowProc(hWnd, iMessage, wParam, lParam);
+ } else {
+ return sci->WndProc(iMessage, wParam, lParam);
+ }
+ }
+}
+
+// This function is externally visible so it can be called from container when building statically
+void Scintilla_RegisterClasses(HINSTANCE hInstance) {
+ ScintillaWin::Register(hInstance);
+}
+
+#ifndef STATIC_BUILD
+extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) {
+ //Platform::DebugPrintf("Scintilla::DllMain %d %d\n", hInstance, dwReason);
+ if (dwReason == DLL_PROCESS_ATTACH) {
+ Scintilla_RegisterClasses(hInstance);
+ }
+ return TRUE;
+}
+#endif
diff --git a/win32/makefile b/win32/makefile
new file mode 100644
index 000000000..0dfded5a9
--- /dev/null
+++ b/win32/makefile
@@ -0,0 +1,98 @@
+# Make file for Scintilla on Windows
+# Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile assumes the mingw32 version of GCC 2.95.2 is used and changes will
+# be needed to use other compilers.
+
+.SUFFIXES: .cxx
+CC = g++
+DLLWRAP = dllwrap
+
+COMPONENT = ../bin/Scintilla.dll
+LEXCOMPONENT = ../bin/SciLexer.dll
+
+vpath %.h ../src ../include
+vpath %.cxx ../src
+
+LDFLAGS = -lkernel32 -lgdi32 -luser32 -lwinmm -lcomdlg32 -lcomctl32 -limm32 -lole32 -luuid
+#CXXFLAGS = -W -Wall
+# Add -MMD to get dependencies
+#CXXFLAGS = -g -pg -pedantic -Os -fno-exceptions -fvtable-thunks -fno-rtti
+INCLUDEDIRS=-I ../include -I ../src
+CXXFLAGS = -pedantic $(INCLUDEDIRS) -Os -fno-exceptions -fvtable-thunks -fno-rtti
+
+.cxx.o:
+ $(CC) $(CXXFLAGS) -c $< -o $@
+
+ALL: $(COMPONENT) $(LEXCOMPONENT) ScintillaWinS.o
+
+clean:
+ del /q *.exe *.o *.obj *.dll *.res *.map
+
+SOBJS = ScintillaWin.o ScintillaBase.o Editor.o Document.o \
+ ContractionState.o CellBuffer.o CallTip.o \
+ ScintRes.o PlatWin.o KeyMap.o Indicator.o LineMarker.o Style.o \
+ ViewStyle.o AutoComplete.o
+$(COMPONENT): $(SOBJS)
+ $(DLLWRAP) --target i386-mingw32 -o $(COMPONENT) $(SOBJS) $(LDFLAGS) -s --relocatable
+
+LOBJS = ScintillaWinL.o ScintillaBaseL.o Editor.o Document.o \
+ ContractionState.o CellBuffer.o CallTip.o \
+ ScintRes.o PlatWin.o KeyMap.o Indicator.o LineMarker.o Style.o \
+ ViewStyle.o AutoComplete.o KeyWords.o Accessor.o PropSet.o
+$(LEXCOMPONENT): $(LOBJS)
+ $(DLLWRAP) --target i386-mingw32 -o $(LEXCOMPONENT) $(LOBJS) $(LDFLAGS) -s --relocatable
+
+Accessor.o: Accessor.cxx Platform.h PropSet.h Accessor.h Scintilla.h
+AutoComplete.o: AutoComplete.cxx Platform.h AutoComplete.h
+CallTip.o: CallTip.cxx Platform.h CallTip.h
+CellBuffer.o: CellBuffer.cxx Platform.h Scintilla.h CellBuffer.h
+ContractionState.o: ContractionState.cxx Platform.h ContractionState.h
+Document.o: Document.cxx Platform.h Scintilla.h CellBuffer.h \
+ Document.h
+Editor.o: Editor.cxx Platform.h Scintilla.h ContractionState.h \
+ CellBuffer.h KeyMap.h Indicator.h LineMarker.h Style.h ViewStyle.h \
+ Document.h Editor.h
+Indicator.o: Indicator.cxx Platform.h Scintilla.h Indicator.h
+KeyMap.o: KeyMap.cxx Platform.h Scintilla.h KeyMap.h
+KeyWords.o: KeyWords.cxx Platform.h PropSet.h Accessor.h KeyWords.h \
+ Scintilla.h SciLexer.h
+LineMarker.o: LineMarker.cxx Platform.h Scintilla.h LineMarker.h
+PlatWin.o: PlatWin.cxx Platform.h PlatformRes.h
+PropSet.o: PropSet.cxx Platform.h PropSet.h
+ScintillaBase.o: ScintillaBase.cxx Platform.h Scintilla.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h ViewStyle.h AutoComplete.h Document.h Editor.h \
+ ScintillaBase.h
+ScintillaBaseL.o: ScintillaBase.cxx Platform.h Scintilla.h SciLexer.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h PropSet.h Accessor.h KeyWords.h
+ScintillaWin.o: ScintillaWin.cxx Platform.h Scintilla.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h
+ScintillaWinL.o: ScintillaWin.cxx Platform.h Scintilla.h SciLexer.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h PropSet.h Accessor.h KeyWords.h
+ScintillaWinS.o: ScintillaWin.cxx Platform.h Scintilla.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h
+Style.o: Style.cxx Platform.h Style.h
+ViewStyle.o: ViewStyle.cxx Platform.h Scintilla.h Indicator.h \
+ LineMarker.h Style.h ViewStyle.h
+
+ScintillaBaseL.o:
+ $(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o ScintillaBaseL.o
+
+ScintillaWinS.o:
+ $(CC) $(CXXFLAGS) -D STATIC_BUILD -c $< -o ScintillaWinS.o
+
+ScintillaWinL.o:
+ $(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o ScintillaWinL.o
+
+ScintRes.o: ScintRes.rc PlatformRes.h
+ windres ScintRes.rc ScintRes.o
+
diff --git a/win32/makefile_bor b/win32/makefile_bor
new file mode 100644
index 000000000..0b2cda968
--- /dev/null
+++ b/win32/makefile_bor
@@ -0,0 +1,120 @@
+# Make file for Scintilla on Windows Borland C++ Builder version
+# Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile is for using Visual C++ and nmake.
+# The main makefile uses mingw32 gcc and may be more current than this file.
+
+.SUFFIXES: .cxx
+CC = bcc32
+RC = brcc32
+LD = tlink32
+
+COMPONENT = ..\bin\Scintilla.dll
+LEXCOMPONENT = ..\bin\SciLexer.dll
+
+LDFLAGS = import32 cw32mt
+INCLUDEDIRS=-I../include -I../src
+CXXFLAGS = -P -tW -w -RT- -x- -v
+
+.cxx.obj:
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c $*.cxx
+
+.rc.res:
+ $(RC) /r $*.rc
+
+ALL: $(COMPONENT) $(LEXCOMPONENT) ScintillaWinS.obj
+
+clean:
+ del /q *.exe *.o *.obj *.dll *.res *.map
+
+SOBJS = ScintillaWin.obj ScintillaBase.obj Editor.obj Document.obj \
+ ContractionState.obj CellBuffer.obj CallTip.obj \
+ PlatWin.obj KeyMap.obj Indicator.obj LineMarker.obj Style.obj \
+ ViewStyle.obj AutoComplete.obj
+$(COMPONENT): $(SOBJS) ScintRes.res
+ $(LD) -Tpd /c c0d32 $(SOBJS), $(COMPONENT), ,$(LDFLAGS), , ScintRes.res
+
+LOBJS = ScintillaWinL.obj ScintillaBaseL.obj Editor.obj Document.obj \
+ ContractionState.obj CellBuffer.obj CallTip.obj \
+ PlatWin.obj KeyMap.obj Indicator.obj LineMarker.obj Style.obj \
+ ViewStyle.obj AutoComplete.obj KeyWords.obj Accessor.obj PropSet.obj
+$(LEXCOMPONENT): $(LOBJS)
+ $(LD) -Tpd /c c0d32 $(LOBJS), $(LEXCOMPONENT), ,$(LDFLAGS), , ScintRes.res
+
+Accessor.obj: ..\src\Accessor.cxx ..\include\Platform.h ..\include\PropSet.h ..\include\Accessor.h ..\include\Scintilla.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+AutoComplete.obj: ..\src\AutoComplete.cxx ..\include\Platform.h ..\src\AutoComplete.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+CallTip.obj: ..\src\CallTip.cxx ..\include\Platform.h ..\src\CallTip.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+CellBuffer.obj: ..\src\CellBuffer.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\CellBuffer.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+ContractionState.obj: ..\src\ContractionState.cxx ..\include\Platform.h ..\src\ContractionState.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+Document.obj: ..\src\Document.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\CellBuffer.h \
+ ..\src\Document.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+Editor.obj: ..\src\Editor.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\ContractionState.h \
+ ..\src\CellBuffer.h ..\src\KeyMap.h ..\src\Indicator.h ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h \
+ ..\src\Document.h ..\src\Editor.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+Indicator.obj: ..\src\Indicator.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\Indicator.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+KeyMap.obj: ..\src\KeyMap.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\KeyMap.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+KeyWords.obj: ..\src\KeyWords.cxx ..\include\Platform.h ..\include\PropSet.h ..\include\Accessor.h ..\include\KeyWords.h \
+ ..\include\Scintilla.h ..\include\SciLexer.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+LineMarker.obj: ..\src\LineMarker.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\LineMarker.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+PlatWin.obj: PlatWin.cxx ..\include\Platform.h PlatformRes.h
+
+PropSet.obj: ..\src\PropSet.cxx ..\include\Platform.h ..\include\PropSet.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$*
+
+ScintillaBase.obj: ..\src\ScintillaBase.cxx ..\include\Platform.h ..\include\Scintilla.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h ..\src\AutoComplete.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\ScintillaBase.cxx -o$@
+
+ScintillaBaseL.obj: ..\src\ScintillaBase.cxx ..\include\Platform.h ..\include\Scintilla.h ..\include\SciLexer.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h ..\include\PropSet.h ..\include\Accessor.h ..\include\KeyWords.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) /DSCI_LEXER -o$* /c ..\src\ScintillaBase.cxx
+
+ScintillaWin.obj: ScintillaWin.cxx ..\include\Platform.h ..\include\Scintilla.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h
+
+ScintillaWinL.obj: ScintillaWin.cxx ..\include\Platform.h ..\include\Scintilla.h ..\include\SciLexer.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h ..\include\PropSet.h ..\include\Accessor.h ..\include\KeyWords.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) /DSCI_LEXER -o$* /c ScintillaWin.cxx
+
+ScintillaWinS.obj: ScintillaWin.cxx ..\include\Platform.h ..\include\Scintilla.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) /DSTATIC_BUILD -o$* /c ScintillaWin.cxx
+
+Style.obj: ..\src\Style.cxx ..\include\Platform.h ..\src\Style.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$@
+
+ViewStyle.obj: ..\src\ViewStyle.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o$@
diff --git a/win32/makefile_vc b/win32/makefile_vc
new file mode 100644
index 000000000..32a52a385
--- /dev/null
+++ b/win32/makefile_vc
@@ -0,0 +1,125 @@
+# Make file for Scintilla on Windows Visual C++ version
+# Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile is for using Visual C++ and nmake.
+# The main makefile uses mingw32 gcc and may be more current than this file.
+
+.SUFFIXES: .cxx
+CC = cl
+RC = rc
+LD = link
+
+COMPONENT = ../bin/Scintilla.dll
+LEXCOMPONENT = ../bin/SciLexer.dll
+
+LDFLAGS = /NODEFAULTLIB:LIBC KERNEL32.lib USER32.lib GDI32.lib COMDLG32.lib WINMM.lib COMCTL32.lib ADVAPI32.lib IMM32.lib SHELL32.LIB OLE32.LIB
+INCLUDEDIRS=-I ../include -I ../src
+CXXFLAGS = /TP /MD /Ox
+
+!IFDEF DEBUG
+CXXFLAGS=$(CXXFLAGS) /Zi
+LDFLAGS=/DEBUG $(LDFLAGS)
+!ENDIF
+
+.cxx.obj:
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c $< -o $@
+
+.rc.res:
+ $(RC) $*.rc
+
+ALL: $(COMPONENT) $(LEXCOMPONENT) ScintillaWinS.obj
+
+clean:
+ del /q *.exe *.o *.obj *.dll *.res *.map
+
+SOBJS = ScintillaWin.obj ScintillaBase.obj Editor.obj Document.obj \
+ ContractionState.obj CellBuffer.obj CallTip.obj \
+ PlatWin.obj KeyMap.obj Indicator.obj LineMarker.obj Style.obj \
+ ViewStyle.obj AutoComplete.obj
+$(COMPONENT): $(SOBJS) ScintRes.res
+ $(LD) /DLL /OUT:$(COMPONENT) $(SOBJS) ScintRes.res $(LDFLAGS)
+
+LOBJS = ScintillaWinL.obj ScintillaBaseL.obj Editor.obj Document.obj \
+ ContractionState.obj CellBuffer.obj CallTip.obj \
+ PlatWin.obj KeyMap.obj Indicator.obj LineMarker.obj Style.obj \
+ ViewStyle.obj AutoComplete.obj KeyWords.obj Accessor.obj PropSet.obj
+$(LEXCOMPONENT): $(LOBJS)
+ $(LD) /DLL /OUT:$(LEXCOMPONENT) $(LOBJS) ScintRes.res $(LDFLAGS)
+
+Accessor.obj: ..\src\Accessor.cxx ..\include\Platform.h ..\include\PropSet.h ..\include\Accessor.h ..\include\Scintilla.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+AutoComplete.obj: ..\src\AutoComplete.cxx ..\include\Platform.h ..\src\AutoComplete.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+CallTip.obj: ..\src\CallTip.cxx ..\include\Platform.h ..\src\CallTip.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+CellBuffer.obj: ..\src\CellBuffer.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\CellBuffer.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+ContractionState.obj: ..\src\ContractionState.cxx ..\include\Platform.h ..\src\ContractionState.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+Document.obj: ..\src\Document.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\CellBuffer.h \
+ ..\src\Document.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+Editor.obj: ..\src\Editor.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\ContractionState.h \
+ ..\src\CellBuffer.h ..\src\KeyMap.h ..\src\Indicator.h ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h \
+ ..\src\Document.h ..\src\Editor.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+Indicator.obj: ..\src\Indicator.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\Indicator.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+KeyMap.obj: ..\src\KeyMap.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\KeyMap.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+KeyWords.obj: ..\src\KeyWords.cxx ..\include\Platform.h ..\include\PropSet.h ..\include\Accessor.h ..\include\KeyWords.h \
+ ..\include\Scintilla.h ..\include\SciLexer.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+LineMarker.obj: ..\src\LineMarker.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\LineMarker.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+PlatWin.obj: PlatWin.cxx ..\include\Platform.h PlatformRes.h
+
+PropSet.obj: ..\src\PropSet.cxx ..\include\Platform.h ..\include\PropSet.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+ScintillaBase.obj: ..\src\ScintillaBase.cxx ..\include\Platform.h ..\include\Scintilla.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h ..\src\AutoComplete.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\ScintillaBase.cxx -o $@
+
+ScintillaBaseL.obj: ..\src\ScintillaBase.cxx ..\include\Platform.h ..\include\Scintilla.h ..\include\SciLexer.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h ..\include\PropSet.h ..\include\Accessor.h ..\include\KeyWords.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) /D SCI_LEXER /c ..\src\ScintillaBase.cxx /Fo$@
+
+ScintillaWin.obj: ScintillaWin.cxx ..\include\Platform.h ..\include\Scintilla.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h
+
+ScintillaWinL.obj: ScintillaWin.cxx ..\include\Platform.h ..\include\Scintilla.h ..\include\SciLexer.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h ..\include\PropSet.h ..\include\Accessor.h ..\include\KeyWords.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) /D SCI_LEXER /c ScintillaWin.cxx /Fo$@
+
+ScintillaWinS.obj: ScintillaWin.cxx ..\include\Platform.h ..\include\Scintilla.h \
+ ..\src\ContractionState.h ..\src\CellBuffer.h ..\src\CallTip.h ..\src\KeyMap.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\AutoComplete.h ..\src\ViewStyle.h ..\src\Document.h ..\src\Editor.h \
+ ..\src\ScintillaBase.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) /D STATIC_BUILD /c ScintillaWin.cxx /Fo$@
+
+Style.obj: ..\src\Style.cxx ..\include\Platform.h ..\src\Style.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@
+
+ViewStyle.obj: ..\src\ViewStyle.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\Indicator.h \
+ ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h
+ $(CC) $(INCLUDEDIRS) $(CXXFLAGS) -c ..\src\$*.cxx -o $@