sptr_t Editor::WndProc()

in ext/scintilla/src/Editor.cxx [5784:8284]


sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	//Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);

	// Optional macro recording hook
	if (recordingMacro)
		NotifyMacroRecord(iMessage, wParam, lParam);

	switch (iMessage) {

	case SCI_GETTEXT: {
			if (lParam == 0)
				return pdoc->Length() + 1;
			if (wParam == 0)
				return 0;
			char *ptr = CharPtrFromSPtr(lParam);
			size_t iChar = 0;
			for (; iChar < wParam - 1; iChar++)
				ptr[iChar] = pdoc->CharAt(iChar);
			ptr[iChar] = '\0';
			return iChar;
		}

	case SCI_SETTEXT: {
			if (lParam == 0)
				return 0;
			UndoGroup ug(pdoc);
			pdoc->DeleteChars(0, pdoc->Length());
			SetEmptySelection(0);
			const char *text = CharPtrFromSPtr(lParam);
			pdoc->InsertString(0, text, strlen(text));
			return 1;
		}

	case SCI_GETTEXTLENGTH:
		return pdoc->Length();

	case SCI_CUT:
		Cut();
		SetLastXChosen();
		break;

	case SCI_COPY:
		Copy();
		break;

	case SCI_COPYALLOWLINE:
		CopyAllowLine();
		break;

	case SCI_VERTICALCENTRECARET:
		VerticalCentreCaret();
		break;

	case SCI_MOVESELECTEDLINESUP:
		MoveSelectedLinesUp();
		break;

	case SCI_MOVESELECTEDLINESDOWN:
		MoveSelectedLinesDown();
		break;

	case SCI_COPYRANGE:
		CopyRangeToClipboard(static_cast<Sci::Position>(wParam), lParam);
		break;

	case SCI_COPYTEXT:
		CopyText(wParam, CharPtrFromSPtr(lParam));
		break;

	case SCI_PASTE:
		Paste();
		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
			SetLastXChosen();
		}
		EnsureCaretVisible();
		break;

	case SCI_CLEAR:
		Clear();
		SetLastXChosen();
		EnsureCaretVisible();
		break;

	case SCI_UNDO:
		Undo();
		SetLastXChosen();
		break;

	case SCI_CANUNDO:
		return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;

	case SCI_EMPTYUNDOBUFFER:
		pdoc->DeleteUndoHistory();
		return 0;

	case SCI_GETFIRSTVISIBLELINE:
		return topLine;

	case SCI_SETFIRSTVISIBLELINE:
		ScrollTo(static_cast<Sci::Line>(wParam));
		break;

	case SCI_GETLINE: {	// Risk of overwriting the end of the buffer
			const Sci::Position lineStart =
				pdoc->LineStart(static_cast<Sci::Line>(wParam));
			const Sci::Position lineEnd =
				pdoc->LineStart(static_cast<Sci::Line>(wParam + 1));
			if (lParam == 0) {
				return lineEnd - lineStart;
			}
			char *ptr = CharPtrFromSPtr(lParam);
			Sci::Position iPlace = 0;
			for (Sci::Position iChar = lineStart; iChar < lineEnd; iChar++) {
				ptr[iPlace++] = pdoc->CharAt(iChar);
			}
			return iPlace;
		}

	case SCI_GETLINECOUNT:
		if (pdoc->LinesTotal() == 0)
			return 1;
		else
			return pdoc->LinesTotal();

	case SCI_GETMODIFY:
		return !pdoc->IsSavePoint();

	case SCI_SETSEL: {
			Sci::Position nStart = static_cast<Sci::Position>(wParam);
			Sci::Position nEnd = lParam;
			if (nEnd < 0)
				nEnd = pdoc->Length();
			if (nStart < 0)
				nStart = nEnd; 	// Remove selection
			InvalidateSelection(SelectionRange(nStart, nEnd));
			sel.Clear();
			sel.selType = Selection::selStream;
			SetSelection(nEnd, nStart);
			EnsureCaretVisible();
		}
		break;

	case SCI_GETSELTEXT: {
			SelectionText selectedText;
			CopySelectionRange(&selectedText);
			if (lParam == 0) {
				return selectedText.LengthWithTerminator();
			} else {
				char *ptr = CharPtrFromSPtr(lParam);
				size_t iChar = 0;
				if (selectedText.Length()) {
					for (; iChar < selectedText.LengthWithTerminator(); iChar++)
						ptr[iChar] = selectedText.Data()[iChar];
				} else {
					ptr[0] = '\0';
				}
				return iChar;
			}
		}

	case SCI_LINEFROMPOSITION:
		if (static_cast<Sci::Position>(wParam) < 0)
			return 0;
		return pdoc->LineFromPosition(static_cast<Sci::Position>(wParam));

	case SCI_POSITIONFROMLINE:
		if (static_cast<Sci::Position>(wParam) < 0)
			wParam = pdoc->LineFromPosition(SelectionStart().Position());
		if (wParam == 0)
			return 0; 	// Even if there is no text, there is a first line that starts at 0
		if (static_cast<Sci::Line>(wParam) > pdoc->LinesTotal())
			return -1;
		//if (wParam > pdoc->LineFromPosition(pdoc->Length()))	// Useful test, anyway...
		//	return -1;
		return pdoc->LineStart(static_cast<Sci::Position>(wParam));

		// Replacement of the old Scintilla interpretation of EM_LINELENGTH
	case SCI_LINELENGTH:
		if ((static_cast<Sci::Position>(wParam) < 0) ||
		        (static_cast<Sci::Position>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
			return 0;
		return pdoc->LineStart(static_cast<Sci::Position>(wParam) + 1) - pdoc->LineStart(static_cast<Sci::Position>(wParam));

	case SCI_REPLACESEL: {
			if (lParam == 0)
				return 0;
			UndoGroup ug(pdoc);
			ClearSelection();
			const char *replacement = CharPtrFromSPtr(lParam);
			const Sci::Position lengthInserted = pdoc->InsertString(
				sel.MainCaret(), replacement, strlen(replacement));
			SetEmptySelection(sel.MainCaret() + lengthInserted);
			SetLastXChosen();
			EnsureCaretVisible();
		}
		break;

	case SCI_SETTARGETSTART:
		targetStart = static_cast<Sci::Position>(wParam);
		break;

	case SCI_GETTARGETSTART:
		return targetStart;

	case SCI_SETTARGETEND:
		targetEnd = static_cast<Sci::Position>(wParam);
		break;

	case SCI_GETTARGETEND:
		return targetEnd;

	case SCI_SETTARGETRANGE:
		targetStart = static_cast<Sci::Position>(wParam);
		targetEnd = lParam;
		break;

	case SCI_TARGETWHOLEDOCUMENT:
		targetStart = 0;
		targetEnd = pdoc->Length();
		break;

	case SCI_TARGETFROMSELECTION:
		if (sel.MainCaret() < sel.MainAnchor()) {
			targetStart = sel.MainCaret();
			targetEnd = sel.MainAnchor();
		} else {
			targetStart = sel.MainAnchor();
			targetEnd = sel.MainCaret();
		}
		break;

	case SCI_GETTARGETTEXT: {
			std::string text = RangeText(targetStart, targetEnd);
			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(text.c_str()), text.length());
		}

	case SCI_REPLACETARGET:
		PLATFORM_ASSERT(lParam);
		return ReplaceTarget(false, CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));

	case SCI_REPLACETARGETRE:
		PLATFORM_ASSERT(lParam);
		return ReplaceTarget(true, CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));

	case SCI_SEARCHINTARGET:
		PLATFORM_ASSERT(lParam);
		return SearchInTarget(CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));

	case SCI_SETSEARCHFLAGS:
		searchFlags = static_cast<int>(wParam);
		break;

	case SCI_GETSEARCHFLAGS:
		return searchFlags;

	case SCI_GETTAG:
		return GetTag(CharPtrFromSPtr(lParam), static_cast<int>(wParam));

	case SCI_POSITIONBEFORE:
		return pdoc->MovePositionOutsideChar(static_cast<Sci::Position>(wParam) - 1, -1, true);

	case SCI_POSITIONAFTER:
		return pdoc->MovePositionOutsideChar(static_cast<Sci::Position>(wParam) + 1, 1, true);

	case SCI_POSITIONRELATIVE:
		return std::clamp<Sci::Position>(pdoc->GetRelativePosition(
			static_cast<Sci::Position>(wParam), lParam),
			0, pdoc->Length());

	case SCI_POSITIONRELATIVECODEUNITS:
		return std::clamp<Sci::Position>(pdoc->GetRelativePositionUTF16(
			static_cast<Sci::Position>(wParam), lParam),
			0, pdoc->Length());

	case SCI_LINESCROLL:
		ScrollTo(topLine + static_cast<Sci::Line>(lParam));
		HorizontalScrollTo(xOffset + static_cast<int>(wParam) * static_cast<int>(vs.spaceWidth));
		return 1;

	case SCI_SETXOFFSET:
		xOffset = static_cast<int>(wParam);
		ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
		SetHorizontalScrollPos();
		Redraw();
		break;

	case SCI_GETXOFFSET:
		return xOffset;

	case SCI_CHOOSECARETX:
		SetLastXChosen();
		break;

	case SCI_SCROLLCARET:
		EnsureCaretVisible();
		break;

	case SCI_SETREADONLY:
		pdoc->SetReadOnly(wParam != 0);
		return 1;

	case SCI_GETREADONLY:
		return pdoc->IsReadOnly();

	case SCI_CANPASTE:
		return CanPaste();

	case SCI_POINTXFROMPOSITION:
		if (lParam < 0) {
			return 0;
		} else {
			const Point pt = LocationFromPosition(lParam);
			// Convert to view-relative
			return static_cast<int>(pt.x) - vs.textStart + vs.fixedColumnWidth;
		}

	case SCI_POINTYFROMPOSITION:
		if (lParam < 0) {
			return 0;
		} else {
			const Point pt = LocationFromPosition(lParam);
			return static_cast<int>(pt.y);
		}

	case SCI_FINDTEXT:
		return FindText(wParam, lParam);

	case SCI_GETTEXTRANGE: {
			if (lParam == 0)
				return 0;
			Sci_TextRange *tr = static_cast<Sci_TextRange *>(PtrFromSPtr(lParam));
			Sci::Position cpMax = static_cast<Sci::Position>(tr->chrg.cpMax);
			if (cpMax == -1)
				cpMax = pdoc->Length();
			PLATFORM_ASSERT(cpMax <= pdoc->Length());
			Sci::Position 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 SCI_HIDESELECTION:
		view.hideSelection = wParam != 0;
		Redraw();
		break;

	case SCI_FORMATRANGE:
		return FormatRange(wParam != 0, static_cast<Sci_RangeToFormat *>(PtrFromSPtr(lParam)));

	case SCI_GETMARGINLEFT:
		return vs.leftMarginWidth;

	case SCI_GETMARGINRIGHT:
		return vs.rightMarginWidth;

	case SCI_SETMARGINLEFT:
		lastXChosen += static_cast<int>(lParam) - vs.leftMarginWidth;
		vs.leftMarginWidth = static_cast<int>(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETMARGINRIGHT:
		vs.rightMarginWidth = static_cast<int>(lParam);
		InvalidateStyleRedraw();
		break;

		// Control specific mesages

	case SCI_ADDTEXT: {
			if (lParam == 0)
				return 0;
			const Sci::Position lengthInserted = pdoc->InsertString(
				CurrentPosition(), CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
			SetEmptySelection(sel.MainCaret() + lengthInserted);
			return 0;
		}

	case SCI_ADDSTYLEDTEXT:
		if (lParam)
			AddStyledText(CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
		return 0;

	case SCI_INSERTTEXT: {
			if (lParam == 0)
				return 0;
			Sci::Position insertPos = static_cast<Sci::Position>(wParam);
			if (insertPos == -1)
				insertPos = CurrentPosition();
			Sci::Position newCurrent = CurrentPosition();
			const char *sz = CharPtrFromSPtr(lParam);
			const Sci::Position lengthInserted = pdoc->InsertString(insertPos, sz, strlen(sz));
			if (newCurrent > insertPos)
				newCurrent += lengthInserted;
			SetEmptySelection(newCurrent);
			return 0;
		}

	case SCI_CHANGEINSERTION:
		PLATFORM_ASSERT(lParam);
		pdoc->ChangeInsertion(CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
		return 0;

	case SCI_APPENDTEXT:
		pdoc->InsertString(pdoc->Length(),
			CharPtrFromSPtr(lParam), static_cast<Sci::Position>(wParam));
		return 0;

	case SCI_CLEARALL:
		ClearAll();
		return 0;

	case SCI_DELETERANGE:
		pdoc->DeleteChars(static_cast<Sci::Position>(wParam), lParam);
		return 0;

	case SCI_CLEARDOCUMENTSTYLE:
		ClearDocumentStyle();
		return 0;

	case SCI_SETUNDOCOLLECTION:
		pdoc->SetUndoCollection(wParam != 0);
		return 0;

	case SCI_GETUNDOCOLLECTION:
		return pdoc->IsCollectingUndo();

	case SCI_BEGINUNDOACTION:
		pdoc->BeginUndoAction();
		return 0;

	case SCI_ENDUNDOACTION:
		pdoc->EndUndoAction();
		return 0;

	case SCI_GETCARETPERIOD:
		return caret.period;

	case SCI_SETCARETPERIOD:
		CaretSetPeriod(static_cast<int>(wParam));
		break;

	case SCI_GETWORDCHARS:
		return pdoc->GetCharsOfClass(CharClassify::ccWord, UCharPtrFromSPtr(lParam));

	case SCI_SETWORDCHARS: {
			pdoc->SetDefaultCharClasses(false);
			if (lParam == 0)
				return 0;
			pdoc->SetCharClasses(ConstUCharPtrFromSPtr(lParam), CharClassify::ccWord);
		}
		break;

	case SCI_GETWHITESPACECHARS:
		return pdoc->GetCharsOfClass(CharClassify::ccSpace, UCharPtrFromSPtr(lParam));

	case SCI_SETWHITESPACECHARS: {
			if (lParam == 0)
				return 0;
			pdoc->SetCharClasses(ConstUCharPtrFromSPtr(lParam), CharClassify::ccSpace);
		}
		break;

	case SCI_GETPUNCTUATIONCHARS:
		return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, UCharPtrFromSPtr(lParam));

	case SCI_SETPUNCTUATIONCHARS: {
			if (lParam == 0)
				return 0;
			pdoc->SetCharClasses(ConstUCharPtrFromSPtr(lParam), CharClassify::ccPunctuation);
		}
		break;

	case SCI_SETCHARSDEFAULT:
		pdoc->SetDefaultCharClasses(true);
		break;

	case SCI_SETCHARACTERCATEGORYOPTIMIZATION:
		pdoc->SetCharacterCategoryOptimization(static_cast<int>(wParam));
		break;

	case SCI_GETCHARACTERCATEGORYOPTIMIZATION:
		return pdoc->CharacterCategoryOptimization();

	case SCI_GETLENGTH:
		return pdoc->Length();

	case SCI_ALLOCATE:
		pdoc->Allocate(static_cast<Sci::Position>(wParam));
		break;

	case SCI_GETCHARAT:
		return pdoc->CharAt(static_cast<Sci::Position>(wParam));

	case SCI_SETCURRENTPOS:
		if (sel.IsRectangular()) {
			sel.Rectangular().caret.SetPosition(static_cast<Sci::Position>(wParam));
			SetRectangularRange();
			Redraw();
		} else {
			SetSelection(static_cast<Sci::Position>(wParam), sel.MainAnchor());
		}
		break;

	case SCI_GETCURRENTPOS:
		return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret();

	case SCI_SETANCHOR:
		if (sel.IsRectangular()) {
			sel.Rectangular().anchor.SetPosition(static_cast<Sci::Position>(wParam));
			SetRectangularRange();
			Redraw();
		} else {
			SetSelection(sel.MainCaret(), static_cast<Sci::Position>(wParam));
		}
		break;

	case SCI_GETANCHOR:
		return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor();

	case SCI_SETSELECTIONSTART:
		SetSelection(std::max(sel.MainCaret(), static_cast<Sci::Position>(wParam)), static_cast<Sci::Position>(wParam));
		break;

	case SCI_GETSELECTIONSTART:
		return sel.LimitsForRectangularElseMain().start.Position();

	case SCI_SETSELECTIONEND:
		SetSelection(static_cast<Sci::Position>(wParam), std::min(sel.MainAnchor(), static_cast<Sci::Position>(wParam)));
		break;

	case SCI_GETSELECTIONEND:
		return sel.LimitsForRectangularElseMain().end.Position();

	case SCI_SETEMPTYSELECTION:
		SetEmptySelection(static_cast<Sci::Position>(wParam));
		break;

	case SCI_SETPRINTMAGNIFICATION:
		view.printParameters.magnification = static_cast<int>(wParam);
		break;

	case SCI_GETPRINTMAGNIFICATION:
		return view.printParameters.magnification;

	case SCI_SETPRINTCOLOURMODE:
		view.printParameters.colourMode = static_cast<int>(wParam);
		break;

	case SCI_GETPRINTCOLOURMODE:
		return view.printParameters.colourMode;

	case SCI_SETPRINTWRAPMODE:
		view.printParameters.wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
		break;

	case SCI_GETPRINTWRAPMODE:
		return view.printParameters.wrapState;

	case SCI_GETSTYLEAT:
		if (static_cast<Sci::Position>(wParam) >= pdoc->Length())
			return 0;
		else
			return pdoc->StyleAt(static_cast<Sci::Position>(wParam));

	case SCI_REDO:
		Redo();
		break;

	case SCI_SELECTALL:
		SelectAll();
		break;

	case SCI_SETSAVEPOINT:
		pdoc->SetSavePoint();
		break;

	case SCI_GETSTYLEDTEXT: {
			if (lParam == 0)
				return 0;
			Sci_TextRange *tr = static_cast<Sci_TextRange *>(PtrFromSPtr(lParam));
			int iPlace = 0;
			for (long 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() && !pdoc->IsReadOnly()) ? 1 : 0;

	case SCI_MARKERLINEFROMHANDLE:
		return pdoc->LineFromHandle(static_cast<int>(wParam));

	case SCI_MARKERDELETEHANDLE:
		pdoc->DeleteMarkFromHandle(static_cast<int>(wParam));
		break;

	case SCI_GETVIEWWS:
		return vs.viewWhitespace;

	case SCI_SETVIEWWS:
		vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam);
		Redraw();
		break;

	case SCI_GETTABDRAWMODE:
		return vs.tabDrawMode;

	case SCI_SETTABDRAWMODE:
		vs.tabDrawMode = static_cast<TabDrawMode>(wParam);
		Redraw();
		break;

	case SCI_GETWHITESPACESIZE:
		return vs.whitespaceSize;

	case SCI_SETWHITESPACESIZE:
		vs.whitespaceSize = static_cast<int>(wParam);
		Redraw();
		break;

	case SCI_POSITIONFROMPOINT:
		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
					    false, false);

	case SCI_POSITIONFROMPOINTCLOSE:
		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
					    true, false);

	case SCI_CHARPOSITIONFROMPOINT:
		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
					    false, true);

	case SCI_CHARPOSITIONFROMPOINTCLOSE:
		return PositionFromLocation(Point::FromInts(static_cast<int>(wParam) - vs.ExternalMarginWidth(), static_cast<int>(lParam)),
					    true, true);

	case SCI_GOTOLINE:
		GoToLine(static_cast<Sci::Line>(wParam));
		break;

	case SCI_GOTOPOS:
		SetEmptySelection(static_cast<Sci::Position>(wParam));
		EnsureCaretVisible();
		break;

	case SCI_GETCURLINE: {
			const Sci::Line lineCurrentPos = pdoc->SciLineFromPosition(sel.MainCaret());
			const Sci::Position lineStart = pdoc->LineStart(lineCurrentPos);
			const Sci::Position lineEnd = pdoc->LineStart(lineCurrentPos + 1);
			if (lParam == 0) {
				return 1 + lineEnd - lineStart;
			}
			PLATFORM_ASSERT(wParam > 0);
			char *ptr = CharPtrFromSPtr(lParam);
			unsigned int iPlace = 0;
			for (Sci::Position iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) {
				ptr[iPlace++] = pdoc->CharAt(iChar);
			}
			ptr[iPlace] = '\0';
			return sel.MainCaret() - lineStart;
		}

	case SCI_GETENDSTYLED:
		return pdoc->GetEndStyled();

	case SCI_GETEOLMODE:
		return pdoc->eolMode;

	case SCI_SETEOLMODE:
		pdoc->eolMode = static_cast<int>(wParam);
		break;

	case SCI_SETLINEENDTYPESALLOWED:
		if (pdoc->SetLineEndTypesAllowed(static_cast<int>(wParam))) {
			pcs->Clear();
			pcs->InsertLines(0, pdoc->LinesTotal() - 1);
			SetAnnotationHeights(0, pdoc->LinesTotal());
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETLINEENDTYPESALLOWED:
		return pdoc->GetLineEndTypesAllowed();

	case SCI_GETLINEENDTYPESACTIVE:
		return pdoc->GetLineEndTypesActive();

	case SCI_STARTSTYLING:
		pdoc->StartStyling(static_cast<Sci::Position>(wParam));
		break;

	case SCI_SETSTYLING:
		if (static_cast<Sci::Position>(wParam) < 0)
			errorStatus = SC_STATUS_FAILURE;
		else
			pdoc->SetStyleFor(static_cast<Sci::Position>(wParam), static_cast<char>(lParam));
		break;

	case SCI_SETSTYLINGEX:             // Specify a complete styling buffer
		if (lParam == 0)
			return 0;
		pdoc->SetStyles(static_cast<Sci::Position>(wParam), CharPtrFromSPtr(lParam));
		break;

	case SCI_SETBUFFEREDDRAW:
		view.bufferedDraw = wParam != 0;
		break;

	case SCI_GETBUFFEREDDRAW:
		return view.bufferedDraw;

#ifdef INCLUDE_DEPRECATED_FEATURES
	case SCI_GETTWOPHASEDRAW:
		return view.phasesDraw == EditView::phasesTwo;

	case SCI_SETTWOPHASEDRAW:
		if (view.SetTwoPhaseDraw(wParam != 0))
			InvalidateStyleRedraw();
		break;
#endif

	case SCI_GETPHASESDRAW:
		return view.phasesDraw;

	case SCI_SETPHASESDRAW:
		if (view.SetPhasesDraw(static_cast<int>(wParam)))
			InvalidateStyleRedraw();
		break;

	case SCI_SETFONTQUALITY:
		vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK;
		vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK);
		InvalidateStyleRedraw();
		break;

	case SCI_GETFONTQUALITY:
		return (vs.extraFontFlag & SC_EFF_QUALITY_MASK);

	case SCI_SETTABWIDTH:
		if (wParam > 0) {
			pdoc->tabInChars = static_cast<int>(wParam);
			if (pdoc->indentInChars == 0)
				pdoc->actualIndentInChars = pdoc->tabInChars;
		}
		InvalidateStyleRedraw();
		break;

	case SCI_GETTABWIDTH:
		return pdoc->tabInChars;

	case SCI_CLEARTABSTOPS:
		if (view.ClearTabstops(static_cast<Sci::Line>(wParam))) {
			const DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, nullptr, static_cast<Sci::Line>(wParam));
			NotifyModified(pdoc, mh, nullptr);
		}
		break;

	case SCI_ADDTABSTOP:
		if (view.AddTabstop(static_cast<Sci::Line>(wParam), static_cast<int>(lParam))) {
			const DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, nullptr, static_cast<Sci::Line>(wParam));
			NotifyModified(pdoc, mh, nullptr);
		}
		break;

	case SCI_GETNEXTTABSTOP:
		return view.GetNextTabstop(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));

	case SCI_SETINDENT:
		pdoc->indentInChars = static_cast<int>(wParam);
		if (pdoc->indentInChars != 0)
			pdoc->actualIndentInChars = pdoc->indentInChars;
		else
			pdoc->actualIndentInChars = pdoc->tabInChars;
		InvalidateStyleRedraw();
		break;

	case SCI_GETINDENT:
		return pdoc->indentInChars;

	case SCI_SETUSETABS:
		pdoc->useTabs = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETUSETABS:
		return pdoc->useTabs;

	case SCI_SETLINEINDENTATION:
		pdoc->SetLineIndentation(static_cast<Sci::Line>(wParam), lParam);
		break;

	case SCI_GETLINEINDENTATION:
		return pdoc->GetLineIndentation(static_cast<Sci::Line>(wParam));

	case SCI_GETLINEINDENTPOSITION:
		return pdoc->GetLineIndentPosition(static_cast<Sci::Line>(wParam));

	case SCI_SETTABINDENTS:
		pdoc->tabIndents = wParam != 0;
		break;

	case SCI_GETTABINDENTS:
		return pdoc->tabIndents;

	case SCI_SETBACKSPACEUNINDENTS:
		pdoc->backspaceUnindents = wParam != 0;
		break;

	case SCI_GETBACKSPACEUNINDENTS:
		return pdoc->backspaceUnindents;

	case SCI_SETMOUSEDWELLTIME:
		dwellDelay = static_cast<int>(wParam);
		ticksToDwell = dwellDelay;
		break;

	case SCI_GETMOUSEDWELLTIME:
		return dwellDelay;

	case SCI_WORDSTARTPOSITION:
		return pdoc->ExtendWordSelect(static_cast<Sci::Position>(wParam), -1, lParam != 0);

	case SCI_WORDENDPOSITION:
		return pdoc->ExtendWordSelect(static_cast<Sci::Position>(wParam), 1, lParam != 0);

	case SCI_ISRANGEWORD:
		return pdoc->IsWordAt(static_cast<Sci::Position>(wParam), lParam);

	case SCI_SETIDLESTYLING:
		idleStyling = static_cast<int>(wParam);
		break;

	case SCI_GETIDLESTYLING:
		return idleStyling;

	case SCI_SETWRAPMODE:
		if (vs.SetWrapState(static_cast<int>(wParam))) {
			xOffset = 0;
			ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPMODE:
		return vs.wrapState;

	case SCI_SETWRAPVISUALFLAGS:
		if (vs.SetWrapVisualFlags(static_cast<int>(wParam))) {
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPVISUALFLAGS:
		return vs.wrapVisualFlags;

	case SCI_SETWRAPVISUALFLAGSLOCATION:
		if (vs.SetWrapVisualFlagsLocation(static_cast<int>(wParam))) {
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETWRAPVISUALFLAGSLOCATION:
		return vs.wrapVisualFlagsLocation;

	case SCI_SETWRAPSTARTINDENT:
		if (vs.SetWrapVisualStartIndent(static_cast<int>(wParam))) {
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPSTARTINDENT:
		return vs.wrapVisualStartIndent;

	case SCI_SETWRAPINDENTMODE:
		if (vs.SetWrapIndentMode(static_cast<int>(wParam))) {
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPINDENTMODE:
		return vs.wrapIndentMode;

	case SCI_SETLAYOUTCACHE:
		view.llc.SetLevel(static_cast<int>(wParam));
		break;

	case SCI_GETLAYOUTCACHE:
		return view.llc.GetLevel();

	case SCI_SETPOSITIONCACHE:
		view.posCache.SetSize(wParam);
		break;

	case SCI_GETPOSITIONCACHE:
		return view.posCache.GetSize();

	case SCI_SETSCROLLWIDTH:
		PLATFORM_ASSERT(wParam > 0);
		if ((wParam > 0) && (wParam != static_cast<unsigned int>(scrollWidth))) {
			view.lineWidthMaxSeen = 0;
			scrollWidth = static_cast<int>(wParam);
			SetScrollBars();
		}
		break;

	case SCI_GETSCROLLWIDTH:
		return scrollWidth;

	case SCI_SETSCROLLWIDTHTRACKING:
		trackLineWidth = wParam != 0;
		break;

	case SCI_GETSCROLLWIDTHTRACKING:
		return trackLineWidth;

	case SCI_LINESJOIN:
		LinesJoin();
		break;

	case SCI_LINESSPLIT:
		LinesSplit(static_cast<int>(wParam));
		break;

	case SCI_TEXTWIDTH:
		PLATFORM_ASSERT(wParam < vs.styles.size());
		PLATFORM_ASSERT(lParam);
		return TextWidth(static_cast<int>(wParam), CharPtrFromSPtr(lParam));

	case SCI_TEXTHEIGHT:
		RefreshStyleData();
		return vs.lineHeight;

	case SCI_SETENDATLASTLINE:
		PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
		if (endAtLastLine != (wParam != 0)) {
			endAtLastLine = wParam != 0;
			SetScrollBars();
		}
		break;

	case SCI_GETENDATLASTLINE:
		return endAtLastLine;

	case SCI_SETCARETSTICKY:
		PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE);
		if (wParam <= SC_CARETSTICKY_WHITESPACE) {
			caretSticky = static_cast<int>(wParam);
		}
		break;

	case SCI_GETCARETSTICKY:
		return caretSticky;

	case SCI_TOGGLECARETSTICKY:
		caretSticky = !caretSticky;
		break;

	case SCI_GETCOLUMN:
		return pdoc->GetColumn(static_cast<Sci::Position>(wParam));

	case SCI_FINDCOLUMN:
		return pdoc->FindColumn(static_cast<Sci::Line>(wParam), lParam);

	case SCI_SETHSCROLLBAR :
		if (horizontalScrollBarVisible != (wParam != 0)) {
			horizontalScrollBarVisible = wParam != 0;
			SetScrollBars();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETHSCROLLBAR:
		return horizontalScrollBarVisible;

	case SCI_SETVSCROLLBAR:
		if (verticalScrollBarVisible != (wParam != 0)) {
			verticalScrollBarVisible = wParam != 0;
			SetScrollBars();
			ReconfigureScrollBars();
			if (verticalScrollBarVisible)
				SetVerticalScrollPos();
		}
		break;

	case SCI_GETVSCROLLBAR:
		return verticalScrollBarVisible;

	case SCI_SETINDENTATIONGUIDES:
		vs.viewIndentationGuides = static_cast<IndentView>(wParam);
		Redraw();
		break;

	case SCI_GETINDENTATIONGUIDES:
		return vs.viewIndentationGuides;

	case SCI_SETHIGHLIGHTGUIDE:
		if ((highlightGuideColumn != static_cast<int>(wParam)) || (wParam > 0)) {
			highlightGuideColumn = static_cast<int>(wParam);
			Redraw();
		}
		break;

	case SCI_GETHIGHLIGHTGUIDE:
		return highlightGuideColumn;

	case SCI_GETLINEENDPOSITION:
		return pdoc->LineEnd(static_cast<Sci::Line>(wParam));

	case SCI_SETCODEPAGE:
		if (ValidCodePage(static_cast<int>(wParam))) {
			if (pdoc->SetDBCSCodePage(static_cast<int>(wParam))) {
				pcs->Clear();
				pcs->InsertLines(0, pdoc->LinesTotal() - 1);
				SetAnnotationHeights(0, pdoc->LinesTotal());
				InvalidateStyleRedraw();
				SetRepresentations();
			}
		}
		break;

	case SCI_GETCODEPAGE:
		return pdoc->dbcsCodePage;

	case SCI_SETIMEINTERACTION:
		imeInteraction = static_cast<EditModel::IMEInteraction>(wParam);
		break;

	case SCI_GETIMEINTERACTION:
		return imeInteraction;

	case SCI_SETBIDIRECTIONAL:
		// SCI_SETBIDIRECTIONAL is implemented on platform subclasses if they support bidirectional text.
		break;

	case SCI_GETBIDIRECTIONAL:
		return static_cast<sptr_t>(bidirectional);

	case SCI_GETLINECHARACTERINDEX:
		return pdoc->LineCharacterIndex();

	case SCI_ALLOCATELINECHARACTERINDEX:
		pdoc->AllocateLineCharacterIndex(static_cast<int>(wParam));
		break;

	case SCI_RELEASELINECHARACTERINDEX:
		pdoc->ReleaseLineCharacterIndex(static_cast<int>(wParam));
		break;

	case SCI_LINEFROMINDEXPOSITION:
		return pdoc->LineFromPositionIndex(static_cast<Sci::Position>(wParam), static_cast<int>(lParam));

	case SCI_INDEXPOSITIONFROMLINE:
		return pdoc->IndexLineStart(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));

		// Marker definition and setting
	case SCI_MARKERDEFINE:
		if (wParam <= MARKER_MAX) {
			vs.markers[wParam].markType = static_cast<int>(lParam);
			vs.CalcLargestMarkerHeight();
		}
		InvalidateStyleData();
		RedrawSelMargin();
		break;

	case SCI_MARKERSYMBOLDEFINED:
		if (wParam <= MARKER_MAX)
			return vs.markers[wParam].markType;
		else
			return 0;

	case SCI_MARKERSETFORE:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].fore = ColourDesired(static_cast<int>(lParam));
		InvalidateStyleData();
		RedrawSelMargin();
		break;
	case SCI_MARKERSETBACKSELECTED:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].backSelected = ColourDesired(static_cast<int>(lParam));
		InvalidateStyleData();
		RedrawSelMargin();
		break;
	case SCI_MARKERENABLEHIGHLIGHT:
		marginView.highlightDelimiter.isEnabled = wParam == 1;
		RedrawSelMargin();
		break;
	case SCI_MARKERSETBACK:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].back = ColourDesired(static_cast<int>(lParam));
		InvalidateStyleData();
		RedrawSelMargin();
		break;
	case SCI_MARKERSETALPHA:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].alpha = static_cast<int>(lParam);
		InvalidateStyleRedraw();
		break;
	case SCI_MARKERADD: {
			const int markerID = pdoc->AddMark(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
			return markerID;
		}
	case SCI_MARKERADDSET:
		if (lParam != 0)
			pdoc->AddMarkSet(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
		break;

	case SCI_MARKERDELETE:
		pdoc->DeleteMark(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
		break;

	case SCI_MARKERDELETEALL:
		pdoc->DeleteAllMarks(static_cast<int>(wParam));
		break;

	case SCI_MARKERGET:
		return pdoc->GetMark(static_cast<Sci::Line>(wParam));

	case SCI_MARKERNEXT:
		return pdoc->MarkerNext(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));

	case SCI_MARKERPREVIOUS: {
			for (Sci::Line iLine = static_cast<Sci::Line>(wParam); iLine >= 0; iLine--) {
				if ((pdoc->GetMark(iLine) & lParam) != 0)
					return iLine;
			}
		}
		return -1;

	case SCI_MARKERDEFINEPIXMAP:
		if (wParam <= MARKER_MAX) {
			vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam));
			vs.CalcLargestMarkerHeight();
		}
		InvalidateStyleData();
		RedrawSelMargin();
		break;

	case SCI_RGBAIMAGESETWIDTH:
		sizeRGBAImage.x = static_cast<XYPOSITION>(wParam);
		break;

	case SCI_RGBAIMAGESETHEIGHT:
		sizeRGBAImage.y = static_cast<XYPOSITION>(wParam);
		break;

	case SCI_RGBAIMAGESETSCALE:
		scaleRGBAImage = static_cast<float>(wParam);
		break;

	case SCI_MARKERDEFINERGBAIMAGE:
		if (wParam <= MARKER_MAX) {
			vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0f, ConstUCharPtrFromSPtr(lParam));
			vs.CalcLargestMarkerHeight();
		}
		InvalidateStyleData();
		RedrawSelMargin();
		break;

	case SCI_SETMARGINTYPEN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].style = static_cast<int>(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINTYPEN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].style;
		else
			return 0;

	case SCI_SETMARGINWIDTHN:
		if (ValidMargin(wParam)) {
			// Short-circuit if the width is unchanged, to avoid unnecessary redraw.
			if (vs.ms[wParam].width != lParam) {
				lastXChosen += static_cast<int>(lParam) - vs.ms[wParam].width;
				vs.ms[wParam].width = static_cast<int>(lParam);
				InvalidateStyleRedraw();
			}
		}
		break;

	case SCI_GETMARGINWIDTHN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].width;
		else
			return 0;

	case SCI_SETMARGINMASKN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].mask = static_cast<int>(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINMASKN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].mask;
		else
			return 0;

	case SCI_SETMARGINSENSITIVEN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].sensitive = lParam != 0;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINSENSITIVEN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].sensitive ? 1 : 0;
		else
			return 0;

	case SCI_SETMARGINCURSORN:
		if (ValidMargin(wParam))
			vs.ms[wParam].cursor = static_cast<int>(lParam);
		break;

	case SCI_GETMARGINCURSORN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].cursor;
		else
			return 0;

	case SCI_SETMARGINBACKN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].back = ColourDesired(static_cast<int>(lParam));
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINBACKN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].back.AsInteger();
		else
			return 0;

	case SCI_SETMARGINS:
		if (wParam < 1000)
			vs.ms.resize(wParam);
		break;

	case SCI_GETMARGINS:
		return vs.ms.size();

	case SCI_STYLECLEARALL:
		vs.ClearStyles();
		InvalidateStyleRedraw();
		break;

	case SCI_STYLESETFORE:
	case SCI_STYLESETBACK:
	case SCI_STYLESETBOLD:
	case SCI_STYLESETWEIGHT:
	case SCI_STYLESETITALIC:
	case SCI_STYLESETEOLFILLED:
	case SCI_STYLESETSIZE:
	case SCI_STYLESETSIZEFRACTIONAL:
	case SCI_STYLESETFONT:
	case SCI_STYLESETUNDERLINE:
	case SCI_STYLESETCASE:
	case SCI_STYLESETCHARACTERSET:
	case SCI_STYLESETVISIBLE:
	case SCI_STYLESETCHANGEABLE:
	case SCI_STYLESETHOTSPOT:
		StyleSetMessage(iMessage, wParam, lParam);
		break;

	case SCI_STYLEGETFORE:
	case SCI_STYLEGETBACK:
	case SCI_STYLEGETBOLD:
	case SCI_STYLEGETWEIGHT:
	case SCI_STYLEGETITALIC:
	case SCI_STYLEGETEOLFILLED:
	case SCI_STYLEGETSIZE:
	case SCI_STYLEGETSIZEFRACTIONAL:
	case SCI_STYLEGETFONT:
	case SCI_STYLEGETUNDERLINE:
	case SCI_STYLEGETCASE:
	case SCI_STYLEGETCHARACTERSET:
	case SCI_STYLEGETVISIBLE:
	case SCI_STYLEGETCHANGEABLE:
	case SCI_STYLEGETHOTSPOT:
		return StyleGetMessage(iMessage, wParam, lParam);

	case SCI_STYLERESETDEFAULT:
		vs.ResetDefaultStyle();
		InvalidateStyleRedraw();
		break;

#ifdef INCLUDE_DEPRECATED_FEATURES
	case SCI_SETSTYLEBITS:
		vs.EnsureStyle(0xff);
		break;

	case SCI_GETSTYLEBITS:
		return 8;
#endif

	case SCI_SETLINESTATE:
		return pdoc->SetLineState(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));

	case SCI_GETLINESTATE:
		return pdoc->GetLineState(static_cast<Sci::Line>(wParam));

	case SCI_GETMAXLINESTATE:
		return pdoc->GetMaxLineState();

	case SCI_GETCARETLINEVISIBLE:
		return vs.showCaretLineBackground;
	case SCI_SETCARETLINEVISIBLE:
		vs.showCaretLineBackground = wParam != 0;
		InvalidateStyleRedraw();
		break;
	case SCI_GETCARETLINEVISIBLEALWAYS:
		return vs.alwaysShowCaretLineBackground;
	case SCI_SETCARETLINEVISIBLEALWAYS:
		vs.alwaysShowCaretLineBackground = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETLINEFRAME:
		return vs.caretLineFrame;
	case SCI_SETCARETLINEFRAME:
		vs.caretLineFrame = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;
	case SCI_GETCARETLINEBACK:
		return vs.caretLineBackground.AsInteger();
	case SCI_SETCARETLINEBACK:
		vs.caretLineBackground = ColourDesired(static_cast<int>(wParam));
		InvalidateStyleRedraw();
		break;
	case SCI_GETCARETLINEBACKALPHA:
		return vs.caretLineAlpha;
	case SCI_SETCARETLINEBACKALPHA:
		vs.caretLineAlpha = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

		// Folding messages

	case SCI_VISIBLEFROMDOCLINE:
		return pcs->DisplayFromDoc(static_cast<Sci::Line>(wParam));

	case SCI_DOCLINEFROMVISIBLE:
		return pcs->DocFromDisplay(static_cast<Sci::Line>(wParam));

	case SCI_WRAPCOUNT:
		return WrapCount(static_cast<Sci::Line>(wParam));

	case SCI_SETFOLDLEVEL: {
			const int prev = pdoc->SetLevel(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
			if (prev != static_cast<int>(lParam))
				RedrawSelMargin();
			return prev;
		}

	case SCI_GETFOLDLEVEL:
		return pdoc->GetLevel(static_cast<Sci::Line>(wParam));

	case SCI_GETLASTCHILD:
		return pdoc->GetLastChild(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));

	case SCI_GETFOLDPARENT:
		return pdoc->GetFoldParent(static_cast<Sci::Line>(wParam));

	case SCI_SHOWLINES:
		pcs->SetVisible(static_cast<Sci::Line>(wParam), static_cast<Sci::Line>(lParam), true);
		SetScrollBars();
		Redraw();
		break;

	case SCI_HIDELINES:
		if (wParam > 0)
			pcs->SetVisible(static_cast<Sci::Line>(wParam), static_cast<Sci::Line>(lParam), false);
		SetScrollBars();
		Redraw();
		break;

	case SCI_GETLINEVISIBLE:
		return pcs->GetVisible(static_cast<Sci::Line>(wParam));

	case SCI_GETALLLINESVISIBLE:
		return pcs->HiddenLines() ? 0 : 1;

	case SCI_SETFOLDEXPANDED:
		SetFoldExpanded(static_cast<Sci::Line>(wParam), lParam != 0);
		break;

	case SCI_GETFOLDEXPANDED:
		return pcs->GetExpanded(static_cast<Sci::Line>(wParam));

	case SCI_SETAUTOMATICFOLD:
		foldAutomatic = static_cast<int>(wParam);
		break;

	case SCI_GETAUTOMATICFOLD:
		return foldAutomatic;

	case SCI_SETFOLDFLAGS:
		foldFlags = static_cast<int>(wParam);
		Redraw();
		break;

	case SCI_TOGGLEFOLDSHOWTEXT:
		pcs->SetFoldDisplayText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
		FoldLine(static_cast<Sci::Line>(wParam), SC_FOLDACTION_TOGGLE);
		break;

	case SCI_FOLDDISPLAYTEXTSETSTYLE:
		foldDisplayTextStyle = static_cast<int>(wParam);
		Redraw();
		break;

	case SCI_FOLDDISPLAYTEXTGETSTYLE:
		return foldDisplayTextStyle;

	case SCI_SETDEFAULTFOLDDISPLAYTEXT:
		SetDefaultFoldDisplayText(CharPtrFromSPtr(lParam));
		Redraw();
		break;

	case SCI_GETDEFAULTFOLDDISPLAYTEXT:
		return StringResult(lParam, GetDefaultFoldDisplayText());

	case SCI_TOGGLEFOLD:
		FoldLine(static_cast<Sci::Line>(wParam), SC_FOLDACTION_TOGGLE);
		break;

	case SCI_FOLDLINE:
		FoldLine(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
		break;

	case SCI_FOLDCHILDREN:
		FoldExpand(static_cast<Sci::Line>(wParam), static_cast<int>(lParam), pdoc->GetLevel(static_cast<int>(wParam)));
		break;

	case SCI_FOLDALL:
		FoldAll(static_cast<int>(wParam));
		break;

	case SCI_EXPANDCHILDREN:
		FoldExpand(static_cast<Sci::Line>(wParam), SC_FOLDACTION_EXPAND, static_cast<int>(lParam));
		break;

	case SCI_CONTRACTEDFOLDNEXT:
		return ContractedFoldNext(static_cast<Sci::Line>(wParam));

	case SCI_ENSUREVISIBLE:
		EnsureLineVisible(static_cast<Sci::Line>(wParam), false);
		break;

	case SCI_ENSUREVISIBLEENFORCEPOLICY:
		EnsureLineVisible(static_cast<Sci::Line>(wParam), true);
		break;

	case SCI_SCROLLRANGE:
		ScrollRange(SelectionRange(static_cast<Sci::Position>(wParam), lParam));
		break;

	case SCI_SEARCHANCHOR:
		SearchAnchor();
		break;

	case SCI_SEARCHNEXT:
	case SCI_SEARCHPREV:
		return SearchText(iMessage, wParam, lParam);

	case SCI_SETXCARETPOLICY:
		caretXPolicy = static_cast<int>(wParam);
		caretXSlop = static_cast<int>(lParam);
		break;

	case SCI_SETYCARETPOLICY:
		caretYPolicy = static_cast<int>(wParam);
		caretYSlop = static_cast<int>(lParam);
		break;

	case SCI_SETVISIBLEPOLICY:
		visiblePolicy = static_cast<int>(wParam);
		visibleSlop = static_cast<int>(lParam);
		break;

	case SCI_LINESONSCREEN:
		return LinesOnScreen();

	case SCI_SETSELFORE:
		vs.selColours.fore = ColourOptional(wParam, lParam);
		vs.selAdditionalForeground = ColourDesired(static_cast<int>(lParam));
		InvalidateStyleRedraw();
		break;

	case SCI_SETSELBACK:
		vs.selColours.back = ColourOptional(wParam, lParam);
		vs.selAdditionalBackground = ColourDesired(static_cast<int>(lParam));
		InvalidateStyleRedraw();
		break;

	case SCI_SETSELALPHA:
		vs.selAlpha = static_cast<int>(wParam);
		vs.selAdditionalAlpha = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETSELALPHA:
		return vs.selAlpha;

	case SCI_GETSELEOLFILLED:
		return vs.selEOLFilled;

	case SCI_SETSELEOLFILLED:
		vs.selEOLFilled = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_SETWHITESPACEFORE:
		vs.whitespaceColours.fore = ColourOptional(wParam, lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETWHITESPACEBACK:
		vs.whitespaceColours.back = ColourOptional(wParam, lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETCARETFORE:
		vs.caretcolour = ColourDesired(static_cast<int>(wParam));
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETFORE:
		return vs.caretcolour.AsInteger();

	case SCI_SETCARETSTYLE:
		if (wParam <= (CARETSTYLE_BLOCK | CARETSTYLE_OVERSTRIKE_BLOCK))
			vs.caretStyle = static_cast<int>(wParam);
		else
			/* Default to the line caret */
			vs.caretStyle = CARETSTYLE_LINE;
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETSTYLE:
		return vs.caretStyle;

	case SCI_SETCARETWIDTH:
		vs.caretWidth = std::clamp(static_cast<int>(wParam), 0, 3);
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETWIDTH:
		return vs.caretWidth;

	case SCI_ASSIGNCMDKEY:
		kmap.AssignCmdKey(LowShortFromWParam(wParam),
			HighShortFromWParam(wParam), static_cast<unsigned int>(lParam));
		break;

	case SCI_CLEARCMDKEY:
		kmap.AssignCmdKey(LowShortFromWParam(wParam),
			HighShortFromWParam(wParam), SCI_NULL);
		break;

	case SCI_CLEARALLCMDKEYS:
		kmap.Clear();
		break;

	case SCI_INDICSETSTYLE:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].sacNormal.style = static_cast<int>(lParam);
			vs.indicators[wParam].sacHover.style = static_cast<int>(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETSTYLE:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.style : 0;

	case SCI_INDICSETFORE:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].sacNormal.fore = ColourDesired(static_cast<int>(lParam));
			vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast<int>(lParam));
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETFORE:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.fore.AsInteger() : 0;

	case SCI_INDICSETHOVERSTYLE:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].sacHover.style = static_cast<int>(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETHOVERSTYLE:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.style : 0;

	case SCI_INDICSETHOVERFORE:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast<int>(lParam));
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETHOVERFORE:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.fore.AsInteger() : 0;

	case SCI_INDICSETFLAGS:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].SetFlags(static_cast<int>(lParam));
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETFLAGS:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].Flags() : 0;

	case SCI_INDICSETUNDER:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].under = lParam != 0;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETUNDER:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0;

	case SCI_INDICSETALPHA:
		if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
			vs.indicators[wParam].fillAlpha = static_cast<int>(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETALPHA:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0;

	case SCI_INDICSETOUTLINEALPHA:
		if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
			vs.indicators[wParam].outlineAlpha = static_cast<int>(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETOUTLINEALPHA:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0;

	case SCI_SETINDICATORCURRENT:
		pdoc->DecorationSetCurrentIndicator(static_cast<int>(wParam));
		break;
	case SCI_GETINDICATORCURRENT:
		return pdoc->decorations->GetCurrentIndicator();
	case SCI_SETINDICATORVALUE:
		pdoc->decorations->SetCurrentValue(static_cast<int>(wParam));
		break;
	case SCI_GETINDICATORVALUE:
		return pdoc->decorations->GetCurrentValue();

	case SCI_INDICATORFILLRANGE:
		pdoc->DecorationFillRange(static_cast<Sci::Position>(wParam),
			pdoc->decorations->GetCurrentValue(), lParam);
		break;

	case SCI_INDICATORCLEARRANGE:
		pdoc->DecorationFillRange(static_cast<Sci::Position>(wParam), 0,
			lParam);
		break;

	case SCI_INDICATORALLONFOR:
		return pdoc->decorations->AllOnFor(static_cast<Sci::Position>(wParam));

	case SCI_INDICATORVALUEAT:
		return pdoc->decorations->ValueAt(static_cast<int>(wParam), lParam);

	case SCI_INDICATORSTART:
		return pdoc->decorations->Start(static_cast<int>(wParam), lParam);

	case SCI_INDICATOREND:
		return pdoc->decorations->End(static_cast<int>(wParam), lParam);

	case SCI_LINEDOWN:
	case SCI_LINEDOWNEXTEND:
	case SCI_PARADOWN:
	case SCI_PARADOWNEXTEND:
	case SCI_LINEUP:
	case SCI_LINEUPEXTEND:
	case SCI_PARAUP:
	case SCI_PARAUPEXTEND:
	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_WORDLEFTEND:
	case SCI_WORDLEFTENDEXTEND:
	case SCI_WORDRIGHTEND:
	case SCI_WORDRIGHTENDEXTEND:
	case SCI_HOME:
	case SCI_HOMEEXTEND:
	case SCI_LINEEND:
	case SCI_LINEENDEXTEND:
	case SCI_HOMEWRAP:
	case SCI_HOMEWRAPEXTEND:
	case SCI_LINEENDWRAP:
	case SCI_LINEENDWRAPEXTEND:
	case SCI_DOCUMENTSTART:
	case SCI_DOCUMENTSTARTEXTEND:
	case SCI_DOCUMENTEND:
	case SCI_DOCUMENTENDEXTEND:
	case SCI_SCROLLTOSTART:
	case SCI_SCROLLTOEND:

	case SCI_STUTTEREDPAGEUP:
	case SCI_STUTTEREDPAGEUPEXTEND:
	case SCI_STUTTEREDPAGEDOWN:
	case SCI_STUTTEREDPAGEDOWNEXTEND:

	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_VCHOMEWRAP:
	case SCI_VCHOMEWRAPEXTEND:
	case SCI_VCHOMEDISPLAY:
	case SCI_VCHOMEDISPLAYEXTEND:
	case SCI_ZOOMIN:
	case SCI_ZOOMOUT:
	case SCI_DELWORDLEFT:
	case SCI_DELWORDRIGHT:
	case SCI_DELWORDRIGHTEND:
	case SCI_DELLINELEFT:
	case SCI_DELLINERIGHT:
	case SCI_LINECOPY:
	case SCI_LINECUT:
	case SCI_LINEDELETE:
	case SCI_LINETRANSPOSE:
	case SCI_LINEREVERSE:
	case SCI_LINEDUPLICATE:
	case SCI_LOWERCASE:
	case SCI_UPPERCASE:
	case SCI_LINESCROLLDOWN:
	case SCI_LINESCROLLUP:
	case SCI_WORDPARTLEFT:
	case SCI_WORDPARTLEFTEXTEND:
	case SCI_WORDPARTRIGHT:
	case SCI_WORDPARTRIGHTEXTEND:
	case SCI_DELETEBACKNOTLINE:
	case SCI_HOMEDISPLAY:
	case SCI_HOMEDISPLAYEXTEND:
	case SCI_LINEENDDISPLAY:
	case SCI_LINEENDDISPLAYEXTEND:
	case SCI_LINEDOWNRECTEXTEND:
	case SCI_LINEUPRECTEXTEND:
	case SCI_CHARLEFTRECTEXTEND:
	case SCI_CHARRIGHTRECTEXTEND:
	case SCI_HOMERECTEXTEND:
	case SCI_VCHOMERECTEXTEND:
	case SCI_LINEENDRECTEXTEND:
	case SCI_PAGEUPRECTEXTEND:
	case SCI_PAGEDOWNRECTEXTEND:
	case SCI_SELECTIONDUPLICATE:
		return KeyCommand(iMessage);

	case SCI_BRACEHIGHLIGHT:
		SetBraceHighlight(static_cast<Sci::Position>(wParam), lParam, STYLE_BRACELIGHT);
		break;

	case SCI_BRACEHIGHLIGHTINDICATOR:
		if (lParam >= 0 && lParam <= INDIC_MAX) {
			vs.braceHighlightIndicatorSet = wParam != 0;
			vs.braceHighlightIndicator = static_cast<int>(lParam);
		}
		break;

	case SCI_BRACEBADLIGHT:
		SetBraceHighlight(static_cast<Sci::Position>(wParam), -1, STYLE_BRACEBAD);
		break;

	case SCI_BRACEBADLIGHTINDICATOR:
		if (lParam >= 0 && lParam <= INDIC_MAX) {
			vs.braceBadLightIndicatorSet = wParam != 0;
			vs.braceBadLightIndicator = static_cast<int>(lParam);
		}
		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 pdoc->BraceMatch(static_cast<Sci::Position>(wParam), lParam);

	case SCI_GETVIEWEOL:
		return vs.viewEOL;

	case SCI_SETVIEWEOL:
		vs.viewEOL = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_SETZOOM: {
			const int zoomLevel = static_cast<int>(wParam);
			if (zoomLevel != vs.zoomLevel) {
				vs.zoomLevel = zoomLevel;
				InvalidateStyleRedraw();
				NotifyZoom();
			}
			break;
		}

	case SCI_GETZOOM:
		return vs.zoomLevel;

	case SCI_GETEDGECOLUMN:
		return vs.theEdge.column;

	case SCI_SETEDGECOLUMN:
		vs.theEdge.column = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETEDGEMODE:
		return vs.edgeState;

	case SCI_SETEDGEMODE:
		vs.edgeState = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETEDGECOLOUR:
		return vs.theEdge.colour.AsInteger();

	case SCI_SETEDGECOLOUR:
		vs.theEdge.colour = ColourDesired(static_cast<int>(wParam));
		InvalidateStyleRedraw();
		break;

	case SCI_MULTIEDGEADDLINE:
		vs.theMultiEdge.push_back(EdgeProperties(wParam, lParam));
		InvalidateStyleRedraw();
		break;

	case SCI_MULTIEDGECLEARALL:
		std::vector<EdgeProperties>().swap(vs.theMultiEdge); // Free vector and memory, C++03 compatible
		InvalidateStyleRedraw();
		break;

	case SCI_GETACCESSIBILITY:
		return SC_ACCESSIBILITY_DISABLED;

	case SCI_SETACCESSIBILITY:
		// May be implemented by platform code.
		break;

	case SCI_GETDOCPOINTER:
		return reinterpret_cast<sptr_t>(pdoc);

	case SCI_SETDOCPOINTER:
		CancelModes();
		SetDocPointer(static_cast<Document *>(PtrFromSPtr(lParam)));
		return 0;

	case SCI_CREATEDOCUMENT: {
			Document *doc = new Document(static_cast<int>(lParam));
			doc->AddRef();
			doc->Allocate(static_cast<Sci::Position>(wParam));
			pcs = ContractionStateCreate(pdoc->IsLarge());
			return reinterpret_cast<sptr_t>(doc);
		}

	case SCI_ADDREFDOCUMENT:
		(static_cast<Document *>(PtrFromSPtr(lParam)))->AddRef();
		break;

	case SCI_RELEASEDOCUMENT:
		(static_cast<Document *>(PtrFromSPtr(lParam)))->Release();
		break;

	case SCI_GETDOCUMENTOPTIONS:
		return pdoc->Options();

	case SCI_CREATELOADER: {
			Document *doc = new Document(static_cast<int>(lParam));
			doc->AddRef();
			doc->Allocate(static_cast<Sci::Position>(wParam));
			doc->SetUndoCollection(false);
			pcs = ContractionStateCreate(pdoc->IsLarge());
			return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
		}

	case SCI_SETMODEVENTMASK:
		modEventMask = static_cast<int>(wParam);
		return 0;

	case SCI_GETMODEVENTMASK:
		return modEventMask;

	case SCI_SETCOMMANDEVENTS:
		commandEvents = static_cast<bool>(wParam);
		return 0;

	case SCI_GETCOMMANDEVENTS:
		return commandEvents;

	case SCI_CONVERTEOLS:
		pdoc->ConvertLineEnds(static_cast<int>(wParam));
		SetSelection(sel.MainCaret(), sel.MainAnchor());	// Ensure selection inside document
		return 0;

	case SCI_SETLENGTHFORENCODE:
		lengthForEncode = static_cast<Sci::Position>(wParam);
		return 0;

	case SCI_SELECTIONISRECTANGLE:
		return sel.selType == Selection::selRectangle ? 1 : 0;

	case SCI_SETSELECTIONMODE: {
			switch (wParam) {
			case SC_SEL_STREAM:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
				sel.selType = Selection::selStream;
				break;
			case SC_SEL_RECTANGLE:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
				sel.selType = Selection::selRectangle;
				sel.Rectangular() = sel.RangeMain(); // adjust current selection
				break;
			case SC_SEL_LINES:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
				sel.selType = Selection::selLines;
				SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection
				break;
			case SC_SEL_THIN:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
				sel.selType = Selection::selThin;
				break;
			default:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
				sel.selType = Selection::selStream;
			}
			InvalidateWholeSelection();
			break;
		}
	case SCI_GETSELECTIONMODE:
		switch (sel.selType) {
		case Selection::selStream:
			return SC_SEL_STREAM;
		case Selection::selRectangle:
			return SC_SEL_RECTANGLE;
		case Selection::selLines:
			return SC_SEL_LINES;
		case Selection::selThin:
			return SC_SEL_THIN;
		default:	// ?!
			return SC_SEL_STREAM;
		}
	case SCI_GETMOVEEXTENDSSELECTION:
		return sel.MoveExtends();
	case SCI_GETLINESELSTARTPOSITION:
	case SCI_GETLINESELENDPOSITION: {
			const SelectionSegment segmentLine(
				SelectionPosition(pdoc->LineStart(static_cast<Sci::Position>(wParam))),
				SelectionPosition(pdoc->LineEnd(static_cast<Sci::Position>(wParam))));
			for (size_t r=0; r<sel.Count(); r++) {
				const SelectionSegment portion = sel.Range(r).Intersect(segmentLine);
				if (portion.start.IsValid()) {
					return (iMessage == SCI_GETLINESELSTARTPOSITION) ? portion.start.Position() : portion.end.Position();
				}
			}
			return INVALID_POSITION;
		}

	case SCI_SETOVERTYPE:
		if (inOverstrike != (wParam != 0)) {
			inOverstrike = wParam != 0;
			ContainerNeedsUpdate(SC_UPDATE_SELECTION);
			ShowCaretAtCurrentPosition();
			SetIdle(true);
		}
		break;

	case SCI_GETOVERTYPE:
		return inOverstrike ? 1 : 0;

	case SCI_SETFOCUS:
		SetFocusState(wParam != 0);
		break;

	case SCI_GETFOCUS:
		return hasFocus;

	case SCI_SETSTATUS:
		errorStatus = static_cast<int>(wParam);
		break;

	case SCI_GETSTATUS:
		return errorStatus;

	case SCI_SETMOUSEDOWNCAPTURES:
		mouseDownCaptures = wParam != 0;
		break;

	case SCI_GETMOUSEDOWNCAPTURES:
		return mouseDownCaptures;

	case SCI_SETMOUSEWHEELCAPTURES:
		mouseWheelCaptures = wParam != 0;
		break;

	case SCI_GETMOUSEWHEELCAPTURES:
		return mouseWheelCaptures;

	case SCI_SETCURSOR:
		cursorMode = static_cast<int>(wParam);
		DisplayCursor(Window::cursorText);
		break;

	case SCI_GETCURSOR:
		return cursorMode;

	case SCI_SETCONTROLCHARSYMBOL:
		vs.controlCharSymbol = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETCONTROLCHARSYMBOL:
		return vs.controlCharSymbol;

	case SCI_SETREPRESENTATION:
		reprs.SetRepresentation(ConstCharPtrFromUPtr(wParam), ConstCharPtrFromSPtr(lParam));
		break;

	case SCI_GETREPRESENTATION: {
			const Representation *repr = reprs.RepresentationFromCharacter(
				ConstCharPtrFromUPtr(wParam), UTF8MaxBytes);
			if (repr) {
				return StringResult(lParam, repr->stringRep.c_str());
			}
			return 0;
		}

	case SCI_CLEARREPRESENTATION:
		reprs.ClearRepresentation(ConstCharPtrFromUPtr(wParam));
		break;

	case SCI_STARTRECORD:
		recordingMacro = true;
		return 0;

	case SCI_STOPRECORD:
		recordingMacro = false;
		return 0;

	case SCI_MOVECARETINSIDEVIEW:
		MoveCaretInsideView();
		break;

	case SCI_SETFOLDMARGINCOLOUR:
		vs.foldmarginColour = ColourOptional(wParam, lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETFOLDMARGINHICOLOUR:
		vs.foldmarginHighlightColour = ColourOptional(wParam, lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETHOTSPOTACTIVEFORE:
		vs.hotspotColours.fore = ColourOptional(wParam, lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTACTIVEFORE:
		return vs.hotspotColours.fore.AsInteger();

	case SCI_SETHOTSPOTACTIVEBACK:
		vs.hotspotColours.back = ColourOptional(wParam, lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTACTIVEBACK:
		return vs.hotspotColours.back.AsInteger();

	case SCI_SETHOTSPOTACTIVEUNDERLINE:
		vs.hotspotUnderline = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTACTIVEUNDERLINE:
		return vs.hotspotUnderline ? 1 : 0;

	case SCI_SETHOTSPOTSINGLELINE:
		vs.hotspotSingleLine = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTSINGLELINE:
		return vs.hotspotSingleLine ? 1 : 0;

	case SCI_SETPASTECONVERTENDINGS:
		convertPastes = wParam != 0;
		break;

	case SCI_GETPASTECONVERTENDINGS:
		return convertPastes ? 1 : 0;

	case SCI_GETCHARACTERPOINTER:
		return reinterpret_cast<sptr_t>(pdoc->BufferPointer());

	case SCI_GETRANGEPOINTER:
		return reinterpret_cast<sptr_t>(pdoc->RangePointer(
			static_cast<Sci::Position>(wParam), lParam));

	case SCI_GETGAPPOSITION:
		return pdoc->GapPosition();

	case SCI_SETEXTRAASCENT:
		vs.extraAscent = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETEXTRAASCENT:
		return vs.extraAscent;

	case SCI_SETEXTRADESCENT:
		vs.extraDescent = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETEXTRADESCENT:
		return vs.extraDescent;

	case SCI_MARGINSETSTYLEOFFSET:
		vs.marginStyleOffset = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_MARGINGETSTYLEOFFSET:
		return vs.marginStyleOffset;

	case SCI_SETMARGINOPTIONS:
		marginOptions = static_cast<int>(wParam);
		break;

	case SCI_GETMARGINOPTIONS:
		return marginOptions;

	case SCI_MARGINSETTEXT:
		pdoc->MarginSetText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
		break;

	case SCI_MARGINGETTEXT: {
			const StyledText st = pdoc->MarginStyledText(static_cast<Sci::Line>(wParam));
			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(st.text), st.length);
		}

	case SCI_MARGINSETSTYLE:
		pdoc->MarginSetStyle(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
		break;

	case SCI_MARGINGETSTYLE: {
			const StyledText st = pdoc->MarginStyledText(static_cast<Sci::Line>(wParam));
			return st.style;
		}

	case SCI_MARGINSETSTYLES:
		pdoc->MarginSetStyles(static_cast<Sci::Line>(wParam), ConstUCharPtrFromSPtr(lParam));
		break;

	case SCI_MARGINGETSTYLES: {
			const StyledText st = pdoc->MarginStyledText(static_cast<Sci::Line>(wParam));
			return BytesResult(lParam, st.styles, st.length);
		}

	case SCI_MARGINTEXTCLEARALL:
		pdoc->MarginClearAll();
		break;

	case SCI_ANNOTATIONSETTEXT:
		pdoc->AnnotationSetText(static_cast<Sci::Line>(wParam), CharPtrFromSPtr(lParam));
		break;

	case SCI_ANNOTATIONGETTEXT: {
			const StyledText st = pdoc->AnnotationStyledText(static_cast<Sci::Line>(wParam));
			return BytesResult(lParam, reinterpret_cast<const unsigned char *>(st.text), st.length);
		}

	case SCI_ANNOTATIONGETSTYLE: {
			const StyledText st = pdoc->AnnotationStyledText(static_cast<Sci::Line>(wParam));
			return st.style;
		}

	case SCI_ANNOTATIONSETSTYLE:
		pdoc->AnnotationSetStyle(static_cast<Sci::Line>(wParam), static_cast<int>(lParam));
		break;

	case SCI_ANNOTATIONSETSTYLES:
		pdoc->AnnotationSetStyles(static_cast<Sci::Line>(wParam), ConstUCharPtrFromSPtr(lParam));
		break;

	case SCI_ANNOTATIONGETSTYLES: {
			const StyledText st = pdoc->AnnotationStyledText(static_cast<Sci::Line>(wParam));
			return BytesResult(lParam, st.styles, st.length);
		}

	case SCI_ANNOTATIONGETLINES:
		return pdoc->AnnotationLines(static_cast<Sci::Line>(wParam));

	case SCI_ANNOTATIONCLEARALL:
		pdoc->AnnotationClearAll();
		break;

	case SCI_ANNOTATIONSETVISIBLE:
		SetAnnotationVisible(static_cast<int>(wParam));
		break;

	case SCI_ANNOTATIONGETVISIBLE:
		return vs.annotationVisible;

	case SCI_ANNOTATIONSETSTYLEOFFSET:
		vs.annotationStyleOffset = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_ANNOTATIONGETSTYLEOFFSET:
		return vs.annotationStyleOffset;

	case SCI_RELEASEALLEXTENDEDSTYLES:
		vs.ReleaseAllExtendedStyles();
		break;

	case SCI_ALLOCATEEXTENDEDSTYLES:
		return vs.AllocateExtendedStyles(static_cast<int>(wParam));

	case SCI_ADDUNDOACTION:
		pdoc->AddUndoAction(static_cast<Sci::Position>(wParam), lParam & UNDO_MAY_COALESCE);
		break;

	case SCI_SETMOUSESELECTIONRECTANGULARSWITCH:
		mouseSelectionRectangularSwitch = wParam != 0;
		break;

	case SCI_GETMOUSESELECTIONRECTANGULARSWITCH:
		return mouseSelectionRectangularSwitch;

	case SCI_SETMULTIPLESELECTION:
		multipleSelection = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETMULTIPLESELECTION:
		return multipleSelection;

	case SCI_SETADDITIONALSELECTIONTYPING:
		additionalSelectionTyping = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETADDITIONALSELECTIONTYPING:
		return additionalSelectionTyping;

	case SCI_SETMULTIPASTE:
		multiPasteMode = static_cast<int>(wParam);
		break;

	case SCI_GETMULTIPASTE:
		return multiPasteMode;

	case SCI_SETADDITIONALCARETSBLINK:
		view.additionalCaretsBlink = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETADDITIONALCARETSBLINK:
		return view.additionalCaretsBlink;

	case SCI_SETADDITIONALCARETSVISIBLE:
		view.additionalCaretsVisible = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETADDITIONALCARETSVISIBLE:
		return view.additionalCaretsVisible;

	case SCI_GETSELECTIONS:
		return sel.Count();

	case SCI_GETSELECTIONEMPTY:
		return sel.Empty();

	case SCI_CLEARSELECTIONS:
		sel.Clear();
		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
		Redraw();
		break;

	case SCI_SETSELECTION:
		sel.SetSelection(SelectionRange(static_cast<Sci::Position>(wParam), lParam));
		Redraw();
		break;

	case SCI_ADDSELECTION:
		sel.AddSelection(SelectionRange(static_cast<Sci::Position>(wParam), lParam));
		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
		Redraw();
		break;

	case SCI_DROPSELECTIONN:
		sel.DropSelection(static_cast<size_t>(wParam));
		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
		Redraw();
		break;

	case SCI_SETMAINSELECTION:
		sel.SetMain(static_cast<size_t>(wParam));
		ContainerNeedsUpdate(SC_UPDATE_SELECTION);
		Redraw();
		break;

	case SCI_GETMAINSELECTION:
		return sel.Main();

	case SCI_SETSELECTIONNCARET:
	case SCI_SETSELECTIONNANCHOR:
	case SCI_SETSELECTIONNCARETVIRTUALSPACE:
	case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
	case SCI_SETSELECTIONNSTART:
	case SCI_SETSELECTIONNEND:
		SetSelectionNMessage(iMessage, wParam, lParam);
		break;

	case SCI_GETSELECTIONNCARET:
		return sel.Range(wParam).caret.Position();

	case SCI_GETSELECTIONNANCHOR:
		return sel.Range(wParam).anchor.Position();

	case SCI_GETSELECTIONNCARETVIRTUALSPACE:
		return sel.Range(wParam).caret.VirtualSpace();

	case SCI_GETSELECTIONNANCHORVIRTUALSPACE:
		return sel.Range(wParam).anchor.VirtualSpace();

	case SCI_GETSELECTIONNSTART:
		return sel.Range(wParam).Start().Position();

	case SCI_GETSELECTIONNEND:
		return sel.Range(wParam).End().Position();

	case SCI_SETRECTANGULARSELECTIONCARET:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().caret.SetPosition(static_cast<Sci::Position>(wParam));
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONCARET:
		return sel.Rectangular().caret.Position();

	case SCI_SETRECTANGULARSELECTIONANCHOR:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().anchor.SetPosition(static_cast<Sci::Position>(wParam));
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONANCHOR:
		return sel.Rectangular().anchor.Position();

	case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().caret.SetVirtualSpace(static_cast<Sci::Position>(wParam));
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE:
		return sel.Rectangular().caret.VirtualSpace();

	case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().anchor.SetVirtualSpace(static_cast<Sci::Position>(wParam));
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
		return sel.Rectangular().anchor.VirtualSpace();

	case SCI_SETVIRTUALSPACEOPTIONS:
		virtualSpaceOptions = static_cast<int>(wParam);
		break;

	case SCI_GETVIRTUALSPACEOPTIONS:
		return virtualSpaceOptions;

	case SCI_SETADDITIONALSELFORE:
		vs.selAdditionalForeground = ColourDesired(static_cast<int>(wParam));
		InvalidateStyleRedraw();
		break;

	case SCI_SETADDITIONALSELBACK:
		vs.selAdditionalBackground = ColourDesired(static_cast<int>(wParam));
		InvalidateStyleRedraw();
		break;

	case SCI_SETADDITIONALSELALPHA:
		vs.selAdditionalAlpha = static_cast<int>(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETADDITIONALSELALPHA:
		return vs.selAdditionalAlpha;

	case SCI_SETADDITIONALCARETFORE:
		vs.additionalCaretColour = ColourDesired(static_cast<int>(wParam));
		InvalidateStyleRedraw();
		break;

	case SCI_GETADDITIONALCARETFORE:
		return vs.additionalCaretColour.AsInteger();

	case SCI_ROTATESELECTION:
		sel.RotateMain();
		InvalidateWholeSelection();
		break;

	case SCI_SWAPMAINANCHORCARET:
		InvalidateSelection(sel.RangeMain());
		sel.RangeMain().Swap();
		break;

	case SCI_MULTIPLESELECTADDNEXT:
		MultipleSelectAdd(addOne);
		break;

	case SCI_MULTIPLESELECTADDEACH:
		MultipleSelectAdd(addEach);
		break;

	case SCI_CHANGELEXERSTATE:
		pdoc->ChangeLexerState(static_cast<Sci::Position>(wParam), lParam);
		break;

	case SCI_SETIDENTIFIER:
		SetCtrlID(static_cast<int>(wParam));
		break;

	case SCI_GETIDENTIFIER:
		return GetCtrlID();

	case SCI_SETTECHNOLOGY:
		// No action by default
		break;

	case SCI_GETTECHNOLOGY:
		return technology;

	case SCI_COUNTCHARACTERS:
		return pdoc->CountCharacters(static_cast<Sci::Position>(wParam), lParam);

	case SCI_COUNTCODEUNITS:
		return pdoc->CountUTF16(static_cast<Sci::Position>(wParam), lParam);

	default:
		return DefWndProc(iMessage, wParam, lParam);
	}
	//Platform::DebugPrintf("end wnd proc\n");
	return 0;
}