diff --git a/Makefile.in b/Makefile.in index de571fc4db..947dd80d4c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -236,6 +236,7 @@ WXSCINTILLA_OBJECTS = \ wxscintilla_LexBaan.o \ wxscintilla_LexBash.o \ wxscintilla_LexBasic.o \ + wxscintilla_LexBibTeX.o \ wxscintilla_LexBullant.o \ wxscintilla_LexCaml.o \ wxscintilla_LexCLW.o \ @@ -249,6 +250,7 @@ WXSCINTILLA_OBJECTS = \ wxscintilla_LexCSS.o \ wxscintilla_LexD.o \ wxscintilla_LexDMAP.o \ + wxscintilla_LexDMIS.o \ wxscintilla_LexECL.o \ wxscintilla_LexEiffel.o \ wxscintilla_LexErlang.o \ @@ -259,6 +261,7 @@ WXSCINTILLA_OBJECTS = \ wxscintilla_LexGAP.o \ wxscintilla_LexGui4Cli.o \ wxscintilla_LexHaskell.o \ + wxscintilla_LexHex.o \ wxscintilla_LexHTML.o \ wxscintilla_LexInno.o \ wxscintilla_LexKix.o \ @@ -294,6 +297,7 @@ WXSCINTILLA_OBJECTS = \ wxscintilla_LexPython.o \ wxscintilla_LexR.o \ wxscintilla_LexRebol.o \ + wxscintilla_LexRegistry.o \ wxscintilla_LexRuby.o \ wxscintilla_LexRust.o \ wxscintilla_LexScriptol.o \ @@ -336,11 +340,14 @@ WXSCINTILLA_OBJECTS = \ wxscintilla_ContractionState.o \ wxscintilla_Decoration.o \ wxscintilla_Document.o \ + wxscintilla_EditModel.o \ + wxscintilla_EditView.o \ wxscintilla_Editor.o \ wxscintilla_ExternalLexer.o \ wxscintilla_Indicator.o \ wxscintilla_KeyMap.o \ wxscintilla_LineMarker.o \ + wxscintilla_MarginView.o \ wxscintilla_PerLine.o \ wxscintilla_PositionCache.o \ wxscintilla_RESearch.o \ @@ -17059,6 +17066,9 @@ wxscintilla_LexBash.o: $(srcdir)/src/stc/scintilla/lexers/LexBash.cxx wxscintilla_LexBasic.o: $(srcdir)/src/stc/scintilla/lexers/LexBasic.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexBasic.cxx +wxscintilla_LexBibTeX.o: $(srcdir)/src/stc/scintilla/lexers/LexBibTeX.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexBibTeX.cxx + wxscintilla_LexBullant.o: $(srcdir)/src/stc/scintilla/lexers/LexBullant.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexBullant.cxx @@ -17098,6 +17108,9 @@ wxscintilla_LexD.o: $(srcdir)/src/stc/scintilla/lexers/LexD.cxx wxscintilla_LexDMAP.o: $(srcdir)/src/stc/scintilla/lexers/LexDMAP.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexDMAP.cxx +wxscintilla_LexDMIS.o: $(srcdir)/src/stc/scintilla/lexers/LexDMIS.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexDMIS.cxx + wxscintilla_LexECL.o: $(srcdir)/src/stc/scintilla/lexers/LexECL.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexECL.cxx @@ -17128,6 +17141,9 @@ wxscintilla_LexGui4Cli.o: $(srcdir)/src/stc/scintilla/lexers/LexGui4Cli.cxx wxscintilla_LexHaskell.o: $(srcdir)/src/stc/scintilla/lexers/LexHaskell.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexHaskell.cxx +wxscintilla_LexHex.o: $(srcdir)/src/stc/scintilla/lexers/LexHex.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexHex.cxx + wxscintilla_LexHTML.o: $(srcdir)/src/stc/scintilla/lexers/LexHTML.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexHTML.cxx @@ -17233,6 +17249,9 @@ wxscintilla_LexR.o: $(srcdir)/src/stc/scintilla/lexers/LexR.cxx wxscintilla_LexRebol.o: $(srcdir)/src/stc/scintilla/lexers/LexRebol.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexRebol.cxx +wxscintilla_LexRegistry.o: $(srcdir)/src/stc/scintilla/lexers/LexRegistry.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexRegistry.cxx + wxscintilla_LexRuby.o: $(srcdir)/src/stc/scintilla/lexers/LexRuby.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexRuby.cxx @@ -17359,6 +17378,12 @@ wxscintilla_Decoration.o: $(srcdir)/src/stc/scintilla/src/Decoration.cxx wxscintilla_Document.o: $(srcdir)/src/stc/scintilla/src/Document.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/Document.cxx +wxscintilla_EditModel.o: $(srcdir)/src/stc/scintilla/src/EditModel.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/EditModel.cxx + +wxscintilla_EditView.o: $(srcdir)/src/stc/scintilla/src/EditView.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/EditView.cxx + wxscintilla_Editor.o: $(srcdir)/src/stc/scintilla/src/Editor.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/Editor.cxx @@ -17374,6 +17399,9 @@ wxscintilla_KeyMap.o: $(srcdir)/src/stc/scintilla/src/KeyMap.cxx wxscintilla_LineMarker.o: $(srcdir)/src/stc/scintilla/src/LineMarker.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/LineMarker.cxx +wxscintilla_MarginView.o: $(srcdir)/src/stc/scintilla/src/MarginView.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/MarginView.cxx + wxscintilla_PerLine.o: $(srcdir)/src/stc/scintilla/src/PerLine.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/src/PerLine.cxx diff --git a/build/bakefiles/scintilla.bkl b/build/bakefiles/scintilla.bkl index 9a24e9304f..06d41a15b1 100644 --- a/build/bakefiles/scintilla.bkl +++ b/build/bakefiles/scintilla.bkl @@ -69,6 +69,7 @@ src/stc/scintilla/lexers/LexBaan.cxx src/stc/scintilla/lexers/LexBash.cxx src/stc/scintilla/lexers/LexBasic.cxx + src/stc/scintilla/lexers/LexBibTeX.cxx src/stc/scintilla/lexers/LexBullant.cxx src/stc/scintilla/lexers/LexCaml.cxx src/stc/scintilla/lexers/LexCLW.cxx @@ -82,6 +83,7 @@ src/stc/scintilla/lexers/LexCSS.cxx src/stc/scintilla/lexers/LexD.cxx src/stc/scintilla/lexers/LexDMAP.cxx + src/stc/scintilla/lexers/LexDMIS.cxx src/stc/scintilla/lexers/LexECL.cxx src/stc/scintilla/lexers/LexEiffel.cxx src/stc/scintilla/lexers/LexErlang.cxx @@ -92,6 +94,7 @@ src/stc/scintilla/lexers/LexGAP.cxx src/stc/scintilla/lexers/LexGui4Cli.cxx src/stc/scintilla/lexers/LexHaskell.cxx + src/stc/scintilla/lexers/LexHex.cxx src/stc/scintilla/lexers/LexHTML.cxx src/stc/scintilla/lexers/LexInno.cxx src/stc/scintilla/lexers/LexKix.cxx @@ -127,6 +130,7 @@ src/stc/scintilla/lexers/LexPython.cxx src/stc/scintilla/lexers/LexR.cxx src/stc/scintilla/lexers/LexRebol.cxx + src/stc/scintilla/lexers/LexRegistry.cxx src/stc/scintilla/lexers/LexRuby.cxx src/stc/scintilla/lexers/LexRust.cxx src/stc/scintilla/lexers/LexScriptol.cxx @@ -169,11 +173,14 @@ src/stc/scintilla/src/ContractionState.cxx src/stc/scintilla/src/Decoration.cxx src/stc/scintilla/src/Document.cxx + src/stc/scintilla/src/EditModel.cxx + src/stc/scintilla/src/EditView.cxx src/stc/scintilla/src/Editor.cxx src/stc/scintilla/src/ExternalLexer.cxx src/stc/scintilla/src/Indicator.cxx src/stc/scintilla/src/KeyMap.cxx src/stc/scintilla/src/LineMarker.cxx + src/stc/scintilla/src/MarginView.cxx src/stc/scintilla/src/PerLine.cxx src/stc/scintilla/src/PositionCache.cxx src/stc/scintilla/src/RESearch.cxx diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index f231e69412..aab7be56ea 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -217,6 +217,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexBaan.obj \ $(OBJS)\wxscintilla_LexBash.obj \ $(OBJS)\wxscintilla_LexBasic.obj \ + $(OBJS)\wxscintilla_LexBibTeX.obj \ $(OBJS)\wxscintilla_LexBullant.obj \ $(OBJS)\wxscintilla_LexCaml.obj \ $(OBJS)\wxscintilla_LexCLW.obj \ @@ -230,6 +231,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexCSS.obj \ $(OBJS)\wxscintilla_LexD.obj \ $(OBJS)\wxscintilla_LexDMAP.obj \ + $(OBJS)\wxscintilla_LexDMIS.obj \ $(OBJS)\wxscintilla_LexECL.obj \ $(OBJS)\wxscintilla_LexEiffel.obj \ $(OBJS)\wxscintilla_LexErlang.obj \ @@ -240,6 +242,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexGAP.obj \ $(OBJS)\wxscintilla_LexGui4Cli.obj \ $(OBJS)\wxscintilla_LexHaskell.obj \ + $(OBJS)\wxscintilla_LexHex.obj \ $(OBJS)\wxscintilla_LexHTML.obj \ $(OBJS)\wxscintilla_LexInno.obj \ $(OBJS)\wxscintilla_LexKix.obj \ @@ -275,6 +278,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexPython.obj \ $(OBJS)\wxscintilla_LexR.obj \ $(OBJS)\wxscintilla_LexRebol.obj \ + $(OBJS)\wxscintilla_LexRegistry.obj \ $(OBJS)\wxscintilla_LexRuby.obj \ $(OBJS)\wxscintilla_LexRust.obj \ $(OBJS)\wxscintilla_LexScriptol.obj \ @@ -317,11 +321,14 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_ContractionState.obj \ $(OBJS)\wxscintilla_Decoration.obj \ $(OBJS)\wxscintilla_Document.obj \ + $(OBJS)\wxscintilla_EditModel.obj \ + $(OBJS)\wxscintilla_EditView.obj \ $(OBJS)\wxscintilla_Editor.obj \ $(OBJS)\wxscintilla_ExternalLexer.obj \ $(OBJS)\wxscintilla_Indicator.obj \ $(OBJS)\wxscintilla_KeyMap.obj \ $(OBJS)\wxscintilla_LineMarker.obj \ + $(OBJS)\wxscintilla_MarginView.obj \ $(OBJS)\wxscintilla_PerLine.obj \ $(OBJS)\wxscintilla_PositionCache.obj \ $(OBJS)\wxscintilla_RESearch.obj \ @@ -5941,6 +5948,9 @@ $(OBJS)\wxscintilla_LexBash.obj: ..\..\src\stc\scintilla\lexers\LexBash.cxx $(OBJS)\wxscintilla_LexBasic.obj: ..\..\src\stc\scintilla\lexers\LexBasic.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexBasic.cxx +$(OBJS)\wxscintilla_LexBibTeX.obj: ..\..\src\stc\scintilla\lexers\LexBibTeX.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexBibTeX.cxx + $(OBJS)\wxscintilla_LexBullant.obj: ..\..\src\stc\scintilla\lexers\LexBullant.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexBullant.cxx @@ -5980,6 +5990,9 @@ $(OBJS)\wxscintilla_LexD.obj: ..\..\src\stc\scintilla\lexers\LexD.cxx $(OBJS)\wxscintilla_LexDMAP.obj: ..\..\src\stc\scintilla\lexers\LexDMAP.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexDMAP.cxx +$(OBJS)\wxscintilla_LexDMIS.obj: ..\..\src\stc\scintilla\lexers\LexDMIS.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexDMIS.cxx + $(OBJS)\wxscintilla_LexECL.obj: ..\..\src\stc\scintilla\lexers\LexECL.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexECL.cxx @@ -6010,6 +6023,9 @@ $(OBJS)\wxscintilla_LexGui4Cli.obj: ..\..\src\stc\scintilla\lexers\LexGui4Cli.cx $(OBJS)\wxscintilla_LexHaskell.obj: ..\..\src\stc\scintilla\lexers\LexHaskell.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHaskell.cxx +$(OBJS)\wxscintilla_LexHex.obj: ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(OBJS)\wxscintilla_LexHTML.obj: ..\..\src\stc\scintilla\lexers\LexHTML.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHTML.cxx @@ -6115,6 +6131,9 @@ $(OBJS)\wxscintilla_LexR.obj: ..\..\src\stc\scintilla\lexers\LexR.cxx $(OBJS)\wxscintilla_LexRebol.obj: ..\..\src\stc\scintilla\lexers\LexRebol.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexRebol.cxx +$(OBJS)\wxscintilla_LexRegistry.obj: ..\..\src\stc\scintilla\lexers\LexRegistry.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexRegistry.cxx + $(OBJS)\wxscintilla_LexRuby.obj: ..\..\src\stc\scintilla\lexers\LexRuby.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexRuby.cxx @@ -6241,6 +6260,12 @@ $(OBJS)\wxscintilla_Decoration.obj: ..\..\src\stc\scintilla\src\Decoration.cxx $(OBJS)\wxscintilla_Document.obj: ..\..\src\stc\scintilla\src\Document.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\Document.cxx +$(OBJS)\wxscintilla_EditModel.obj: ..\..\src\stc\scintilla\src\EditModel.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\EditModel.cxx + +$(OBJS)\wxscintilla_EditView.obj: ..\..\src\stc\scintilla\src\EditView.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\EditView.cxx + $(OBJS)\wxscintilla_Editor.obj: ..\..\src\stc\scintilla\src\Editor.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\Editor.cxx @@ -6256,6 +6281,9 @@ $(OBJS)\wxscintilla_KeyMap.obj: ..\..\src\stc\scintilla\src\KeyMap.cxx $(OBJS)\wxscintilla_LineMarker.obj: ..\..\src\stc\scintilla\src\LineMarker.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\LineMarker.cxx +$(OBJS)\wxscintilla_MarginView.obj: ..\..\src\stc\scintilla\src\MarginView.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\MarginView.cxx + $(OBJS)\wxscintilla_PerLine.obj: ..\..\src\stc\scintilla\src\PerLine.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\PerLine.cxx diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index f9e6858055..e9a450f975 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -205,6 +205,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexBaan.o \ $(OBJS)\wxscintilla_LexBash.o \ $(OBJS)\wxscintilla_LexBasic.o \ + $(OBJS)\wxscintilla_LexBibTeX.o \ $(OBJS)\wxscintilla_LexBullant.o \ $(OBJS)\wxscintilla_LexCaml.o \ $(OBJS)\wxscintilla_LexCLW.o \ @@ -218,6 +219,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexCSS.o \ $(OBJS)\wxscintilla_LexD.o \ $(OBJS)\wxscintilla_LexDMAP.o \ + $(OBJS)\wxscintilla_LexDMIS.o \ $(OBJS)\wxscintilla_LexECL.o \ $(OBJS)\wxscintilla_LexEiffel.o \ $(OBJS)\wxscintilla_LexErlang.o \ @@ -228,6 +230,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexGAP.o \ $(OBJS)\wxscintilla_LexGui4Cli.o \ $(OBJS)\wxscintilla_LexHaskell.o \ + $(OBJS)\wxscintilla_LexHex.o \ $(OBJS)\wxscintilla_LexHTML.o \ $(OBJS)\wxscintilla_LexInno.o \ $(OBJS)\wxscintilla_LexKix.o \ @@ -263,6 +266,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexPython.o \ $(OBJS)\wxscintilla_LexR.o \ $(OBJS)\wxscintilla_LexRebol.o \ + $(OBJS)\wxscintilla_LexRegistry.o \ $(OBJS)\wxscintilla_LexRuby.o \ $(OBJS)\wxscintilla_LexRust.o \ $(OBJS)\wxscintilla_LexScriptol.o \ @@ -305,11 +309,14 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_ContractionState.o \ $(OBJS)\wxscintilla_Decoration.o \ $(OBJS)\wxscintilla_Document.o \ + $(OBJS)\wxscintilla_EditModel.o \ + $(OBJS)\wxscintilla_EditView.o \ $(OBJS)\wxscintilla_Editor.o \ $(OBJS)\wxscintilla_ExternalLexer.o \ $(OBJS)\wxscintilla_Indicator.o \ $(OBJS)\wxscintilla_KeyMap.o \ $(OBJS)\wxscintilla_LineMarker.o \ + $(OBJS)\wxscintilla_MarginView.o \ $(OBJS)\wxscintilla_PerLine.o \ $(OBJS)\wxscintilla_PositionCache.o \ $(OBJS)\wxscintilla_RESearch.o \ @@ -6116,6 +6123,9 @@ $(OBJS)\wxscintilla_LexBash.o: ../../src/stc/scintilla/lexers/LexBash.cxx $(OBJS)\wxscintilla_LexBasic.o: ../../src/stc/scintilla/lexers/LexBasic.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_LexBibTeX.o: ../../src/stc/scintilla/lexers/LexBibTeX.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_LexBullant.o: ../../src/stc/scintilla/lexers/LexBullant.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< @@ -6155,6 +6165,9 @@ $(OBJS)\wxscintilla_LexD.o: ../../src/stc/scintilla/lexers/LexD.cxx $(OBJS)\wxscintilla_LexDMAP.o: ../../src/stc/scintilla/lexers/LexDMAP.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_LexDMIS.o: ../../src/stc/scintilla/lexers/LexDMIS.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_LexECL.o: ../../src/stc/scintilla/lexers/LexECL.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< @@ -6185,6 +6198,9 @@ $(OBJS)\wxscintilla_LexGui4Cli.o: ../../src/stc/scintilla/lexers/LexGui4Cli.cxx $(OBJS)\wxscintilla_LexHaskell.o: ../../src/stc/scintilla/lexers/LexHaskell.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_LexHex.o: ../../src/stc/scintilla/lexers/LexHex.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_LexHTML.o: ../../src/stc/scintilla/lexers/LexHTML.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< @@ -6290,6 +6306,9 @@ $(OBJS)\wxscintilla_LexR.o: ../../src/stc/scintilla/lexers/LexR.cxx $(OBJS)\wxscintilla_LexRebol.o: ../../src/stc/scintilla/lexers/LexRebol.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_LexRegistry.o: ../../src/stc/scintilla/lexers/LexRegistry.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_LexRuby.o: ../../src/stc/scintilla/lexers/LexRuby.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< @@ -6416,6 +6435,12 @@ $(OBJS)\wxscintilla_Decoration.o: ../../src/stc/scintilla/src/Decoration.cxx $(OBJS)\wxscintilla_Document.o: ../../src/stc/scintilla/src/Document.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_EditModel.o: ../../src/stc/scintilla/src/EditModel.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + +$(OBJS)\wxscintilla_EditView.o: ../../src/stc/scintilla/src/EditView.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_Editor.o: ../../src/stc/scintilla/src/Editor.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< @@ -6431,6 +6456,9 @@ $(OBJS)\wxscintilla_KeyMap.o: ../../src/stc/scintilla/src/KeyMap.cxx $(OBJS)\wxscintilla_LineMarker.o: ../../src/stc/scintilla/src/LineMarker.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_MarginView.o: ../../src/stc/scintilla/src/MarginView.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_PerLine.o: ../../src/stc/scintilla/src/PerLine.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 7c672251ce..85e140a1fe 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -228,6 +228,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexBaan.obj \ $(OBJS)\wxscintilla_LexBash.obj \ $(OBJS)\wxscintilla_LexBasic.obj \ + $(OBJS)\wxscintilla_LexBibTeX.obj \ $(OBJS)\wxscintilla_LexBullant.obj \ $(OBJS)\wxscintilla_LexCaml.obj \ $(OBJS)\wxscintilla_LexCLW.obj \ @@ -241,6 +242,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexCSS.obj \ $(OBJS)\wxscintilla_LexD.obj \ $(OBJS)\wxscintilla_LexDMAP.obj \ + $(OBJS)\wxscintilla_LexDMIS.obj \ $(OBJS)\wxscintilla_LexECL.obj \ $(OBJS)\wxscintilla_LexEiffel.obj \ $(OBJS)\wxscintilla_LexErlang.obj \ @@ -251,6 +253,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexGAP.obj \ $(OBJS)\wxscintilla_LexGui4Cli.obj \ $(OBJS)\wxscintilla_LexHaskell.obj \ + $(OBJS)\wxscintilla_LexHex.obj \ $(OBJS)\wxscintilla_LexHTML.obj \ $(OBJS)\wxscintilla_LexInno.obj \ $(OBJS)\wxscintilla_LexKix.obj \ @@ -286,6 +289,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexPython.obj \ $(OBJS)\wxscintilla_LexR.obj \ $(OBJS)\wxscintilla_LexRebol.obj \ + $(OBJS)\wxscintilla_LexRegistry.obj \ $(OBJS)\wxscintilla_LexRuby.obj \ $(OBJS)\wxscintilla_LexRust.obj \ $(OBJS)\wxscintilla_LexScriptol.obj \ @@ -328,11 +332,14 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_ContractionState.obj \ $(OBJS)\wxscintilla_Decoration.obj \ $(OBJS)\wxscintilla_Document.obj \ + $(OBJS)\wxscintilla_EditModel.obj \ + $(OBJS)\wxscintilla_EditView.obj \ $(OBJS)\wxscintilla_Editor.obj \ $(OBJS)\wxscintilla_ExternalLexer.obj \ $(OBJS)\wxscintilla_Indicator.obj \ $(OBJS)\wxscintilla_KeyMap.obj \ $(OBJS)\wxscintilla_LineMarker.obj \ + $(OBJS)\wxscintilla_MarginView.obj \ $(OBJS)\wxscintilla_PerLine.obj \ $(OBJS)\wxscintilla_PositionCache.obj \ $(OBJS)\wxscintilla_RESearch.obj \ @@ -6633,6 +6640,9 @@ $(OBJS)\wxscintilla_LexBash.obj: ..\..\src\stc\scintilla\lexers\LexBash.cxx $(OBJS)\wxscintilla_LexBasic.obj: ..\..\src\stc\scintilla\lexers\LexBasic.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexBasic.cxx +$(OBJS)\wxscintilla_LexBibTeX.obj: ..\..\src\stc\scintilla\lexers\LexBibTeX.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexBibTeX.cxx + $(OBJS)\wxscintilla_LexBullant.obj: ..\..\src\stc\scintilla\lexers\LexBullant.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexBullant.cxx @@ -6672,6 +6682,9 @@ $(OBJS)\wxscintilla_LexD.obj: ..\..\src\stc\scintilla\lexers\LexD.cxx $(OBJS)\wxscintilla_LexDMAP.obj: ..\..\src\stc\scintilla\lexers\LexDMAP.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexDMAP.cxx +$(OBJS)\wxscintilla_LexDMIS.obj: ..\..\src\stc\scintilla\lexers\LexDMIS.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexDMIS.cxx + $(OBJS)\wxscintilla_LexECL.obj: ..\..\src\stc\scintilla\lexers\LexECL.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexECL.cxx @@ -6702,6 +6715,9 @@ $(OBJS)\wxscintilla_LexGui4Cli.obj: ..\..\src\stc\scintilla\lexers\LexGui4Cli.cx $(OBJS)\wxscintilla_LexHaskell.obj: ..\..\src\stc\scintilla\lexers\LexHaskell.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHaskell.cxx +$(OBJS)\wxscintilla_LexHex.obj: ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(OBJS)\wxscintilla_LexHTML.obj: ..\..\src\stc\scintilla\lexers\LexHTML.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHTML.cxx @@ -6807,6 +6823,9 @@ $(OBJS)\wxscintilla_LexR.obj: ..\..\src\stc\scintilla\lexers\LexR.cxx $(OBJS)\wxscintilla_LexRebol.obj: ..\..\src\stc\scintilla\lexers\LexRebol.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexRebol.cxx +$(OBJS)\wxscintilla_LexRegistry.obj: ..\..\src\stc\scintilla\lexers\LexRegistry.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexRegistry.cxx + $(OBJS)\wxscintilla_LexRuby.obj: ..\..\src\stc\scintilla\lexers\LexRuby.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexRuby.cxx @@ -6933,6 +6952,12 @@ $(OBJS)\wxscintilla_Decoration.obj: ..\..\src\stc\scintilla\src\Decoration.cxx $(OBJS)\wxscintilla_Document.obj: ..\..\src\stc\scintilla\src\Document.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\Document.cxx +$(OBJS)\wxscintilla_EditModel.obj: ..\..\src\stc\scintilla\src\EditModel.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\EditModel.cxx + +$(OBJS)\wxscintilla_EditView.obj: ..\..\src\stc\scintilla\src\EditView.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\EditView.cxx + $(OBJS)\wxscintilla_Editor.obj: ..\..\src\stc\scintilla\src\Editor.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\Editor.cxx @@ -6948,6 +6973,9 @@ $(OBJS)\wxscintilla_KeyMap.obj: ..\..\src\stc\scintilla\src\KeyMap.cxx $(OBJS)\wxscintilla_LineMarker.obj: ..\..\src\stc\scintilla\src\LineMarker.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\LineMarker.cxx +$(OBJS)\wxscintilla_MarginView.obj: ..\..\src\stc\scintilla\src\MarginView.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\MarginView.cxx + $(OBJS)\wxscintilla_PerLine.obj: ..\..\src\stc\scintilla\src\PerLine.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\src\PerLine.cxx diff --git a/build/msw/wx_vc7_wxscintilla.vcproj b/build/msw/wx_vc7_wxscintilla.vcproj index 0dc370af45..a9bd1621bd 100644 --- a/build/msw/wx_vc7_wxscintilla.vcproj +++ b/build/msw/wx_vc7_wxscintilla.vcproj @@ -286,6 +286,12 @@ + + + + @@ -337,6 +343,9 @@ + + @@ -376,6 +385,9 @@ + + @@ -409,6 +421,9 @@ + + @@ -511,6 +526,9 @@ + + @@ -592,6 +610,9 @@ + + diff --git a/build/msw/wx_vc8_wxscintilla.vcproj b/build/msw/wx_vc8_wxscintilla.vcproj index 48d22ef8ff..c5888d7105 100644 --- a/build/msw/wx_vc8_wxscintilla.vcproj +++ b/build/msw/wx_vc8_wxscintilla.vcproj @@ -730,6 +730,14 @@ RelativePath="..\..\src\stc\scintilla\src\Document.cxx" > + + + + @@ -798,6 +806,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexBasic.cxx" > + + @@ -850,6 +862,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexDMAP.cxx" > + + @@ -894,6 +910,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexHaskell.cxx" > + + @@ -1030,6 +1050,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexRebol.cxx" > + + @@ -1138,6 +1162,10 @@ RelativePath="..\..\src\stc\scintilla\src\LineMarker.cxx" > + + diff --git a/build/msw/wx_vc9_wxscintilla.vcproj b/build/msw/wx_vc9_wxscintilla.vcproj index 922a184ffd..61b58586ce 100644 --- a/build/msw/wx_vc9_wxscintilla.vcproj +++ b/build/msw/wx_vc9_wxscintilla.vcproj @@ -726,6 +726,14 @@ RelativePath="..\..\src\stc\scintilla\src\Document.cxx" > + + + + @@ -794,6 +802,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexBasic.cxx" > + + @@ -846,6 +858,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexDMAP.cxx" > + + @@ -890,6 +906,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexHaskell.cxx" > + + @@ -1026,6 +1046,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexRebol.cxx" > + + @@ -1134,6 +1158,10 @@ RelativePath="..\..\src\stc\scintilla\src\LineMarker.cxx" > + + diff --git a/build/msw/wx_wxscintilla.vcxproj b/build/msw/wx_wxscintilla.vcxproj index 94d5c0d658..fd8b973e13 100644 --- a/build/msw/wx_wxscintilla.vcxproj +++ b/build/msw/wx_wxscintilla.vcxproj @@ -415,6 +415,8 @@ + + @@ -432,6 +434,7 @@ + @@ -445,6 +448,7 @@ + @@ -456,6 +460,7 @@ + @@ -490,6 +495,7 @@ + @@ -517,6 +523,7 @@ + diff --git a/build/msw/wx_wxscintilla.vcxproj.filters b/build/msw/wx_wxscintilla.vcxproj.filters index 6b8eeae322..30a0a1dca5 100644 --- a/build/msw/wx_wxscintilla.vcxproj.filters +++ b/build/msw/wx_wxscintilla.vcxproj.filters @@ -50,6 +50,12 @@ Source Files + + Source Files + + + Source Files + Source Files @@ -101,6 +107,9 @@ Source Files + + Source Files + Source Files @@ -140,6 +149,9 @@ Source Files + + Source Files + Source Files @@ -173,6 +185,9 @@ Source Files + + Source Files + Source Files @@ -275,6 +290,9 @@ Source Files + + Source Files + Source Files @@ -356,6 +374,9 @@ Source Files + + Source Files + Source Files diff --git a/docs/changes.txt b/docs/changes.txt index d1182e9302..0807ff4f0b 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -98,7 +98,7 @@ All (GUI): - Optimized wxRTC insertion and deletion when floating objects are present. - Added on-demand image loading option to wxRTC. - Add wxFont::GetBaseFont() (Melroy Tellis). -- Update included Scintilla to version 3.4.1 (Christian Walther, Heyoupeng). +- Update Scintilla to v3.5.5 (Christian Walther, Heyoupeng, ARATA Mizuki). - Add wxStyledTextCtrl copy/paste text events (Christian Walther). - Improve RTL support in wxStyledTextCtrl (Zane U. Ji). - Add support for loading old V1 BMP files to wxImage (Artur Wieczorek). diff --git a/include/wx/stc/stc.h b/include/wx/stc/stc.h index c8adbb3854..abc8de19bc 100644 --- a/include/wx/stc/stc.h +++ b/include/wx/stc/stc.h @@ -75,6 +75,8 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; /// The SC_CP_UTF8 value can be used to enter Unicode mode. /// This is the same value as CP_UTF8 in Windows #define wxSTC_CP_UTF8 65001 +#define wxSTC_IME_WINDOWED 0 +#define wxSTC_IME_INLINE 1 #define wxSTC_MARKER_MAX 31 #define wxSTC_MARK_CIRCLE 0 #define wxSTC_MARK_ROUNDRECT 1 @@ -190,12 +192,20 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_INDIC_DOTBOX 12 #define wxSTC_INDIC_SQUIGGLEPIXMAP 13 #define wxSTC_INDIC_COMPOSITIONTHICK 14 -#define wxSTC_INDIC_MAX 31 +#define wxSTC_INDIC_COMPOSITIONTHIN 15 +#define wxSTC_INDIC_FULLBOX 16 +#define wxSTC_INDIC_TEXTFORE 17 +#define wxSTC_INDIC_IME 32 +#define wxSTC_INDIC_IME_MAX 35 +#define wxSTC_INDIC_MAX 35 #define wxSTC_INDIC_CONTAINER 8 #define wxSTC_INDIC0_MASK 0x20 #define wxSTC_INDIC1_MASK 0x40 #define wxSTC_INDIC2_MASK 0x80 #define wxSTC_INDICS_MASK 0xE0 +#define wxSTC_INDICVALUEBIT 0x1000000 +#define wxSTC_INDICVALUEMASK 0xFFFFFF +#define wxSTC_INDICFLAG_VALUEFORE 1 #define wxSTC_IV_NONE 0 #define wxSTC_IV_REAL 1 #define wxSTC_IV_LOOKFORWARD 2 @@ -220,6 +230,7 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_FIND_WORDSTART 0x00100000 #define wxSTC_FIND_REGEXP 0x00200000 #define wxSTC_FIND_POSIX 0x00400000 +#define wxSTC_FIND_CXX11REGEX 0x00800000 #define wxSTC_FOLDLEVELBASE 0x400 #define wxSTC_FOLDLEVELWHITEFLAG 0x1000 #define wxSTC_FOLDLEVELHEADERFLAG 0x2000 @@ -235,6 +246,7 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008 #define wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010 #define wxSTC_FOLDFLAG_LEVELNUMBERS 0x0040 +#define wxSTC_FOLDFLAG_LINESTATE 0x0080 #define wxSTC_TIME_FOREVER 10000000 #define wxSTC_WRAP_NONE 0 #define wxSTC_WRAP_WORD 1 @@ -254,6 +266,9 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_CACHE_CARET 1 #define wxSTC_CACHE_PAGE 2 #define wxSTC_CACHE_DOCUMENT 3 +#define wxSTC_PHASES_ONE 0 +#define wxSTC_PHASES_TWO 1 +#define wxSTC_PHASES_MULTIPLE 2 /// Control font anti-aliasing. #define wxSTC_EFF_QUALITY_MASK 0xF @@ -269,6 +284,8 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_STATUS_OK 0 #define wxSTC_STATUS_FAILURE 1 #define wxSTC_STATUS_BADALLOC 2 +#define wxSTC_STATUS_WARN_START 1000 +#define wxSTC_STATUS_WARN_REGEX 1001 #define wxSTC_CURSORNORMAL -1 #define wxSTC_CURSORARROW 2 #define wxSTC_CURSORWAIT 4 @@ -309,6 +326,8 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_SEL_THIN 3 #define wxSTC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE 0 #define wxSTC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1 +#define wxSTC_MULTIAUTOC_ONCE 0 +#define wxSTC_MULTIAUTOC_EACH 1 #define wxSTC_ORDER_PRESORTED 0 #define wxSTC_ORDER_PERFORMSORT 1 #define wxSTC_ORDER_CUSTOM 2 @@ -326,12 +345,15 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_ANNOTATION_HIDDEN 0 #define wxSTC_ANNOTATION_STANDARD 1 #define wxSTC_ANNOTATION_BOXED 2 +#define wxSTC_ANNOTATION_INDENTED 3 #define wxSTC_UNDO_MAY_COALESCE 1 #define wxSTC_SCVS_NONE 0 #define wxSTC_SCVS_RECTANGULARSELECTION 1 #define wxSTC_SCVS_USERACCESSIBLE 2 #define wxSTC_TECHNOLOGY_DEFAULT 0 #define wxSTC_TECHNOLOGY_DIRECTWRITE 1 +#define wxSTC_TECHNOLOGY_DIRECTWRITERETAIN 2 +#define wxSTC_TECHNOLOGY_DIRECTWRITEDC 3 /// Line end types which may be used in addition to LF, CR, and CRLF /// SC_LINE_END_TYPE_UNICODE includes U+2028 Line Separator, @@ -369,7 +391,9 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_MOD_CHANGEANNOTATION 0x20000 #define wxSTC_MOD_CONTAINER 0x40000 #define wxSTC_MOD_LEXERSTATE 0x80000 -#define wxSTC_MODEVENTMASKALL 0xFFFFF +#define wxSTC_MOD_INSERTCHECK 0x100000 +#define wxSTC_MOD_CHANGETABSTOPS 0x200000 +#define wxSTC_MODEVENTMASKALL 0x3FFFFF #define wxSTC_UPDATE_CONTENT 0x1 #define wxSTC_UPDATE_SELECTION 0x2 #define wxSTC_UPDATE_V_SCROLL 0x4 @@ -518,6 +542,12 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_LEX_RUST 111 #define wxSTC_LEX_DMAP 112 #define wxSTC_LEX_AS 113 +#define wxSTC_LEX_DMIS 114 +#define wxSTC_LEX_REGISTRY 115 +#define wxSTC_LEX_BIBTEX 116 +#define wxSTC_LEX_SREC 117 +#define wxSTC_LEX_IHEX 118 +#define wxSTC_LEX_TEHEX 119 /// When a lexer specifies its language as SCLEX_AUTOMATIC it receives a /// value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -568,6 +598,8 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_C_PREPROCESSORCOMMENT 23 #define wxSTC_C_PREPROCESSORCOMMENTDOC 24 #define wxSTC_C_USERLITERAL 25 +#define wxSTC_C_TASKMARKER 26 +#define wxSTC_C_ESCAPESEQUENCE 27 /// Lexical states for SCLEX_D #define wxSTC_D_DEFAULT 0 @@ -1399,6 +1431,11 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_V_IDENTIFIER 11 #define wxSTC_V_STRINGEOL 12 #define wxSTC_V_USER 19 +#define wxSTC_V_COMMENT_WORD 20 +#define wxSTC_V_INPUT 21 +#define wxSTC_V_OUTPUT 22 +#define wxSTC_V_INOUT 23 +#define wxSTC_V_PORT_CONNECT 24 /// Lexical states for SCLEX_KIX #define wxSTC_KIX_DEFAULT 0 @@ -1411,6 +1448,7 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_KIX_KEYWORD 7 #define wxSTC_KIX_FUNCTIONS 8 #define wxSTC_KIX_OPERATOR 9 +#define wxSTC_KIX_COMMENTSTREAM 10 #define wxSTC_KIX_IDENTIFIER 31 /// Lexical states for SCLEX_GUI4CLI @@ -1521,6 +1559,7 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_VHDL_STDPACKAGE 12 #define wxSTC_VHDL_STDTYPE 13 #define wxSTC_VHDL_USERWORD 14 +#define wxSTC_VHDL_BLOCK_COMMENT 15 /// Lexical states for SCLEX_CAML #define wxSTC_CAML_DEFAULT 0 @@ -1642,6 +1681,7 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_SQL_USER3 21 #define wxSTC_SQL_USER4 22 #define wxSTC_SQL_QUOTEDIDENTIFIER 23 +#define wxSTC_SQL_QOPERATOR 24 /// Lexical states for SCLEX_SMALLTALK #define wxSTC_ST_DEFAULT 0 @@ -2287,6 +2327,9 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_RUST_LIFETIME 18 #define wxSTC_RUST_MACRO 19 #define wxSTC_RUST_LEXERROR 20 +#define wxSTC_RUST_BYTESTRING 21 +#define wxSTC_RUST_BYTESTRINGR 22 +#define wxSTC_RUST_BYTECHARACTER 23 /// Lexical states for SCLEX_DMAP #define wxSTC_DMAP_DEFAULT 0 @@ -2301,6 +2344,63 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_DMAP_WORD2 9 #define wxSTC_DMAP_WORD3 10 +/// Lexical states for SCLEX_DMIS +#define wxSTC_DMIS_DEFAULT 0 +#define wxSTC_DMIS_COMMENT 1 +#define wxSTC_DMIS_STRING 2 +#define wxSTC_DMIS_NUMBER 3 +#define wxSTC_DMIS_KEYWORD 4 +#define wxSTC_DMIS_MAJORWORD 5 +#define wxSTC_DMIS_MINORWORD 6 +#define wxSTC_DMIS_UNSUPPORTED_MAJOR 7 +#define wxSTC_DMIS_UNSUPPORTED_MINOR 8 +#define wxSTC_DMIS_LABEL 9 + +/// Lexical states for SCLEX_REGISTRY +#define wxSTC_REG_DEFAULT 0 +#define wxSTC_REG_COMMENT 1 +#define wxSTC_REG_VALUENAME 2 +#define wxSTC_REG_STRING 3 +#define wxSTC_REG_HEXDIGIT 4 +#define wxSTC_REG_VALUETYPE 5 +#define wxSTC_REG_ADDEDKEY 6 +#define wxSTC_REG_DELETEDKEY 7 +#define wxSTC_REG_ESCAPED 8 +#define wxSTC_REG_KEYPATH_GUID 9 +#define wxSTC_REG_STRING_GUID 10 +#define wxSTC_REG_PARAMETER 11 +#define wxSTC_REG_OPERATOR 12 + +/// Lexical state for SCLEX_BIBTEX +#define wxSTC_BIBTEX_DEFAULT 0 +#define wxSTC_BIBTEX_ENTRY 1 +#define wxSTC_BIBTEX_UNKNOWN_ENTRY 2 +#define wxSTC_BIBTEX_KEY 3 +#define wxSTC_BIBTEX_PARAMETER 4 +#define wxSTC_BIBTEX_VALUE 5 +#define wxSTC_BIBTEX_COMMENT 6 + +/// Lexical state for SCLEX_SREC +#define wxSTC_HEX_DEFAULT 0 +#define wxSTC_HEX_RECSTART 1 +#define wxSTC_HEX_RECTYPE 2 +#define wxSTC_HEX_RECTYPE_UNKNOWN 3 +#define wxSTC_HEX_BYTECOUNT 4 +#define wxSTC_HEX_BYTECOUNT_WRONG 5 +#define wxSTC_HEX_NOADDRESS 6 +#define wxSTC_HEX_DATAADDRESS 7 +#define wxSTC_HEX_RECCOUNT 8 +#define wxSTC_HEX_STARTADDRESS 9 +#define wxSTC_HEX_ADDRESSFIELD_UNKNOWN 10 +#define wxSTC_HEX_EXTENDEDADDRESS 11 +#define wxSTC_HEX_DATA_ODD 12 +#define wxSTC_HEX_DATA_EVEN 13 +#define wxSTC_HEX_DATA_UNKNOWN 14 +#define wxSTC_HEX_DATA_EMPTY 15 +#define wxSTC_HEX_CHECKSUM 16 +#define wxSTC_HEX_CHECKSUM_WRONG 17 +#define wxSTC_HEX_GARBAGE 18 + //}}} //---------------------------------------------------------------------- @@ -2666,6 +2766,9 @@ public: // Insert string at a position. void InsertText(int pos, const wxString& text); + // Change the text that is being inserted in response to SC_MOD_INSERTCHECK + void ChangeInsertion(int length, const wxString& text); + // Delete all text in the document. void ClearAll(); @@ -2745,6 +2848,7 @@ public: // Retrieve the text of the line containing the caret. // Returns the index of the caret on the line. + // Result is NUL-terminated. #ifdef SWIG wxString GetCurLine(int* OUTPUT); #else @@ -2784,9 +2888,24 @@ public: // Retrieve the visible size of a tab. int GetTabWidth() const; + // Clear explicit tabstops on a line. + void ClearTabStops(int line); + + // Add an explicit tab stop for a line. + void AddTabStop(int line, int x); + + // Find the next explicit tab stop position on a line after a position. + int GetNextTabStop(int line, int x); + // Set the code page used to interpret the bytes of the document as characters. void SetCodePage(int codePage); + // Is the IME displayed in a winow or inline? + int GetIMEInteraction() const; + + // Choose to display the the IME in a winow or inline. + void SetIMEInteraction(int imeInteraction); + // Set the symbol used for a particular marker number, // and optionally the fore and background colours. void MarkerDefine(int markerNumber, int markerSymbol, @@ -3025,6 +3144,24 @@ public: // Retrieve whether indicator drawn under or over text. bool IndicatorGetUnder(int indic) const; + // Set a hover indicator to plain, squiggle or TT. + void IndicatorSetHoverStyle(int indic, int style); + + // Retrieve the hover style of an indicator. + int IndicatorGetHoverStyle(int indic) const; + + // Set the foreground hover colour of an indicator. + void IndicatorSetHoverForeground(int indic, const wxColour& fore); + + // Retrieve the foreground hover colour of an indicator. + wxColour IndicatorGetHoverForeground(int indic) const; + + // Set the attributes of an indicator. + void IndicatorSetFlags(int indic, int flags); + + // Retrieve the attributes of an indicator. + int IndicatorGetFlags(int indic) const; + // Set the foreground colour of all whitespace and whether to use this setting. void SetWhitespaceForeground(bool useSetting, const wxColour& fore); @@ -3383,6 +3520,12 @@ public: // Get the position that ends the target. int GetTargetEnd() const; + // Sets both the start and end of the target in one call. + void SetTargetRange(int start, int end); + + // Retrieve the text in the target. + wxString GetTargetText() const; + // Replace the target text with the argument text. // Text is counted so it can contain NULs. // Returns the length of the replacement text. @@ -3610,13 +3753,22 @@ public: // Append a string to the end of the document without changing the selection. void AppendText(const wxString& text); - // Is drawing done in two phases with backgrounds drawn before faoregrounds? + // Is drawing done in two phases with backgrounds drawn before foregrounds? bool GetTwoPhaseDraw() const; // In twoPhaseDraw mode, drawing is performed in two phases, first the background // and then the foreground. This avoids chopping off characters that overlap the next run. void SetTwoPhaseDraw(bool twoPhase); + // How many phases is drawing done in? + int GetPhasesDraw() const; + + // In one phase draw, text is drawn in a series of rectangular blocks with no overlap. + // In two phase draw, text is drawn in a series of lines allowing runs to overlap horizontally. + // In multiple phase draw, each element is drawn over the whole drawing area, allowing text + // to overlap from one line to the next. + void SetPhasesDraw(int phases); + // Scroll so that a display line is at the top of the display. void SetFirstVisibleLine(int lineDisplay); @@ -3627,6 +3779,7 @@ public: int GetMultiPaste() const; // Retrieve the value of a tag from a regular expression search. + // Result is NUL-terminated. wxString GetTag(int tagNumber) const; // Make the target range start and end be the same as the selection range start and end. @@ -4129,6 +4282,12 @@ public: // Get auto-completion case insensitive behaviour. int AutoCompGetCaseInsensitiveBehaviour() const; + // Change the effect of autocompleting when there are multiple selections. + void AutoCompSetMulti(int multi); + + // Retrieve the effect of autocompleting when there are multiple selections.. + int AutoCompGetMulti() const; + // Set the way autocompletion lists are ordered. void AutoCompSetOrder(int order); @@ -4224,12 +4383,6 @@ public: // the range of a call to GetRangePointer. int GetGapPosition() const; - // Always interpret keyboard input as Unicode - void SetKeysUnicode(bool keysUnicode); - - // Are keys always interpreted as Unicode? - bool GetKeysUnicode() const; - // Set the alpha fill colour of the given indicator. void IndicatorSetAlpha(int indicator, int alpha); @@ -4539,6 +4692,7 @@ public: void SetRepresentation(const wxString& encodedCharacter, const wxString& representation); // Set the way a character is drawn. + // Result is NUL-terminated. wxString GetRepresentation(const wxString& encodedCharacter) const; // Remove a character representation. @@ -4586,15 +4740,18 @@ public: void* PrivateLexerCall(int operation, void* pointer); // Retrieve a '\n' separated list of properties understood by the current lexer. + // Result is NUL-terminated. wxString PropertyNames() const; // Retrieve the type of a property. int PropertyType(const wxString& name); // Describe a property. + // Result is NUL-terminated. wxString DescribeProperty(const wxString& name) const; // Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. + // Result is NUL-terminated. wxString DescribeKeyWordSets() const; // Bit set of LineEndType enumertion for which line ends beyond the standard @@ -4627,6 +4784,7 @@ public: int DistanceToSecondaryStyles() const; // Get the set of base styles that can be extended with sub styles + // Result is NUL-terminated. wxString GetSubStyleBases() const; //}}} diff --git a/interface/wx/stc/stc.h b/interface/wx/stc/stc.h index a4fa06151c..62ed006e2a 100644 --- a/interface/wx/stc/stc.h +++ b/interface/wx/stc/stc.h @@ -31,6 +31,8 @@ /// The SC_CP_UTF8 value can be used to enter Unicode mode. /// This is the same value as CP_UTF8 in Windows #define wxSTC_CP_UTF8 65001 +#define wxSTC_IME_WINDOWED 0 +#define wxSTC_IME_INLINE 1 #define wxSTC_MARKER_MAX 31 #define wxSTC_MARK_CIRCLE 0 #define wxSTC_MARK_ROUNDRECT 1 @@ -146,12 +148,20 @@ #define wxSTC_INDIC_DOTBOX 12 #define wxSTC_INDIC_SQUIGGLEPIXMAP 13 #define wxSTC_INDIC_COMPOSITIONTHICK 14 -#define wxSTC_INDIC_MAX 31 +#define wxSTC_INDIC_COMPOSITIONTHIN 15 +#define wxSTC_INDIC_FULLBOX 16 +#define wxSTC_INDIC_TEXTFORE 17 +#define wxSTC_INDIC_IME 32 +#define wxSTC_INDIC_IME_MAX 35 +#define wxSTC_INDIC_MAX 35 #define wxSTC_INDIC_CONTAINER 8 #define wxSTC_INDIC0_MASK 0x20 #define wxSTC_INDIC1_MASK 0x40 #define wxSTC_INDIC2_MASK 0x80 #define wxSTC_INDICS_MASK 0xE0 +#define wxSTC_INDICVALUEBIT 0x1000000 +#define wxSTC_INDICVALUEMASK 0xFFFFFF +#define wxSTC_INDICFLAG_VALUEFORE 1 #define wxSTC_IV_NONE 0 #define wxSTC_IV_REAL 1 #define wxSTC_IV_LOOKFORWARD 2 @@ -176,6 +186,7 @@ #define wxSTC_FIND_WORDSTART 0x00100000 #define wxSTC_FIND_REGEXP 0x00200000 #define wxSTC_FIND_POSIX 0x00400000 +#define wxSTC_FIND_CXX11REGEX 0x00800000 #define wxSTC_FOLDLEVELBASE 0x400 #define wxSTC_FOLDLEVELWHITEFLAG 0x1000 #define wxSTC_FOLDLEVELHEADERFLAG 0x2000 @@ -191,6 +202,7 @@ #define wxSTC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008 #define wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010 #define wxSTC_FOLDFLAG_LEVELNUMBERS 0x0040 +#define wxSTC_FOLDFLAG_LINESTATE 0x0080 #define wxSTC_TIME_FOREVER 10000000 #define wxSTC_WRAP_NONE 0 #define wxSTC_WRAP_WORD 1 @@ -210,6 +222,9 @@ #define wxSTC_CACHE_CARET 1 #define wxSTC_CACHE_PAGE 2 #define wxSTC_CACHE_DOCUMENT 3 +#define wxSTC_PHASES_ONE 0 +#define wxSTC_PHASES_TWO 1 +#define wxSTC_PHASES_MULTIPLE 2 /// Control font anti-aliasing. #define wxSTC_EFF_QUALITY_MASK 0xF @@ -225,6 +240,8 @@ #define wxSTC_STATUS_OK 0 #define wxSTC_STATUS_FAILURE 1 #define wxSTC_STATUS_BADALLOC 2 +#define wxSTC_STATUS_WARN_START 1000 +#define wxSTC_STATUS_WARN_REGEX 1001 #define wxSTC_CURSORNORMAL -1 #define wxSTC_CURSORARROW 2 #define wxSTC_CURSORWAIT 4 @@ -265,6 +282,8 @@ #define wxSTC_SEL_THIN 3 #define wxSTC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE 0 #define wxSTC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1 +#define wxSTC_MULTIAUTOC_ONCE 0 +#define wxSTC_MULTIAUTOC_EACH 1 #define wxSTC_ORDER_PRESORTED 0 #define wxSTC_ORDER_PERFORMSORT 1 #define wxSTC_ORDER_CUSTOM 2 @@ -282,12 +301,15 @@ #define wxSTC_ANNOTATION_HIDDEN 0 #define wxSTC_ANNOTATION_STANDARD 1 #define wxSTC_ANNOTATION_BOXED 2 +#define wxSTC_ANNOTATION_INDENTED 3 #define wxSTC_UNDO_MAY_COALESCE 1 #define wxSTC_SCVS_NONE 0 #define wxSTC_SCVS_RECTANGULARSELECTION 1 #define wxSTC_SCVS_USERACCESSIBLE 2 #define wxSTC_TECHNOLOGY_DEFAULT 0 #define wxSTC_TECHNOLOGY_DIRECTWRITE 1 +#define wxSTC_TECHNOLOGY_DIRECTWRITERETAIN 2 +#define wxSTC_TECHNOLOGY_DIRECTWRITEDC 3 /// Line end types which may be used in addition to LF, CR, and CRLF /// SC_LINE_END_TYPE_UNICODE includes U+2028 Line Separator, @@ -325,7 +347,9 @@ #define wxSTC_MOD_CHANGEANNOTATION 0x20000 #define wxSTC_MOD_CONTAINER 0x40000 #define wxSTC_MOD_LEXERSTATE 0x80000 -#define wxSTC_MODEVENTMASKALL 0xFFFFF +#define wxSTC_MOD_INSERTCHECK 0x100000 +#define wxSTC_MOD_CHANGETABSTOPS 0x200000 +#define wxSTC_MODEVENTMASKALL 0x3FFFFF #define wxSTC_UPDATE_CONTENT 0x1 #define wxSTC_UPDATE_SELECTION 0x2 #define wxSTC_UPDATE_V_SCROLL 0x4 @@ -474,6 +498,12 @@ #define wxSTC_LEX_RUST 111 #define wxSTC_LEX_DMAP 112 #define wxSTC_LEX_AS 113 +#define wxSTC_LEX_DMIS 114 +#define wxSTC_LEX_REGISTRY 115 +#define wxSTC_LEX_BIBTEX 116 +#define wxSTC_LEX_SREC 117 +#define wxSTC_LEX_IHEX 118 +#define wxSTC_LEX_TEHEX 119 /// When a lexer specifies its language as SCLEX_AUTOMATIC it receives a /// value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -524,6 +554,8 @@ #define wxSTC_C_PREPROCESSORCOMMENT 23 #define wxSTC_C_PREPROCESSORCOMMENTDOC 24 #define wxSTC_C_USERLITERAL 25 +#define wxSTC_C_TASKMARKER 26 +#define wxSTC_C_ESCAPESEQUENCE 27 /// Lexical states for SCLEX_D #define wxSTC_D_DEFAULT 0 @@ -1355,6 +1387,11 @@ #define wxSTC_V_IDENTIFIER 11 #define wxSTC_V_STRINGEOL 12 #define wxSTC_V_USER 19 +#define wxSTC_V_COMMENT_WORD 20 +#define wxSTC_V_INPUT 21 +#define wxSTC_V_OUTPUT 22 +#define wxSTC_V_INOUT 23 +#define wxSTC_V_PORT_CONNECT 24 /// Lexical states for SCLEX_KIX #define wxSTC_KIX_DEFAULT 0 @@ -1367,6 +1404,7 @@ #define wxSTC_KIX_KEYWORD 7 #define wxSTC_KIX_FUNCTIONS 8 #define wxSTC_KIX_OPERATOR 9 +#define wxSTC_KIX_COMMENTSTREAM 10 #define wxSTC_KIX_IDENTIFIER 31 /// Lexical states for SCLEX_GUI4CLI @@ -1477,6 +1515,7 @@ #define wxSTC_VHDL_STDPACKAGE 12 #define wxSTC_VHDL_STDTYPE 13 #define wxSTC_VHDL_USERWORD 14 +#define wxSTC_VHDL_BLOCK_COMMENT 15 /// Lexical states for SCLEX_CAML #define wxSTC_CAML_DEFAULT 0 @@ -1598,6 +1637,7 @@ #define wxSTC_SQL_USER3 21 #define wxSTC_SQL_USER4 22 #define wxSTC_SQL_QUOTEDIDENTIFIER 23 +#define wxSTC_SQL_QOPERATOR 24 /// Lexical states for SCLEX_SMALLTALK #define wxSTC_ST_DEFAULT 0 @@ -2243,6 +2283,9 @@ #define wxSTC_RUST_LIFETIME 18 #define wxSTC_RUST_MACRO 19 #define wxSTC_RUST_LEXERROR 20 +#define wxSTC_RUST_BYTESTRING 21 +#define wxSTC_RUST_BYTESTRINGR 22 +#define wxSTC_RUST_BYTECHARACTER 23 /// Lexical states for SCLEX_DMAP #define wxSTC_DMAP_DEFAULT 0 @@ -2257,6 +2300,63 @@ #define wxSTC_DMAP_WORD2 9 #define wxSTC_DMAP_WORD3 10 +/// Lexical states for SCLEX_DMIS +#define wxSTC_DMIS_DEFAULT 0 +#define wxSTC_DMIS_COMMENT 1 +#define wxSTC_DMIS_STRING 2 +#define wxSTC_DMIS_NUMBER 3 +#define wxSTC_DMIS_KEYWORD 4 +#define wxSTC_DMIS_MAJORWORD 5 +#define wxSTC_DMIS_MINORWORD 6 +#define wxSTC_DMIS_UNSUPPORTED_MAJOR 7 +#define wxSTC_DMIS_UNSUPPORTED_MINOR 8 +#define wxSTC_DMIS_LABEL 9 + +/// Lexical states for SCLEX_REGISTRY +#define wxSTC_REG_DEFAULT 0 +#define wxSTC_REG_COMMENT 1 +#define wxSTC_REG_VALUENAME 2 +#define wxSTC_REG_STRING 3 +#define wxSTC_REG_HEXDIGIT 4 +#define wxSTC_REG_VALUETYPE 5 +#define wxSTC_REG_ADDEDKEY 6 +#define wxSTC_REG_DELETEDKEY 7 +#define wxSTC_REG_ESCAPED 8 +#define wxSTC_REG_KEYPATH_GUID 9 +#define wxSTC_REG_STRING_GUID 10 +#define wxSTC_REG_PARAMETER 11 +#define wxSTC_REG_OPERATOR 12 + +/// Lexical state for SCLEX_BIBTEX +#define wxSTC_BIBTEX_DEFAULT 0 +#define wxSTC_BIBTEX_ENTRY 1 +#define wxSTC_BIBTEX_UNKNOWN_ENTRY 2 +#define wxSTC_BIBTEX_KEY 3 +#define wxSTC_BIBTEX_PARAMETER 4 +#define wxSTC_BIBTEX_VALUE 5 +#define wxSTC_BIBTEX_COMMENT 6 + +/// Lexical state for SCLEX_SREC +#define wxSTC_HEX_DEFAULT 0 +#define wxSTC_HEX_RECSTART 1 +#define wxSTC_HEX_RECTYPE 2 +#define wxSTC_HEX_RECTYPE_UNKNOWN 3 +#define wxSTC_HEX_BYTECOUNT 4 +#define wxSTC_HEX_BYTECOUNT_WRONG 5 +#define wxSTC_HEX_NOADDRESS 6 +#define wxSTC_HEX_DATAADDRESS 7 +#define wxSTC_HEX_RECCOUNT 8 +#define wxSTC_HEX_STARTADDRESS 9 +#define wxSTC_HEX_ADDRESSFIELD_UNKNOWN 10 +#define wxSTC_HEX_EXTENDEDADDRESS 11 +#define wxSTC_HEX_DATA_ODD 12 +#define wxSTC_HEX_DATA_EVEN 13 +#define wxSTC_HEX_DATA_UNKNOWN 14 +#define wxSTC_HEX_DATA_EMPTY 15 +#define wxSTC_HEX_CHECKSUM 16 +#define wxSTC_HEX_CHECKSUM_WRONG 17 +#define wxSTC_HEX_GARBAGE 18 + //}}} // Commands that can be bound to keystrokes {{{ @@ -2708,6 +2808,11 @@ public: */ void InsertText(int pos, const wxString& text); + /** + Change the text that is being inserted in response to SC_MOD_INSERTCHECK + */ + void ChangeInsertion(int length, const wxString& text); + /** Delete all text in the document. */ @@ -2836,6 +2941,7 @@ public: /** Retrieve the text of the line containing the caret. Returns the index of the caret on the line. + Result is NUL-terminated. */ wxString GetCurLine(int* linePos=NULL); @@ -2892,11 +2998,36 @@ public: */ int GetTabWidth() const; + /** + Clear explicit tabstops on a line. + */ + void ClearTabStops(int line); + + /** + Add an explicit tab stop for a line. + */ + void AddTabStop(int line, int x); + + /** + Find the next explicit tab stop position on a line after a position. + */ + int GetNextTabStop(int line, int x); + /** Set the code page used to interpret the bytes of the document as characters. */ void SetCodePage(int codePage); + /** + Is the IME displayed in a winow or inline? + */ + int GetIMEInteraction() const; + + /** + Choose to display the the IME in a winow or inline. + */ + void SetIMEInteraction(int imeInteraction); + /** Set the symbol used for a particular marker number, and optionally the fore and background colours. @@ -3289,6 +3420,36 @@ public: */ bool IndicatorGetUnder(int indic) const; + /** + Set a hover indicator to plain, squiggle or TT. + */ + void IndicatorSetHoverStyle(int indic, int style); + + /** + Retrieve the hover style of an indicator. + */ + int IndicatorGetHoverStyle(int indic) const; + + /** + Set the foreground hover colour of an indicator. + */ + void IndicatorSetHoverForeground(int indic, const wxColour& fore); + + /** + Retrieve the foreground hover colour of an indicator. + */ + wxColour IndicatorGetHoverForeground(int indic) const; + + /** + Set the attributes of an indicator. + */ + void IndicatorSetFlags(int indic, int flags); + + /** + Retrieve the attributes of an indicator. + */ + int IndicatorGetFlags(int indic) const; + /** Set the foreground colour of all whitespace and whether to use this setting. */ @@ -3869,6 +4030,16 @@ public: */ int GetTargetEnd() const; + /** + Sets both the start and end of the target in one call. + */ + void SetTargetRange(int start, int end); + + /** + Retrieve the text in the target. + */ + wxString GetTargetText() const; + /** Replace the target text with the argument text. Text is counted so it can contain NULs. @@ -4237,7 +4408,7 @@ public: void AppendText(const wxString& text); /** - Is drawing done in two phases with backgrounds drawn before faoregrounds? + Is drawing done in two phases with backgrounds drawn before foregrounds? */ bool GetTwoPhaseDraw() const; @@ -4247,6 +4418,19 @@ public: */ void SetTwoPhaseDraw(bool twoPhase); + /** + How many phases is drawing done in? + */ + int GetPhasesDraw() const; + + /** + In one phase draw, text is drawn in a series of rectangular blocks with no overlap. + In two phase draw, text is drawn in a series of lines allowing runs to overlap horizontally. + In multiple phase draw, each element is drawn over the whole drawing area, allowing text + to overlap from one line to the next. + */ + void SetPhasesDraw(int phases); + /** Scroll so that a display line is at the top of the display. */ @@ -4264,6 +4448,7 @@ public: /** Retrieve the value of a tag from a regular expression search. + Result is NUL-terminated. */ wxString GetTag(int tagNumber) const; @@ -5073,6 +5258,16 @@ public: */ int AutoCompGetCaseInsensitiveBehaviour() const; + /** + Change the effect of autocompleting when there are multiple selections. + */ + void AutoCompSetMulti(int multi); + + /** + Retrieve the effect of autocompleting when there are multiple selections.. + */ + int AutoCompGetMulti() const; + /** Set the way autocompletion lists are ordered. */ @@ -5228,16 +5423,6 @@ public: */ int GetGapPosition() const; - /** - Always interpret keyboard input as Unicode - */ - void SetKeysUnicode(bool keysUnicode); - - /** - Are keys always interpreted as Unicode? - */ - bool GetKeysUnicode() const; - /** Set the alpha fill colour of the given indicator. */ @@ -5734,6 +5919,7 @@ public: /** Set the way a character is drawn. + Result is NUL-terminated. */ wxString GetRepresentation(const wxString& encodedCharacter) const; @@ -5811,6 +5997,7 @@ public: /** Retrieve a '\n' separated list of properties understood by the current lexer. + Result is NUL-terminated. */ wxString PropertyNames() const; @@ -5821,11 +6008,13 @@ public: /** Describe a property. + Result is NUL-terminated. */ wxString DescribeProperty(const wxString& name) const; /** Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. + Result is NUL-terminated. */ wxString DescribeKeyWordSets() const; @@ -5878,6 +6067,7 @@ public: /** Get the set of base styles that can be extended with sub styles + Result is NUL-terminated. */ wxString GetSubStyleBases() const; diff --git a/src/stc/PlatWX.cpp b/src/stc/PlatWX.cpp index 98cde26a90..dbd2397134 100644 --- a/src/stc/PlatWX.cpp +++ b/src/stc/PlatWX.cpp @@ -1643,10 +1643,11 @@ wxWX2MBbuf wx2stc(const wxString& str) size_t wclen = str.length(); size_t len = UTF8Length(wcstr, wclen); - wxCharBuffer buffer(len+1); - UTF8FromUTF16(wcstr, wclen, buffer.data(), len); - - // TODO check NULL termination!! + // The buffer object adds extra byte for the terminating NUL and we must + // pass the total length, including this NUL, to UTF8FromUTF16() to ensure + // that it NULL-terminates the string. + wxCharBuffer buffer(len); + UTF8FromUTF16(wcstr, wclen, buffer.data(), len + 1); return buffer; } diff --git a/src/stc/ScintillaWX.cpp b/src/stc/ScintillaWX.cpp index a22707ce58..a6c7d01aef 100644 --- a/src/stc/ScintillaWX.cpp +++ b/src/stc/ScintillaWX.cpp @@ -545,7 +545,7 @@ void ScintillaWX::Paste() { } else { - InsertPaste(selStart, buf, len); + InsertPaste(buf, len); } } #endif // wxUSE_DATAOBJ diff --git a/src/stc/ScintillaWX.h b/src/stc/ScintillaWX.h index 54f4bb0217..003cc0696c 100644 --- a/src/stc/ScintillaWX.h +++ b/src/stc/ScintillaWX.h @@ -26,6 +26,7 @@ #include #include #include +#include // These are all Scintilla headers #include "Platform.h" @@ -59,6 +60,9 @@ #include "Document.h" #include "Selection.h" #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" #include "Editor.h" #include "PropSetSimple.h" #include "ScintillaBase.h" @@ -113,38 +117,38 @@ public: ~ScintillaWX(); // base class virtuals - virtual void Initialise(); - virtual void Finalise(); - virtual void StartDrag(); - virtual bool SetIdle(bool on); - 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 Copy(); - virtual void Paste(); - virtual void CopyToClipboard(const SelectionText &selectedText); + virtual void Initialise() wxOVERRIDE; + virtual void Finalise() wxOVERRIDE; + virtual void StartDrag() wxOVERRIDE; + virtual bool SetIdle(bool on) wxOVERRIDE; + virtual void SetTicking(bool on) wxOVERRIDE; + virtual void SetMouseCapture(bool on) wxOVERRIDE; + virtual bool HaveMouseCapture() wxOVERRIDE; + virtual void ScrollText(int linesToMove) wxOVERRIDE; + virtual void SetVerticalScrollPos() wxOVERRIDE; + virtual void SetHorizontalScrollPos() wxOVERRIDE; + virtual bool ModifyScrollBars(int nMax, int nPage) wxOVERRIDE; + virtual void Copy() wxOVERRIDE; + virtual void Paste() wxOVERRIDE; + virtual void CopyToClipboard(const SelectionText &selectedText) wxOVERRIDE; - virtual void CreateCallTipWindow(PRectangle rc); - virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); - virtual void ClaimSelection(); + virtual void CreateCallTipWindow(PRectangle rc) wxOVERRIDE; + virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true) wxOVERRIDE; + virtual void ClaimSelection() wxOVERRIDE; virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, - sptr_t lParam); + sptr_t lParam) wxOVERRIDE; virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, - sptr_t lParam); + sptr_t lParam) wxOVERRIDE; - virtual void NotifyChange(); - virtual void NotifyParent(SCNotification scn); + virtual void NotifyChange() wxOVERRIDE; + virtual void NotifyParent(SCNotification scn) wxOVERRIDE; - virtual void CancelModes(); + virtual void CancelModes() wxOVERRIDE; - virtual void UpdateSystemCaret(); + virtual void UpdateSystemCaret() wxOVERRIDE; // Event delegates void DoPaint(wxDC* dc, wxRect rect); @@ -182,7 +186,7 @@ public: void FullPaint(); void FullPaintDC(wxDC* dc); bool CanPaste(); - bool GetHideSelection() { return hideSelection; } + bool GetHideSelection() { return view.hideSelection; } void DoScrollToLine(int line); void DoScrollToColumn(int column); void ClipChildren(wxDC& dc, PRectangle rect); diff --git a/src/stc/gen_iface.py b/src/stc/gen_iface.py index 78fe754bd2..19b2875fb8 100755 --- a/src/stc/gen_iface.py +++ b/src/stc/gen_iface.py @@ -371,6 +371,12 @@ methodOverrideMap = { 'IndicGetFore' : ('IndicatorGetForeground', 0, 0, 0), 'IndicSetUnder': ('IndicatorSetUnder', 0, 0, 0), 'IndicGetUnder': ('IndicatorGetUnder', 0, 0, 0), + 'IndicSetHoverStyle': ('IndicatorSetHoverStyle', 0, 0, 0), + 'IndicGetHoverStyle': ('IndicatorGetHoverStyle', 0, 0, 0), + 'IndicSetHoverFore': ('IndicatorSetHoverForeground', 0, 0, 0), + 'IndicGetHoverFore': ('IndicatorGetHoverForeground', 0, 0, 0), + 'IndicSetFlags': ('IndicatorSetFlags', 0, 0, 0), + 'IndicGetFlags': ('IndicatorGetFlags', 0, 0, 0), 'SetWhitespaceFore' : ('SetWhitespaceForeground', 0, 0, 0), 'SetWhitespaceBack' : ('SetWhitespaceBackground', 0, 0, 0), @@ -406,6 +412,8 @@ methodOverrideMap = { 'AutoCGetMaxHeight' : ('AutoCompGetMaxHeight', 0, 0, 0), 'AutoCSetCaseInsensitiveBehaviour' : ('AutoCompSetCaseInsensitiveBehaviour', 0, 0, 0), 'AutoCGetCaseInsensitiveBehaviour' : ('AutoCompGetCaseInsensitiveBehaviour', 0, 0, 0), + 'AutoCSetMulti' : ('AutoCompSetMulti', 0, 0, 0), + 'AutoCGetMulti' : ('AutoCompGetMulti', 0, 0, 0), 'AutoCSetOrder' : ('AutoCompSetOrder', 0, 0, 0), 'AutoCGetOrder' : ('AutoCompGetOrder', 0, 0, 0), @@ -586,6 +594,22 @@ methodOverrideMap = { 'GetDirectFunction' : (None, 0, 0, 0), 'GetDirectPointer' : (None, 0, 0, 0), + 'GetTargetText' : + (0, + 'wxString %s() const;', + + '''wxString %s() const { + int startPos = GetTargetStart(); + int endPos = GetTargetEnd(); + wxMemoryBuffer mbuf(endPos-startPos+1); // leave room for the null... + char* buf = (char*)mbuf.GetWriteBuf(endPos-startPos+1); + SendMsg(%s, 0, (sptr_t)buf); + mbuf.UngetWriteBuf(endPos-startPos); + mbuf.AppendByte(0); + return stc2wx(buf);''', + + 0), + 'CallTipPosStart' : ('CallTipPosAtStart', 0, 0, 0), 'CallTipSetPosStart': ('CallTipSetPosAtStart', 0, 0, 0), 'CallTipSetHlt' : ('CallTipSetHighlight', 0, 0, 0), diff --git a/src/stc/scintilla/README.txt b/src/stc/scintilla/README.txt index a4a6618069..9bedc7a813 100644 --- a/src/stc/scintilla/README.txt +++ b/src/stc/scintilla/README.txt @@ -3,7 +3,7 @@ directories from the Scintilla source distribution. All other code needed to implement Scintilla on top of wxWidgets is located in the directory above this one. -The current version of the Scintilla code is 3.4.1 +The current version of the Scintilla code is 3.5.5 These are the basic steps needed to update the version of Scintilla used by wxSTC. diff --git a/src/stc/scintilla/include/Platform.h b/src/stc/scintilla/include/Platform.h index f8150b992d..4ef7e2aab2 100644 --- a/src/stc/scintilla/include/Platform.h +++ b/src/stc/scintilla/include/Platform.h @@ -77,7 +77,9 @@ namespace Scintilla { typedef float XYPOSITION; typedef double XYACCUMULATOR; -//#define XYPOSITION int +inline int RoundXYPosition(XYPOSITION xyPos) { + return int(xyPos + 0.5); +} // Underlying the implementation of the platform classes are platform specific types. // Sometimes these need to be passed around by client code so they are defined here @@ -92,7 +94,7 @@ typedef void *IdlerID; /** * A geometric point class. - * Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably. + * Point is similar to the Win32 POINT and GTK+ GdkPoint types. */ class Point { public: @@ -102,6 +104,10 @@ public: explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) { } + static Point FromInts(int x_, int y_) { + return Point(static_cast(x_), static_cast(y_)); + } + // Other automatically defined methods (assignment, copy constructor, destructor) are fine static Point FromLong(long lpoint); @@ -109,7 +115,7 @@ public: /** * A geometric rectangle class. - * PRectangle is exactly the same as the Win32 RECT so can be used interchangeably. + * PRectangle is similar to the Win32 RECT. * PRectangles contain their top and left sides, but not their right and bottom sides. */ class PRectangle { @@ -119,10 +125,15 @@ public: XYPOSITION right; XYPOSITION bottom; - PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : + explicit PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : left(left_), top(top_), right(right_), bottom(bottom_) { } + static PRectangle FromInts(int left_, int top_, int right_, int bottom_) { + return PRectangle(static_cast(left_), static_cast(top_), + static_cast(right_), static_cast(bottom_)); + } + // Other automatically defined methods (assignment, copy constructor, destructor) are fine bool operator==(PRectangle &rc) const { @@ -133,6 +144,11 @@ public: return (pt.x >= left) && (pt.x <= right) && (pt.y >= top) && (pt.y <= bottom); } + bool ContainsWholePixel(Point pt) const { + // Does the rectangle contain all of the pixel to left/below the point + return (pt.x >= left) && ((pt.x+1) <= right) && + (pt.y >= top) && ((pt.y+1) <= bottom); + } bool Contains(PRectangle rc) const { return (rc.left >= left) && (rc.right <= right) && (rc.top >= top) && (rc.bottom <= bottom); @@ -255,7 +271,6 @@ struct FontParameters { class Font { protected: FontID fid; - // Private so Font objects can not be copied Font(const Font &); Font &operator=(const Font &); @@ -269,7 +284,6 @@ public: FontID GetID() { return fid; } // Alias another font - caller guarantees not to Release void SetID(FontID fid_) { fid = fid_; } - friend class Surface; friend class SurfaceImpl; }; @@ -512,11 +526,6 @@ public: } #endif -// Shut up annoying Visual C++ warnings: -#ifdef _MSC_VER -#pragma warning(disable: 4244 4309 4514 4710) -#endif - #if defined(__GNUC__) && defined(SCINTILLA_QT) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif diff --git a/src/stc/scintilla/include/SciLexer.h b/src/stc/scintilla/include/SciLexer.h index cb4079b8cb..034060a4bb 100644 --- a/src/stc/scintilla/include/SciLexer.h +++ b/src/stc/scintilla/include/SciLexer.h @@ -126,6 +126,12 @@ #define SCLEX_RUST 111 #define SCLEX_DMAP 112 #define SCLEX_AS 113 +#define SCLEX_DMIS 114 +#define SCLEX_REGISTRY 115 +#define SCLEX_BIBTEX 116 +#define SCLEX_SREC 117 +#define SCLEX_IHEX 118 +#define SCLEX_TEHEX 119 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -169,6 +175,8 @@ #define SCE_C_PREPROCESSORCOMMENT 23 #define SCE_C_PREPROCESSORCOMMENTDOC 24 #define SCE_C_USERLITERAL 25 +#define SCE_C_TASKMARKER 26 +#define SCE_C_ESCAPESEQUENCE 27 #define SCE_D_DEFAULT 0 #define SCE_D_COMMENT 1 #define SCE_D_COMMENTLINE 2 @@ -893,6 +901,11 @@ #define SCE_V_IDENTIFIER 11 #define SCE_V_STRINGEOL 12 #define SCE_V_USER 19 +#define SCE_V_COMMENT_WORD 20 +#define SCE_V_INPUT 21 +#define SCE_V_OUTPUT 22 +#define SCE_V_INOUT 23 +#define SCE_V_PORT_CONNECT 24 #define SCE_KIX_DEFAULT 0 #define SCE_KIX_COMMENT 1 #define SCE_KIX_STRING1 2 @@ -903,6 +916,7 @@ #define SCE_KIX_KEYWORD 7 #define SCE_KIX_FUNCTIONS 8 #define SCE_KIX_OPERATOR 9 +#define SCE_KIX_COMMENTSTREAM 10 #define SCE_KIX_IDENTIFIER 31 #define SCE_GC_DEFAULT 0 #define SCE_GC_COMMENTLINE 1 @@ -999,6 +1013,7 @@ #define SCE_VHDL_STDPACKAGE 12 #define SCE_VHDL_STDTYPE 13 #define SCE_VHDL_USERWORD 14 +#define SCE_VHDL_BLOCK_COMMENT 15 #define SCE_CAML_DEFAULT 0 #define SCE_CAML_IDENTIFIER 1 #define SCE_CAML_TAGNAME 2 @@ -1110,6 +1125,7 @@ #define SCE_SQL_USER3 21 #define SCE_SQL_USER4 22 #define SCE_SQL_QUOTEDIDENTIFIER 23 +#define SCE_SQL_QOPERATOR 24 #define SCE_ST_DEFAULT 0 #define SCE_ST_STRING 1 #define SCE_ST_NUMBER 2 @@ -1689,6 +1705,9 @@ #define SCE_RUST_LIFETIME 18 #define SCE_RUST_MACRO 19 #define SCE_RUST_LEXERROR 20 +#define SCE_RUST_BYTESTRING 21 +#define SCE_RUST_BYTESTRINGR 22 +#define SCE_RUST_BYTECHARACTER 23 #define SCE_DMAP_DEFAULT 0 #define SCE_DMAP_COMMENT 1 #define SCE_DMAP_NUMBER 2 @@ -1700,6 +1719,55 @@ #define SCE_DMAP_WORD 8 #define SCE_DMAP_WORD2 9 #define SCE_DMAP_WORD3 10 +#define SCE_DMIS_DEFAULT 0 +#define SCE_DMIS_COMMENT 1 +#define SCE_DMIS_STRING 2 +#define SCE_DMIS_NUMBER 3 +#define SCE_DMIS_KEYWORD 4 +#define SCE_DMIS_MAJORWORD 5 +#define SCE_DMIS_MINORWORD 6 +#define SCE_DMIS_UNSUPPORTED_MAJOR 7 +#define SCE_DMIS_UNSUPPORTED_MINOR 8 +#define SCE_DMIS_LABEL 9 +#define SCE_REG_DEFAULT 0 +#define SCE_REG_COMMENT 1 +#define SCE_REG_VALUENAME 2 +#define SCE_REG_STRING 3 +#define SCE_REG_HEXDIGIT 4 +#define SCE_REG_VALUETYPE 5 +#define SCE_REG_ADDEDKEY 6 +#define SCE_REG_DELETEDKEY 7 +#define SCE_REG_ESCAPED 8 +#define SCE_REG_KEYPATH_GUID 9 +#define SCE_REG_STRING_GUID 10 +#define SCE_REG_PARAMETER 11 +#define SCE_REG_OPERATOR 12 +#define SCE_BIBTEX_DEFAULT 0 +#define SCE_BIBTEX_ENTRY 1 +#define SCE_BIBTEX_UNKNOWN_ENTRY 2 +#define SCE_BIBTEX_KEY 3 +#define SCE_BIBTEX_PARAMETER 4 +#define SCE_BIBTEX_VALUE 5 +#define SCE_BIBTEX_COMMENT 6 +#define SCE_HEX_DEFAULT 0 +#define SCE_HEX_RECSTART 1 +#define SCE_HEX_RECTYPE 2 +#define SCE_HEX_RECTYPE_UNKNOWN 3 +#define SCE_HEX_BYTECOUNT 4 +#define SCE_HEX_BYTECOUNT_WRONG 5 +#define SCE_HEX_NOADDRESS 6 +#define SCE_HEX_DATAADDRESS 7 +#define SCE_HEX_RECCOUNT 8 +#define SCE_HEX_STARTADDRESS 9 +#define SCE_HEX_ADDRESSFIELD_UNKNOWN 10 +#define SCE_HEX_EXTENDEDADDRESS 11 +#define SCE_HEX_DATA_ODD 12 +#define SCE_HEX_DATA_EVEN 13 +#define SCE_HEX_DATA_UNKNOWN 14 +#define SCE_HEX_DATA_EMPTY 15 +#define SCE_HEX_CHECKSUM 16 +#define SCE_HEX_CHECKSUM_WRONG 17 +#define SCE_HEX_GARBAGE 18 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ #endif diff --git a/src/stc/scintilla/include/Scintilla.h b/src/stc/scintilla/include/Scintilla.h index 08acc5453b..22d36d34d9 100644 --- a/src/stc/scintilla/include/Scintilla.h +++ b/src/stc/scintilla/include/Scintilla.h @@ -18,9 +18,9 @@ extern "C" { #if defined(_WIN32) /* Return false on failure: */ int Scintilla_RegisterClasses(void *hInstance); -int Scintilla_ReleaseResources(); +int Scintilla_ReleaseResources(void); #endif -int Scintilla_LinkLexers(); +int Scintilla_LinkLexers(void); #ifdef __cplusplus } @@ -42,17 +42,6 @@ typedef long sptr_t; typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam); -/* Workaround for building with MinGW (not MinGW-w64) in strict ANSI mode which - * is, notably, enabled by -std=c++NN options. */ -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__STRICT_ANSI__) -/* Other headers included by an application using Scintilla might already - * define isascii() too, for the same reasons, try to play nicely with the. */ -#ifndef isascii -inline int isascii(int c) { return !(c & ~0x7F); } -#define isascii isascii -#endif -#endif - /* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ #define INVALID_POSITION -1 #define SCI_START 2000 @@ -61,6 +50,7 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_ADDTEXT 2001 #define SCI_ADDSTYLEDTEXT 2002 #define SCI_INSERTTEXT 2003 +#define SCI_CHANGEINSERTION 2672 #define SCI_CLEARALL 2004 #define SCI_DELETERANGE 2645 #define SCI_CLEARDOCUMENTSTYLE 2005 @@ -102,8 +92,15 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_SETBUFFEREDDRAW 2035 #define SCI_SETTABWIDTH 2036 #define SCI_GETTABWIDTH 2121 +#define SCI_CLEARTABSTOPS 2675 +#define SCI_ADDTABSTOP 2676 +#define SCI_GETNEXTTABSTOP 2677 #define SC_CP_UTF8 65001 #define SCI_SETCODEPAGE 2037 +#define SC_IME_WINDOWED 0 +#define SC_IME_INLINE 1 +#define SCI_GETIMEINTERACTION 2678 +#define SCI_SETIMEINTERACTION 2679 #define MARKER_MAX 31 #define SC_MARK_CIRCLE 0 #define SC_MARK_ROUNDRECT 1 @@ -277,7 +274,12 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define INDIC_DOTBOX 12 #define INDIC_SQUIGGLEPIXMAP 13 #define INDIC_COMPOSITIONTHICK 14 -#define INDIC_MAX 31 +#define INDIC_COMPOSITIONTHIN 15 +#define INDIC_FULLBOX 16 +#define INDIC_TEXTFORE 17 +#define INDIC_IME 32 +#define INDIC_IME_MAX 35 +#define INDIC_MAX 35 #define INDIC_CONTAINER 8 #define INDIC0_MASK 0x20 #define INDIC1_MASK 0x40 @@ -289,6 +291,15 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_INDICGETFORE 2083 #define SCI_INDICSETUNDER 2510 #define SCI_INDICGETUNDER 2511 +#define SCI_INDICSETHOVERSTYLE 2680 +#define SCI_INDICGETHOVERSTYLE 2681 +#define SCI_INDICSETHOVERFORE 2682 +#define SCI_INDICGETHOVERFORE 2683 +#define SC_INDICVALUEBIT 0x1000000 +#define SC_INDICVALUEMASK 0xFFFFFF +#define SC_INDICFLAG_VALUEFORE 1 +#define SCI_INDICSETFLAGS 2684 +#define SCI_INDICGETFLAGS 2685 #define SCI_SETWHITESPACEFORE 2084 #define SCI_SETWHITESPACEBACK 2085 #define SCI_SETWHITESPACESIZE 2086 @@ -375,6 +386,7 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCFIND_WORDSTART 0x00100000 #define SCFIND_REGEXP 0x00200000 #define SCFIND_POSIX 0x00400000 +#define SCFIND_CXX11REGEX 0x00800000 #define SCI_FINDTEXT 2150 #define SCI_FORMATRANGE 2151 #define SCI_GETFIRSTVISIBLELINE 2152 @@ -420,6 +432,8 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_GETTARGETSTART 2191 #define SCI_SETTARGETEND 2192 #define SCI_GETTARGETEND 2193 +#define SCI_SETTARGETRANGE 2686 +#define SCI_GETTARGETTEXT 2687 #define SCI_REPLACETARGET 2194 #define SCI_REPLACETARGETRE 2195 #define SCI_SEARCHINTARGET 2197 @@ -472,6 +486,7 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008 #define SC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010 #define SC_FOLDFLAG_LEVELNUMBERS 0x0040 +#define SC_FOLDFLAG_LINESTATE 0x0080 #define SCI_SETFOLDFLAGS 2233 #define SCI_ENSUREVISIBLEENFORCEPOLICY 2234 #define SCI_SETTABINDENTS 2260 @@ -526,6 +541,11 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_APPENDTEXT 2282 #define SCI_GETTWOPHASEDRAW 2283 #define SCI_SETTWOPHASEDRAW 2284 +#define SC_PHASES_ONE 0 +#define SC_PHASES_TWO 1 +#define SC_PHASES_MULTIPLE 2 +#define SCI_GETPHASESDRAW 2673 +#define SCI_SETPHASESDRAW 2674 #define SC_EFF_QUALITY_MASK 0xF #define SC_EFF_QUALITY_DEFAULT 0 #define SC_EFF_QUALITY_NON_ANTIALIASED 1 @@ -640,6 +660,8 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SC_STATUS_OK 0 #define SC_STATUS_FAILURE 1 #define SC_STATUS_BADALLOC 2 +#define SC_STATUS_WARN_START 1000 +#define SC_STATUS_WARN_REGEX 1001 #define SCI_SETSTATUS 2382 #define SCI_GETSTATUS 2383 #define SCI_SETMOUSEDOWNCAPTURES 2384 @@ -726,6 +748,10 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1 #define SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR 2634 #define SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR 2635 +#define SC_MULTIAUTOC_ONCE 0 +#define SC_MULTIAUTOC_EACH 1 +#define SCI_AUTOCSETMULTI 2636 +#define SCI_AUTOCGETMULTI 2637 #define SC_ORDER_PRESORTED 0 #define SC_ORDER_PERFORMSORT 1 #define SC_ORDER_CUSTOM 2 @@ -771,8 +797,6 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_GETCHARACTERPOINTER 2520 #define SCI_GETRANGEPOINTER 2643 #define SCI_GETGAPPOSITION 2644 -#define SCI_SETKEYSUNICODE 2521 -#define SCI_GETKEYSUNICODE 2522 #define SCI_INDICSETALPHA 2523 #define SCI_INDICGETALPHA 2524 #define SCI_INDICSETOUTLINEALPHA 2558 @@ -806,6 +830,7 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define ANNOTATION_HIDDEN 0 #define ANNOTATION_STANDARD 1 #define ANNOTATION_BOXED 2 +#define ANNOTATION_INDENTED 3 #define SCI_ANNOTATIONSETVISIBLE 2548 #define SCI_ANNOTATIONGETVISIBLE 2549 #define SCI_ANNOTATIONSETSTYLEOFFSET 2550 @@ -885,6 +910,8 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_SCROLLTOEND 2629 #define SC_TECHNOLOGY_DEFAULT 0 #define SC_TECHNOLOGY_DIRECTWRITE 1 +#define SC_TECHNOLOGY_DIRECTWRITERETAIN 2 +#define SC_TECHNOLOGY_DIRECTWRITEDC 3 #define SCI_SETTECHNOLOGY 2630 #define SCI_GETTECHNOLOGY 2631 #define SCI_CREATELOADER 2632 @@ -956,7 +983,9 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SC_MOD_CHANGEANNOTATION 0x20000 #define SC_MOD_CONTAINER 0x40000 #define SC_MOD_LEXERSTATE 0x80000 -#define SC_MODEVENTMASKALL 0xFFFFF +#define SC_MOD_INSERTCHECK 0x100000 +#define SC_MOD_CHANGETABSTOPS 0x200000 +#define SC_MODEVENTMASKALL 0x3FFFFF #define SC_UPDATE_CONTENT 0x1 #define SC_UPDATE_SELECTION 0x2 #define SC_UPDATE_V_SCROLL 0x4 @@ -1025,7 +1054,7 @@ inline int isascii(int c) { return !(c & ~0x7F); } * CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs. * So older code that treats Scintilla as a RichEdit will work. */ -#ifdef SCI_NAMESPACE +#if defined(__cplusplus) && defined(SCI_NAMESPACE) namespace Scintilla { #endif @@ -1117,7 +1146,7 @@ struct SCNotification { int updated; /* SCN_UPDATEUI */ }; -#ifdef SCI_NAMESPACE +#if defined(__cplusplus) && defined(SCI_NAMESPACE) } #endif @@ -1126,6 +1155,8 @@ struct SCNotification { #define SC_CP_DBCS 1 #define SCI_SETUSEPALETTE 2039 #define SCI_GETUSEPALETTE 2139 +#define SCI_SETKEYSUNICODE 2521 +#define SCI_GETKEYSUNICODE 2522 #endif diff --git a/src/stc/scintilla/include/Scintilla.iface b/src/stc/scintilla/include/Scintilla.iface index 7040b63a91..6432d37aa8 100644 --- a/src/stc/scintilla/include/Scintilla.iface +++ b/src/stc/scintilla/include/Scintilla.iface @@ -72,11 +72,11 @@ ## Line numbers and positions start at 0. ## String arguments may contain NUL ('\0') characters where the calls provide a length -## argument and retrieve NUL characters. All retrieved strings except for those retrieved -## by GetLine also have a NUL appended but client code should calculate the size that -## will be returned rather than relying upon the NUL whenever possible. Allow for the -## extra NUL character when allocating buffers. The size to allocate for a stringresult -## can be determined by calling with a NULL (0) pointer. +## argument and retrieve NUL characters. APIs marked as NUL-terminated also have a +## NUL appended but client code should calculate the size that will be returned rather +## than relying upon the NUL whenever possible. Allow for the extra NUL character when +## allocating buffers. The size to allocate for a stringresult (not including NUL) can be +## determined by calling with a NULL (0) pointer. cat Basics @@ -98,6 +98,9 @@ fun void AddStyledText=2002(int length, cells c) # Insert string at a position. fun void InsertText=2003(position pos, string text) +# Change the text that is being inserted in response to SC_MOD_INSERTCHECK +fun void ChangeInsertion=2672(int length, string text) + # Delete all text in the document. fun void ClearAll=2004(,) @@ -183,6 +186,7 @@ set void SetAnchor=2026(position posAnchor,) # Retrieve the text of the line containing the caret. # Returns the index of the caret on the line. +# Result is NUL-terminated. fun int GetCurLine=2027(int length, stringresult text) # Retrieve the position of the last correctly styled character. @@ -223,6 +227,15 @@ set void SetTabWidth=2036(int tabWidth,) # Retrieve the visible size of a tab. get int GetTabWidth=2121(,) +# Clear explicit tabstops on a line. +fun void ClearTabStops=2675(int line,) + +# Add an explicit tab stop for a line. +fun void AddTabStop=2676(int line, int x) + +# Find the next explicit tab stop position on a line after a position. +fun int GetNextTabStop=2677(int line, int x) + # The SC_CP_UTF8 value can be used to enter Unicode mode. # This is the same value as CP_UTF8 in Windows val SC_CP_UTF8=65001 @@ -231,6 +244,16 @@ val SC_CP_UTF8=65001 # The SC_CP_UTF8 value can be used to enter Unicode mode. set void SetCodePage=2037(int codePage,) +enu IMEInteraction=SC_IME_ +val SC_IME_WINDOWED=0 +val SC_IME_INLINE=1 + +# Is the IME displayed in a winow or inline? +get int GetIMEInteraction=2678(,) + +# Choose to display the the IME in a winow or inline. +set void SetIMEInteraction=2679(int imeInteraction,) + enu MarkerSymbol=SC_MARK_ val MARKER_MAX=31 val SC_MARK_CIRCLE=0 @@ -457,6 +480,7 @@ get int StyleGetSize=2485(int style,) # Get the font of a style. # Returns the length of the fontName +# Result is NUL-terminated. get int StyleGetFont=2486(int style, stringresult fontName) # Get is a style to have its end of line filled or not. @@ -556,7 +580,7 @@ set void SetCaretPeriod=2076(int periodMilliseconds,) set void SetWordChars=2077(, string characters) # Get the set of characters making up words for when moving or selecting by word. -# Retuns the number of characters +# Returns the number of characters get int GetWordChars=2646(, stringresult characters) # Start a sequence of actions that is undone and redone as a unit. @@ -583,7 +607,12 @@ val INDIC_SQUIGGLELOW=11 val INDIC_DOTBOX=12 val INDIC_SQUIGGLEPIXMAP=13 val INDIC_COMPOSITIONTHICK=14 -val INDIC_MAX=31 +val INDIC_COMPOSITIONTHIN=15 +val INDIC_FULLBOX=16 +val INDIC_TEXTFORE=17 +val INDIC_IME=32 +val INDIC_IME_MAX=35 +val INDIC_MAX=35 val INDIC_CONTAINER=8 val INDIC0_MASK=0x20 val INDIC1_MASK=0x40 @@ -608,6 +637,30 @@ set void IndicSetUnder=2510(int indic, bool under) # Retrieve whether indicator drawn under or over text. get bool IndicGetUnder=2511(int indic,) +# Set a hover indicator to plain, squiggle or TT. +set void IndicSetHoverStyle=2680(int indic, int style) + +# Retrieve the hover style of an indicator. +get int IndicGetHoverStyle=2681(int indic,) + +# Set the foreground hover colour of an indicator. +set void IndicSetHoverFore=2682(int indic, colour fore) + +# Retrieve the foreground hover colour of an indicator. +get colour IndicGetHoverFore=2683(int indic,) + +val SC_INDICVALUEBIT=0x1000000 +val SC_INDICVALUEMASK=0xFFFFFF + +enu IndicFlag=SC_INDICFLAG_ +val SC_INDICFLAG_VALUEFORE=1 + +# Set the attributes of an indicator. +set void IndicSetFlags=2684(int indic, int flags) + +# Retrieve the attributes of an indicator. +get int IndicGetFlags=2685(int indic,) + # Set the foreground colour of all whitespace and whether to use this setting. fun void SetWhitespaceFore=2084(bool useSetting, colour fore) @@ -862,6 +915,7 @@ val SCFIND_MATCHCASE=0x4 val SCFIND_WORDSTART=0x00100000 val SCFIND_REGEXP=0x00200000 val SCFIND_POSIX=0x00400000 +val SCFIND_CXX11REGEX=0x00800000 # Find some text in the document. fun position FindText=2150(int flags, findtext ft) @@ -899,6 +953,7 @@ fun void SetSel=2160(position start, position end) # Retrieve the selected text. # Return the length of the text. +# Result is NUL-terminated. fun int GetSelText=2161(, stringresult text) # Retrieve a range of text. @@ -969,6 +1024,7 @@ fun void SetText=2181(, string text) # Retrieve all the text in the document. # Returns number of characters retrieved. +# Result is NUL-terminated. fun int GetText=2182(int length, stringresult text) # Retrieve the number of characters in the document. @@ -1007,6 +1063,12 @@ set void SetTargetEnd=2192(position pos,) # Get the position that ends the target. get position GetTargetEnd=2193(,) +# Sets both the start and end of the target in one call. +fun void SetTargetRange=2686(position start, position end) + +# Retrieve the text in the target. +get int GetTargetText=2687(, stringresult characters) + # Replace the target text with the argument text. # Text is counted so it can contain NULs. # Returns the length of the replacement text. @@ -1151,6 +1213,7 @@ val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004 val SC_FOLDFLAG_LINEAFTER_EXPANDED=0x0008 val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010 val SC_FOLDFLAG_LEVELNUMBERS=0x0040 +val SC_FOLDFLAG_LINESTATE=0x0080 # Set some style options for folding. set void SetFoldFlags=2233(int flags,) @@ -1287,13 +1350,27 @@ get bool GetVScrollBar=2281(,) # Append a string to the end of the document without changing the selection. fun void AppendText=2282(int length, string text) -# Is drawing done in two phases with backgrounds drawn before faoregrounds? +# Is drawing done in two phases with backgrounds drawn before foregrounds? get bool GetTwoPhaseDraw=2283(,) # In twoPhaseDraw mode, drawing is performed in two phases, first the background # and then the foreground. This avoids chopping off characters that overlap the next run. set void SetTwoPhaseDraw=2284(bool twoPhase,) +enu FontQuality=SC_PHASES_ +val SC_PHASES_ONE=0 +val SC_PHASES_TWO=1 +val SC_PHASES_MULTIPLE=2 + +# How many phases is drawing done in? +get int GetPhasesDraw=2673(,) + +# In one phase draw, text is drawn in a series of rectangular blocks with no overlap. +# In two phase draw, text is drawn in a series of lines allowing runs to overlap horizontally. +# In multiple phase draw, each element is drawn over the whole drawing area, allowing text +# to overlap from one line to the next. +set void SetPhasesDraw=2674(int phases,) + # Control font anti-aliasing. enu FontQuality=SC_EFF_ @@ -1323,6 +1400,7 @@ set void SetMultiPaste=2614(int multiPaste,) get int GetMultiPaste=2615(,) # Retrieve the value of a tag from a regular expression search. +# Result is NUL-terminated. get int GetTag=2616(int tagNumber, stringresult tagValue) # Make the target range start and end be the same as the selection range start and end. @@ -1624,6 +1702,8 @@ enu Status=SC_STATUS_ val SC_STATUS_OK=0 val SC_STATUS_FAILURE=1 val SC_STATUS_BADALLOC=2 +val SC_STATUS_WARN_START=1000 +val SC_STATUS_WARN_REGEX=1001 # Change error status - 0 = OK. set void SetStatus=2382(int statusCode,) @@ -1868,6 +1948,7 @@ get int AutoCGetCurrent=2445(,) # Get currently selected item text in the auto-completion list # Returns the length of the item text +# Result is NUL-terminated. get int AutoCGetCurrentText=2610(, stringresult s) enu CaseInsensitiveBehaviour=SC_CASEINSENSITIVEBEHAVIOUR_ @@ -1880,6 +1961,16 @@ set void AutoCSetCaseInsensitiveBehaviour=2634(int behaviour,) # Get auto-completion case insensitive behaviour. get int AutoCGetCaseInsensitiveBehaviour=2635(,) +enu MultiAutoComplete=SC_MULTIAUTOC_ +val SC_MULTIAUTOC_ONCE=0 +val SC_MULTIAUTOC_EACH=1 + +# Change the effect of autocompleting when there are multiple selections. +set void AutoCSetMulti=2636(int multi,) + +# Retrieve the effect of autocompleting when there are multiple selections.. +get int AutoCGetMulti=2637(,) + enu Ordering=SC_ORDER_ val SC_ORDER_PRESORTED=0 val SC_ORDER_PERFORMSORT=1 @@ -2007,12 +2098,6 @@ get int GetRangePointer=2643(int position, int rangeLength) # the range of a call to GetRangePointer. get position GetGapPosition=2644(,) -# Always interpret keyboard input as Unicode -set void SetKeysUnicode=2521(bool keysUnicode,) - -# Are keys always interpreted as Unicode? -get bool GetKeysUnicode=2522(,) - # Set the alpha fill colour of the given indicator. set void IndicSetAlpha=2523(int indicator, int alpha) @@ -2105,6 +2190,7 @@ enu AnnotationVisible=ANNOTATION_ val ANNOTATION_HIDDEN=0 val ANNOTATION_STANDARD=1 val ANNOTATION_BOXED=2 +val ANNOTATION_INDENTED=3 # Set the visibility for the annotations for a view set void AnnotationSetVisible=2548(int visible,) @@ -2312,6 +2398,8 @@ fun void ScrollToEnd=2629(,) val SC_TECHNOLOGY_DEFAULT=0 val SC_TECHNOLOGY_DIRECTWRITE=1 +val SC_TECHNOLOGY_DIRECTWRITERETAIN=2 +val SC_TECHNOLOGY_DIRECTWRITEDC=3 # Set the technology used. set void SetTechnology=2630(int technology,) @@ -2364,6 +2452,7 @@ get int GetLineEndTypesActive=2658(,) set void SetRepresentation=2665(string encodedCharacter, string representation) # Set the way a character is drawn. +# Result is NUL-terminated. get int GetRepresentation=2666(string encodedCharacter, stringresult representation) # Remove a character representation. @@ -2400,10 +2489,12 @@ set void SetLexerLanguage=4006(, string language) fun void LoadLexerLibrary=4007(, string path) # Retrieve a "property" value previously set with SetProperty. +# Result is NUL-terminated. get int GetProperty=4008(string key, stringresult buf) # Retrieve a "property" value previously set with SetProperty, # with "$()" variable replacement on returned buffer. +# Result is NUL-terminated. get int GetPropertyExpanded=4009(string key, stringresult buf) # Retrieve a "property" value previously set with SetProperty, @@ -2415,12 +2506,14 @@ get int GetStyleBitsNeeded=4011(,) # Retrieve the name of the lexer. # Return the length of the text. +# Result is NUL-terminated. get int GetLexerLanguage=4012(, stringresult text) # For private communication between an application and a known lexer. fun int PrivateLexerCall=4013(int operation, int pointer) # Retrieve a '\n' separated list of properties understood by the current lexer. +# Result is NUL-terminated. fun int PropertyNames=4014(, stringresult names) enu TypeProperty=SC_TYPE_ @@ -2432,9 +2525,11 @@ val SC_TYPE_STRING=2 fun int PropertyType=4015(string name,) # Describe a property. +# Result is NUL-terminated. fun int DescribeProperty=4016(string name, stringresult description) # Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. +# Result is NUL-terminated. fun int DescribeKeyWordSets=4017(, stringresult descriptions) # Bit set of LineEndType enumertion for which line ends beyond the standard @@ -2467,6 +2562,7 @@ set void SetIdentifiers=4024(int style, string identifiers) get int DistanceToSecondaryStyles=4025(,) # Get the set of base styles that can be extended with sub styles +# Result is NUL-terminated. get int GetSubStyleBases=4026(, stringresult styles) # Notifications @@ -2494,7 +2590,9 @@ val SC_MOD_CHANGEMARGIN=0x10000 val SC_MOD_CHANGEANNOTATION=0x20000 val SC_MOD_CONTAINER=0x40000 val SC_MOD_LEXERSTATE=0x80000 -val SC_MODEVENTMASKALL=0xFFFFF +val SC_MOD_INSERTCHECK=0x100000 +val SC_MOD_CHANGETABSTOPS=0x200000 +val SC_MODEVENTMASKALL=0x3FFFFF enu Update=SC_UPDATE_ val SC_UPDATE_CONTENT=0x1 @@ -2659,6 +2757,12 @@ val SCLEX_KVIRC=110 val SCLEX_RUST=111 val SCLEX_DMAP=112 val SCLEX_AS=113 +val SCLEX_DMIS=114 +val SCLEX_REGISTRY=115 +val SCLEX_BIBTEX=116 +val SCLEX_SREC=117 +val SCLEX_IHEX=118 +val SCLEX_TEHEX=119 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -2711,6 +2815,8 @@ val SCE_C_HASHQUOTEDSTRING=22 val SCE_C_PREPROCESSORCOMMENT=23 val SCE_C_PREPROCESSORCOMMENTDOC=24 val SCE_C_USERLITERAL=25 +val SCE_C_TASKMARKER=26 +val SCE_C_ESCAPESEQUENCE=27 # Lexical states for SCLEX_D lex D=SCLEX_D SCE_D_ val SCE_D_DEFAULT=0 @@ -3537,6 +3643,11 @@ val SCE_V_OPERATOR=10 val SCE_V_IDENTIFIER=11 val SCE_V_STRINGEOL=12 val SCE_V_USER=19 +val SCE_V_COMMENT_WORD=20 +val SCE_V_INPUT=21 +val SCE_V_OUTPUT=22 +val SCE_V_INOUT=23 +val SCE_V_PORT_CONNECT=24 # Lexical states for SCLEX_KIX lex Kix=SCLEX_KIX SCE_KIX_ val SCE_KIX_DEFAULT=0 @@ -3549,6 +3660,7 @@ val SCE_KIX_MACRO=6 val SCE_KIX_KEYWORD=7 val SCE_KIX_FUNCTIONS=8 val SCE_KIX_OPERATOR=9 +val SCE_KIX_COMMENTSTREAM=10 val SCE_KIX_IDENTIFIER=31 # Lexical states for SCLEX_GUI4CLI lex Gui4Cli=SCLEX_GUI4CLI SCE_GC_ @@ -3659,6 +3771,7 @@ val SCE_VHDL_STDFUNCTION=11 val SCE_VHDL_STDPACKAGE=12 val SCE_VHDL_STDTYPE=13 val SCE_VHDL_USERWORD=14 +val SCE_VHDL_BLOCK_COMMENT=15 # Lexical states for SCLEX_CAML lex Caml=SCLEX_CAML SCE_CAML_ val SCE_CAML_DEFAULT=0 @@ -3780,6 +3893,7 @@ val SCE_SQL_USER2=20 val SCE_SQL_USER3=21 val SCE_SQL_USER4=22 val SCE_SQL_QUOTEDIDENTIFIER=23 +val SCE_SQL_QOPERATOR=24 # Lexical states for SCLEX_SMALLTALK lex Smalltalk=SCLEX_SMALLTALK SCE_ST_ val SCE_ST_DEFAULT=0 @@ -4425,6 +4539,9 @@ val SCE_RUST_IDENTIFIER=17 val SCE_RUST_LIFETIME=18 val SCE_RUST_MACRO=19 val SCE_RUST_LEXERROR=20 +val SCE_RUST_BYTESTRING=21 +val SCE_RUST_BYTESTRINGR=22 +val SCE_RUST_BYTECHARACTER=23 # Lexical states for SCLEX_DMAP lex DMAP=SCLEX_DMAP SCE_DMAP_ val SCE_DMAP_DEFAULT=0 @@ -4438,6 +4555,67 @@ val SCE_DMAP_IDENTIFIER=7 val SCE_DMAP_WORD=8 val SCE_DMAP_WORD2=9 val SCE_DMAP_WORD3=10 +# Lexical states for SCLEX_DMIS +lex DMIS=SCLEX_DMIS SCE_DMIS_ +val SCE_DMIS_DEFAULT=0 +val SCE_DMIS_COMMENT=1 +val SCE_DMIS_STRING=2 +val SCE_DMIS_NUMBER=3 +val SCE_DMIS_KEYWORD=4 +val SCE_DMIS_MAJORWORD=5 +val SCE_DMIS_MINORWORD=6 +val SCE_DMIS_UNSUPPORTED_MAJOR=7 +val SCE_DMIS_UNSUPPORTED_MINOR=8 +val SCE_DMIS_LABEL=9 +# Lexical states for SCLEX_REGISTRY +lex REG=SCLEX_REGISTRY SCE_REG_ +val SCE_REG_DEFAULT=0 +val SCE_REG_COMMENT=1 +val SCE_REG_VALUENAME=2 +val SCE_REG_STRING=3 +val SCE_REG_HEXDIGIT=4 +val SCE_REG_VALUETYPE=5 +val SCE_REG_ADDEDKEY=6 +val SCE_REG_DELETEDKEY=7 +val SCE_REG_ESCAPED=8 +val SCE_REG_KEYPATH_GUID=9 +val SCE_REG_STRING_GUID=10 +val SCE_REG_PARAMETER=11 +val SCE_REG_OPERATOR=12 +# Lexical state for SCLEX_BIBTEX +lex BibTeX=SCLEX_BIBTEX SCE_BIBTEX_ +val SCE_BIBTEX_DEFAULT=0 +val SCE_BIBTEX_ENTRY=1 +val SCE_BIBTEX_UNKNOWN_ENTRY=2 +val SCE_BIBTEX_KEY=3 +val SCE_BIBTEX_PARAMETER=4 +val SCE_BIBTEX_VALUE=5 +val SCE_BIBTEX_COMMENT=6 +# Lexical state for SCLEX_SREC +lex Srec=SCLEX_SREC SCE_HEX_ +val SCE_HEX_DEFAULT=0 +val SCE_HEX_RECSTART=1 +val SCE_HEX_RECTYPE=2 +val SCE_HEX_RECTYPE_UNKNOWN=3 +val SCE_HEX_BYTECOUNT=4 +val SCE_HEX_BYTECOUNT_WRONG=5 +val SCE_HEX_NOADDRESS=6 +val SCE_HEX_DATAADDRESS=7 +val SCE_HEX_RECCOUNT=8 +val SCE_HEX_STARTADDRESS=9 +val SCE_HEX_ADDRESSFIELD_UNKNOWN=10 +val SCE_HEX_EXTENDEDADDRESS=11 +val SCE_HEX_DATA_ODD=12 +val SCE_HEX_DATA_EVEN=13 +val SCE_HEX_DATA_UNKNOWN=14 +val SCE_HEX_DATA_EMPTY=15 +val SCE_HEX_CHECKSUM=16 +val SCE_HEX_CHECKSUM_WRONG=17 +val SCE_HEX_GARBAGE=18 +# Lexical state for SCLEX_IHEX (shared with Srec) +lex IHex=SCLEX_IHEX SCE_HEX_ +# Lexical state for SCLEX_TEHEX (shared with Srec) +lex TEHex=SCLEX_TEHEX SCE_HEX_ # Events @@ -4490,3 +4668,11 @@ get bool GetUsePalette=2139(,) # In palette mode, Scintilla uses the environment's palette calls to display # more colours. This may lead to ugly displays. set void SetUsePalette=2039(bool usePalette,) + +# Deprecated in 3.5.5 + +# Always interpret keyboard input as Unicode +set void SetKeysUnicode=2521(bool keysUnicode,) + +# Are keys always interpreted as Unicode? +get bool GetKeysUnicode=2522(,) diff --git a/src/stc/scintilla/lexers/LexA68k.cxx b/src/stc/scintilla/lexers/LexA68k.cxx index 6ab03bf0fa..0b600195a7 100644 --- a/src/stc/scintilla/lexers/LexA68k.cxx +++ b/src/stc/scintilla/lexers/LexA68k.cxx @@ -117,20 +117,20 @@ static inline bool IsDoxygenChar (const int ch) static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - // Used to buffer a string, to be able to compare it using built-in functions - char Buffer[100]; - - - // Used to know the length of an operator - int OpType; - + // Used to buffer a string, to be able to compare it using built-in functions + char Buffer[100]; + + + // Used to know the length of an operator + int OpType; + // Get references to keywords lists WordList &cpuInstruction = *keywordlists[0]; WordList ®isters = *keywordlists[1]; WordList &directive = *keywordlists[2]; WordList &extInstruction = *keywordlists[3]; - WordList &alert = *keywordlists[4]; + WordList &alert = *keywordlists[4]; WordList &doxygenKeyword = *keywordlists[5]; @@ -140,109 +140,109 @@ static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, /************************************************************ * - * Parse the source + * Parse the source * ************************************************************/ for ( ; sc.More(); sc.Forward()) { - /************************************************************ - * - * A style always terminates at the end of a line, even for - * comments (no multi-lines comments) - * - ************************************************************/ - if (sc.atLineStart) { + /************************************************************ + * + * A style always terminates at the end of a line, even for + * comments (no multi-lines comments) + * + ************************************************************/ + if (sc.atLineStart) { sc.SetState(SCE_A68K_DEFAULT); - } + } /************************************************************ * - * If we are not in "default style", check if the style continues - * In this case, we just have to loop + * If we are not in "default style", check if the style continues + * In this case, we just have to loop * ************************************************************/ if (sc.state != SCE_A68K_DEFAULT) { - if ( ((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch)) // Decimal number + if ( ((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch)) // Decimal number || ((sc.state == SCE_A68K_NUMBER_BIN) && IsBin(sc.ch)) // Binary number || ((sc.state == SCE_A68K_NUMBER_HEX) && isxdigit(sc.ch)) // Hexa number - || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Macro argument + || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Macro argument || ((sc.state == SCE_A68K_STRING1) && (sc.ch != '\'')) // String single-quoted || ((sc.state == SCE_A68K_STRING2) && (sc.ch != '\"')) // String double-quoted - || ((sc.state == SCE_A68K_MACRO_DECLARATION) && IsIdentifierChar(sc.ch)) // Macro declaration (or global label, we don't know at this point) - || ((sc.state == SCE_A68K_IDENTIFIER) && IsIdentifierChar(sc.ch)) // Identifier - || ((sc.state == SCE_A68K_LABEL) && IsIdentifierChar(sc.ch)) // Label (local) - || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && IsDoxygenChar(sc.ch)) // Doxygen keyword - || ((sc.state == SCE_A68K_COMMENT_SPECIAL) && isalpha(sc.ch)) // Alert - || ((sc.state == SCE_A68K_COMMENT) && !isalpha(sc.ch) && (sc.ch != '\\'))) // Normal comment + || ((sc.state == SCE_A68K_MACRO_DECLARATION) && IsIdentifierChar(sc.ch)) // Macro declaration (or global label, we don't know at this point) + || ((sc.state == SCE_A68K_IDENTIFIER) && IsIdentifierChar(sc.ch)) // Identifier + || ((sc.state == SCE_A68K_LABEL) && IsIdentifierChar(sc.ch)) // Label (local) + || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && IsDoxygenChar(sc.ch)) // Doxygen keyword + || ((sc.state == SCE_A68K_COMMENT_SPECIAL) && isalpha(sc.ch)) // Alert + || ((sc.state == SCE_A68K_COMMENT) && !isalpha(sc.ch) && (sc.ch != '\\'))) // Normal comment { continue; } - /************************************************************ - * - * Check if current state terminates - * - ************************************************************/ + /************************************************************ + * + * Check if current state terminates + * + ************************************************************/ - // Strings: include terminal ' or " in the current string by skipping it - if ((sc.state == SCE_A68K_STRING1) || (sc.state == SCE_A68K_STRING2)) { - sc.Forward(); + // Strings: include terminal ' or " in the current string by skipping it + if ((sc.state == SCE_A68K_STRING1) || (sc.state == SCE_A68K_STRING2)) { + sc.Forward(); } - - - // If a macro declaration was terminated with ':', it was a label - else if ((sc.state == SCE_A68K_MACRO_DECLARATION) && (sc.chPrev == ':')) { - sc.ChangeState(SCE_A68K_LABEL); + + + // If a macro declaration was terminated with ':', it was a label + else if ((sc.state == SCE_A68K_MACRO_DECLARATION) && (sc.chPrev == ':')) { + sc.ChangeState(SCE_A68K_LABEL); } - - // If it wasn't a Doxygen keyword, change it to normal comment - else if (sc.state == SCE_A68K_COMMENT_DOXYGEN) { + + // If it wasn't a Doxygen keyword, change it to normal comment + else if (sc.state == SCE_A68K_COMMENT_DOXYGEN) { sc.GetCurrent(Buffer, sizeof(Buffer)); - if (!doxygenKeyword.InList(Buffer)) { + if (!doxygenKeyword.InList(Buffer)) { sc.ChangeState(SCE_A68K_COMMENT); } sc.SetState(SCE_A68K_COMMENT); continue; } - - // If it wasn't an Alert, change it to normal comment - else if (sc.state == SCE_A68K_COMMENT_SPECIAL) { - sc.GetCurrent(Buffer, sizeof(Buffer)); - if (!alert.InList(Buffer)) { + + // If it wasn't an Alert, change it to normal comment + else if (sc.state == SCE_A68K_COMMENT_SPECIAL) { + sc.GetCurrent(Buffer, sizeof(Buffer)); + if (!alert.InList(Buffer)) { sc.ChangeState(SCE_A68K_COMMENT); } - // Reset style to normal comment, or to Doxygen keyword if it begins with '\' - if (sc.ch == '\\') { - sc.SetState(SCE_A68K_COMMENT_DOXYGEN); - } - else { + // Reset style to normal comment, or to Doxygen keyword if it begins with '\' + if (sc.ch == '\\') { + sc.SetState(SCE_A68K_COMMENT_DOXYGEN); + } + else { sc.SetState(SCE_A68K_COMMENT); - } + } continue; } - - // If we are in a comment, it's a Doxygen keyword or an Alert - else if (sc.state == SCE_A68K_COMMENT) { - if (sc.ch == '\\') { - sc.SetState(SCE_A68K_COMMENT_DOXYGEN); - } - else { - sc.SetState(SCE_A68K_COMMENT_SPECIAL); - } - continue; + + // If we are in a comment, it's a Doxygen keyword or an Alert + else if (sc.state == SCE_A68K_COMMENT) { + if (sc.ch == '\\') { + sc.SetState(SCE_A68K_COMMENT_DOXYGEN); + } + else { + sc.SetState(SCE_A68K_COMMENT_SPECIAL); + } + continue; } - + // Check if we are at the end of an identifier // In this case, colourise it if was a keyword. - else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch)) { + else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch)) { sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context if (cpuInstruction.InList(Buffer)) { // And check if it belongs to a keyword list sc.ChangeState(SCE_A68K_CPUINSTRUCTION); @@ -269,30 +269,30 @@ static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, * ************************************************************/ - // Something which begins at the beginning of a line, and with - // - '\' + an identifier start char, or - // - '\\@' + an identifier start char - // is a local label (second case is used for macro local labels). We set it already as a label, it can't be a macro/equ declaration - if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.chNext) && (sc.ch == '\\')) { - sc.SetState(SCE_A68K_LABEL); - } - - if (sc.atLineStart && (sc.ch < 0x80) && (sc.ch == '\\') && (sc.chNext == '\\')) { - sc.Forward(2); - if ((sc.ch == '@') && IsIdentifierStart(sc.chNext)) { - sc.ChangeState(SCE_A68K_LABEL); - sc.SetState(SCE_A68K_LABEL); - } - } - + // Something which begins at the beginning of a line, and with + // - '\' + an identifier start char, or + // - '\\@' + an identifier start char + // is a local label (second case is used for macro local labels). We set it already as a label, it can't be a macro/equ declaration + if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.chNext) && (sc.ch == '\\')) { + sc.SetState(SCE_A68K_LABEL); + } + + if (sc.atLineStart && (sc.ch < 0x80) && (sc.ch == '\\') && (sc.chNext == '\\')) { + sc.Forward(2); + if ((sc.ch == '@') && IsIdentifierStart(sc.chNext)) { + sc.ChangeState(SCE_A68K_LABEL); + sc.SetState(SCE_A68K_LABEL); + } + } + // Label and macro identifiers start at the beginning of a line - // We set both as a macro id, but if it wasn't one (':' at the end), - // it will be changed as a label. + // We set both as a macro id, but if it wasn't one (':' at the end), + // it will be changed as a label. if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { - sc.SetState(SCE_A68K_MACRO_DECLARATION); + sc.SetState(SCE_A68K_MACRO_DECLARATION); } - else if ((sc.ch < 0x80) && (sc.ch == ';')) { // Default: alert in a comment. If it doesn't match - sc.SetState(SCE_A68K_COMMENT); // with an alert, it will be toggle to a normal comment + else if ((sc.ch < 0x80) && (sc.ch == ';')) { // Default: alert in a comment. If it doesn't match + sc.SetState(SCE_A68K_COMMENT); // with an alert, it will be toggle to a normal comment } else if ((sc.ch < 0x80) && isdigit(sc.ch)) { // Decimal numbers haven't prefix sc.SetState(SCE_A68K_NUMBER_DEC); @@ -309,7 +309,7 @@ static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, else if ((sc.ch < 0x80) && (sc.ch == '\"')) { // String (double-quoted) sc.SetState(SCE_A68K_STRING2); } - else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) { // Replacement symbols in macro are prefixed with '\' + else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) { // Replacement symbols in macro are prefixed with '\' sc.SetState(SCE_A68K_MACRO_ARG); } else if ((sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { // An identifier: constant, label, etc... diff --git a/src/stc/scintilla/lexers/LexBash.cxx b/src/stc/scintilla/lexers/LexBash.cxx index b85d01a7dc..a5f0f6e695 100644 --- a/src/stc/scintilla/lexers/LexBash.cxx +++ b/src/stc/scintilla/lexers/LexBash.cxx @@ -419,8 +419,6 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, sc.Forward(); HereDoc.Quoted = true; HereDoc.State = 1; - } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case - HereDoc.Indent = true; } else if (setHereDoc.Contains(sc.chNext)) { // an unquoted here-doc delimiter, no special handling // TODO check what exactly bash considers part of the delim @@ -469,7 +467,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, if (sc.atLineStart) { sc.SetState(SCE_SH_HERE_Q); int prefixws = 0; - while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix + while (sc.ch == '\t' && !sc.atLineEnd) { // tabulation prefix sc.Forward(); prefixws++; } @@ -481,7 +479,8 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, char s[HERE_DELIM_MAX]; sc.GetCurrent(s, sizeof(s)); if (sc.LengthCurrent() == 0) { // '' or "" delimiters - if (prefixws == 0 && HereDoc.Quoted && HereDoc.DelimiterLength == 0) + if ((prefixws == 0 || HereDoc.Indent) && + HereDoc.Quoted && HereDoc.DelimiterLength == 0) sc.SetState(SCE_SH_DEFAULT); break; } @@ -672,7 +671,12 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, } else if (sc.Match('<', '<')) { sc.SetState(SCE_SH_HERE_DELIM); HereDoc.State = 0; - HereDoc.Indent = false; + if (sc.GetRelative(2) == '-') { // <<- indent case + HereDoc.Indent = true; + sc.Forward(); + } else { + HereDoc.Indent = false; + } } else if (sc.ch == '-' && // one-char file test operators setSingleCharOp.Contains(sc.chNext) && !setWord.Contains(sc.GetRelative(2)) && @@ -767,6 +771,7 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; unsigned int endPos = startPos + length; int visibleChars = 0; + int skipHereCh = 0; int lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; @@ -798,7 +803,15 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], // Here Document folding if (style == SCE_SH_HERE_DELIM) { if (ch == '<' && chNext == '<') { - levelCurrent++; + if (styler.SafeGetCharAt(i + 2) == '<') { + skipHereCh = 1; + } else { + if (skipHereCh == 0) { + levelCurrent++; + } else { + skipHereCh = 0; + } + } } } else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_SH_DEFAULT) { levelCurrent--; diff --git a/src/stc/scintilla/lexers/LexBibTeX.cxx b/src/stc/scintilla/lexers/LexBibTeX.cxx new file mode 100644 index 0000000000..cdbce8d493 --- /dev/null +++ b/src/stc/scintilla/lexers/LexBibTeX.cxx @@ -0,0 +1,310 @@ +// Copyright 2008-2010 Sergiu Dotenco. The License.txt file describes the +// conditions under which this software may be distributed. + +/** + * @file LexBibTeX.cxx + * @brief General BibTeX coloring scheme. + * @author Sergiu Dotenco + * @date April 18, 2009 + */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +namespace { + bool IsAlphabetic(unsigned int ch) + { + return IsASCII(ch) && std::isalpha(ch) != 0; + } + bool IsAlphaNumeric(char ch) + { + return IsASCII(ch) && std::isalnum(ch); + } + + bool EqualCaseInsensitive(const char* a, const char* b) + { + return CompareCaseInsensitive(a, b) == 0; + } + + bool EntryWithoutKey(const char* name) + { + return EqualCaseInsensitive(name,"string"); + } + + char GetClosingBrace(char openbrace) + { + char result = openbrace; + + switch (openbrace) { + case '(': result = ')'; break; + case '{': result = '}'; break; + } + + return result; + } + + bool IsEntryStart(char prev, char ch) + { + return prev != '\\' && ch == '@'; + } + + bool IsEntryStart(const StyleContext& sc) + { + return IsEntryStart(sc.chPrev, sc.ch); + } + + void ColorizeBibTeX(unsigned start_pos, int length, int /*init_style*/, WordList* keywordlists[], Accessor& styler) + { + WordList &EntryNames = *keywordlists[0]; + bool fold_compact = styler.GetPropertyInt("fold.compact", 1) != 0; + + std::string buffer; + buffer.reserve(25); + + // We always colorize a section from the beginning, so let's + // search for the @ character which isn't escaped, i.e. \@ + while (start_pos > 0 && !IsEntryStart(styler.SafeGetCharAt(start_pos - 1), + styler.SafeGetCharAt(start_pos))) { + --start_pos; ++length; + } + + styler.StartAt(start_pos); + styler.StartSegment(start_pos); + + int current_line = styler.GetLine(start_pos); + int prev_level = styler.LevelAt(current_line) & SC_FOLDLEVELNUMBERMASK; + int current_level = prev_level; + int visible_chars = 0; + + bool in_comment = false ; + StyleContext sc(start_pos, length, SCE_BIBTEX_DEFAULT, styler); + + bool going = sc.More(); // needed because of a fuzzy end of file state + char closing_brace = 0; + bool collect_entry_name = false; + + for (; going; sc.Forward()) { + if (!sc.More()) + going = false; // we need to go one behind the end of text + + if (in_comment) { + if (sc.atLineEnd) { + sc.SetState(SCE_BIBTEX_DEFAULT); + in_comment = false; + } + } + else { + // Found @entry + if (IsEntryStart(sc)) { + sc.SetState(SCE_BIBTEX_UNKNOWN_ENTRY); + sc.Forward(); + ++current_level; + + buffer.clear(); + collect_entry_name = true; + } + else if ((sc.state == SCE_BIBTEX_ENTRY || sc.state == SCE_BIBTEX_UNKNOWN_ENTRY) + && (sc.ch == '{' || sc.ch == '(')) { + // Entry name colorization done + // Found either a { or a ( after entry's name, e.g. @entry(...) @entry{...} + // Closing counterpart needs to be stored. + closing_brace = GetClosingBrace(sc.ch); + + sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize { ( + + // @string doesn't have any key + if (EntryWithoutKey(buffer.c_str())) + sc.ForwardSetState(SCE_BIBTEX_PARAMETER); + else + sc.ForwardSetState(SCE_BIBTEX_KEY); // Key/label colorization + } + + // Need to handle the case where entry's key is empty + // e.g. @book{,...} + if (sc.state == SCE_BIBTEX_KEY && sc.ch == ',') { + // Key/label colorization done + sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the , + sc.ForwardSetState(SCE_BIBTEX_PARAMETER); // Parameter colorization + } + else if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == '=') { + sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the = + sc.ForwardSetState(SCE_BIBTEX_VALUE); // Parameter value colorization + + int start = sc.currentPos; + + // We need to handle multiple situations: + // 1. name"one two {three}" + // 2. name={one {one two {two}} three} + // 3. year=2005 + + // Skip ", { until we encounter the first alphanumerical character + while (sc.More() && !(IsAlphaNumeric(sc.ch) || sc.ch == '"' || sc.ch == '{')) + sc.Forward(); + + if (sc.More()) { + // Store " or { + char ch = sc.ch; + + // Not interested in alphanumerical characters + if (IsAlphaNumeric(ch)) + ch = 0; + + int skipped = 0; + + if (ch) { + // Skip preceding " or { such as in name={{test}}. + // Remember how many characters have been skipped + // Make sure that empty values, i.e. "" are also handled correctly + while (sc.More() && (sc.ch == ch && (ch != '"' || skipped < 1))) { + sc.Forward(); + ++skipped; + } + } + + // Closing counterpart for " is the same character + if (ch == '{') + ch = '}'; + + // We have reached the parameter value + // In case the open character was a alnum char, skip until , is found + // otherwise until skipped == 0 + while (sc.More() && (skipped > 0 || (!ch && !(sc.ch == ',' || sc.ch == closing_brace)))) { + // Make sure the character isn't escaped + if (sc.chPrev != '\\') { + // Parameter value contains a { which is the 2nd case described above + if (sc.ch == '{') + ++skipped; // Remember it + else if (sc.ch == '}') + --skipped; + else if (skipped == 1 && sc.ch == ch && ch == '"') // Don't ignore cases like {"o} + skipped = 0; + } + + sc.Forward(); + } + } + + // Don't colorize the , + sc.SetState(SCE_BIBTEX_DEFAULT); + + // Skip until the , or entry's closing closing_brace is found + // since this parameter might be the last one + while (sc.More() && !(sc.ch == ',' || sc.ch == closing_brace)) + sc.Forward(); + + int state = SCE_BIBTEX_PARAMETER; // The might be more parameters + + // We've reached the closing closing_brace for the bib entry + // in case no " or {} has been used to enclose the value, + // as in 3rd case described above + if (sc.ch == closing_brace) { + --current_level; + // Make sure the text between entries is not colored + // using parameter's style + state = SCE_BIBTEX_DEFAULT; + } + + int end = sc.currentPos; + current_line = styler.GetLine(end); + + // We have possibly skipped some lines, so the folding levels + // have to be adjusted separately + for (int i = styler.GetLine(start); i <= styler.GetLine(end); ++i) + styler.SetLevel(i, prev_level); + + sc.ForwardSetState(state); + } + + if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == closing_brace) { + sc.SetState(SCE_BIBTEX_DEFAULT); + --current_level; + } + + // Non escaped % found which represents a comment until the end of the line + if (sc.chPrev != '\\' && sc.ch == '%') { + in_comment = true; + sc.SetState(SCE_BIBTEX_COMMENT); + } + } + + if (sc.state == SCE_BIBTEX_UNKNOWN_ENTRY || sc.state == SCE_BIBTEX_ENTRY) { + if (!IsAlphabetic(sc.ch) && collect_entry_name) + collect_entry_name = false; + + if (collect_entry_name) { + buffer += static_cast(tolower(sc.ch)); + if (EntryNames.InList(buffer.c_str())) + sc.ChangeState(SCE_BIBTEX_ENTRY); + else + sc.ChangeState(SCE_BIBTEX_UNKNOWN_ENTRY); + } + } + + if (sc.atLineEnd) { + int level = prev_level; + + if (visible_chars == 0 && fold_compact) + level |= SC_FOLDLEVELWHITEFLAG; + + if ((current_level > prev_level)) + level |= SC_FOLDLEVELHEADERFLAG; + // else if (current_level < prev_level) + // level |= SC_FOLDLEVELBOXFOOTERFLAG; // Deprecated + + if (level != styler.LevelAt(current_line)) { + styler.SetLevel(current_line, level); + } + + ++current_line; + prev_level = current_level; + visible_chars = 0; + } + + if (!isspacechar(sc.ch)) + ++visible_chars; + } + + sc.Complete(); + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(current_line) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(current_line, prev_level | flagsNext); + } +} +static const char * const BibTeXWordLists[] = { + "Entry Names", + 0, +}; + + +LexerModule lmBibTeX(SCLEX_BIBTEX, ColorizeBibTeX, "bib", 0, BibTeXWordLists); + +// Entry Names +// article, book, booklet, conference, inbook, +// incollection, inproceedings, manual, mastersthesis, +// misc, phdthesis, proceedings, techreport, unpublished, +// string, url + diff --git a/src/stc/scintilla/lexers/LexCPP.cxx b/src/stc/scintilla/lexers/LexCPP.cxx index 04628b4df7..ab982bb4bb 100644 --- a/src/stc/scintilla/lexers/LexCPP.cxx +++ b/src/stc/scintilla/lexers/LexCPP.cxx @@ -8,10 +8,10 @@ #include #include -#include #include #include #include +#include #include #include @@ -36,7 +36,10 @@ using namespace Scintilla; #endif -static bool IsSpaceEquiv(int state) { +namespace { + // Use an unnamed namespace to protect the functions and classes from name conflicts + +bool IsSpaceEquiv(int state) { return (state <= SCE_C_COMMENTDOC) || // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || @@ -50,7 +53,7 @@ static bool IsSpaceEquiv(int state) { // a = b+++/ptn/... // Putting a space between the '++' post-inc operator and the '+' binary op // fixes this, and is highly recommended for readability anyway. -static bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) { +bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) { int pos = (int) sc.currentPos; while (--pos > 0) { char ch = styler[pos]; @@ -61,7 +64,7 @@ static bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) { return false; } -static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { +bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { // Don't look at styles, so no need to flush. int pos = (int) sc.currentPos; int currentLine = styler.GetLine(pos); @@ -83,7 +86,120 @@ static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { return !*s; } -static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { +bool IsSpaceOrTab(int ch) { + return ch == ' ' || ch == '\t'; +} + +bool OnlySpaceOrTab(const std::string &s) { + for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { + if (!IsSpaceOrTab(*it)) + return false; + } + return true; +} + +std::vector StringSplit(const std::string &text, int separator) { + std::vector vs(text.empty() ? 0 : 1); + for (std::string::const_iterator it = text.begin(); it != text.end(); ++it) { + if (*it == separator) { + vs.push_back(std::string()); + } else { + vs.back() += *it; + } + } + return vs; +} + +struct BracketPair { + std::vector::iterator itBracket; + std::vector::iterator itEndBracket; +}; + +BracketPair FindBracketPair(std::vector &tokens) { + BracketPair bp; + std::vector::iterator itTok = std::find(tokens.begin(), tokens.end(), "("); + bp.itBracket = tokens.end(); + bp.itEndBracket = tokens.end(); + if (itTok != tokens.end()) { + bp.itBracket = itTok; + size_t nest = 0; + while (itTok != tokens.end()) { + if (*itTok == "(") { + nest++; + } else if (*itTok == ")") { + nest--; + if (nest == 0) { + bp.itEndBracket = itTok; + return bp; + } + } + ++itTok; + } + } + bp.itBracket = tokens.end(); + return bp; +} + +void highlightTaskMarker(StyleContext &sc, LexAccessor &styler, + int activity, WordList &markerList, bool caseSensitive){ + if ((isoperator(sc.chPrev) || IsASpace(sc.chPrev)) && markerList.Length()) { + const int lengthMarker = 50; + char marker[lengthMarker+1]; + int currPos = (int) sc.currentPos; + int i = 0; + while (i < lengthMarker) { + char ch = styler.SafeGetCharAt(currPos + i); + if (IsASpace(ch) || isoperator(ch)) { + break; + } + if (caseSensitive) + marker[i] = ch; + else + marker[i] = static_cast(tolower(ch)); + i++; + } + marker[i] = '\0'; + if (markerList.InList(marker)) { + sc.SetState(SCE_C_TASKMARKER|activity); + } + } +} + +struct EscapeSequence { + int digitsLeft; + CharacterSet setHexDigits; + CharacterSet setOctDigits; + CharacterSet setNoneNumeric; + CharacterSet *escapeSetValid; + EscapeSequence() { + digitsLeft = 0; + escapeSetValid = 0; + setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef"); + setOctDigits = CharacterSet(CharacterSet::setNone, "01234567"); + } + void resetEscapeState(int nextChar) { + digitsLeft = 0; + escapeSetValid = &setNoneNumeric; + if (nextChar == 'U') { + digitsLeft = 9; + escapeSetValid = &setHexDigits; + } else if (nextChar == 'u') { + digitsLeft = 5; + escapeSetValid = &setHexDigits; + } else if (nextChar == 'x') { + digitsLeft = 5; + escapeSetValid = &setHexDigits; + } else if (setOctDigits.Contains(nextChar)) { + digitsLeft = 3; + escapeSetValid = &setOctDigits; + } + } + bool atEscapeEnd(int currChar) const { + return (digitsLeft <= 0) || !escapeSetValid->Contains(currChar); + } +}; + +std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { std::string restOfLine; int i =0; char ch = styler.SafeGetCharAt(start, '\n'); @@ -100,40 +216,21 @@ static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace return restOfLine; } -static bool IsStreamCommentStyle(int style) { +bool IsStreamCommentStyle(int style) { return style == SCE_C_COMMENT || style == SCE_C_COMMENTDOC || style == SCE_C_COMMENTDOCKEYWORD || style == SCE_C_COMMENTDOCKEYWORDERROR; } -static std::vector Tokenize(const std::string &s) { - // Break into space separated tokens - std::string word; - std::vector tokens; - for (const char *cp = s.c_str(); *cp; cp++) { - if ((*cp == ' ') || (*cp == '\t')) { - if (!word.empty()) { - tokens.push_back(word); - word = ""; - } - } else { - word += *cp; - } - } - if (!word.empty()) { - tokens.push_back(word); - } - return tokens; -} - struct PPDefinition { int line; std::string key; std::string value; bool isUndef; - PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false) : - line(line_), key(key_), value(value_), isUndef(isUndef_) { + std::string arguments; + PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false, std::string arguments_="") : + line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) { } }; @@ -209,8 +306,11 @@ struct OptionsCPP { bool identifiersAllowDollars; bool trackPreprocessor; bool updatePreprocessor; + bool verbatimStringsAllowEscapes; bool triplequotedStrings; bool hashquotedStrings; + bool backQuotedStrings; + bool escapeSequence; bool fold; bool foldSyntaxBased; bool foldComment; @@ -227,8 +327,11 @@ struct OptionsCPP { identifiersAllowDollars = true; trackPreprocessor = true; updatePreprocessor = true; + verbatimStringsAllowEscapes = false; triplequotedStrings = false; hashquotedStrings = false; + backQuotedStrings = false; + escapeSequence = false; fold = false; foldSyntaxBased = true; foldComment = false; @@ -243,12 +346,13 @@ struct OptionsCPP { } }; -static const char *const cppWordLists[] = { +const char *const cppWordLists[] = { "Primary keywords and identifiers", "Secondary keywords and identifiers", "Documentation comment keywords", "Global classes and typedefs", "Preprocessor definitions", + "Task marker and error marker keywords", 0, }; @@ -268,12 +372,21 @@ struct OptionSetCPP : public OptionSet { DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor, "Set to 1 to update preprocessor definitions when #define found."); + DefineProperty("lexer.cpp.verbatim.strings.allow.escapes", &OptionsCPP::verbatimStringsAllowEscapes, + "Set to 1 to allow verbatim strings to contain escape sequences."); + DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings, "Set to 1 to enable highlighting of triple-quoted strings."); DefineProperty("lexer.cpp.hashquoted.strings", &OptionsCPP::hashquotedStrings, "Set to 1 to enable highlighting of hash-quoted strings."); + DefineProperty("lexer.cpp.backquoted.strings", &OptionsCPP::backQuotedStrings, + "Set to 1 to enable highlighting of back-quoted raw strings ."); + + DefineProperty("lexer.cpp.escape.sequence", &OptionsCPP::escapeSequence, + "Set to 1 to enable highlighting of escape sequences in strings"); + DefineProperty("fold", &OptionsCPP::fold); DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased, @@ -312,7 +425,9 @@ struct OptionSetCPP : public OptionSet { } }; -static const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0}; +const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0}; + +} class LexerCPP : public ILexerWithSubStyles { bool caseSensitive; @@ -321,6 +436,7 @@ class LexerCPP : public ILexerWithSubStyles { CharacterSet setArithmethicOp; CharacterSet setRelOp; CharacterSet setLogicalOp; + CharacterSet setWordStart; PPStates vlls; std::vector ppDefineHistory; WordList keywords; @@ -328,9 +444,26 @@ class LexerCPP : public ILexerWithSubStyles { WordList keywords3; WordList keywords4; WordList ppDefinitions; - std::map preprocessorDefinitionsStart; + WordList markerList; + struct SymbolValue { + std::string value; + std::string arguments; + SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) { + } + SymbolValue &operator = (const std::string &value_) { + value = value_; + arguments.clear(); + return *this; + } + bool IsMacro() const { + return !arguments.empty(); + } + }; + typedef std::map SymbolTable; + SymbolTable preprocessorDefinitionsStart; OptionsCPP options; OptionSetCPP osCPP; + EscapeSequence escapeSeq; SparseState rawStringTerminators; enum { activeFlag = 0x40 }; enum { ssIdentifier, ssDocKeyword }; @@ -394,7 +527,7 @@ public: } int SCI_METHOD PrimaryStyleFromStyle(int style) { return MaskActive(style); - } + } void SCI_METHOD FreeSubStyles() { subStyles.Free(); } @@ -417,8 +550,9 @@ public: static int MaskActive(int style) { return style & ~activeFlag; } - void EvaluateTokens(std::vector &tokens); - bool EvaluateExpression(const std::string &expr, const std::map &preprocessorDefinitions); + void EvaluateTokens(std::vector &tokens, const SymbolTable &preprocessorDefinitions); + std::vector Tokenize(const std::string &expr) const; + bool EvaluateExpression(const std::string &expr, const SymbolTable &preprocessorDefinitions); }; int SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) { @@ -452,6 +586,9 @@ int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) { case 4: wordListN = &ppDefinitions; break; + case 5: + wordListN = &markerList; + break; } int firstModification = -1; if (wordListN) { @@ -469,7 +606,16 @@ int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) { if (cpEquals) { std::string name(cpDefinition, cpEquals - cpDefinition); std::string val(cpEquals+1); - preprocessorDefinitionsStart[name] = val; + size_t bracket = name.find('('); + size_t bracketEnd = name.find(')'); + if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) { + // Macro + std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1); + name = name.substr(0, bracket); + preprocessorDefinitionsStart[name] = SymbolValue(val, args); + } else { + preprocessorDefinitionsStart[name] = val; + } } else { std::string name(cpDefinition); std::string val("1"); @@ -499,7 +645,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + setWordStart = CharacterSet(CharacterSet::setAlpha, "_", 0x80, true); CharacterSet setInvalidRawFirst(CharacterSet::setNone, " )\\\t\v\f\n"); @@ -511,6 +657,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, int visibleChars = 0; bool lastWordWasUUID = false; int styleBeforeDCKeyword = SCE_C_DEFAULT; + int styleBeforeTaskMarker = SCE_C_DEFAULT; bool continuationLine = false; bool isIncludePreprocessor = false; bool isStringInPreprocessor = false; @@ -540,7 +687,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } } - StyleContext sc(startPos, length, initStyle, styler, static_cast(0xff)); + StyleContext sc(startPos, length, initStyle, styler, static_cast(0xff)); LinePPState preproc = vlls.ForLine(lineCurrent); bool definitionsChanged = false; @@ -556,12 +703,12 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, definitionsChanged = true; } - std::map preprocessorDefinitions = preprocessorDefinitionsStart; + SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart; for (std::vector::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { if (itDef->isUndef) preprocessorDefinitions.erase(itDef->key); else - preprocessorDefinitions[itDef->key] = itDef->value; + preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments); } std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1); @@ -581,13 +728,13 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, // Inside inactive preprocessor declaration, state will be reset anyway at the end of this block. if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) { // Prevent SCE_C_STRINGEOL from leaking back to previous line which - // ends with a line continuation by locking in the state upto this position. + // ends with a line continuation by locking in the state up to this position. sc.SetState(sc.state); } if ((MaskActive(sc.state) == SCE_C_PREPROCESSOR) && (!continuationLine)) { sc.SetState(SCE_C_DEFAULT|activitySet); } - // Reset states to begining of colourise so no surprises + // Reset states to beginning of colourise so no surprises // if different sets of lines lexed. visibleChars = 0; lastWordWasUUID = false; @@ -679,10 +826,18 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, ((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) || ((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8')); if (valid) { - if (literalString) - sc.ChangeState((raw ? SCE_C_STRINGRAW : SCE_C_STRING)|activitySet); - else + if (literalString) { + if (raw) { + // Set the style of the string prefix to SCE_C_STRINGRAW but then change to + // SCE_C_DEFAULT as that allows the raw string start code to run. + sc.ChangeState(SCE_C_STRINGRAW|activitySet); + sc.SetState(SCE_C_DEFAULT|activitySet); + } else { + sc.ChangeState(SCE_C_STRING|activitySet); + } + } else { sc.ChangeState(SCE_C_CHARACTER|activitySet); + } } else { sc.SetState(SCE_C_DEFAULT | activitySet); } @@ -725,6 +880,9 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.Match('*', '/')) { sc.Forward(); sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else { + styleBeforeTaskMarker = SCE_C_COMMENT; + highlightTaskMarker(sc, styler, activitySet, markerList, caseSensitive); } break; case SCE_C_COMMENTDOC: @@ -742,6 +900,9 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, case SCE_C_COMMENTLINE: if (sc.atLineStart && !continuationLine) { sc.SetState(SCE_C_DEFAULT|activitySet); + } else { + styleBeforeTaskMarker = SCE_C_COMMENTLINE; + highlightTaskMarker(sc, styler, activitySet, markerList, caseSensitive); } break; case SCE_C_COMMENTLINEDOC: @@ -794,9 +955,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, isIncludePreprocessor = false; } } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); + if (options.escapeSequence) { + sc.SetState(SCE_C_ESCAPESEQUENCE|activitySet); + escapeSeq.resetEscapeState(sc.chNext); } + sc.Forward(); // Skip all characters after the backslash } else if (sc.ch == '\"') { if (sc.chNext == '_') { sc.ChangeState(SCE_C_USERLITERAL|activitySet); @@ -805,6 +968,24 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } } break; + case SCE_C_ESCAPESEQUENCE: + escapeSeq.digitsLeft--; + if (!escapeSeq.atEscapeEnd(sc.ch)) { + break; + } + if (sc.ch == '"') { + sc.SetState(SCE_C_STRING|activitySet); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '\\') { + escapeSeq.resetEscapeState(sc.chNext); + sc.Forward(); + } else { + sc.SetState(SCE_C_STRING|activitySet); + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } + } + break; case SCE_C_HASHQUOTEDSTRING: if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { @@ -860,7 +1041,9 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } break; case SCE_C_VERBATIM: - if (sc.ch == '\"') { + if (options.verbatimStringsAllowEscapes && (sc.ch == '\\')) { + sc.Forward(); // Skip all characters after the backslash + } else if (sc.ch == '\"') { if (sc.chNext == '\"') { sc.Forward(); } else { @@ -880,6 +1063,12 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd || sc.ch == ')') { sc.SetState(SCE_C_DEFAULT|activitySet); } + break; + case SCE_C_TASKMARKER: + if (isoperator(sc.ch) || IsASpace(sc.ch)) { + sc.SetState(styleBeforeTaskMarker|activitySet); + styleBeforeTaskMarker = SCE_C_DEFAULT; + } } if (sc.atLineEnd && !atLineEndBeforeSwitch) { @@ -900,6 +1089,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else if (options.hashquotedStrings && sc.Match('#', '\"')) { sc.SetState(SCE_C_HASHQUOTEDSTRING|activitySet); sc.Forward(); + } else if (options.backQuotedStrings && sc.Match('`')) { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = "`"; + sc.Forward(); } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { if (lastWordWasUUID) { sc.SetState(SCE_C_UUID|activitySet); @@ -1018,19 +1211,37 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else if (sc.Match("define")) { if (options.updatePreprocessor && !preproc.IsInactive()) { std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); - if (restOfLine.find(")") == std::string::npos) { // Don't handle macros with arguments - std::vector tokens = Tokenize(restOfLine); - std::string key; - std::string value("1"); - if (tokens.size() >= 1) { - key = tokens[0]; - if (tokens.size() >= 2) { - value = tokens[1]; - } - preprocessorDefinitions[key] = value; - ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value)); - definitionsChanged = true; - } + size_t startName = 0; + while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName])) + startName++; + size_t endName = startName; + while ((endName < restOfLine.length()) && setWord.Contains(static_cast(restOfLine[endName]))) + endName++; + std::string key = restOfLine.substr(startName, endName-startName); + if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) { + // Macro + size_t endArgs = endName; + while ((endArgs < restOfLine.length()) && (restOfLine[endArgs] != ')')) + endArgs++; + std::string args = restOfLine.substr(endName + 1, endArgs - endName - 1); + size_t startValue = endArgs+1; + while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) + startValue++; + std::string value; + if (startValue < restOfLine.length()) + value = restOfLine.substr(startValue); + preprocessorDefinitions[key] = SymbolValue(value, args); + ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value, false, args)); + definitionsChanged = true; + } else { + // Value + size_t startValue = endName; + while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) + startValue++; + std::string value = restOfLine.substr(startValue); + preprocessorDefinitions[key] = value; + ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value)); + definitionsChanged = true; } } } else if (sc.Match("undef")) { @@ -1140,14 +1351,14 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, } } if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { - if (ch == '{') { + if (ch == '{' || ch == '[') { // Measure the minimum before a '{' to allow // folding on "} else {" if (levelMinCurrent > levelNext) { levelMinCurrent = levelNext; } levelNext++; - } else if (ch == '}') { + } else if (ch == '}' || ch == ']') { levelNext--; } } @@ -1180,19 +1391,36 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, } } -void LexerCPP::EvaluateTokens(std::vector &tokens) { +void LexerCPP::EvaluateTokens(std::vector &tokens, const SymbolTable &preprocessorDefinitions) { - // Evaluate defined() statements to either 0 or 1 - for (size_t i=0; (i+2)) - tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4); - val = "1"; + if (tokens[i+1] == "(") { + if (((i + 2)) + SymbolTable::const_iterator it = preprocessorDefinitions.find(tokens[i+2]); + if (it != preprocessorDefinitions.end()) { + val = "1"; + } + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4); + } else { + // Spurious '(' so erase as more likely to result in false + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 2); + } + } else { + // defined + SymbolTable::const_iterator it = preprocessorDefinitions.find(tokens[i+1]); + if (it != preprocessorDefinitions.end()) { + val = "1"; + } } tokens[i] = val; } else { @@ -1200,21 +1428,82 @@ void LexerCPP::EvaluateTokens(std::vector &tokens) { } } + // Evaluate identifiers + const size_t maxIterations = 100; + size_t iterations = 0; // Limit number of iterations in case there is a recursive macro. + for (size_t i = 0; (i(tokens[i][0]))) { + SymbolTable::const_iterator it = preprocessorDefinitions.find(tokens[i]); + if (it != preprocessorDefinitions.end()) { + // Tokenize value + std::vector macroTokens = Tokenize(it->second.value); + if (it->second.IsMacro()) { + if ((i + 1 < tokens.size()) && (tokens.at(i + 1) == "(")) { + // Create map of argument name to value + std::vector argumentNames = StringSplit(it->second.arguments, ','); + std::map arguments; + size_t arg = 0; + size_t tok = i+2; + while ((tok < tokens.size()) && (arg < argumentNames.size()) && (tokens.at(tok) != ")")) { + if (tokens.at(tok) != ",") { + arguments[argumentNames.at(arg)] = tokens.at(tok); + arg++; + } + tok++; + } + + // Remove invocation + tokens.erase(tokens.begin() + i, tokens.begin() + tok + 1); + + // Substitute values into macro + macroTokens.erase(std::remove_if(macroTokens.begin(), macroTokens.end(), OnlySpaceOrTab), macroTokens.end()); + + for (size_t iMacro = 0; iMacro < macroTokens.size();) { + if (setWordStart.Contains(static_cast(macroTokens[iMacro][0]))) { + std::map::const_iterator itFind = arguments.find(macroTokens[iMacro]); + if (itFind != arguments.end()) { + // TODO: Possible that value will be expression so should insert tokenized form + macroTokens[iMacro] = itFind->second; + } + } + iMacro++; + } + + // Insert results back into tokens + tokens.insert(tokens.begin() + i, macroTokens.begin(), macroTokens.end()); + + } else { + i++; + } + } else { + // Remove invocation + tokens.erase(tokens.begin() + i); + // Insert results back into tokens + tokens.insert(tokens.begin() + i, macroTokens.begin(), macroTokens.end()); + } + } else { + // Identifier not found + tokens.erase(tokens.begin() + i); + } + } else { + i++; + } + } + // Find bracketed subexpressions and recurse on them - std::vector::iterator itBracket = std::find(tokens.begin(), tokens.end(), "("); - std::vector::iterator itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); - while ((itBracket != tokens.end()) && (itEndBracket != tokens.end()) && (itEndBracket > itBracket)) { - std::vector inBracket(itBracket + 1, itEndBracket); - EvaluateTokens(inBracket); + BracketPair bracketPair = FindBracketPair(tokens); + while (bracketPair.itBracket != tokens.end()) { + std::vector inBracket(bracketPair.itBracket + 1, bracketPair.itEndBracket); + EvaluateTokens(inBracket, preprocessorDefinitions); // The insertion is done before the removal because there were failures with the opposite approach - tokens.insert(itBracket, inBracket.begin(), inBracket.end()); - itBracket = std::find(tokens.begin(), tokens.end(), "("); - itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); - tokens.erase(itBracket, itEndBracket + 1); + tokens.insert(bracketPair.itBracket, inBracket.begin(), inBracket.end()); - itBracket = std::find(tokens.begin(), tokens.end(), "("); - itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + bracketPair = FindBracketPair(tokens); + tokens.erase(bracketPair.itBracket, bracketPair.itEndBracket + 1); + + bracketPair = FindBracketPair(tokens); } // Evaluate logical negations @@ -1283,45 +1572,51 @@ void LexerCPP::EvaluateTokens(std::vector &tokens) { } } -bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map &preprocessorDefinitions) { - // Break into tokens, replacing with definitions - std::string word; +std::vector LexerCPP::Tokenize(const std::string &expr) const { + // Break into tokens std::vector tokens; const char *cp = expr.c_str(); - for (;;) { + while (*cp) { + std::string word; if (setWord.Contains(static_cast(*cp))) { + // Identifiers and numbers + while (setWord.Contains(static_cast(*cp))) { + word += *cp; + cp++; + } + } else if (IsSpaceOrTab(*cp)) { + while (IsSpaceOrTab(*cp)) { + word += *cp; + cp++; + } + } else if (setRelOp.Contains(static_cast(*cp))) { word += *cp; + cp++; + if (setRelOp.Contains(static_cast(*cp))) { + word += *cp; + cp++; + } + } else if (setLogicalOp.Contains(static_cast(*cp))) { + word += *cp; + cp++; + if (setLogicalOp.Contains(static_cast(*cp))) { + word += *cp; + cp++; + } } else { - std::map::const_iterator it = preprocessorDefinitions.find(word); - if (it != preprocessorDefinitions.end()) { - tokens.push_back(it->second); - } else if (!word.empty() && ((word[0] >= '0' && word[0] <= '9') || (word == "defined"))) { - tokens.push_back(word); - } - word = ""; - if (!*cp) { - break; - } - if ((*cp != ' ') && (*cp != '\t')) { - std::string op(cp, 1); - if (setRelOp.Contains(static_cast(*cp))) { - if (setRelOp.Contains(static_cast(cp[1]))) { - op += cp[1]; - cp++; - } - } else if (setLogicalOp.Contains(static_cast(*cp))) { - if (setLogicalOp.Contains(static_cast(cp[1]))) { - op += cp[1]; - cp++; - } - } - tokens.push_back(op); - } + // Should handle strings, characters, and comments here + word += *cp; + cp++; } - cp++; + tokens.push_back(word); } + return tokens; +} - EvaluateTokens(tokens); +bool LexerCPP::EvaluateExpression(const std::string &expr, const SymbolTable &preprocessorDefinitions) { + std::vector tokens = Tokenize(expr); + + EvaluateTokens(tokens, preprocessorDefinitions); // "0" or "" -> false else true bool isFalse = tokens.empty() || diff --git a/src/stc/scintilla/lexers/LexCoffeeScript.cxx b/src/stc/scintilla/lexers/LexCoffeeScript.cxx index fc9b4998a9..1667683218 100644 --- a/src/stc/scintilla/lexers/LexCoffeeScript.cxx +++ b/src/stc/scintilla/lexers/LexCoffeeScript.cxx @@ -31,11 +31,8 @@ using namespace Scintilla; #endif static bool IsSpaceEquiv(int state) { - return (state <= SCE_COFFEESCRIPT_COMMENTDOC - // including SCE_COFFEESCRIPT_DEFAULT, SCE_COFFEESCRIPT_COMMENT, SCE_COFFEESCRIPT_COMMENTLINE - || state == SCE_COFFEESCRIPT_COMMENTLINEDOC - || state == SCE_COFFEESCRIPT_COMMENTDOCKEYWORD - || state == SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR + return (state == SCE_COFFEESCRIPT_DEFAULT + || state == SCE_COFFEESCRIPT_COMMENTLINE || state == SCE_COFFEESCRIPT_COMMENTBLOCK || state == SCE_COFFEESCRIPT_VERBOSE_REGEX || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT @@ -88,51 +85,16 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3]; - // property styling.within.preprocessor - // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) - // or only from the initial # to the end of the command word(1). - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - // property lexer.cpp.allow.dollars - // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. - if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { - setWordStart.Add('$'); - setWord.Add('$'); - } + CharacterSet setWordStart(CharacterSet::setAlpha, "_$@", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._$", 0x80, true); int chPrevNonWhite = ' '; int visibleChars = 0; - bool lastWordWasUUID = false; - int styleBeforeDCKeyword = SCE_COFFEESCRIPT_DEFAULT; - bool continuationLine = false; - bool isIncludePreprocessor = false; - - if (initStyle == SCE_COFFEESCRIPT_PREPROCESSOR) { - // Set continuationLine if last character of previous line is '\' - int lineCurrent = styler.GetLine(startPos); - if (lineCurrent > 0) { - int chBack = styler.SafeGetCharAt(startPos-1, 0); - int chBack2 = styler.SafeGetCharAt(startPos-2, 0); - int lineEndChar = '!'; - if (chBack2 == '\r' && chBack == '\n') { - lineEndChar = styler.SafeGetCharAt(startPos-3, 0); - } else if (chBack == '\n' || chBack == '\r') { - lineEndChar = chBack2; - } - continuationLine = lineEndChar == '\\'; - } - } // look back to set chPrevNonWhite properly for better regex colouring int endPos = startPos + length; @@ -158,23 +120,9 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init for (; sc.More(); sc.Forward()) { if (sc.atLineStart) { - // Reset states to begining of colourise so no surprises + // Reset states to beginning of colourise so no surprises // if different sets of lines lexed. visibleChars = 0; - lastWordWasUUID = false; - isIncludePreprocessor = false; - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continuationLine = true; - continue; - } } // Determine if the current state should terminate. @@ -193,7 +141,6 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init char s[1000]; sc.GetCurrent(s, sizeof(s)); if (keywords.InList(s)) { - lastWordWasUUID = strcmp(s, "uuid") == 0; sc.ChangeState(SCE_COFFEESCRIPT_WORD); } else if (keywords2.InList(s)) { sc.ChangeState(SCE_COFFEESCRIPT_WORD2); @@ -210,74 +157,13 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init sc.SetState(SCE_COFFEESCRIPT_DEFAULT); } break; - case SCE_COFFEESCRIPT_PREPROCESSOR: - if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_COFFEESCRIPT_DEFAULT); - } else if (stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_COFFEESCRIPT_DEFAULT); - } - } else { - if (sc.Match('/', '*') || sc.Match('/', '/')) { - sc.SetState(SCE_COFFEESCRIPT_DEFAULT); - } - } - break; - case SCE_COFFEESCRIPT_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); - } - break; - case SCE_COFFEESCRIPT_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_COFFEESCRIPT_COMMENTDOC; - sc.SetState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORD); - } - } - break; case SCE_COFFEESCRIPT_COMMENTLINE: if (sc.atLineStart) { sc.SetState(SCE_COFFEESCRIPT_DEFAULT); } break; - case SCE_COFFEESCRIPT_COMMENTLINEDOC: - if (sc.atLineStart) { - sc.SetState(SCE_COFFEESCRIPT_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_COFFEESCRIPT_COMMENTLINEDOC; - sc.SetState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORD); - } - } - break; - case SCE_COFFEESCRIPT_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_COFFEESCRIPT_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); - } else if (!setDoxygen.Contains(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; case SCE_COFFEESCRIPT_STRING: - if (isIncludePreprocessor) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); - isIncludePreprocessor = false; - } - } else if (sc.ch == '\\') { + if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } @@ -314,20 +200,6 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init sc.SetState(SCE_COFFEESCRIPT_DEFAULT); } break; - case SCE_COFFEESCRIPT_VERBATIM: - if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); - } - } - break; - case SCE_COFFEESCRIPT_UUID: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { - sc.SetState(SCE_COFFEESCRIPT_DEFAULT); - } - break; case SCE_COFFEESCRIPT_COMMENTBLOCK: if (sc.Match("###")) { sc.Forward(); @@ -357,30 +229,10 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init // Determine if a new state should be entered. if (sc.state == SCE_COFFEESCRIPT_DEFAULT) { - if (sc.Match('@', '\"')) { - sc.SetState(SCE_COFFEESCRIPT_VERBATIM); - sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - if (lastWordWasUUID) { - sc.SetState(SCE_COFFEESCRIPT_UUID); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_COFFEESCRIPT_NUMBER); - } - } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@') || (sc.ch == '$')) { - if (lastWordWasUUID) { - sc.SetState(SCE_COFFEESCRIPT_UUID); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_COFFEESCRIPT_IDENTIFIER); - } - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_COFFEESCRIPT_COMMENTDOC); - } else { - sc.SetState(SCE_COFFEESCRIPT_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_COFFEESCRIPT_NUMBER); + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_COFFEESCRIPT_IDENTIFIER); } else if (sc.Match("///")) { sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); sc.Forward(); @@ -393,9 +245,6 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init sc.SetState(SCE_COFFEESCRIPT_REGEX); // JavaScript's RegEx } else if (sc.ch == '\"') { sc.SetState(SCE_COFFEESCRIPT_STRING); - isIncludePreprocessor = false; // ensure that '>' won't end the string - } else if (isIncludePreprocessor && sc.ch == '<') { - sc.SetState(SCE_COFFEESCRIPT_STRING); } else if (sc.ch == '\'') { sc.SetState(SCE_COFFEESCRIPT_CHARACTER); } else if (sc.ch == '#') { @@ -403,7 +252,6 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK); sc.Forward(); sc.Forward(); - } else { sc.SetState(SCE_COFFEESCRIPT_COMMENTLINE); } @@ -416,7 +264,6 @@ static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int init chPrevNonWhite = sc.ch; visibleChars++; } - continuationLine = false; } sc.Complete(); } @@ -428,10 +275,6 @@ static bool IsCommentLine(int line, Accessor &styler) { char ch = styler[i]; if (ch == '#') return true; - else if (ch == '/' - && i < eol_pos - 1 - && styler[i + 1] == '*') - return true; else if (ch != ' ' && ch != '\t') return false; } @@ -563,6 +406,9 @@ static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int, static const char *const csWordLists[] = { "Keywords", + "Secondary keywords", + "Unused", + "Global classes", 0, }; diff --git a/src/stc/scintilla/lexers/LexDMIS.cxx b/src/stc/scintilla/lexers/LexDMIS.cxx new file mode 100644 index 0000000000..a903e9da65 --- /dev/null +++ b/src/stc/scintilla/lexers/LexDMIS.cxx @@ -0,0 +1,355 @@ +// Scintilla source code edit control +/** @file LexDMIS.cxx + ** Lexer for DMIS. + **/ +// Copyright 1998-2005 by Neil Hodgson +// Copyright 2013-2014 by Andreas Tscharner +// The License.txt file describes the conditions under which this software may be distributed. + + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static const char *const DMISWordListDesc[] = { + "DMIS Major Words", + "DMIS Minor Words", + "Unsupported DMIS Major Words", + "Unsupported DMIS Minor Words", + "Keywords for code folding start", + "Corresponding keywords for code folding end", + 0 +}; + + +class LexerDMIS : public ILexer +{ + private: + char *m_wordListSets; + WordList m_majorWords; + WordList m_minorWords; + WordList m_unsupportedMajor; + WordList m_unsupportedMinor; + WordList m_codeFoldingStart; + WordList m_codeFoldingEnd; + + char * SCI_METHOD UpperCase(char *item); + void SCI_METHOD InitWordListSets(void); + + public: + LexerDMIS(void); + virtual ~LexerDMIS(void); + + int SCI_METHOD Version() const { + return lvOriginal; + } + + void SCI_METHOD Release() { + delete this; + } + + const char * SCI_METHOD PropertyNames() { + return NULL; + } + + int SCI_METHOD PropertyType(const char *) { + return -1; + } + + const char * SCI_METHOD DescribeProperty(const char *) { + return NULL; + } + + int SCI_METHOD PropertySet(const char *, const char *) { + return -1; + } + + int SCI_METHOD WordListSet(int n, const char *wl); + + void * SCI_METHOD PrivateCall(int, void *) { + return NULL; + } + + static ILexer *LexerFactoryDMIS() { + return new LexerDMIS; + } + + const char * SCI_METHOD DescribeWordListSets(); + void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); +}; + + +char * SCI_METHOD LexerDMIS::UpperCase(char *item) +{ + char *itemStart; + + + itemStart = item; + while (item && *item) { + *item = toupper(*item); + item++; + }; + return itemStart; +} + +void SCI_METHOD LexerDMIS::InitWordListSets(void) +{ + size_t totalLen = 0; + + + for (int i=0; DMISWordListDesc[i]; i++) { + totalLen += strlen(DMISWordListDesc[i]); + totalLen++; + }; + + totalLen++; + this->m_wordListSets = new char[totalLen]; + memset(this->m_wordListSets, 0, totalLen); + + for (int i=0; DMISWordListDesc[i]; i++) { + strcat(this->m_wordListSets, DMISWordListDesc[i]); + strcat(this->m_wordListSets, "\n"); + }; +} + + +LexerDMIS::LexerDMIS(void) { + this->InitWordListSets(); + + this->m_majorWords.Clear(); + this->m_minorWords.Clear(); + this->m_unsupportedMajor.Clear(); + this->m_unsupportedMinor.Clear(); + this->m_codeFoldingStart.Clear(); + this->m_codeFoldingEnd.Clear(); +} + +LexerDMIS::~LexerDMIS(void) { + delete[] this->m_wordListSets; +} + +int SCI_METHOD LexerDMIS::WordListSet(int n, const char *wl) +{ + switch (n) { + case 0: + this->m_majorWords.Clear(); + this->m_majorWords.Set(wl); + break; + case 1: + this->m_minorWords.Clear(); + this->m_minorWords.Set(wl); + break; + case 2: + this->m_unsupportedMajor.Clear(); + this->m_unsupportedMajor.Set(wl); + break; + case 3: + this->m_unsupportedMinor.Clear(); + this->m_unsupportedMinor.Set(wl); + break; + case 4: + this->m_codeFoldingStart.Clear(); + this->m_codeFoldingStart.Set(wl); + break; + case 5: + this->m_codeFoldingEnd.Clear(); + this->m_codeFoldingEnd.Set(wl); + break; + default: + return -1; + break; + } + + return 0; +} + +const char * SCI_METHOD LexerDMIS::DescribeWordListSets() +{ + return this->m_wordListSets; +} + +void SCI_METHOD LexerDMIS::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) +{ + const unsigned int MAX_STR_LEN = 100; + + LexAccessor styler(pAccess); + StyleContext scCTX(startPos, lengthDoc, initStyle, styler); + CharacterSet setDMISNumber(CharacterSet::setDigits, ".-+eE"); + CharacterSet setDMISWordStart(CharacterSet::setAlpha, "-234", 0x80, true); + CharacterSet setDMISWord(CharacterSet::setAlpha); + + + bool isIFLine = false; + + for (; scCTX.More(); scCTX.Forward()) { + if (scCTX.atLineEnd) { + isIFLine = false; + }; + + switch (scCTX.state) { + case SCE_DMIS_DEFAULT: + if (scCTX.Match('$', '$')) { + scCTX.SetState(SCE_DMIS_COMMENT); + scCTX.Forward(); + }; + if (scCTX.Match('\'')) { + scCTX.SetState(SCE_DMIS_STRING); + }; + if (IsADigit(scCTX.ch) || ((scCTX.Match('-') || scCTX.Match('+')) && IsADigit(scCTX.chNext))) { + scCTX.SetState(SCE_DMIS_NUMBER); + break; + }; + if (setDMISWordStart.Contains(scCTX.ch)) { + scCTX.SetState(SCE_DMIS_KEYWORD); + }; + if (scCTX.Match('(') && (!isIFLine)) { + scCTX.SetState(SCE_DMIS_LABEL); + }; + break; + + case SCE_DMIS_COMMENT: + if (scCTX.atLineEnd) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_STRING: + if (scCTX.Match('\'')) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_NUMBER: + if (!setDMISNumber.Contains(scCTX.ch)) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_KEYWORD: + if (!setDMISWord.Contains(scCTX.ch)) { + char tmpStr[MAX_STR_LEN]; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + scCTX.GetCurrent(tmpStr, (MAX_STR_LEN-1)); + strncpy(tmpStr, this->UpperCase(tmpStr), (MAX_STR_LEN-1)); + + if (this->m_minorWords.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_MINORWORD); + }; + if (this->m_majorWords.InList(tmpStr)) { + isIFLine = (strcmp(tmpStr, "IF") == 0); + scCTX.ChangeState(SCE_DMIS_MAJORWORD); + }; + if (this->m_unsupportedMajor.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MAJOR); + }; + if (this->m_unsupportedMinor.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MINOR); + }; + + if (scCTX.Match('(') && (!isIFLine)) { + scCTX.SetState(SCE_DMIS_LABEL); + } else { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + }; + break; + + case SCE_DMIS_LABEL: + if (scCTX.Match(')')) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + }; + }; + scCTX.Complete(); +} + +void SCI_METHOD LexerDMIS::Fold(unsigned int startPos, int lengthDoc, int, IDocument *pAccess) +{ + const int MAX_STR_LEN = 100; + + LexAccessor styler(pAccess); + unsigned int endPos = startPos + lengthDoc; + char chNext = styler[startPos]; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int strPos = 0; + bool foldWordPossible = false; + CharacterSet setDMISFoldWord(CharacterSet::setAlpha); + char *tmpStr; + + + tmpStr = new char[MAX_STR_LEN]; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + + for (unsigned int i=startPos; i= (MAX_STR_LEN-1)) { + strPos = MAX_STR_LEN-1; + }; + + int style = styler.StyleAt(i); + bool noFoldPos = ((style == SCE_DMIS_COMMENT) || (style == SCE_DMIS_STRING)); + + if (foldWordPossible) { + if (setDMISFoldWord.Contains(ch)) { + tmpStr[strPos++] = ch; + } else { + tmpStr = this->UpperCase(tmpStr); + if (this->m_codeFoldingStart.InList(tmpStr) && (!noFoldPos)) { + levelCurrent++; + }; + if (this->m_codeFoldingEnd.InList(tmpStr) && (!noFoldPos)) { + levelCurrent--; + }; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + strPos = 0; + foldWordPossible = false; + }; + } else { + if (setDMISFoldWord.Contains(ch)) { + tmpStr[strPos++] = ch; + foldWordPossible = true; + }; + }; + + if (atEOL || (i == (endPos-1))) { + int lev = levelPrev; + + if (levelCurrent > levelPrev) { + lev |= SC_FOLDLEVELHEADERFLAG; + }; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + }; + lineCurrent++; + levelPrev = levelCurrent; + }; + }; + delete[] tmpStr; +} + + +LexerModule lmDMIS(SCLEX_DMIS, LexerDMIS::LexerFactoryDMIS, "DMIS", DMISWordListDesc); diff --git a/src/stc/scintilla/lexers/LexECL.cxx b/src/stc/scintilla/lexers/LexECL.cxx index 6a08d58c25..d8065f7226 100644 --- a/src/stc/scintilla/lexers/LexECL.cxx +++ b/src/stc/scintilla/lexers/LexECL.cxx @@ -7,10 +7,10 @@ #include #include -#include #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable: 4786) diff --git a/src/stc/scintilla/lexers/LexEScript.cxx b/src/stc/scintilla/lexers/LexEScript.cxx index 9a7560e1e4..28466bc8e0 100644 --- a/src/stc/scintilla/lexers/LexEScript.cxx +++ b/src/stc/scintilla/lexers/LexEScript.cxx @@ -6,10 +6,10 @@ #include #include -#include #include #include #include +#include #include "ILexer.h" #include "Scintilla.h" diff --git a/src/stc/scintilla/lexers/LexFortran.cxx b/src/stc/scintilla/lexers/LexFortran.cxx index 0c65a6ca50..5deaf11737 100644 --- a/src/stc/scintilla/lexers/LexFortran.cxx +++ b/src/stc/scintilla/lexers/LexFortran.cxx @@ -1,7 +1,7 @@ // Scintilla source code edit control /** @file LexFortran.cxx ** Lexer for Fortran. - ** Writen by Chuan-jian Shen, Last changed Sep. 2003 + ** Written by Chuan-jian Shen, Last changed Sep. 2003 **/ // Copyright 1998-2001 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. @@ -455,11 +455,11 @@ static void FoldFortranDoc(unsigned int startPos, int length, int initStyle, if (strcmp(s, "do") == 0 && IsADigit(chNextNonBlank)) { // Remove delta for do-label levelDeltaNext -= wordLevelDelta; - } } + } strcpy(prevWord, s); } - } + } if (atEOL) { int lev = levelCurrent; if (visibleChars == 0 && foldCompact) diff --git a/src/stc/scintilla/lexers/LexHTML.cxx b/src/stc/scintilla/lexers/LexHTML.cxx index 5ea24d481d..02047930ce 100644 --- a/src/stc/scintilla/lexers/LexHTML.cxx +++ b/src/stc/scintilla/lexers/LexHTML.cxx @@ -576,8 +576,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty WordList &keywords5 = *keywordlists[4]; WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords - // Lexer for HTML requires more lexical states (8 bits worth) than most lexers - styler.StartAt(startPos, static_cast(STYLE_MAX)); + styler.StartAt(startPos); char prevWord[200]; prevWord[0] = '\0'; char phpStringDelimiter[200]; // PHP is not limited in length, we are @@ -609,7 +608,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty if (startPos == 0) state = SCE_H_DEFAULT; } - styler.StartAt(startPos, static_cast(STYLE_MAX)); + styler.StartAt(startPos); int lineCurrent = styler.GetLine(startPos); int lineState; @@ -811,8 +810,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } styler.SetLineState(lineCurrent, ((inScriptType & 0x03) << 0) | - ((tagOpened & 0x01) << 2) | - ((tagClosing & 0x01) << 3) | + ((tagOpened ? 1 : 0) << 2) | + ((tagClosing ? 1 : 0) << 3) | ((aspScript & 0x0F) << 4) | ((clientScript & 0x0F) << 8) | ((beforePreProc & 0xFF) << 12)); @@ -823,19 +822,27 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty // handle start of Mako comment line if (isMako && ch == '#' && chNext == '#') { makoComment = 1; + state = SCE_HP_COMMENTLINE; } // handle end of Mako comment line else if (isMako && makoComment && (ch == '\r' || ch == '\n')) { makoComment = 0; - styler.ColourTo(i, SCE_HP_COMMENTLINE); - state = SCE_HP_DEFAULT; + styler.ColourTo(i, StateToPrint); + if (scriptLanguage == eScriptPython) { + state = SCE_HP_DEFAULT; + } else { + state = SCE_H_DEFAULT; + } } // Allow falling through to mako handling code if newline is going to end a block if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && (!isMako || (0 != strcmp(makoBlockType, "%")))) { } + // Ignore everything in mako comment until the line ends + else if (isMako && makoComment) { + } // generic end of script processing else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { @@ -2180,6 +2187,6 @@ static const char * const phpscriptWordListDesc[] = { 0, }; -LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8); -LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8); -LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8); +LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc); +LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc); +LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc); diff --git a/src/stc/scintilla/lexers/LexHaskell.cxx b/src/stc/scintilla/lexers/LexHaskell.cxx index e10cb8c810..24355fa4e4 100644 --- a/src/stc/scintilla/lexers/LexHaskell.cxx +++ b/src/stc/scintilla/lexers/LexHaskell.cxx @@ -38,9 +38,9 @@ #include "Accessor.h" #include "StyleContext.h" #include "CharacterSet.h" +#include "CharacterCategory.h" #include "LexerModule.h" #include "OptionSet.h" -#include "CharacterCategory.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/lexers/LexHex.cxx b/src/stc/scintilla/lexers/LexHex.cxx new file mode 100644 index 0000000000..fe972ffe82 --- /dev/null +++ b/src/stc/scintilla/lexers/LexHex.cxx @@ -0,0 +1,1045 @@ +// Scintilla source code edit control +/** @file LexHex.cxx + ** Lexers for Motorola S-Record, Intel HEX and Tektronix extended HEX. + ** + ** Written by Markus Heidelberg + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +/* + * Motorola S-Record + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 ('S') SCE_HEX_RECSTART + * +----------+ + * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | address | 4/6/8 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, SCE_HEX_RECCOUNT, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | data | 0..504/502/500 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, (SCE_HEX_DATA_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * + * + * Intel HEX + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 (':') SCE_HEX_RECSTART + * +----------+ + * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | address | 4 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | type | 2 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | data | 0..510 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, SCE_HEX_EXTENDEDADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_DATA_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * + * + * Folding: + * + * Data records (type 0x00), which follow an extended address record (type + * 0x02 or 0x04), can be folded. The extended address record is the fold + * point at fold level 0, the corresponding data records are set to level 1. + * + * Any record, which is not a data record, sets the fold level back to 0. + * Any line, which is not a record (blank lines and lines starting with a + * character other than ':'), leaves the fold level unchanged. + * + * + * Tektronix extended HEX + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 ('%') SCE_HEX_RECSTART + * +----------+ + * | length | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * | address | 9 SCE_HEX_DATAADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | data | 0..241 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN + * +----------+ + * + * + * General notes for all lexers + * =============================== + * + * - Depending on where the helper functions are invoked, some of them have to + * read beyond the current position. In case of malformed data (record too + * short), it has to be ensured that this either does not have bad influence + * or will be captured deliberately. + * + * - States in parentheses in the upper format descriptions indicate that they + * should not appear in a valid hex file. + * + * - State SCE_HEX_GARBAGE means garbage data after the intended end of the + * record, the line is too long then. This state is used in all lexers. + */ + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// prototypes for general helper functions +static inline bool IsNewline(const int ch); +static int GetHexaNibble(char hd); +static int GetHexaChar(char hd1, char hd2); +static int GetHexaChar(unsigned int pos, Accessor &styler); +static bool ForwardWithinLine(StyleContext &sc, int nb = 1); +static bool PosInSameRecord(unsigned int pos1, unsigned int pos2, Accessor &styler); +static int CountByteCount(unsigned int startPos, int uncountedDigits, Accessor &styler); +static int CalcChecksum(unsigned int startPos, int cnt, bool twosCompl, Accessor &styler); + +// prototypes for file format specific helper functions +static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler); +static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler); +static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler); +static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler); +static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler); +static int GetSrecDataFieldType(unsigned int recStartPos, Accessor &styler); +static int GetSrecRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler); +static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler); +static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler); + +static unsigned int GetIHexRecStartPosition(unsigned int pos, Accessor &styler); +static int GetIHexByteCount(unsigned int recStartPos, Accessor &styler); +static int CountIHexByteCount(unsigned int recStartPos, Accessor &styler); +static int GetIHexAddressFieldType(unsigned int recStartPos, Accessor &styler); +static int GetIHexDataFieldType(unsigned int recStartPos, Accessor &styler); +static int GetIHexRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler); +static int GetIHexChecksum(unsigned int recStartPos, Accessor &styler); +static int CalcIHexChecksum(unsigned int recStartPos, Accessor &styler); + +static int GetTEHexDigitCount(unsigned int recStartPos, Accessor &styler); +static int CountTEHexDigitCount(unsigned int recStartPos, Accessor &styler); +static int GetTEHexAddressFieldType(unsigned int recStartPos, Accessor &styler); +static int GetTEHexChecksum(unsigned int recStartPos, Accessor &styler); +static int CalcTEHexChecksum(unsigned int recStartPos, Accessor &styler); + +static inline bool IsNewline(const int ch) +{ + return (ch == '\n' || ch == '\r'); +} + +static int GetHexaNibble(char hd) +{ + int hexValue = 0; + + if (hd >= '0' && hd <= '9') { + hexValue += hd - '0'; + } else if (hd >= 'A' && hd <= 'F') { + hexValue += hd - 'A' + 10; + } else if (hd >= 'a' && hd <= 'f') { + hexValue += hd - 'a' + 10; + } else { + return -1; + } + + return hexValue; +} + +static int GetHexaChar(char hd1, char hd2) +{ + int hexValue = 0; + + if (hd1 >= '0' && hd1 <= '9') { + hexValue += 16 * (hd1 - '0'); + } else if (hd1 >= 'A' && hd1 <= 'F') { + hexValue += 16 * (hd1 - 'A' + 10); + } else if (hd1 >= 'a' && hd1 <= 'f') { + hexValue += 16 * (hd1 - 'a' + 10); + } else { + return -1; + } + + if (hd2 >= '0' && hd2 <= '9') { + hexValue += hd2 - '0'; + } else if (hd2 >= 'A' && hd2 <= 'F') { + hexValue += hd2 - 'A' + 10; + } else if (hd2 >= 'a' && hd2 <= 'f') { + hexValue += hd2 - 'a' + 10; + } else { + return -1; + } + + return hexValue; +} + +static int GetHexaChar(unsigned int pos, Accessor &styler) +{ + char highNibble, lowNibble; + + highNibble = styler.SafeGetCharAt(pos); + lowNibble = styler.SafeGetCharAt(pos + 1); + + return GetHexaChar(highNibble, lowNibble); +} + +// Forward characters, but abort (and return false) if hitting the line +// end. Return true if forwarding within the line was possible. +// Avoids influence on highlighting of the subsequent line if the current line +// is malformed (too short). +static bool ForwardWithinLine(StyleContext &sc, int nb) +{ + for (int i = 0; i < nb; i++) { + if (sc.atLineEnd) { + // line is too short + sc.SetState(SCE_HEX_DEFAULT); + sc.Forward(); + return false; + } else { + sc.Forward(); + } + } + + return true; +} + +// Checks whether the given positions are in the same record. +static bool PosInSameRecord(unsigned int pos1, unsigned int pos2, Accessor &styler) +{ + return styler.GetLine(pos1) == styler.GetLine(pos2); +} + +// Count the number of digit pairs from till end of record, ignoring +// digits. +// If the record is too short, a negative count may be returned. +static int CountByteCount(unsigned int startPos, int uncountedDigits, Accessor &styler) +{ + int cnt; + unsigned int pos; + + pos = startPos; + + while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) { + pos++; + } + + // number of digits in this line minus number of digits of uncounted fields + cnt = static_cast(pos - startPos) - uncountedDigits; + + // Prepare round up if odd (digit pair incomplete), this way the byte + // count is considered to be valid if the checksum is incomplete. + if (cnt >= 0) { + cnt++; + } + + // digit pairs + cnt /= 2; + + return cnt; +} + +// Calculate the checksum of the record. +// is the position of the first character of the starting digit +// pair, is the number of digit pairs. +static int CalcChecksum(unsigned int startPos, int cnt, bool twosCompl, Accessor &styler) +{ + int cs = 0; + + for (unsigned int pos = startPos; pos < startPos + cnt; pos += 2) { + int val = GetHexaChar(pos, styler); + + if (val < 0) { + return val; + } + + // overflow does not matter + cs += val; + } + + if (twosCompl) { + // low byte of two's complement + return -cs & 0xFF; + } else { + // low byte of one's complement + return ~cs & 0xFF; + } +} + +// Get the position of the record "start" field (first character in line) in +// the record around position . +static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler) +{ + while (styler.SafeGetCharAt(pos) != 'S') { + pos--; + } + + return pos; +} + +// Get the value of the "byte count" field, it counts the number of bytes in +// the subsequent fields ("address", "data" and "checksum" fields). +static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler) +{ + int val; + + val = GetHexaChar(recStartPos + 2, styler); + if (val < 0) { + val = 0; + } + + return val; +} + +// Count the number of digit pairs for the "address", "data" and "checksum" +// fields in this record. Has to be equal to the "byte count" field value. +// If the record is too short, a negative count may be returned. +static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler) +{ + return CountByteCount(recStartPos, 4, styler); +} + +// Get the size of the "address" field. +static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + case '1': + case '5': + case '9': + return 2; // 16 bit + + case '2': + case '6': + case '8': + return 3; // 24 bit + + case '3': + case '7': + return 4; // 32 bit + + default: + return 0; + } +} + +// Get the type of the "address" field content. +static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + return SCE_HEX_NOADDRESS; + + case '1': + case '2': + case '3': + return SCE_HEX_DATAADDRESS; + + case '5': + case '6': + return SCE_HEX_RECCOUNT; + + case '7': + case '8': + case '9': + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the type of the "data" field content. +static int GetSrecDataFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + case '1': + case '2': + case '3': + return SCE_HEX_DATA_ODD; + + case '5': + case '6': + case '7': + case '8': + case '9': + return SCE_HEX_DATA_EMPTY; + + default: // handle possible format extension in the future + return SCE_HEX_DATA_UNKNOWN; + } +} + +// Get the required size of the "data" field. Useless for block header and +// ordinary data records (type S0, S1, S2, S3), return the value calculated +// from the "byte count" and "address field" size in this case. +static int GetSrecRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '5': + case '6': + case '7': + case '8': + case '9': + return 0; + + default: + return GetSrecByteCount(recStartPos, styler) + - GetSrecAddressFieldSize(recStartPos, styler) + - 1; // -1 for checksum field + } +} + +// Get the value of the "checksum" field. +static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetSrecByteCount(recStartPos, styler); + + return GetHexaChar(recStartPos + 2 + byteCount * 2, styler); +} + +// Calculate the checksum of the record. +static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetSrecByteCount(recStartPos, styler); + + // sum over "byte count", "address" and "data" fields (6..510 digits) + return CalcChecksum(recStartPos + 2, byteCount * 2, false, styler); +} + +// Get the position of the record "start" field (first character in line) in +// the record around position . +static unsigned int GetIHexRecStartPosition(unsigned int pos, Accessor &styler) +{ + while (styler.SafeGetCharAt(pos) != ':') { + pos--; + } + + return pos; +} + +// Get the value of the "byte count" field, it counts the number of bytes in +// the "data" field. +static int GetIHexByteCount(unsigned int recStartPos, Accessor &styler) +{ + int val; + + val = GetHexaChar(recStartPos + 1, styler); + if (val < 0) { + val = 0; + } + + return val; +} + +// Count the number of digit pairs for the "data" field in this record. Has to +// be equal to the "byte count" field value. +// If the record is too short, a negative count may be returned. +static int CountIHexByteCount(unsigned int recStartPos, Accessor &styler) +{ + return CountByteCount(recStartPos, 11, styler); +} + +// Get the type of the "address" field content. +static int GetIHexAddressFieldType(unsigned int recStartPos, Accessor &styler) +{ + if (!PosInSameRecord(recStartPos, recStartPos + 7, styler)) { + // malformed (record too short) + // type cannot be determined + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } + + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x00: + return SCE_HEX_DATAADDRESS; + + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + return SCE_HEX_NOADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the type of the "data" field content. +static int GetIHexDataFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x00: + return SCE_HEX_DATA_ODD; + + case 0x01: + return SCE_HEX_DATA_EMPTY; + + case 0x02: + case 0x04: + return SCE_HEX_EXTENDEDADDRESS; + + case 0x03: + case 0x05: + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_DATA_UNKNOWN; + } +} + +// Get the required size of the "data" field. Useless for an ordinary data +// record (type 00), return the "byte count" in this case. +static int GetIHexRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler) +{ + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x01: + return 0; + + case 0x02: + case 0x04: + return 2; + + case 0x03: + case 0x05: + return 4; + + default: + return GetIHexByteCount(recStartPos, styler); + } +} + +// Get the value of the "checksum" field. +static int GetIHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetIHexByteCount(recStartPos, styler); + + return GetHexaChar(recStartPos + 9 + byteCount * 2, styler); +} + +// Calculate the checksum of the record. +static int CalcIHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetIHexByteCount(recStartPos, styler); + + // sum over "byte count", "address", "type" and "data" fields (8..518 digits) + return CalcChecksum(recStartPos + 1, 8 + byteCount * 2, true, styler); +} + + +// Get the value of the "record length" field, it counts the number of digits in +// the record excluding the percent. +static int GetTEHexDigitCount(unsigned int recStartPos, Accessor &styler) +{ + int val = GetHexaChar(recStartPos + 1, styler); + if (val < 0) + val = 0; + + return val; +} + +// Count the number of digits in this record. Has to +// be equal to the "record length" field value. +static int CountTEHexDigitCount(unsigned int recStartPos, Accessor &styler) +{ + unsigned int pos; + + pos = recStartPos+1; + + while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) { + pos++; + } + + return static_cast(pos - (recStartPos+1)); +} + +// Get the type of the "address" field content. +static int GetTEHexAddressFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 3)) { + case '6': + return SCE_HEX_DATAADDRESS; + + case '8': + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the value of the "checksum" field. +static int GetTEHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + return GetHexaChar(recStartPos+4, styler); +} + +// Calculate the checksum of the record (excluding the checksum field). +static int CalcTEHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + unsigned int pos = recStartPos +1; + unsigned int length = GetTEHexDigitCount(recStartPos, styler); + + int cs = GetHexaNibble(styler.SafeGetCharAt(pos++));//length + cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//length + + cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//type + + pos += 2;// jump over CS field + + for (; pos <= recStartPos + length; ++pos) { + int val = GetHexaNibble(styler.SafeGetCharAt(pos)); + + if (val < 0) { + return val; + } + + // overflow does not matter + cs += val; + } + + // low byte + return cs & 0xFF; + +} + +static void ColouriseSrecDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + unsigned int recStartPos; + int byteCount, reqByteCount, addrFieldSize, addrFieldType, dataFieldSize, dataFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match('S')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + recStartPos = sc.currentPos - 1; + addrFieldType = GetSrecAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 2; + byteCount = GetSrecByteCount(recStartPos, styler); + reqByteCount = GetSrecAddressFieldSize(recStartPos, styler) + + GetSrecRequiredDataFieldSize(recStartPos, styler) + + 1; // +1 for checksum field + + if (byteCount == CountSrecByteCount(recStartPos, styler) + && byteCount == reqByteCount) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 4; + addrFieldSize = GetSrecAddressFieldSize(recStartPos, styler); + addrFieldType = GetSrecAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, addrFieldSize * 2); + break; + + case SCE_HEX_NOADDRESS: + case SCE_HEX_DATAADDRESS: + case SCE_HEX_RECCOUNT: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = GetSrecRecStartPosition(sc.currentPos, styler); + dataFieldType = GetSrecDataFieldType(recStartPos, styler); + + // Using the required size here if possible has the effect that the + // checksum is highlighted at a fixed position after this field for + // specific record types, independent on the "byte count" value. + dataFieldSize = GetSrecRequiredDataFieldSize(recStartPos, styler); + + sc.SetState(dataFieldType); + + if (dataFieldType == SCE_HEX_DATA_ODD) { + for (int i = 0; i < dataFieldSize * 2; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + } else { + ForwardWithinLine(sc, dataFieldSize * 2); + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_DATA_EMPTY: + case SCE_HEX_DATA_UNKNOWN: + recStartPos = GetSrecRecStartPosition(sc.currentPos, styler); + cs1 = CalcSrecChecksum(recStartPos, styler); + cs2 = GetSrecChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +static void ColouriseIHexDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + unsigned int recStartPos; + int byteCount, addrFieldType, dataFieldSize, dataFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match(':')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + recStartPos = sc.currentPos - 1; + byteCount = GetIHexByteCount(recStartPos, styler); + dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler); + + if (byteCount == CountIHexByteCount(recStartPos, styler) + && byteCount == dataFieldSize) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 3; + addrFieldType = GetIHexAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, 4); + break; + + case SCE_HEX_NOADDRESS: + case SCE_HEX_DATAADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = sc.currentPos - 7; + addrFieldType = GetIHexAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 9; + dataFieldType = GetIHexDataFieldType(recStartPos, styler); + + // Using the required size here if possible has the effect that the + // checksum is highlighted at a fixed position after this field for + // specific record types, independent on the "byte count" value. + dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler); + + sc.SetState(dataFieldType); + + if (dataFieldType == SCE_HEX_DATA_ODD) { + for (int i = 0; i < dataFieldSize * 2; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + } else { + ForwardWithinLine(sc, dataFieldSize * 2); + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_DATA_EMPTY: + case SCE_HEX_EXTENDEDADDRESS: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_DATA_UNKNOWN: + recStartPos = GetIHexRecStartPosition(sc.currentPos, styler); + cs1 = CalcIHexChecksum(recStartPos, styler); + cs2 = GetIHexChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +static void FoldIHexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + unsigned int endPos = startPos + length; + + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1); + + unsigned int lineStartNext = styler.LineStart(lineCurrent + 1); + int levelNext = SC_FOLDLEVELBASE; // default if no specific line found + + for (unsigned int i = startPos; i < endPos; i++) { + bool atEOL = i == (lineStartNext - 1); + int style = styler.StyleAt(i); + + // search for specific lines + if (style == SCE_HEX_EXTENDEDADDRESS) { + // extended addres record + levelNext = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + } else if (style == SCE_HEX_DATAADDRESS + || (style == SCE_HEX_DEFAULT + && i == (unsigned int)styler.LineStart(lineCurrent))) { + // data record or no record start code at all + if (levelCurrent & SC_FOLDLEVELHEADERFLAG) { + levelNext = SC_FOLDLEVELBASE + 1; + } else { + // continue level 0 or 1, no fold point + levelNext = levelCurrent; + } + } + + if (atEOL || (i == endPos - 1)) { + styler.SetLevel(lineCurrent, levelNext); + + lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent + 1); + levelCurrent = levelNext; + levelNext = SC_FOLDLEVELBASE; + } + } +} + +static void ColouriseTEHexDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + unsigned int recStartPos; + int digitCount, addrFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match('%')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + + recStartPos = sc.currentPos - 1; + + if (GetTEHexDigitCount(recStartPos, styler) == CountTEHexDigitCount(recStartPos, styler)) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 3; + addrFieldType = GetTEHexAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 4; + cs1 = CalcTEHexChecksum(recStartPos, styler); + cs2 = GetTEHexChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + recStartPos = sc.currentPos - 6; + addrFieldType = GetTEHexAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, 9); + break; + + case SCE_HEX_DATAADDRESS: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = sc.currentPos - 15; + digitCount = GetTEHexDigitCount(recStartPos, styler) - 14; + + sc.SetState(SCE_HEX_DATA_ODD); + + for (int i = 0; i < digitCount; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +LexerModule lmSrec(SCLEX_SREC, ColouriseSrecDoc, "srec", 0, NULL); +LexerModule lmIHex(SCLEX_IHEX, ColouriseIHexDoc, "ihex", FoldIHexDoc, NULL); +LexerModule lmTEHex(SCLEX_TEHEX, ColouriseTEHexDoc, "tehex", 0, NULL); diff --git a/src/stc/scintilla/lexers/LexKVIrc.cxx b/src/stc/scintilla/lexers/LexKVIrc.cxx index 67bcb43a6c..958a2cf67c 100644 --- a/src/stc/scintilla/lexers/LexKVIrc.cxx +++ b/src/stc/scintilla/lexers/LexKVIrc.cxx @@ -359,7 +359,7 @@ static void FoldKVIrcDoc(unsigned int startPos, int length, int /*initStyle - un WordList *[], Accessor &styler) { /* Based on CMake's folder */ - + /* Exiting if folding isnt enabled */ if ( styler.GetPropertyInt("fold") == 0 ) return; diff --git a/src/stc/scintilla/lexers/LexKix.cxx b/src/stc/scintilla/lexers/LexKix.cxx index 32af263fdf..dc509e4caa 100644 --- a/src/stc/scintilla/lexers/LexKix.cxx +++ b/src/stc/scintilla/lexers/LexKix.cxx @@ -4,6 +4,7 @@ **/ // Copyright 2004 by Manfred Becker // The License.txt file describes the conditions under which this software may be distributed. +// Edited by Lee Wilmott (24-Jun-2014) added support for block comments #include #include @@ -54,6 +55,10 @@ static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd) { sc.SetState(SCE_KIX_DEFAULT); } + } else if (sc.state == SCE_KIX_COMMENTSTREAM) { + if (sc.ch == '/' && sc.chPrev == '*') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } } else if (sc.state == SCE_KIX_STRING1) { // This is a doubles quotes string if (sc.ch == '\"') { @@ -104,6 +109,8 @@ static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, if (sc.state == SCE_KIX_DEFAULT) { if (sc.ch == ';') { sc.SetState(SCE_KIX_COMMENT); + } else if (sc.ch == '/' && sc.chNext == '*') { + sc.SetState(SCE_KIX_COMMENTSTREAM); } else if (sc.ch == '\"') { sc.SetState(SCE_KIX_STRING1); } else if (sc.ch == '\'') { diff --git a/src/stc/scintilla/lexers/LexLaTeX.cxx b/src/stc/scintilla/lexers/LexLaTeX.cxx index 7cfa8a197f..f8af1e7dcc 100644 --- a/src/stc/scintilla/lexers/LexLaTeX.cxx +++ b/src/stc/scintilla/lexers/LexLaTeX.cxx @@ -60,7 +60,7 @@ private: if (static_cast(modes.size()) > numLines * 2 + 256) modes.resize(numLines + 128); } - + vector saves; void setSave(int line, const latexFoldSave &save) { if (line >= static_cast(saves.size())) saves.resize(line + 1); @@ -192,7 +192,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle int state = initStyle; if (state == SCE_L_ERROR || state == SCE_L_SHORTCMD || state == SCE_L_SPECIAL) // should not happen latexStateReset(mode, state); - + char chNext = styler.SafeGetCharAt(startPos); char chVerbatimDelim = '\0'; styler.StartSegment(startPos); @@ -207,7 +207,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle chNext = styler.SafeGetCharAt(i + 1); continue; } - + if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode); @@ -256,7 +256,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle state = SCE_L_COMMENT; break; } - break; + break; // These 3 will never be reached. case SCE_L_ERROR: case SCE_L_SPECIAL: @@ -400,7 +400,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle chNext = styler.SafeGetCharAt(i + 1); mode = 0; state = SCE_L_DEFAULT; - } else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation} + } else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation} styler.ColourTo(i, SCE_L_SHORTCMD); } break; diff --git a/src/stc/scintilla/lexers/LexLua.cxx b/src/stc/scintilla/lexers/LexLua.cxx index 62bb44dd1c..fd0d70fd4d 100644 --- a/src/stc/scintilla/lexers/LexLua.cxx +++ b/src/stc/scintilla/lexers/LexLua.cxx @@ -141,7 +141,7 @@ static void ColouriseLuaDoc( char s[100]; while (setWord.Contains(c = sc.GetRelative(ln))) { // get potential label if (i < 90) - s[i++] = c; + s[i++] = static_cast(c); ln++; } s[i] = '\0'; int lbl = ln; diff --git a/src/stc/scintilla/lexers/LexMatlab.cxx b/src/stc/scintilla/lexers/LexMatlab.cxx index 6fbbc438e0..4dfd512c83 100644 --- a/src/stc/scintilla/lexers/LexMatlab.cxx +++ b/src/stc/scintilla/lexers/LexMatlab.cxx @@ -12,6 +12,9 @@ ** - added ... displayed as a comment ** - removed unused IsAWord functions ** - added some comments + ** + ** Changes by John Donoghue 2014/08/01 + ** - fix allowed transpose ' after {} operator **/ // Copyright 1998-2001 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. @@ -64,7 +67,7 @@ static void ColouriseMatlabOctaveDoc( styler.StartAt(startPos); - // boolean for when the ' is allowed to be transpose vs the start/end + // boolean for when the ' is allowed to be transpose vs the start/end // of a string bool transpose = false; @@ -82,14 +85,14 @@ static void ColouriseMatlabOctaveDoc( for (; sc.More(); sc.Forward(), column++) { - if(sc.atLineStart) { - // set the line state to the current commentDepth + if(sc.atLineStart) { + // set the line state to the current commentDepth curLine = styler.GetLine(sc.currentPos); styler.SetLineState(curLine, commentDepth); // reset the column to 0, nonSpace to -1 (not set) column = 0; - nonSpaceColumn = -1; + nonSpaceColumn = -1; } // save the column position of first non space character in a line @@ -108,7 +111,7 @@ static void ColouriseMatlabOctaveDoc( sc.ForwardSetState(SCE_MATLAB_DEFAULT); transpose = true; } else if(sc.ch == '.' && sc.chNext == '.') { - // we werent an operator, but a '...' + // we werent an operator, but a '...' sc.ChangeState(SCE_MATLAB_COMMENT); transpose = false; } else { @@ -161,8 +164,8 @@ static void ColouriseMatlabOctaveDoc( } else if (sc.state == SCE_MATLAB_COMMENT) { // end or start of a nested a block comment? if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column) { - if(commentDepth > 0) commentDepth --; - + if(commentDepth > 0) commentDepth --; + curLine = styler.GetLine(sc.currentPos); styler.SetLineState(curLine, commentDepth); sc.Forward(); @@ -174,7 +177,7 @@ static void ColouriseMatlabOctaveDoc( } else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column) { - commentDepth ++; + commentDepth ++; curLine = styler.GetLine(sc.currentPos); styler.SetLineState(curLine, commentDepth); @@ -218,7 +221,7 @@ static void ColouriseMatlabOctaveDoc( } else if (isalpha(sc.ch)) { sc.SetState(SCE_MATLAB_KEYWORD); } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '\\') { - if (sc.ch == ')' || sc.ch == ']') { + if (sc.ch == ')' || sc.ch == ']' || sc.ch == '}') { transpose = true; } else { transpose = false; diff --git a/src/stc/scintilla/lexers/LexMySQL.cxx b/src/stc/scintilla/lexers/LexMySQL.cxx index d3e0033b09..b873ccda1f 100644 --- a/src/stc/scintilla/lexers/LexMySQL.cxx +++ b/src/stc/scintilla/lexers/LexMySQL.cxx @@ -570,4 +570,4 @@ static const char * const mysqlWordListDesc[] = { 0 }; -LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc, 7); +LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc); diff --git a/src/stc/scintilla/lexers/LexPO.cxx b/src/stc/scintilla/lexers/LexPO.cxx index fb0c769241..7b44107cfa 100644 --- a/src/stc/scintilla/lexers/LexPO.cxx +++ b/src/stc/scintilla/lexers/LexPO.cxx @@ -41,7 +41,7 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor int curLine = styler.GetLine(startPos); // the line state holds the last state on or before the line that isn't the default style int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : SCE_PO_DEFAULT; - + for (; sc.More(); sc.Forward()) { // whether we should leave a state switch (sc.state) { @@ -57,19 +57,19 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor // on its own like a keyword rather than changing the whole flags style sc.ChangeState(SCE_PO_FUZZY); break; - + case SCE_PO_MSGCTXT: case SCE_PO_MSGID: case SCE_PO_MSGSTR: if (isspacechar(sc.ch)) sc.SetState(SCE_PO_DEFAULT); break; - + case SCE_PO_ERROR: if (sc.atLineEnd) sc.SetState(SCE_PO_DEFAULT); break; - + case SCE_PO_MSGCTXT_TEXT: case SCE_PO_MSGID_TEXT: case SCE_PO_MSGSTR_TEXT: @@ -92,7 +92,7 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor } break; } - + // whether we should enter a new state if (sc.state == SCE_PO_DEFAULT) { // forward to the first non-white character on the line @@ -103,11 +103,11 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor // and anyway the styling don't use line state for comments if (curLineState == SCE_PO_COMMENT) curLineState = SCE_PO_DEFAULT; - + while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch)) sc.Forward(); } - + if (atLineStart && sc.ch == '#') { if (sc.chNext == '.') sc.SetState(SCE_PO_PROGRAMMER_COMMENT); @@ -134,11 +134,11 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor sc.SetState(SCE_PO_ERROR); } else if (! isspacechar(sc.ch)) sc.SetState(SCE_PO_ERROR); - + if (sc.state != SCE_PO_DEFAULT) curLineState = sc.state; } - + if (sc.atLineEnd) { // Update the line state, so it can be seen by next line curLine = styler.GetLine(sc.currentPos); @@ -163,7 +163,7 @@ static void FoldPODoc(unsigned int startPos, int length, int, WordList *[], Acce return; bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - + unsigned int endPos = startPos + length; int curLine = styler.GetLine(startPos); int lineState = styler.GetLineState(curLine); @@ -172,17 +172,17 @@ static void FoldPODoc(unsigned int startPos, int length, int, WordList *[], Acce int nextLevel; int visible = 0; int chNext = styler[startPos]; - + for (unsigned int i = startPos; i < endPos; i++) { int ch = chNext; chNext = styler.SafeGetCharAt(i+1); - + if (! isspacechar(ch)) { visible++; } else if ((ch == '\r' && chNext != '\n') || ch == '\n' || i+1 >= endPos) { int lvl = level; int nextLine = curLine + 1; - + nextLineState = styler.GetLineState(nextLine); if ((lineState != SCE_PO_COMMENT || foldComment) && nextLineState == lineState && @@ -190,14 +190,14 @@ static void FoldPODoc(unsigned int startPos, int length, int, WordList *[], Acce nextLevel = SC_FOLDLEVELBASE + 1; else nextLevel = SC_FOLDLEVELBASE; - + if (nextLevel > level) lvl |= SC_FOLDLEVELHEADERFLAG; if (visible == 0 && foldCompact) lvl |= SC_FOLDLEVELWHITEFLAG; - + styler.SetLevel(curLine, lvl); - + lineState = nextLineState; curLine = nextLine; level = nextLevel; diff --git a/src/stc/scintilla/lexers/LexPS.cxx b/src/stc/scintilla/lexers/LexPS.cxx index 3661c4b66e..2c8917daea 100644 --- a/src/stc/scintilla/lexers/LexPS.cxx +++ b/src/stc/scintilla/lexers/LexPS.cxx @@ -6,6 +6,12 @@ ** The License.txt file describes the conditions under which this software may be distributed. **/ +// Previous releases of this lexer included support for marking token starts with +// a style byte indicator. This was used by the wxGhostscript IDE/debugger. +// Style byte indicators were removed in version 3.4.3. +// Anyone wanting to restore this functionality for wxGhostscript using 'modern' +// indicators can examine the earlier source in the Mercurial repository. + #include #include #include @@ -72,7 +78,6 @@ static void ColourisePSDoc( StyleContext sc(startPos, length, initStyle, styler); - bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0; int pslevel = styler.GetPropertyInt("ps.level", 3); int lineCurrent = styler.GetLine(startPos); int nestTextCurrent = 0; @@ -83,15 +88,6 @@ static void ColourisePSDoc( bool numHasExponent = false; bool numHasSign = false; - // Clear out existing tokenization - if (tokenizing && length > 0) { - styler.StartAt(startPos, static_cast(INDIC2_MASK)); - styler.ColourTo(startPos + length-1, 0); - styler.Flush(); - styler.StartAt(startPos); - styler.StartSegment(startPos); - } - for (; sc.More(); sc.Forward()) { if (sc.atLineStart) lineCurrent = styler.GetLine(sc.currentPos); @@ -196,7 +192,6 @@ static void ColourisePSDoc( // Determine if a new state should be entered. if (sc.state == SCE_C_DEFAULT) { - unsigned int tokenpos = sc.currentPos; if (sc.ch == '[' || sc.ch == ']') { sc.SetState(SCE_PS_PAREN_ARRAY); @@ -262,17 +257,6 @@ static void ColourisePSDoc( } else if (!IsAWhitespaceChar(sc.ch)) { sc.SetState(SCE_PS_NAME); } - - // Mark the start of tokens - if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT && - sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) { - styler.Flush(); - styler.StartAt(tokenpos, static_cast(INDIC2_MASK)); - styler.ColourTo(tokenpos, INDIC2_MASK); - styler.Flush(); - styler.StartAt(tokenpos); - styler.StartSegment(tokenpos); - } } if (sc.atLineEnd) @@ -296,11 +280,10 @@ static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[], int levelNext = levelCurrent; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); - int style; for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); - style = styleNext; + int style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); //mac?? if ((style & 31) == SCE_PS_PAREN_PROC) { diff --git a/src/stc/scintilla/lexers/LexPerl.cxx b/src/stc/scintilla/lexers/LexPerl.cxx index 5a7447af31..b4a2dd12eb 100644 --- a/src/stc/scintilla/lexers/LexPerl.cxx +++ b/src/stc/scintilla/lexers/LexPerl.cxx @@ -662,7 +662,7 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, } else if (initStyle == SCE_PL_POD || initStyle == SCE_PL_POD_VERB ) { - // POD backtracking finds preceeding blank lines and goes back past them + // POD backtracking finds preceding blank lines and goes back past them int ln = styler.GetLine(startPos); if (ln > 0) { initStyle = styler.StyleAt(styler.LineStart(--ln)); @@ -1159,12 +1159,12 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, sc.ForwardSetState(SCE_PL_DEFAULT); HereDoc.State = 3; } else { - // invalid indentifier; inexact fallback, but hey + // invalid identifier; inexact fallback, but hey sc.ChangeState(SCE_PL_IDENTIFIER); sc.SetState(SCE_PL_DEFAULT); } } else { - sc.ChangeState(SCE_PL_DEFAULT); // invalid indentifier + sc.ChangeState(SCE_PL_DEFAULT); // invalid identifier } backFlag = BACK_NONE; break; @@ -1726,4 +1726,4 @@ void SCI_METHOD LexerPerl::Fold(unsigned int startPos, int length, int /* initSt styler.SetLevel(lineCurrent, levelPrev | flagsNext); } -LexerModule lmPerl(SCLEX_PERL, LexerPerl::LexerFactoryPerl, "perl", perlWordListDesc, 8); +LexerModule lmPerl(SCLEX_PERL, LexerPerl::LexerFactoryPerl, "perl", perlWordListDesc); diff --git a/src/stc/scintilla/lexers/LexRegistry.cxx b/src/stc/scintilla/lexers/LexRegistry.cxx new file mode 100644 index 0000000000..0f401fa4b5 --- /dev/null +++ b/src/stc/scintilla/lexers/LexRegistry.cxx @@ -0,0 +1,416 @@ +// Scintilla source code edit control +/** + * @file LexRegistry.cxx + * @date July 26 2014 + * @brief Lexer for Windows registration files(.reg) + * @author nkmathew + * + * The License.txt file describes the conditions under which this software may be + * distributed. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static const char *const RegistryWordListDesc[] = { + 0 +}; + +struct OptionsRegistry { + bool foldCompact; + bool fold; + OptionsRegistry() { + foldCompact = false; + fold = false; + } +}; + +struct OptionSetRegistry : public OptionSet { + OptionSetRegistry() { + DefineProperty("fold.compact", &OptionsRegistry::foldCompact); + DefineProperty("fold", &OptionsRegistry::fold); + DefineWordListSets(RegistryWordListDesc); + } +}; + +class LexerRegistry : public ILexer { + OptionsRegistry options; + OptionSetRegistry optSetRegistry; + + static bool IsStringState(int state) { + return (state == SCE_REG_VALUENAME || state == SCE_REG_STRING); + } + + static bool IsKeyPathState(int state) { + return (state == SCE_REG_ADDEDKEY || state == SCE_REG_DELETEDKEY); + } + + static bool AtValueType(LexAccessor &styler, int start) { + int i = 0; + while (i < 10) { + i++; + char curr = styler.SafeGetCharAt(start+i, '\0'); + if (curr == ':') { + return true; + } else if (!curr) { + return false; + } + } + return false; + } + + static bool IsNextNonWhitespace(LexAccessor &styler, int start, char ch) { + int i = 0; + while (i < 100) { + i++; + char curr = styler.SafeGetCharAt(start+i, '\0'); + char next = styler.SafeGetCharAt(start+i+1, '\0'); + bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n'); + if (curr == ch) { + return true; + } else if (!isspacechar(curr) || atEOL) { + return false; + } + } + return false; + } + + // Looks for the equal sign at the end of the string + static bool AtValueName(LexAccessor &styler, int start) { + bool atEOL = false; + int i = 0; + bool escaped = false; + while (!atEOL) { + i++; + char curr = styler.SafeGetCharAt(start+i, '\0'); + char next = styler.SafeGetCharAt(start+i+1, '\0'); + atEOL = (curr == '\r' && next != '\n') || (curr == '\n'); + if (escaped) { + escaped = false; + continue; + } + escaped = curr == '\\'; + if (curr == '"') { + return IsNextNonWhitespace(styler, start+i, '='); + } else if (!curr) { + return false; + } + } + return false; + } + + static bool AtKeyPathEnd(LexAccessor &styler, int start) { + bool atEOL = false; + int i = 0; + while (!atEOL) { + i++; + char curr = styler.SafeGetCharAt(start+i, '\0'); + char next = styler.SafeGetCharAt(start+i+1, '\0'); + atEOL = (curr == '\r' && next != '\n') || (curr == '\n'); + if (curr == ']' || !curr) { + // There's still at least one or more square brackets ahead + return false; + } + } + return true; + } + + static bool AtGUID(LexAccessor &styler, int start) { + int count = 8; + int portion = 0; + int offset = 1; + char digit = '\0'; + while (portion < 5) { + int i = 0; + while (i < count) { + digit = styler.SafeGetCharAt(start+offset); + if (!(isxdigit(digit) || digit == '-')) { + return false; + } + offset++; + i++; + } + portion++; + count = (portion == 4) ? 13 : 5; + } + digit = styler.SafeGetCharAt(start+offset); + if (digit == '}') { + return true; + } else { + return false; + } + } + +public: + LexerRegistry() {} + virtual ~LexerRegistry() {} + virtual int SCI_METHOD Version() const { + return lvOriginal; + } + virtual void SCI_METHOD Release() { + delete this; + } + virtual const char *SCI_METHOD PropertyNames() { + return optSetRegistry.PropertyNames(); + } + virtual int SCI_METHOD PropertyType(const char *name) { + return optSetRegistry.PropertyType(name); + } + virtual const char *SCI_METHOD DescribeProperty(const char *name) { + return optSetRegistry.DescribeProperty(name); + } + virtual int SCI_METHOD PropertySet(const char *key, const char *val) { + if (optSetRegistry.PropertySet(&options, key, val)) { + return 0; + } + return -1; + } + virtual int SCI_METHOD WordListSet(int, const char *) { + return -1; + } + virtual void *SCI_METHOD PrivateCall(int, void *) { + return 0; + } + static ILexer *LexerFactoryRegistry() { + return new LexerRegistry; + } + virtual const char *SCI_METHOD DescribeWordListSets() { + return optSetRegistry.DescribeWordListSets(); + } + virtual void SCI_METHOD Lex(unsigned startPos, + int length, + int initStyle, + IDocument *pAccess); + virtual void SCI_METHOD Fold(unsigned startPos, + int length, + int initStyle, + IDocument *pAccess); +}; + +void SCI_METHOD LexerRegistry::Lex(unsigned startPos, + int length, + int initStyle, + IDocument *pAccess) { + int beforeGUID = SCE_REG_DEFAULT; + int beforeEscape = SCE_REG_DEFAULT; + CharacterSet setOperators = CharacterSet(CharacterSet::setNone, "-,.=:\\@()"); + LexAccessor styler(pAccess); + StyleContext context(startPos, length, initStyle, styler); + bool highlight = true; + bool afterEqualSign = false; + while (context.More()) { + if (context.atLineStart) { + int currPos = static_cast(context.currentPos); + bool continued = styler[currPos-3] == '\\'; + highlight = continued ? true : false; + } + switch (context.state) { + case SCE_REG_COMMENT: + if (context.atLineEnd) { + context.SetState(SCE_REG_DEFAULT); + } + break; + case SCE_REG_VALUENAME: + case SCE_REG_STRING: { + int currPos = static_cast(context.currentPos); + if (context.ch == '"') { + context.ForwardSetState(SCE_REG_DEFAULT); + } else if (context.ch == '\\') { + beforeEscape = context.state; + context.SetState(SCE_REG_ESCAPED); + context.Forward(); + } else if (context.ch == '{') { + if (AtGUID(styler, currPos)) { + beforeGUID = context.state; + context.SetState(SCE_REG_STRING_GUID); + } + } + if (context.state == SCE_REG_STRING && + context.ch == '%' && + (isdigit(context.chNext) || context.chNext == '*')) { + context.SetState(SCE_REG_PARAMETER); + } + } + break; + case SCE_REG_PARAMETER: + context.ForwardSetState(SCE_REG_STRING); + if (context.ch == '"') { + context.ForwardSetState(SCE_REG_DEFAULT); + } + break; + case SCE_REG_VALUETYPE: + if (context.ch == ':') { + context.SetState(SCE_REG_DEFAULT); + afterEqualSign = false; + } + break; + case SCE_REG_HEXDIGIT: + case SCE_REG_OPERATOR: + context.SetState(SCE_REG_DEFAULT); + break; + case SCE_REG_DELETEDKEY: + case SCE_REG_ADDEDKEY: { + int currPos = static_cast(context.currentPos); + if (context.ch == ']' && AtKeyPathEnd(styler, currPos)) { + context.ForwardSetState(SCE_REG_DEFAULT); + } else if (context.ch == '{') { + if (AtGUID(styler, currPos)) { + beforeGUID = context.state; + context.SetState(SCE_REG_KEYPATH_GUID); + } + } + } + break; + case SCE_REG_ESCAPED: + if (context.ch == '"') { + context.SetState(beforeEscape); + context.ForwardSetState(SCE_REG_DEFAULT); + } else if (context.ch == '\\') { + context.Forward(); + } else { + context.SetState(beforeEscape); + beforeEscape = SCE_REG_DEFAULT; + } + break; + case SCE_REG_STRING_GUID: + case SCE_REG_KEYPATH_GUID: { + if (context.ch == '}') { + context.ForwardSetState(beforeGUID); + beforeGUID = SCE_REG_DEFAULT; + } + int currPos = static_cast(context.currentPos); + if (context.ch == '"' && IsStringState(context.state)) { + context.ForwardSetState(SCE_REG_DEFAULT); + } else if (context.ch == ']' && + AtKeyPathEnd(styler, currPos) && + IsKeyPathState(context.state)) { + context.ForwardSetState(SCE_REG_DEFAULT); + } else if (context.ch == '\\' && IsStringState(context.state)) { + beforeEscape = context.state; + context.SetState(SCE_REG_ESCAPED); + context.Forward(); + } + } + break; + } + // Determine if a new state should be entered. + if (context.state == SCE_REG_DEFAULT) { + int currPos = static_cast(context.currentPos); + if (context.ch == ';') { + context.SetState(SCE_REG_COMMENT); + } else if (context.ch == '"') { + if (AtValueName(styler, currPos)) { + context.SetState(SCE_REG_VALUENAME); + } else { + context.SetState(SCE_REG_STRING); + } + } else if (context.ch == '[') { + if (IsNextNonWhitespace(styler, currPos, '-')) { + context.SetState(SCE_REG_DELETEDKEY); + } else { + context.SetState(SCE_REG_ADDEDKEY); + } + } else if (context.ch == '=') { + afterEqualSign = true; + highlight = true; + } else if (afterEqualSign) { + bool wordStart = isalpha(context.ch) && !isalpha(context.chPrev); + if (wordStart && AtValueType(styler, currPos)) { + context.SetState(SCE_REG_VALUETYPE); + } + } else if (isxdigit(context.ch) && highlight) { + context.SetState(SCE_REG_HEXDIGIT); + } + highlight = (context.ch == '@') ? true : highlight; + if (setOperators.Contains(context.ch) && highlight) { + context.SetState(SCE_REG_OPERATOR); + } + } + context.Forward(); + } + context.Complete(); +} + +// Folding similar to that of FoldPropsDoc in LexOthers +void SCI_METHOD LexerRegistry::Fold(unsigned startPos, + int length, + int, + IDocument *pAccess) { + if (!options.fold) { + return; + } + LexAccessor styler(pAccess); + int currLine = styler.GetLine(startPos); + int visibleChars = 0; + unsigned endPos = startPos + length; + bool atKeyPath = false; + for (unsigned i = startPos; i < endPos; i++) { + atKeyPath = IsKeyPathState(styler.StyleAt(i)) ? true : atKeyPath; + char curr = styler.SafeGetCharAt(i); + char next = styler.SafeGetCharAt(i+1); + bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n'); + if (atEOL || i == (endPos-1)) { + int level = SC_FOLDLEVELBASE; + if (currLine > 0) { + int prevLevel = styler.LevelAt(currLine-1); + if (prevLevel & SC_FOLDLEVELHEADERFLAG) { + level += 1; + } else { + level = prevLevel; + } + } + if (!visibleChars && options.foldCompact) { + level |= SC_FOLDLEVELWHITEFLAG; + } else if (atKeyPath) { + level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + } + if (level != styler.LevelAt(currLine)) { + styler.SetLevel(currLine, level); + } + currLine++; + visibleChars = 0; + atKeyPath = false; + } + if (!isspacechar(curr)) { + visibleChars++; + } + } + + // Make the folding reach the last line in the file + int level = SC_FOLDLEVELBASE; + if (currLine > 0) { + int prevLevel = styler.LevelAt(currLine-1); + if (prevLevel & SC_FOLDLEVELHEADERFLAG) { + level += 1; + } else { + level = prevLevel; + } + } + styler.SetLevel(currLine, level); +} + +LexerModule lmRegistry(SCLEX_REGISTRY, + LexerRegistry::LexerFactoryRegistry, + "registry", + RegistryWordListDesc); + diff --git a/src/stc/scintilla/lexers/LexRuby.cxx b/src/stc/scintilla/lexers/LexRuby.cxx index 833ad59288..9529ac24e9 100644 --- a/src/stc/scintilla/lexers/LexRuby.cxx +++ b/src/stc/scintilla/lexers/LexRuby.cxx @@ -29,7 +29,7 @@ using namespace Scintilla; //XXX Identical to Perl, put in common area static inline bool isEOLChar(char ch) { - return (ch == '\r') || (ch == '\n'); + return (ch == '\r') || (ch == '\n'); } #define isSafeASCII(ch) ((unsigned int)(ch) <= 127) @@ -60,7 +60,7 @@ static inline bool isSafeWordcharOrHigh(char ch) { } static bool inline iswhitespace(char ch) { - return ch == ' ' || ch == '\t'; + return ch == ' ' || ch == '\t'; } #define MAX_KEYWORD_LENGTH 200 @@ -74,20 +74,20 @@ static bool followsDot(unsigned int pos, Accessor &styler) { int style = actual_style(styler.StyleAt(pos)); char ch; switch (style) { - case SCE_RB_DEFAULT: - ch = styler[pos]; - if (ch == ' ' || ch == '\t') { - //continue - } else { - return false; - } - break; - - case SCE_RB_OPERATOR: - return styler[pos] == '.'; - - default: + case SCE_RB_DEFAULT: + ch = styler[pos]; + if (ch == ' ' || ch == '\t') { + //continue + } else { return false; + } + break; + + case SCE_RB_OPERATOR: + return styler[pos] == '.'; + + default: + return false; } } return false; @@ -102,26 +102,26 @@ static bool keywordIsModifier(const char *word, Accessor &styler); static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) { - char s[MAX_KEYWORD_LENGTH]; + char s[MAX_KEYWORD_LENGTH]; unsigned int i, j; - unsigned int lim = end - start + 1; // num chars to copy - if (lim >= MAX_KEYWORD_LENGTH) { - lim = MAX_KEYWORD_LENGTH - 1; - } - for (i = start, j = 0; j < lim; i++, j++) { - s[j] = styler[i]; - } + unsigned int lim = end - start + 1; // num chars to copy + if (lim >= MAX_KEYWORD_LENGTH) { + lim = MAX_KEYWORD_LENGTH - 1; + } + for (i = start, j = 0; j < lim; i++, j++) { + s[j] = styler[i]; + } s[j] = '\0'; - int chAttr; - if (0 == strcmp(prevWord, "class")) - chAttr = SCE_RB_CLASSNAME; - else if (0 == strcmp(prevWord, "module")) - chAttr = SCE_RB_MODULE_NAME; - else if (0 == strcmp(prevWord, "def")) - chAttr = SCE_RB_DEFNAME; + int chAttr; + if (0 == strcmp(prevWord, "class")) + chAttr = SCE_RB_CLASSNAME; + else if (0 == strcmp(prevWord, "module")) + chAttr = SCE_RB_MODULE_NAME; + else if (0 == strcmp(prevWord, "def")) + chAttr = SCE_RB_DEFNAME; else if (keywords.InList(s) && ((start == 0) || !followsDot(start - 1, styler))) { if (keywordIsAmbiguous(s) - && keywordIsModifier(s, start, styler)) { + && keywordIsModifier(s, start, styler)) { // Demoted keywords are colored as keywords, // but do not affect changes in indentation. @@ -136,37 +136,37 @@ static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywor } else { chAttr = SCE_RB_WORD; } - } else + } else chAttr = SCE_RB_IDENTIFIER; - styler.ColourTo(end, chAttr); - if (chAttr == SCE_RB_WORD) { - strcpy(prevWord, s); - } else { - prevWord[0] = 0; - } + styler.ColourTo(end, chAttr); + if (chAttr == SCE_RB_WORD) { + strcpy(prevWord, s); + } else { + prevWord[0] = 0; + } return chAttr; } //XXX Identical to Perl, put in common area static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) { - if ((pos + static_cast(strlen(val))) >= lengthDoc) { - return false; - } - while (*val) { - if (*val != styler[pos++]) { - return false; - } - val++; - } - return true; + if ((pos + static_cast(strlen(val))) >= lengthDoc) { + return false; + } + while (*val) { + if (*val != styler[pos++]) { + return false; + } + val++; + } + return true; } // Do Ruby better -- find the end of the line, work back, // and then check for leading white space // Precondition: the here-doc target can be indented -static bool lookingAtHereDocDelim(Accessor &styler, +static bool lookingAtHereDocDelim(Accessor &styler, int pos, int lengthDoc, const char *HereDocDelim) @@ -187,15 +187,15 @@ static bool lookingAtHereDocDelim(Accessor &styler, //XXX Identical to Perl, put in common area static char opposite(char ch) { - if (ch == '(') - return ')'; - if (ch == '[') - return ']'; - if (ch == '{') - return '}'; - if (ch == '<') - return '>'; - return ch; + if (ch == '(') + return ')'; + if (ch == '[') + return ']'; + if (ch == '{') + return '}'; + if (ch == '<') + return '>'; + return ch; } // Null transitions when we see we've reached the end @@ -216,7 +216,7 @@ static void advance_char(int &i, char &ch, char &chNext, char &chNext2) { } // precondition: startPos points to one after the EOL char -static bool currLineContainsHereDelims(int& startPos, +static bool currLineContainsHereDelims(int &startPos, Accessor &styler) { if (startPos <= 1) return false; @@ -249,7 +249,7 @@ static bool currLineContainsHereDelims(int& startPos, // to be hoisted out of the function. class QuoteCls { - public: +public: int Count; char Up; char Down; @@ -266,19 +266,19 @@ class QuoteCls { Up = u; Down = opposite(Up); } - QuoteCls(const QuoteCls& q) { + QuoteCls(const QuoteCls &q) { // copy constructor -- use this for copying in Count = q.Count; Up = q.Up; Down = q.Down; } - QuoteCls& operator=(const QuoteCls& q) { // assignment constructor + QuoteCls &operator=(const QuoteCls &q) { // assignment constructor if (this != &q) { Count = q.Count; Up = q.Up; Down = q.Down; } - return *this; + return *this; } }; @@ -287,11 +287,11 @@ class QuoteCls { static void enterInnerExpression(int *p_inner_string_types, int *p_inner_expn_brace_counts, QuoteCls *p_inner_quotes, - int& inner_string_count, - int& state, - int& brace_counts, + int &inner_string_count, + int &state, + int &brace_counts, QuoteCls curr_quote - ) { + ) { p_inner_string_types[inner_string_count] = state; state = SCE_RB_DEFAULT; p_inner_expn_brace_counts[inner_string_count] = brace_counts; @@ -301,13 +301,13 @@ static void enterInnerExpression(int *p_inner_string_types, } static void exitInnerExpression(int *p_inner_string_types, - int *p_inner_expn_brace_counts, - QuoteCls *p_inner_quotes, - int& inner_string_count, - int& state, - int& brace_counts, - QuoteCls& curr_quote - ) { + int *p_inner_expn_brace_counts, + QuoteCls *p_inner_quotes, + int &inner_string_count, + int &state, + int &brace_counts, + QuoteCls &curr_quote + ) { --inner_string_count; state = p_inner_string_types[inner_string_count]; brace_counts = p_inner_expn_brace_counts[inner_string_count]; @@ -316,28 +316,28 @@ static void exitInnerExpression(int *p_inner_string_types, static bool isEmptyLine(int pos, Accessor &styler) { - int spaceFlags = 0; - int lineCurrent = styler.GetLine(pos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + int spaceFlags = 0; + int lineCurrent = styler.GetLine(pos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0; } static bool RE_CanFollowKeyword(const char *keyword) { if (!strcmp(keyword, "and") - || !strcmp(keyword, "begin") - || !strcmp(keyword, "break") - || !strcmp(keyword, "case") - || !strcmp(keyword, "do") - || !strcmp(keyword, "else") - || !strcmp(keyword, "elsif") - || !strcmp(keyword, "if") - || !strcmp(keyword, "next") - || !strcmp(keyword, "return") - || !strcmp(keyword, "when") - || !strcmp(keyword, "unless") - || !strcmp(keyword, "until") - || !strcmp(keyword, "not") - || !strcmp(keyword, "or")) { + || !strcmp(keyword, "begin") + || !strcmp(keyword, "break") + || !strcmp(keyword, "case") + || !strcmp(keyword, "do") + || !strcmp(keyword, "else") + || !strcmp(keyword, "elsif") + || !strcmp(keyword, "if") + || !strcmp(keyword, "next") + || !strcmp(keyword, "return") + || !strcmp(keyword, "when") + || !strcmp(keyword, "unless") + || !strcmp(keyword, "until") + || !strcmp(keyword, "not") + || !strcmp(keyword, "or")) { return true; } return false; @@ -347,8 +347,8 @@ static bool RE_CanFollowKeyword(const char *keyword) { // Don't look at styles in case we're looking forward static int skipWhitespace(int startPos, - int endPos, - Accessor &styler) { + int endPos, + Accessor &styler) { for (int i = startPos; i < endPos; i++) { if (!iswhitespace(styler[i])) { return i; @@ -378,8 +378,8 @@ static bool sureThisIsHeredoc(int iPrev, int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler); if (firstWordPosn >= iPrev) { // Have something like {^ <<} - //XXX Look at the first previous non-comment non-white line - // to establish the context. Not too likely though. + //XXX Look at the first previous non-comment non-white line + // to establish the context. Not too likely though. return true; } else { switch (prevStyle = styler.StyleAt(firstWordPosn)) { @@ -395,7 +395,7 @@ static bool sureThisIsHeredoc(int iPrev, char *dst = prevWord; for (;;) { if (firstWordEndPosn >= iPrev || - styler.StyleAt(firstWordEndPosn) != prevStyle) { + styler.StyleAt(firstWordEndPosn) != prevStyle) { *dst = 0; break; } @@ -404,8 +404,8 @@ static bool sureThisIsHeredoc(int iPrev, } //XXX Write a style-aware thing to regex scintilla buffer objects if (!strcmp(prevWord, "undef") - || !strcmp(prevWord, "def") - || !strcmp(prevWord, "alias")) { + || !strcmp(prevWord, "def") + || !strcmp(prevWord, "alias")) { // These keywords are what we were looking for return false; } @@ -424,8 +424,8 @@ static bool haveTargetMatch(int currPos, } int i, j; for (i = targetStartPos, j = currPos; - i < targetEndPos && j < lengthDoc; - i++, j++) { + i < targetEndPos && j < lengthDoc; + i++, j++) { if (styler[i] != styler[j]) { return false; } @@ -450,7 +450,7 @@ static bool haveTargetMatch(int currPos, static bool sureThisIsNotHeredoc(int lt2StartPos, Accessor &styler) { int prevStyle; - // Use full document, not just part we're styling + // Use full document, not just part we're styling int lengthDoc = styler.Length(); int lineStart = styler.GetLine(lt2StartPos); int lineStartPosn = styler.LineStart(lineStart); @@ -466,8 +466,8 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, prevStyle = styler.StyleAt(firstWordPosn); // If we have '<<' following a keyword, it's not a heredoc if (prevStyle != SCE_RB_IDENTIFIER - && prevStyle != SCE_RB_INSTANCE_VAR - && prevStyle != SCE_RB_CLASS_VAR) { + && prevStyle != SCE_RB_INSTANCE_VAR + && prevStyle != SCE_RB_CLASS_VAR) { return definitely_not_a_here_doc; } int newStyle = prevStyle; @@ -508,7 +508,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, return definitely_not_a_here_doc; } // OK, now 'j' will point to the current spot moving ahead - int j = firstWordPosn + 1; + int j = firstWordPosn + 1; if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') { // This shouldn't happen return definitely_not_a_here_doc; @@ -560,10 +560,10 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, // don't handle arbitrary expressions yet target_end = j; - if (target_quote) { - // Now we can move to the character after the string delimiter. - j += 1; - } + if (target_quote) { + // Now we can move to the character after the string delimiter. + j += 1; + } j = skipWhitespace(j, lengthDoc, styler); if (j >= lengthDoc) { return definitely_not_a_here_doc; @@ -604,7 +604,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, // move to the start of the first line that is not in a // multi-line construct -static void synchronizeDocStart(unsigned int& startPos, +static void synchronizeDocStart(unsigned int &startPos, int &length, int &initStyle, Accessor &styler, @@ -613,11 +613,11 @@ static void synchronizeDocStart(unsigned int& startPos, styler.Flush(); int style = actual_style(styler.StyleAt(startPos)); switch (style) { - case SCE_RB_STDIN: - case SCE_RB_STDOUT: - case SCE_RB_STDERR: - // Don't do anything else with these. - return; + case SCE_RB_STDIN: + case SCE_RB_STDOUT: + case SCE_RB_STDERR: + // Don't do anything else with these. + return; } int pos = startPos; @@ -655,67 +655,67 @@ static void synchronizeDocStart(unsigned int& startPos, } static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { + WordList *keywordlists[], Accessor &styler) { - // Lexer for Ruby 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 + // Lexer for Ruby 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 - WordList &keywords = *keywordlists[0]; + WordList &keywords = *keywordlists[0]; - class HereDocCls { - public: - int State; + class HereDocCls { + public: + int State; // States // 0: '<<' encountered - // 1: collect the delimiter + // 1: collect the delimiter // 1b: text between the end of the delimiter and the EOL - // 2: here doc text (lines after the delimiter) - char Quote; // the char after '<<' - bool Quoted; // true if Quote in ('\'','"','`') - int DelimiterLength; // strlen(Delimiter) - char Delimiter[256]; // the Delimiter, limit of 256: from Perl + // 2: here doc text (lines after the delimiter) + char Quote; // the char after '<<' + bool Quoted; // true if Quote in ('\'','"','`') + int DelimiterLength; // strlen(Delimiter) + char Delimiter[256]; // the Delimiter, limit of 256: from Perl bool CanBeIndented; - HereDocCls() { - State = 0; - DelimiterLength = 0; - Delimiter[0] = '\0'; + HereDocCls() { + State = 0; + DelimiterLength = 0; + Delimiter[0] = '\0'; CanBeIndented = false; - } - }; - HereDocCls HereDoc; + } + }; + HereDocCls HereDoc; - QuoteCls Quote; + QuoteCls Quote; int numDots = 0; // For numbers -- - // Don't start lexing in the middle of a num + // Don't start lexing in the middle of a num synchronizeDocStart(startPos, length, initStyle, styler, // ref args false); - bool preferRE = true; + bool preferRE = true; int state = initStyle; - int lengthDoc = startPos + length; + int lengthDoc = startPos + length; - char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero - prevWord[0] = '\0'; - if (length == 0) - return; + char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero + prevWord[0] = '\0'; + if (length == 0) + return; - char chPrev = styler.SafeGetCharAt(startPos - 1); - char chNext = styler.SafeGetCharAt(startPos); - bool is_real_number = true; // Differentiate between constants and ?-sequences. - // Ruby uses a different mask because bad indentation is marked by oring with 32 - styler.StartAt(startPos, 127); - styler.StartSegment(startPos); + char chPrev = styler.SafeGetCharAt(startPos - 1); + char chNext = styler.SafeGetCharAt(startPos); + bool is_real_number = true; // Differentiate between constants and ?-sequences. + styler.StartAt(startPos); + styler.StartSegment(startPos); static int q_states[] = {SCE_RB_STRING_Q, SCE_RB_STRING_QQ, SCE_RB_STRING_QR, SCE_RB_STRING_QW, SCE_RB_STRING_QW, - SCE_RB_STRING_QX}; - static const char* q_chars = "qQrwWx"; + SCE_RB_STRING_QX + }; + static const char *q_chars = "qQrwWx"; // In most cases a value of 2 should be ample for the code in the // Ruby library, and the code the user is likely to enter. @@ -731,7 +731,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // If anyone runs into this problem, I recommend raising this // value slightly higher to replacing the fixed array with a linked - // list. Keep in mind this code will be called everytime the lexer + // list. Keep in mind this code will be called every time the lexer // is invoked. #define INNER_STRINGS_MAX_COUNT 5 @@ -744,113 +744,113 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, int brace_counts = 0; // Number of #{ ... } things within an expression int i; - for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { + for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { inner_string_types[i] = 0; inner_expn_brace_counts[i] = 0; } - for (i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - char chNext2 = styler.SafeGetCharAt(i + 2); + for (i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + char chNext2 = styler.SafeGetCharAt(i + 2); if (styler.IsLeadByte(ch)) { - chNext = chNext2; - chPrev = ' '; - i += 1; - continue; - } + chNext = chNext2; + chPrev = ' '; + i += 1; + continue; + } // skip on DOS/Windows //No, don't, because some things will get tagged on, // so we won't recognize keywords, for example #if 0 - if (ch == '\r' && chNext == '\n') { - continue; + if (ch == '\r' && chNext == '\n') { + continue; } #endif if (HereDoc.State == 1 && isEOLChar(ch)) { - // Begin of here-doc (the line after the here-doc delimiter): - HereDoc.State = 2; - styler.ColourTo(i-1, state); + // Begin of here-doc (the line after the here-doc delimiter): + HereDoc.State = 2; + styler.ColourTo(i-1, state); // Don't check for a missing quote, just jump into // the here-doc state state = SCE_RB_HERE_Q; } // Regular transitions - if (state == SCE_RB_DEFAULT) { + if (state == SCE_RB_DEFAULT) { if (isSafeDigit(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_NUMBER; + styler.ColourTo(i - 1, state); + state = SCE_RB_NUMBER; is_real_number = true; numDots = 0; } else if (isHighBitChar(ch) || iswordstart(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_WORD; - } else if (ch == '#') { - styler.ColourTo(i - 1, state); - state = SCE_RB_COMMENTLINE; - } else if (ch == '=') { - // =begin indicates the start of a comment (doc) block + styler.ColourTo(i - 1, state); + state = SCE_RB_WORD; + } else if (ch == '#') { + styler.ColourTo(i - 1, state); + state = SCE_RB_COMMENTLINE; + } else if (ch == '=') { + // =begin indicates the start of a comment (doc) block if ((i == 0 || isEOLChar(chPrev)) - && chNext == 'b' - && styler.SafeGetCharAt(i + 2) == 'e' - && styler.SafeGetCharAt(i + 3) == 'g' - && styler.SafeGetCharAt(i + 4) == 'i' - && styler.SafeGetCharAt(i + 5) == 'n' - && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) { + && chNext == 'b' + && styler.SafeGetCharAt(i + 2) == 'e' + && styler.SafeGetCharAt(i + 3) == 'g' + && styler.SafeGetCharAt(i + 4) == 'i' + && styler.SafeGetCharAt(i + 5) == 'n' + && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) { styler.ColourTo(i - 1, state); state = SCE_RB_POD; - } else { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_RB_OPERATOR); - preferRE = true; - } - } else if (ch == '"') { - styler.ColourTo(i - 1, state); - state = SCE_RB_STRING; - Quote.New(); - Quote.Open(ch); - } else if (ch == '\'') { + } else { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_RB_OPERATOR); + preferRE = true; + } + } else if (ch == '"') { + styler.ColourTo(i - 1, state); + state = SCE_RB_STRING; + Quote.New(); + Quote.Open(ch); + } else if (ch == '\'') { styler.ColourTo(i - 1, state); state = SCE_RB_CHARACTER; Quote.New(); Quote.Open(ch); - } else if (ch == '`') { - styler.ColourTo(i - 1, state); - state = SCE_RB_BACKTICKS; - Quote.New(); - Quote.Open(ch); - } else if (ch == '@') { + } else if (ch == '`') { + styler.ColourTo(i - 1, state); + state = SCE_RB_BACKTICKS; + Quote.New(); + Quote.Open(ch); + } else if (ch == '@') { // Instance or class var - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); if (chNext == '@') { state = SCE_RB_CLASS_VAR; advance_char(i, ch, chNext, chNext2); // pass by ref } else { state = SCE_RB_INSTANCE_VAR; } - } else if (ch == '$') { + } else if (ch == '$') { // Check for a builtin global - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); // Recognize it bit by bit state = SCE_RB_GLOBAL; } else if (ch == '/' && preferRE) { // Ambigous operator - styler.ColourTo(i - 1, state); - state = SCE_RB_REGEX; + styler.ColourTo(i - 1, state); + state = SCE_RB_REGEX; Quote.New(); Quote.Open(ch); - } else if (ch == '<' && chNext == '<' && chNext2 != '=') { + } else if (ch == '<' && chNext == '<' && chNext2 != '=') { // Recognise the '<<' symbol - either a here document or a binary op - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); i++; chNext = chNext2; - styler.ColourTo(i, SCE_RB_OPERATOR); + styler.ColourTo(i, SCE_RB_OPERATOR); - if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) { + if (!(strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) { // It's definitely not a here-doc, // based on Ruby's lexer/parser in the // heredoc_identifier routine. @@ -874,22 +874,47 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } preferRE = (state != SCE_RB_HERE_DELIM); } else if (ch == ':') { - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); if (chNext == ':') { // Mark "::" as an operator, not symbol start styler.ColourTo(i + 1, SCE_RB_OPERATOR); advance_char(i, ch, chNext, chNext2); // pass by ref state = SCE_RB_DEFAULT; - preferRE = false; + preferRE = false; } else if (isSafeWordcharOrHigh(chNext)) { - state = SCE_RB_SYMBOL; + state = SCE_RB_SYMBOL; + } else if ((chNext == '@' || chNext == '$') && + isSafeWordcharOrHigh(chNext2)) { + // instance and global variable followed by an identifier + advance_char(i, ch, chNext, chNext2); + state = SCE_RB_SYMBOL; + } else if (((chNext == '@' && chNext2 == '@') || + (chNext == '$' && chNext2 == '-')) && + isSafeWordcharOrHigh(styler.SafeGetCharAt(i+3))) { + // class variables and special global variable "$-IDENTCHAR" + state = SCE_RB_SYMBOL; + // $-IDENTCHAR doesn't continue past the IDENTCHAR + if (chNext == '$') { + styler.ColourTo(i+3, SCE_RB_SYMBOL); + state = SCE_RB_DEFAULT; + } + i += 3; + ch = styler.SafeGetCharAt(i); + chNext = styler.SafeGetCharAt(i+1); + } else if (chNext == '$' && strchr("_~*$?!@/\\;,.=:<>\"&`'+", chNext2)) { + // single-character special global variables + i += 2; + ch = chNext2; + chNext = styler.SafeGetCharAt(i+1); + styler.ColourTo(i, SCE_RB_SYMBOL); + state = SCE_RB_DEFAULT; } else if (strchr("[*!~+-*/%=<>&^|", chNext)) { // Do the operator analysis in-line, looking ahead // Based on the table in pickaxe 2nd ed., page 339 bool doColoring = true; switch (chNext) { case '[': - if (chNext2 == ']' ) { + if (chNext2 == ']') { char ch_tmp = styler.SafeGetCharAt(i + 3); if (ch_tmp == '=') { i += 3; @@ -955,11 +980,11 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, styler.ColourTo(i, SCE_RB_SYMBOL); state = SCE_RB_DEFAULT; } - } else if (!preferRE) { - // Don't color symbol strings (yet) - // Just color the ":" and color rest as string - styler.ColourTo(i, SCE_RB_SYMBOL); - state = SCE_RB_DEFAULT; + } else if (!preferRE) { + // Don't color symbol strings (yet) + // Just color the ":" and color rest as string + styler.ColourTo(i, SCE_RB_SYMBOL); + state = SCE_RB_DEFAULT; } else { styler.ColourTo(i, SCE_RB_OPERATOR); state = SCE_RB_DEFAULT; @@ -976,7 +1001,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, Quote.Open(chNext2); i += 2; ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); + chNext = styler.SafeGetCharAt(i + 1); have_string = true; } } else if (preferRE && !isSafeWordcharOrHigh(chNext)) { @@ -1012,8 +1037,8 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, is_real_number = false; } } else if (isoperator(ch) || ch == '.') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_RB_OPERATOR); + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_RB_OPERATOR); // If we're ending an expression or block, // assume it ends an object, and the ambivalent // constructs are binary operators @@ -1040,7 +1065,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (isEOLChar(ch)) { // Make sure it's a true line-end, with no backslash if ((ch == '\r' || (ch == '\n' && chPrev != '\r')) - && chPrev != '\\') { + && chPrev != '\\') { // Assume we've hit the end of the statement. preferRE = true; } @@ -1055,11 +1080,11 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // but we don't for now. if (ch == '=' - && isSafeWordcharOrHigh(chPrev) - && (chNext == '(' - || strchr(" \t\n\r", chNext) != NULL) - && (!strcmp(prevWord, "def") - || followsDot(styler.GetStartSegment(), styler))) { + && isSafeWordcharOrHigh(chPrev) + && (chNext == '(' + || strchr(" \t\n\r", chNext) != NULL) + && (!strcmp(prevWord, "def") + || followsDot(styler.GetStartSegment(), styler))) { // = is a name only when being def'd -- Get it the next time // This means that = is always lexed as // , (op, =), @@ -1078,28 +1103,28 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // No need to handle this state -- we'll just move to the end preferRE = false; } else { - int wordStartPos = styler.GetStartSegment(); + int wordStartPos = styler.GetStartSegment(); int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord); switch (word_style) { - case SCE_RB_WORD: - preferRE = RE_CanFollowKeyword(prevWord); - break; + case SCE_RB_WORD: + preferRE = RE_CanFollowKeyword(prevWord); + break; - case SCE_RB_WORD_DEMOTED: + case SCE_RB_WORD_DEMOTED: + preferRE = true; + break; + + case SCE_RB_IDENTIFIER: + if (isMatch(styler, lengthDoc, wordStartPos, "print")) { preferRE = true; - break; - - case SCE_RB_IDENTIFIER: - if (isMatch(styler, lengthDoc, wordStartPos, "print")) { - preferRE = true; - } else if (isEOLChar(ch)) { - preferRE = true; - } else { - preferRE = false; - } - break; - default: + } else if (isEOLChar(ch)) { + preferRE = true; + } else { preferRE = false; + } + break; + default: + preferRE = false; } if (ch == '.') { // We might be redefining an operator-method @@ -1154,7 +1179,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, preferRE = false; } } else if (state == SCE_RB_COMMENTLINE) { - if (isEOLChar(ch)) { + if (isEOLChar(ch)) { styler.ColourTo(i - 1, state); state = SCE_RB_DEFAULT; // Use whatever setting we had going into the comment @@ -1164,8 +1189,8 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Slightly different: if we find an immediate '-', // the target can appear indented. - if (HereDoc.State == 0) { // '<<' encountered - HereDoc.State = 1; + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.State = 1; HereDoc.DelimiterLength = 0; if (ch == '-') { HereDoc.CanBeIndented = true; @@ -1190,7 +1215,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, HereDoc.DelimiterLength = 1; } } - } else if (HereDoc.State == 1) { // collect the delimiter + } else if (HereDoc.State == 1) { // collect the delimiter if (isEOLChar(ch)) { // End the quote now, and go back for more styler.ColourTo(i - 1, state); @@ -1199,32 +1224,32 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, chNext = ch; preferRE = false; } else if (HereDoc.Quoted) { - if (ch == HereDoc.Quote) { // closing quote => end of delimiter - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; + if (ch == HereDoc.Quote) { // closing quote => end of delimiter + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; preferRE = false; } else { - if (ch == '\\' && !isEOLChar(chNext)) { + if (ch == '\\' && !isEOLChar(chNext)) { advance_char(i, ch, chNext, chNext2); - } - HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; } } else { // an unquoted here-doc delimiter - if (isSafeAlnumOrHigh(ch) || ch == '_') { - HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - } else { - styler.ColourTo(i - 1, state); + if (isSafeAlnumOrHigh(ch) || ch == '_') { + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } else { + styler.ColourTo(i - 1, state); redo_char(i, ch, chNext, chNext2, state); preferRE = false; - } + } } - if (HereDoc.DelimiterLength >= static_cast(sizeof(HereDoc.Delimiter)) - 1) { - styler.ColourTo(i - 1, state); - state = SCE_RB_ERROR; + if (HereDoc.DelimiterLength >= static_cast(sizeof(HereDoc.Delimiter)) - 1) { + styler.ColourTo(i - 1, state); + state = SCE_RB_ERROR; preferRE = false; - } + } } } else if (state == SCE_RB_HERE_Q) { // Not needed: HereDoc.State == 2 @@ -1235,7 +1260,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, if (!HereDoc.CanBeIndented) { if (isEOLChar(chPrev) - && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { + && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { styler.ColourTo(i - 1, state); i += HereDoc.DelimiterLength - 1; chNext = styler.SafeGetCharAt(i + 1); @@ -1261,7 +1286,16 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (state == SCE_RB_CLASS_VAR || state == SCE_RB_INSTANCE_VAR || state == SCE_RB_SYMBOL) { - if (!isSafeWordcharOrHigh(ch)) { + if (state == SCE_RB_SYMBOL && + // FIDs suffices '?' and '!' + (((ch == '!' || ch == '?') && chNext != '=') || + // identifier suffix '=' + (ch == '=' && (chNext != '~' && chNext != '>' && + (chNext != '=' || chNext2 == '>'))))) { + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; + preferRE = false; + } else if (!isSafeWordcharOrHigh(ch)) { styler.ColourTo(i - 1, state); redo_char(i, ch, chNext, chNext2, state); // pass by ref preferRE = false; @@ -1285,9 +1319,9 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (state == SCE_RB_POD) { // PODs end with ^=end\s, -- any whitespace can follow =end if (strchr(" \t\n\r", ch) != NULL - && i > 5 - && isEOLChar(styler[i - 5]) - && isMatch(styler, lengthDoc, i - 4, "=end")) { + && i > 5 + && isEOLChar(styler[i - 5]) + && isMatch(styler, lengthDoc, i - 4, "=end")) { styler.ColourTo(i - 1, state); state = SCE_RB_DEFAULT; preferRE = false; @@ -1302,7 +1336,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Include the options while (isSafeAlpha(chNext)) { i++; - ch = chNext; + ch = chNext; chNext = styler.SafeGetCharAt(i + 1); } styler.ColourTo(i, state); @@ -1313,9 +1347,9 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Only if close quoter != open quoter Quote.Count++; - } else if (ch == '#' ) { + } else if (ch == '#') { if (chNext == '{' - && inner_string_count < INNER_STRINGS_MAX_COUNT) { + && inner_string_count < INNER_STRINGS_MAX_COUNT) { // process #{ ... } styler.ColourTo(i - 1, state); styler.ColourTo(i + 1, SCE_RB_OPERATOR); @@ -1355,7 +1389,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, chNext = styler.SafeGetCharAt(i + 1); } } - // Quotes of all kinds... + // Quotes of all kinds... } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW || state == SCE_RB_STRING || state == SCE_RB_CHARACTER || @@ -1430,7 +1464,7 @@ static void getPrevWord(int pos, for (; i <= pos; i++) { *dst++ = styler[i]; } - *dst = 0; + *dst = 0; } static bool keywordIsAmbiguous(const char *prevWord) @@ -1438,11 +1472,11 @@ static bool keywordIsAmbiguous(const char *prevWord) // Order from most likely used to least likely // Lots of ways to do a loop in Ruby besides 'while/until' if (!strcmp(prevWord, "if") - || !strcmp(prevWord, "do") - || !strcmp(prevWord, "while") - || !strcmp(prevWord, "unless") - || !strcmp(prevWord, "until") - || !strcmp(prevWord, "for")) { + || !strcmp(prevWord, "do") + || !strcmp(prevWord, "while") + || !strcmp(prevWord, "unless") + || !strcmp(prevWord, "until") + || !strcmp(prevWord, "for")) { return true; } else { return false; @@ -1462,7 +1496,7 @@ static bool keywordIsModifier(const char *word, } char ch, chPrev, chPrev2; int style = SCE_RB_DEFAULT; - int lineStart = styler.GetLine(pos); + int lineStart = styler.GetLine(pos); int lineStartPosn = styler.LineStart(lineStart); // We want to step backwards until we don't care about the current // position. But first move lineStartPosn back behind any @@ -1482,20 +1516,20 @@ static bool keywordIsModifier(const char *word, break; } } else { - break; + break; } } styler.Flush(); while (--pos >= lineStartPosn) { style = actual_style(styler.StyleAt(pos)); - if (style == SCE_RB_DEFAULT) { - if (iswhitespace(ch = styler[pos])) { - //continue - } else if (ch == '\r' || ch == '\n') { - // Scintilla's LineStart() and GetLine() routines aren't - // platform-independent, so if we have text prepared with - // a different system we can't rely on it. + if (style == SCE_RB_DEFAULT) { + if (iswhitespace(ch = styler[pos])) { + //continue + } else if (ch == '\r' || ch == '\n') { + // Scintilla's LineStart() and GetLine() routines aren't + // platform-independent, so if we have text prepared with + // a different system we can't rely on it. // Also, lineStartPosn may have been moved to more than one // line above word's line while pushing past continuations. @@ -1508,40 +1542,40 @@ static bool keywordIsModifier(const char *word, pos-=2; // gloss over the "\\\r" //continue } else { - return false; + return false; } - } - } else { + } + } else { break; - } + } } if (pos < lineStartPosn) { return false; } // First things where the action is unambiguous switch (style) { - case SCE_RB_DEFAULT: - case SCE_RB_COMMENTLINE: - case SCE_RB_POD: - case SCE_RB_CLASSNAME: - case SCE_RB_DEFNAME: - case SCE_RB_MODULE_NAME: - return false; - case SCE_RB_OPERATOR: - break; - case SCE_RB_WORD: - // Watch out for uses of 'else if' - //XXX: Make a list of other keywords where 'if' isn't a modifier - // and can appear legitimately - // Formulate this to avoid warnings from most compilers - if (strcmp(word, "if") == 0) { - char prevWord[MAX_KEYWORD_LENGTH + 1]; - getPrevWord(pos, prevWord, styler, SCE_RB_WORD); - return strcmp(prevWord, "else") != 0; - } - return true; - default: - return true; + case SCE_RB_DEFAULT: + case SCE_RB_COMMENTLINE: + case SCE_RB_POD: + case SCE_RB_CLASSNAME: + case SCE_RB_DEFNAME: + case SCE_RB_MODULE_NAME: + return false; + case SCE_RB_OPERATOR: + break; + case SCE_RB_WORD: + // Watch out for uses of 'else if' + //XXX: Make a list of other keywords where 'if' isn't a modifier + // and can appear legitimately + // Formulate this to avoid warnings from most compilers + if (strcmp(word, "if") == 0) { + char prevWord[MAX_KEYWORD_LENGTH + 1]; + getPrevWord(pos, prevWord, styler, SCE_RB_WORD); + return strcmp(prevWord, "else") != 0; + } + return true; + default: + return true; } // Assume that if the keyword follows an operator, // usually it's a block assignment, like @@ -1549,12 +1583,12 @@ static bool keywordIsModifier(const char *word, ch = styler[pos]; switch (ch) { - case ')': - case ']': - case '}': - return true; - default: - return false; + case ')': + case ']': + case '}': + return true; + default: + return false; } } @@ -1570,27 +1604,27 @@ static bool keywordDoStartsLoop(int pos, { char ch; int style; - int lineStart = styler.GetLine(pos); + int lineStart = styler.GetLine(pos); int lineStartPosn = styler.LineStart(lineStart); styler.Flush(); while (--pos >= lineStartPosn) { style = actual_style(styler.StyleAt(pos)); - if (style == SCE_RB_DEFAULT) { - if ((ch = styler[pos]) == '\r' || ch == '\n') { - // Scintilla's LineStart() and GetLine() routines aren't - // platform-independent, so if we have text prepared with - // a different system we can't rely on it. - return false; - } - } else if (style == SCE_RB_WORD) { + if (style == SCE_RB_DEFAULT) { + if ((ch = styler[pos]) == '\r' || ch == '\n') { + // Scintilla's LineStart() and GetLine() routines aren't + // platform-independent, so if we have text prepared with + // a different system we can't rely on it. + return false; + } + } else if (style == SCE_RB_WORD) { // Check for while or until, but write the word in backwards char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero char *dst = prevWord; int wordLen = 0; int start_word; for (start_word = pos; - start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD; - start_word--) { + start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD; + start_word--) { if (++wordLen < MAX_KEYWORD_LENGTH) { *dst++ = styler[start_word]; } @@ -1598,8 +1632,8 @@ static bool keywordDoStartsLoop(int pos, *dst = 0; // Did we see our keyword? if (!strcmp(prevWord, WHILE_BACKWARDS) - || !strcmp(prevWord, UNTIL_BACKWARDS) - || !strcmp(prevWord, FOR_BACKWARDS)) { + || !strcmp(prevWord, UNTIL_BACKWARDS) + || !strcmp(prevWord, FOR_BACKWARDS)) { return true; } // We can move pos to the beginning of the keyword, and then @@ -1617,6 +1651,19 @@ static bool keywordDoStartsLoop(int pos, return false; } +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + /* * Folding Ruby * @@ -1673,44 +1720,55 @@ static bool keywordDoStartsLoop(int pos, static void FoldRbDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { - const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; synchronizeDocStart(startPos, length, initStyle, styler, // ref args false); - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent) + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK & ~SC_FOLDLEVELBASE); - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1); + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1); bool buffer_ends_with_eol = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + /*Mutiline comment patch*/ + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent + 1, styler)) + levelCurrent--; + } + if (style == SCE_RB_COMMENTLINE) { if (foldComment && stylePrev != SCE_RB_COMMENTLINE) { if (chNext == '{') { - levelCurrent++; - } else if (chNext == '}' && levelCurrent > 0) { - levelCurrent--; - } + levelCurrent++; + } else if (chNext == '}' && levelCurrent > 0) { + levelCurrent--; + } } } else if (style == SCE_RB_OPERATOR) { - if (strchr("[{(", ch)) { - levelCurrent++; - } else if (strchr(")}]", ch)) { + if (strchr("[{(", ch)) { + levelCurrent++; + } else if (strchr(")}]", ch)) { // Don't decrement below 0 if (levelCurrent > 0) levelCurrent--; - } + } } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) { // Look at the keyword on the left and decide what to do char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero @@ -1720,7 +1778,7 @@ static void FoldRbDoc(unsigned int startPos, int length, int initStyle, // Don't decrement below 0 if (levelCurrent > 0) levelCurrent--; - } else if ( !strcmp(prevWord, "if") + } else if (!strcmp(prevWord, "if") || !strcmp(prevWord, "def") || !strcmp(prevWord, "class") || !strcmp(prevWord, "module") @@ -1731,49 +1789,49 @@ static void FoldRbDoc(unsigned int startPos, int length, int initStyle, || !strcmp(prevWord, "unless") || !strcmp(prevWord, "until") || !strcmp(prevWord, "for") - ) { - levelCurrent++; + ) { + levelCurrent++; } - } else if (style == SCE_RB_HERE_DELIM) { - if (styler.SafeGetCharAt(i-2) == '<' && styler.SafeGetCharAt(i-1) == '<') { - levelCurrent++; - } else if (styleNext == SCE_RB_DEFAULT) { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; + } else if (style == SCE_RB_HERE_DELIM) { + if (styler.SafeGetCharAt(i-2) == '<' && styler.SafeGetCharAt(i-1) == '<') { + levelCurrent++; + } else if (styleNext == SCE_RB_DEFAULT) { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE); - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; buffer_ends_with_eol = true; - } else if (!isspacechar(ch)) { - visibleChars++; + } else if (!isspacechar(ch)) { + visibleChars++; buffer_ends_with_eol = false; } - stylePrev = style; + stylePrev = style; } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later + // Fill in the real level of the next line, keeping the current flags as they will be filled in later if (!buffer_ends_with_eol) { lineCurrent++; int new_lev = levelCurrent; if (visibleChars == 0 && foldCompact) new_lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - new_lev |= SC_FOLDLEVELHEADERFLAG; - levelCurrent = new_lev; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + new_lev |= SC_FOLDLEVELHEADERFLAG; + levelCurrent = new_lev; } - styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE); + styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE); } -static const char * const rubyWordListDesc[] = { - "Keywords", - 0 +static const char *const rubyWordListDesc[] = { + "Keywords", + 0 }; -LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc, 6); +LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc); diff --git a/src/stc/scintilla/lexers/LexRust.cxx b/src/stc/scintilla/lexers/LexRust.cxx index 501b9a8230..80ec014cac 100644 --- a/src/stc/scintilla/lexers/LexRust.cxx +++ b/src/stc/scintilla/lexers/LexRust.cxx @@ -21,6 +21,7 @@ #include "Scintilla.h" #include "SciLexer.h" +#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" @@ -28,7 +29,6 @@ #include "CharacterSet.h" #include "LexerModule.h" #include "OptionSet.h" -#include "PropSetSimple.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -230,7 +230,9 @@ static void ScanIdentifier(Accessor& styler, int& pos, WordList *keywords) { } } -static void ScanDigits(Accessor& styler, int& pos, int base) { +/* Scans a sequence of digits, returning true if it found any. */ +static bool ScanDigits(Accessor& styler, int& pos, int base) { + int old_pos = pos; for (;;) { int c = styler.SafeGetCharAt(pos, '\0'); if (IsADigit(c, base) || c == '_') @@ -238,13 +240,17 @@ static void ScanDigits(Accessor& styler, int& pos, int base) { else break; } + return old_pos != pos; } +/* Scans an integer and floating point literals. */ static void ScanNumber(Accessor& styler, int& pos) { int base = 10; int c = styler.SafeGetCharAt(pos, '\0'); int n = styler.SafeGetCharAt(pos + 1, '\0'); bool error = false; + /* Scan the prefix, thus determining the base. + * 10 is default if there's no prefix. */ if (c == '0' && n == 'x') { pos += 2; base = 16; @@ -255,14 +261,17 @@ static void ScanNumber(Accessor& styler, int& pos) { pos += 2; base = 8; } - int old_pos = pos; - ScanDigits(styler, pos, base); + + /* Scan initial digits. The literal is malformed if there are none. */ + error |= !ScanDigits(styler, pos, base); + /* See if there's an integer suffix. We mimic the Rust's lexer + * and munch it even if there was an error above. */ c = styler.SafeGetCharAt(pos, '\0'); if (c == 'u' || c == 'i') { pos++; c = styler.SafeGetCharAt(pos, '\0'); n = styler.SafeGetCharAt(pos + 1, '\0'); - if (c == '8') { + if (c == '8' || c == 's') { pos++; } else if (c == '1' && n == '6') { pos += 2; @@ -270,15 +279,25 @@ static void ScanNumber(Accessor& styler, int& pos) { pos += 2; } else if (c == '6' && n == '4') { pos += 2; + } else { + error = true; } - } else { + /* See if it's a floating point literal. These literals have to be base 10. + */ + } else if (!error) { + /* If there's a period, it's a floating point literal unless it's + * followed by an identifier (meaning this is a method call, e.g. + * `1.foo()`) or another period, in which case it's a range (e.g. 1..2) + */ n = styler.SafeGetCharAt(pos + 1, '\0'); if (c == '.' && !(IsIdentifierStart(n) || n == '.')) { error |= base != 10; pos++; + /* It's ok to have no digits after the period. */ ScanDigits(styler, pos, 10); } + /* Look for the exponentiation. */ c = styler.SafeGetCharAt(pos, '\0'); if (c == 'e' || c == 'E') { error |= base != 10; @@ -286,13 +305,11 @@ static void ScanNumber(Accessor& styler, int& pos) { c = styler.SafeGetCharAt(pos, '\0'); if (c == '-' || c == '+') pos++; - int old_pos = pos; - ScanDigits(styler, pos, 10); - if (old_pos == pos) { - error = true; - } + /* It is invalid to have no digits in the exponent. */ + error |= !ScanDigits(styler, pos, 10); } - + + /* Scan the floating point suffix. */ c = styler.SafeGetCharAt(pos, '\0'); if (c == 'f') { error |= base != 10; @@ -308,9 +325,7 @@ static void ScanNumber(Accessor& styler, int& pos) { } } } - if (old_pos == pos) { - error = true; - } + if (error) styler.ColourTo(pos - 1, SCE_RUST_LEXERROR); else @@ -351,7 +366,7 @@ static bool IsValidCharacterEscape(int c) { } static bool IsValidStringEscape(int c) { - return IsValidCharacterEscape(c) || c == '\n'; + return IsValidCharacterEscape(c) || c == '\n' || c == '\r'; } static bool ScanNumericEscape(Accessor &styler, int& pos, int num_digits, bool stop_asap) { @@ -373,12 +388,12 @@ static bool ScanNumericEscape(Accessor &styler, int& pos, int num_digits, bool s /* This is overly permissive for character literals in order to accept UTF-8 encoded * character literals. */ -static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) { +static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos, bool ascii_only) { pos++; int c = styler.SafeGetCharAt(pos, '\0'); int n = styler.SafeGetCharAt(pos + 1, '\0'); bool done = false; - bool valid_lifetime = IsIdentifierStart(c); + bool valid_lifetime = !ascii_only && IsIdentifierStart(c); bool valid_char = true; bool first = true; while (!done) { @@ -390,10 +405,10 @@ static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) { } else if (n == 'x') { pos += 2; valid_char = ScanNumericEscape(styler, pos, 2, false); - } else if (n == 'u') { + } else if (n == 'u' && !ascii_only) { pos += 2; valid_char = ScanNumericEscape(styler, pos, 4, false); - } else if (n == 'U') { + } else if (n == 'U' && !ascii_only) { pos += 2; valid_char = ScanNumericEscape(styler, pos, 8, false); } else { @@ -412,7 +427,10 @@ static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) { done = true; break; default: - if (!IsIdentifierContinue(c) && !first) { + if (ascii_only && !IsASCII((char)c)) { + done = true; + valid_char = false; + } else if (!IsIdentifierContinue(c) && !first) { done = true; } else { pos++; @@ -433,7 +451,7 @@ static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) { styler.ColourTo(pos - 1, SCE_RUST_LIFETIME); } else if (valid_char) { pos++; - styler.ColourTo(pos - 1, SCE_RUST_CHARACTER); + styler.ColourTo(pos - 1, ascii_only ? SCE_RUST_BYTECHARACTER : SCE_RUST_CHARACTER); } else { styler.ColourTo(pos - 1, SCE_RUST_LEXERROR); } @@ -542,7 +560,7 @@ static void ScanComments(Accessor &styler, int& pos, int max) { ResumeBlockComment(styler, pos, max, UnknownComment, 1); } -static void ResumeString(Accessor &styler, int& pos, int max) { +static void ResumeString(Accessor &styler, int& pos, int max, bool ascii_only) { int c = styler.SafeGetCharAt(pos, '\0'); bool error = false; while (c != '"' && !error) { @@ -559,10 +577,10 @@ static void ResumeString(Accessor &styler, int& pos, int max) { } else if (n == 'x') { pos += 2; error = !ScanNumericEscape(styler, pos, 2, true); - } else if (n == 'u') { + } else if (n == 'u' && !ascii_only) { pos += 2; error = !ScanNumericEscape(styler, pos, 4, true); - } else if (n == 'U') { + } else if (n == 'U' && !ascii_only) { pos += 2; error = !ScanNumericEscape(styler, pos, 8, true); } else { @@ -570,16 +588,19 @@ static void ResumeString(Accessor &styler, int& pos, int max) { error = true; } } else { - pos++; + if (ascii_only && !IsASCII((char)c)) + error = true; + else + pos++; } c = styler.SafeGetCharAt(pos, '\0'); } if (!error) pos++; - styler.ColourTo(pos - 1, SCE_RUST_STRING); + styler.ColourTo(pos - 1, ascii_only ? SCE_RUST_BYTESTRING : SCE_RUST_STRING); } -static void ResumeRawString(Accessor &styler, int& pos, int max, int num_hashes) { +static void ResumeRawString(Accessor &styler, int& pos, int max, int num_hashes, bool ascii_only) { for (;;) { if (pos == styler.LineEnd(styler.GetLine(pos))) styler.SetLineState(styler.GetLine(pos), num_hashes); @@ -594,19 +615,20 @@ static void ResumeRawString(Accessor &styler, int& pos, int max, int num_hashes) } if (trailing_num_hashes == num_hashes) { styler.SetLineState(styler.GetLine(pos), 0); - styler.ColourTo(pos - 1, SCE_RUST_STRINGR); break; } } else if (pos >= max) { - styler.ColourTo(pos - 1, SCE_RUST_STRINGR); break; } else { + if (ascii_only && !IsASCII((char)c)) + break; pos++; } } + styler.ColourTo(pos - 1, ascii_only ? SCE_RUST_BYTESTRINGR : SCE_RUST_STRINGR); } -static void ScanRawString(Accessor &styler, int& pos, int max) { +static void ScanRawString(Accessor &styler, int& pos, int max, bool ascii_only) { pos++; int num_hashes = 0; while (styler.SafeGetCharAt(pos, '\0') == '#') { @@ -617,7 +639,7 @@ static void ScanRawString(Accessor &styler, int& pos, int max) { styler.ColourTo(pos - 1, SCE_RUST_LEXERROR); } else { pos++; - ResumeRawString(styler, pos, max, num_hashes); + ResumeRawString(styler, pos, max, num_hashes, ascii_only); } } @@ -635,9 +657,13 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle, } else if (initStyle == SCE_RUST_COMMENTLINE || initStyle == SCE_RUST_COMMENTLINEDOC) { ResumeLineComment(styler, pos, max, initStyle == SCE_RUST_COMMENTLINEDOC ? DocComment : NotDocComment); } else if (initStyle == SCE_RUST_STRING) { - ResumeString(styler, pos, max); + ResumeString(styler, pos, max, false); + } else if (initStyle == SCE_RUST_BYTESTRING) { + ResumeString(styler, pos, max, true); } else if (initStyle == SCE_RUST_STRINGR) { - ResumeRawString(styler, pos, max, styler.GetLineState(styler.GetLine(pos) - 1)); + ResumeRawString(styler, pos, max, styler.GetLineState(styler.GetLine(pos) - 1), false); + } else if (initStyle == SCE_RUST_BYTESTRINGR) { + ResumeRawString(styler, pos, max, styler.GetLineState(styler.GetLine(pos) - 1), true); } while (pos < max) { @@ -645,7 +671,7 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle, int n = styler.SafeGetCharAt(pos + 1, '\0'); int n2 = styler.SafeGetCharAt(pos + 2, '\0'); - if (pos == 0 && c == '#' && n == '!') { + if (pos == 0 && c == '#' && n == '!' && n2 != '[') { pos += 2; ResumeLineComment(styler, pos, max, NotDocComment); } else if (IsWhitespace(c)) { @@ -653,7 +679,16 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle, } else if (c == '/' && (n == '/' || n == '*')) { ScanComments(styler, pos, max); } else if (c == 'r' && (n == '#' || n == '"')) { - ScanRawString(styler, pos, max); + ScanRawString(styler, pos, max, false); + } else if (c == 'b' && n == 'r' && (n2 == '#' || n2 == '"')) { + pos++; + ScanRawString(styler, pos, max, true); + } else if (c == 'b' && n == '"') { + pos += 2; + ResumeString(styler, pos, max, true); + } else if (c == 'b' && n == '\'') { + pos++; + ScanCharacterLiteralOrLifetime(styler, pos, true); } else if (IsIdentifierStart(c)) { ScanIdentifier(styler, pos, keywords); } else if (IsADigit(c)) { @@ -668,10 +703,10 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle, pos++; styler.ColourTo(pos - 1, SCE_RUST_OPERATOR); } else if (c == '\'') { - ScanCharacterLiteralOrLifetime(styler, pos); + ScanCharacterLiteralOrLifetime(styler, pos, false); } else if (c == '"') { pos++; - ResumeString(styler, pos, max); + ResumeString(styler, pos, max, false); } else { pos++; styler.ColourTo(pos - 1, SCE_RUST_LEXERROR); diff --git a/src/stc/scintilla/lexers/LexSQL.cxx b/src/stc/scintilla/lexers/LexSQL.cxx index fa22f8e633..176c92c320 100644 --- a/src/stc/scintilla/lexers/LexSQL.cxx +++ b/src/stc/scintilla/lexers/LexSQL.cxx @@ -54,12 +54,12 @@ static inline bool IsADoxygenChar(int ch) { ch == '}' || ch == '[' || ch == ']'); } -static inline bool IsANumberChar(int ch) { +static inline bool IsANumberChar(int ch, int chPrev) { // Not exactly following number definition (several dots are seen as OK, etc.) // but probably enough in most cases. return (ch < 0x80) && (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); + ch == '.' || ((ch == '-' || ch == '+') && chPrev < 0x80 && toupper(chPrev) == 'E')); } typedef unsigned int sql_state_t; @@ -444,6 +444,7 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, StyleContext sc(startPos, length, initStyle, styler); int styleBeforeDCKeyword = SCE_SQL_DEFAULT; int offset = 0; + for (; sc.More(); sc.Forward(), offset++) { // Determine if the current state should terminate. switch (sc.state) { @@ -452,7 +453,7 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, break; case SCE_SQL_NUMBER: // We stop the number definition on non-numerical non-dot non-eE non-sign char - if (!IsANumberChar(sc.ch)) { + if (!IsANumberChar(sc.ch, sc.chPrev)) { sc.SetState(SCE_SQL_DEFAULT); } break; @@ -556,11 +557,45 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, } } break; + case SCE_SQL_QOPERATOR: + // Locate the unique Q operator character + sc.Complete(); + char qOperator = 0x00; + for (int styleStartPos = sc.currentPos; styleStartPos > 0; --styleStartPos) { + if (styler.StyleAt(styleStartPos - 1) != SCE_SQL_QOPERATOR) { + qOperator = styler.SafeGetCharAt(styleStartPos + 2); + break; + } + } + + char qComplement = 0x00; + + if (qOperator == '<') { + qComplement = '>'; + } else if (qOperator == '(') { + qComplement = ')'; + } else if (qOperator == '{') { + qComplement = '}'; + } else if (qOperator == '[') { + qComplement = ']'; + } else { + qComplement = qOperator; + } + + if (sc.Match(qComplement, '\'')) { + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + break; } // Determine if a new state should be entered. if (sc.state == SCE_SQL_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (sc.Match('q', '\'') || sc.Match('Q', '\'')) { + sc.SetState(SCE_SQL_QOPERATOR); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)) || + ((sc.ch == '-' || sc.ch == '+') && IsADigit(sc.chNext) && !IsADigit(sc.chPrev))) { sc.SetState(SCE_SQL_NUMBER); } else if (IsAWordStart(sc.ch)) { sc.SetState(SCE_SQL_IDENTIFIER); diff --git a/src/stc/scintilla/lexers/LexSTTXT.cxx b/src/stc/scintilla/lexers/LexSTTXT.cxx index 49ac7bdbb1..e1d2d371fe 100644 --- a/src/stc/scintilla/lexers/LexSTTXT.cxx +++ b/src/stc/scintilla/lexers/LexSTTXT.cxx @@ -33,9 +33,9 @@ static void ClassifySTTXTWord(WordList *keywordlists[], StyleContext &sc) char s[256] = { 0 }; sc.GetCurrentLowered(s, sizeof(s)); - if ((*keywordlists[0]).InList(s)) { - sc.ChangeState(SCE_STTXT_KEYWORD); - } + if ((*keywordlists[0]).InList(s)) { + sc.ChangeState(SCE_STTXT_KEYWORD); + } else if ((*keywordlists[1]).InList(s)) { sc.ChangeState(SCE_STTXT_TYPE); @@ -72,8 +72,8 @@ static void ColouriseSTTXTDoc (unsigned int startPos, int length, int initStyle, CharacterSet setOperator(CharacterSet::setNone,",.+-*/:;<=>[]()%&"); CharacterSet setDataTime(CharacterSet::setDigits,"_.-:dmshDMSH"); - for ( ; sc.More() ; sc.Forward()) - { + for ( ; sc.More() ; sc.Forward()) + { if(sc.atLineStart && sc.state != SCE_STTXT_COMMENT) sc.SetState(SCE_STTXT_DEFAULT); @@ -181,7 +181,7 @@ static void ColouriseSTTXTDoc (unsigned int startPos, int length, int initStyle, else if (setOperator.Contains(sc.ch)) sc.SetState(SCE_STTXT_OPERATOR); } - } + } if (sc.state == SCE_STTXT_IDENTIFIER && setWord.Contains(sc.chPrev)) ClassifySTTXTWord(keywordlists, sc); @@ -355,7 +355,7 @@ static void FoldSTTXTDoc(unsigned int startPos, int length, int initStyle, WordL } if ( foldComment && atEOL && ( IsCommentLine(lineCurrent, styler,false) || IsCommentLine(lineCurrent,styler,true))) { - if(!IsCommentLine(lineCurrent-1, styler,true) && IsCommentLine(lineCurrent+1, styler,true)) + if(!IsCommentLine(lineCurrent-1, styler,true) && IsCommentLine(lineCurrent+1, styler,true)) levelCurrent++; if (IsCommentLine(lineCurrent-1, styler,true) && !IsCommentLine(lineCurrent+1, styler,true)) levelCurrent--; diff --git a/src/stc/scintilla/lexers/LexScriptol.cxx b/src/stc/scintilla/lexers/LexScriptol.cxx index 31747b88ea..40ef0de580 100644 --- a/src/stc/scintilla/lexers/LexScriptol.cxx +++ b/src/stc/scintilla/lexers/LexScriptol.cxx @@ -127,11 +127,10 @@ static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, } } - styler.StartAt(startPos, 127); + styler.StartAt(startPos); WordList &keywords = *keywordlists[0]; - int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); char prevWord[200]; prevWord[0] = '\0'; if (length == 0) return; @@ -143,37 +142,9 @@ static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, char chPrev2 = ' '; char chNext = styler[startPos]; styler.StartSegment(startPos); - bool atStartLine = true; - int spaceFlags = 0; for (int i = startPos; i < lengthDoc; i++) { - if (atStartLine) - { - char chBad = static_cast(64); - char chGood = static_cast(0); - char chFlags = chGood; - - if (whingeLevel == 1) - { - chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood; - } - else if (whingeLevel == 2) - { - chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood; - } - else if (whingeLevel == 3) - { - chFlags = (spaceFlags & wsSpace) ? chBad : chGood; - } - else if (whingeLevel == 4) - { - chFlags = (spaceFlags & wsTab) ? chBad : chGood; - } - styler.SetFlags(chFlags, static_cast(state)); - atStartLine = false; - } - char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -185,7 +156,6 @@ static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, { styler.ColourTo(i, state); } - atStartLine = true; } if (styler.IsLeadByte(ch)) diff --git a/src/stc/scintilla/lexers/LexSpecman.cxx b/src/stc/scintilla/lexers/LexSpecman.cxx index 1b96482ea0..918edaf987 100644 --- a/src/stc/scintilla/lexers/LexSpecman.cxx +++ b/src/stc/scintilla/lexers/LexSpecman.cxx @@ -8,10 +8,10 @@ #include #include -#include #include #include #include +#include #include "ILexer.h" #include "Scintilla.h" diff --git a/src/stc/scintilla/lexers/LexTCL.cxx b/src/stc/scintilla/lexers/LexTCL.cxx index f6924e05e0..dfcab54ea6 100644 --- a/src/stc/scintilla/lexers/LexTCL.cxx +++ b/src/stc/scintilla/lexers/LexTCL.cxx @@ -30,7 +30,7 @@ using namespace Scintilla; // Extended to accept accented characters static inline bool IsAWordChar(int ch) { return ch >= 0x80 || - (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator + (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator } static inline bool IsAWordStart(int ch) { @@ -49,17 +49,18 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k #define isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT) bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool commentLevel = false; - bool subBrace = false; // substitution begin with a brace ${.....} + bool subBrace = false; // substitution begin with a brace ${.....} enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf, - LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT; + LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 + } lineState = LS_DEFAULT; bool prevSlash = false; int currentLevel = 0; - bool expected = 0; - bool subParen = 0; + bool expected = 0; + bool subParen = 0; int currentLine = styler.GetLine(startPos); - if (currentLine > 0) - currentLine--; + if (currentLine > 0) + currentLine--; length += startPos - styler.LineStart(currentLine); // make sure lines overlap startPos = styler.LineStart(currentLine); @@ -71,14 +72,14 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k WordList &keywords5 = *keywordlists[4]; WordList &keywords6 = *keywordlists[5]; WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - WordList &keywords9 = *keywordlists[8]; + WordList &keywords8 = *keywordlists[7]; + WordList &keywords9 = *keywordlists[8]; if (currentLine > 0) { - int ls = styler.GetLineState(currentLine - 1); + int ls = styler.GetLineState(currentLine - 1); lineState = tLineState(ls & LS_MASK_STATE); expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED); - subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY); + subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY); currentLevel = styler.LevelAt(currentLine - 1) >> 17; commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1; } else @@ -86,105 +87,104 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k bool visibleChars = false; int previousLevel = currentLevel; - StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler); + StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler); for (; ; sc.Forward()) { next: - if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac - continue; - bool atEnd = !sc.More(); // make sure we coloured the last word - if (lineState != LS_DEFAULT) { - sc.SetState(SCE_TCL_DEFAULT); - if (lineState == LS_OPEN_COMMENT) - sc.SetState(SCE_TCL_COMMENTLINE); - else if (lineState == LS_OPEN_DOUBLE_QUOTE) - sc.SetState(SCE_TCL_IN_QUOTE); - else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#'))) - sc.SetState(SCE_TCL_COMMENT_BOX); - lineState = LS_DEFAULT; - } - if (subBrace) { // ${ overrides every thing even \ except } - if (sc.ch == '}') { - subBrace = false; - sc.SetState(SCE_TCL_OPERATOR); - sc.ForwardSetState(SCE_TCL_DEFAULT); - goto next; - } - else - sc.SetState(SCE_TCL_SUB_BRACE); - if (!sc.atLineEnd) - continue; - } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) { - expected &= isspacechar(static_cast(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#'; - } else if (sc.state == SCE_TCL_SUBSTITUTION) { - switch(sc.ch) { - case '(': - subParen=true; - sc.SetState(SCE_TCL_OPERATOR); - sc.ForwardSetState(SCE_TCL_SUBSTITUTION); - continue; - case ')': - sc.SetState(SCE_TCL_OPERATOR); - subParen=false; - continue; - case '$': - continue; - case ',': - sc.SetState(SCE_TCL_OPERATOR); - if (subParen) - sc.ForwardSetState(SCE_TCL_SUBSTITUTION); - continue; - default : - // maybe spaces should be allowed ??? - if (!IsAWordChar(sc.ch)) { // probably the code is wrong - sc.SetState(SCE_TCL_DEFAULT); - subParen = 0; - } - break; - } - } else if (isComment(sc.state)) { - } else if (!IsAWordChar(sc.ch)) { - if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) { - char w[100]; - char *s=w; - sc.GetCurrent(w, sizeof(w)); - if (w[strlen(w)-1]=='\r') - w[strlen(w)-1]=0; - while(*s == ':') // ignore leading : like in ::set a 10 - ++s; - bool quote = sc.state == SCE_TCL_IN_QUOTE; - if (commentLevel || expected) { - if (keywords.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4); - } else if (sc.GetRelative(-static_cast(strlen(s))-1) == '{' && - keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces - sc.ChangeState(SCE_TCL_EXPAND); - } - if (keywords6.InList(s)) { - sc.ChangeState(SCE_TCL_WORD5); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_TCL_WORD6); - } else if (keywords8.InList(s)) { - sc.ChangeState(SCE_TCL_WORD7); - } else if (keywords9.InList(s)) { - sc.ChangeState(SCE_TCL_WORD8); - } - } - expected = false; - sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT); - } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) { - sc.SetState(SCE_TCL_DEFAULT); - } - } + if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac + continue; + bool atEnd = !sc.More(); // make sure we coloured the last word + if (lineState != LS_DEFAULT) { + sc.SetState(SCE_TCL_DEFAULT); + if (lineState == LS_OPEN_COMMENT) + sc.SetState(SCE_TCL_COMMENTLINE); + else if (lineState == LS_OPEN_DOUBLE_QUOTE) + sc.SetState(SCE_TCL_IN_QUOTE); + else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#'))) + sc.SetState(SCE_TCL_COMMENT_BOX); + lineState = LS_DEFAULT; + } + if (subBrace) { // ${ overrides every thing even \ except } + if (sc.ch == '}') { + subBrace = false; + sc.SetState(SCE_TCL_OPERATOR); + sc.ForwardSetState(SCE_TCL_DEFAULT); + goto next; + } else + sc.SetState(SCE_TCL_SUB_BRACE); + if (!sc.atLineEnd) + continue; + } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) { + expected &= isspacechar(static_cast(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#'; + } else if (sc.state == SCE_TCL_SUBSTITUTION) { + switch (sc.ch) { + case '(': + subParen=true; + sc.SetState(SCE_TCL_OPERATOR); + sc.ForwardSetState(SCE_TCL_SUBSTITUTION); + continue; + case ')': + sc.SetState(SCE_TCL_OPERATOR); + subParen=false; + continue; + case '$': + continue; + case ',': + sc.SetState(SCE_TCL_OPERATOR); + if (subParen) + sc.ForwardSetState(SCE_TCL_SUBSTITUTION); + continue; + default : + // maybe spaces should be allowed ??? + if (!IsAWordChar(sc.ch)) { // probably the code is wrong + sc.SetState(SCE_TCL_DEFAULT); + subParen = 0; + } + break; + } + } else if (isComment(sc.state)) { + } else if (!IsAWordChar(sc.ch)) { + if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) { + char w[100]; + char *s=w; + sc.GetCurrent(w, sizeof(w)); + if (w[strlen(w)-1]=='\r') + w[strlen(w)-1]=0; + while (*s == ':') // ignore leading : like in ::set a 10 + ++s; + bool quote = sc.state == SCE_TCL_IN_QUOTE; + if (commentLevel || expected) { + if (keywords.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4); + } else if (sc.GetRelative(-static_cast(strlen(s))-1) == '{' && + keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces + sc.ChangeState(SCE_TCL_EXPAND); + } + if (keywords6.InList(s)) { + sc.ChangeState(SCE_TCL_WORD5); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_TCL_WORD6); + } else if (keywords8.InList(s)) { + sc.ChangeState(SCE_TCL_WORD7); + } else if (keywords9.InList(s)) { + sc.ChangeState(SCE_TCL_WORD8); + } + } + expected = false; + sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT); + } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) { + sc.SetState(SCE_TCL_DEFAULT); + } + } if (atEnd) break; - if (sc.atLineEnd) { - lineState = LS_DEFAULT; + if (sc.atLineEnd) { + lineState = LS_DEFAULT; currentLine = styler.GetLine(sc.currentPos); if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) { if (currentLevel == 0) { @@ -206,45 +206,45 @@ next: styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16)); // Update the line state, so it can be seen by next line - if (sc.state == SCE_TCL_IN_QUOTE) + if (sc.state == SCE_TCL_IN_QUOTE) { lineState = LS_OPEN_DOUBLE_QUOTE; - else { - if (prevSlash) { - if (isComment(sc.state)) - lineState = LS_OPEN_COMMENT; - } else if (sc.state == SCE_TCL_COMMENT_BOX) - lineState = LS_COMMENT_BOX; + } else { + if (prevSlash) { + if (isComment(sc.state)) + lineState = LS_OPEN_COMMENT; + } else if (sc.state == SCE_TCL_COMMENT_BOX) + lineState = LS_COMMENT_BOX; } - styler.SetLineState(currentLine, - (subBrace ? LS_BRACE_ONLY : 0) | - (expected ? LS_COMMAND_EXPECTED : 0) | lineState); - if (lineState == LS_COMMENT_BOX) - sc.ForwardSetState(SCE_TCL_COMMENT_BOX); - else if (lineState == LS_OPEN_DOUBLE_QUOTE) - sc.ForwardSetState(SCE_TCL_IN_QUOTE); - else - sc.ForwardSetState(SCE_TCL_DEFAULT); + styler.SetLineState(currentLine, + (subBrace ? LS_BRACE_ONLY : 0) | + (expected ? LS_COMMAND_EXPECTED : 0) | lineState); + if (lineState == LS_COMMENT_BOX) + sc.ForwardSetState(SCE_TCL_COMMENT_BOX); + else if (lineState == LS_OPEN_DOUBLE_QUOTE) + sc.ForwardSetState(SCE_TCL_IN_QUOTE); + else + sc.ForwardSetState(SCE_TCL_DEFAULT); prevSlash = false; previousLevel = currentLevel; goto next; } if (prevSlash) { - prevSlash = false; - if (sc.ch == '#' && IsANumberChar(sc.chNext)) - sc.ForwardSetState(SCE_TCL_NUMBER); - continue; + prevSlash = false; + if (sc.ch == '#' && IsANumberChar(sc.chNext)) + sc.ForwardSetState(SCE_TCL_NUMBER); + continue; } - prevSlash = sc.ch == '\\'; - if (isComment(sc.state)) - continue; + prevSlash = sc.ch == '\\'; + if (isComment(sc.state)) + continue; if (sc.atLineStart) { visibleChars = false; if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state)) - { + { sc.SetState(SCE_TCL_DEFAULT); - expected = IsAWordStart(sc.ch)|| isspacechar(static_cast(sc.ch)); - } + expected = IsAWordStart(sc.ch)|| isspacechar(static_cast(sc.ch)); + } } switch (sc.state) { @@ -259,28 +259,28 @@ next: goto next; } else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') { sc.SetState(SCE_TCL_OPERATOR); - expected = sc.ch == '['; - sc.ForwardSetState(SCE_TCL_IN_QUOTE); + expected = sc.ch == '['; + sc.ForwardSetState(SCE_TCL_IN_QUOTE); goto next; } - continue; - case SCE_TCL_OPERATOR: + continue; + case SCE_TCL_OPERATOR: sc.SetState(SCE_TCL_DEFAULT); break; } if (sc.ch == '#') { if (visibleChars) { - if (sc.state != SCE_TCL_IN_QUOTE && expected) + if (sc.state != SCE_TCL_IN_QUOTE && expected) sc.SetState(SCE_TCL_COMMENT); } else { - sc.SetState(SCE_TCL_COMMENTLINE); - if (sc.chNext == '~') - sc.SetState(SCE_TCL_BLOCK_COMMENT); - if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-')) - sc.SetState(SCE_TCL_COMMENT_BOX); - } - } + sc.SetState(SCE_TCL_COMMENTLINE); + if (sc.chNext == '~') + sc.SetState(SCE_TCL_BLOCK_COMMENT); + if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-')) + sc.SetState(SCE_TCL_COMMENT_BOX); + } + } if (!isspacechar(static_cast(sc.ch))) { visibleChars = true; @@ -293,7 +293,7 @@ next: // Determine if a new state should be entered. if (sc.state == SCE_TCL_DEFAULT) { - if (IsAWordStart(sc.ch)) { + if (IsAWordStart(sc.ch)) { sc.SetState(SCE_TCL_IDENTIFIER); } else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) { sc.SetState(SCE_TCL_NUMBER); @@ -313,39 +313,38 @@ next: --currentLevel; break; case '[': - expected = true; + expected = true; case ']': case '(': case ')': sc.SetState(SCE_TCL_OPERATOR); break; case ';': - expected = true; + expected = true; break; - case '$': - subParen = 0; - if (sc.chNext != '{') { - sc.SetState(SCE_TCL_SUBSTITUTION); - } - else { - sc.SetState(SCE_TCL_OPERATOR); // $ - sc.Forward(); // { - sc.ForwardSetState(SCE_TCL_SUB_BRACE); - subBrace = true; - } - break; - case '#': - if ((isspacechar(static_cast(sc.chPrev))|| - isoperator(static_cast(sc.chPrev))) && IsADigit(sc.chNext,0x10)) - sc.SetState(SCE_TCL_NUMBER); - break; - case '-': - sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER); - break; - default: - if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_TCL_OPERATOR); - } + case '$': + subParen = 0; + if (sc.chNext != '{') { + sc.SetState(SCE_TCL_SUBSTITUTION); + } else { + sc.SetState(SCE_TCL_OPERATOR); // $ + sc.Forward(); // { + sc.ForwardSetState(SCE_TCL_SUB_BRACE); + subBrace = true; + } + break; + case '#': + if ((isspacechar(static_cast(sc.chPrev))|| + isoperator(static_cast(sc.chPrev))) && IsADigit(sc.chNext,0x10)) + sc.SetState(SCE_TCL_NUMBER); + break; + case '-': + sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER); + break; + default: + if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_TCL_OPERATOR); + } } } } @@ -353,18 +352,18 @@ next: sc.Complete(); } -static const char * const tclWordListDesc[] = { - "TCL Keywords", - "TK Keywords", - "iTCL Keywords", - "tkCommands", - "expand" - "user1", - "user2", - "user3", - "user4", - 0 - }; +static const char *const tclWordListDesc[] = { + "TCL Keywords", + "TK Keywords", + "iTCL Keywords", + "tkCommands", + "expand", + "user1", + "user2", + "user3", + "user4", + 0 +}; // this code supports folding in the colourizer LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc); diff --git a/src/stc/scintilla/lexers/LexVHDL.cxx b/src/stc/scintilla/lexers/LexVHDL.cxx index 88d8efb276..35383f3d85 100644 --- a/src/stc/scintilla/lexers/LexVHDL.cxx +++ b/src/stc/scintilla/lexers/LexVHDL.cxx @@ -12,10 +12,10 @@ #include #include -#include #include #include #include +#include #include "ILexer.h" #include "Scintilla.h" @@ -72,6 +72,7 @@ static void ColouriseVHDLDoc( WordList &User = *keywordlists[6]; StyleContext sc(startPos, length, initStyle, styler); + bool isExtendedId = false; // true when parsing an extended identifier for (; sc.More(); sc.Forward()) { @@ -84,7 +85,7 @@ static void ColouriseVHDLDoc( sc.SetState(SCE_VHDL_DEFAULT); } } else if (sc.state == SCE_VHDL_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + if (!isExtendedId && (!IsAWordChar(sc.ch) || (sc.ch == '.'))) { char s[100]; sc.GetCurrentLowered(s, sizeof(s)); if (Keywords.InList(s)) { @@ -103,6 +104,10 @@ static void ColouriseVHDLDoc( sc.ChangeState(SCE_VHDL_USERWORD); } sc.SetState(SCE_VHDL_DEFAULT); + } else if (isExtendedId && ((sc.ch == '\\') || sc.atLineEnd)) { + // extended identifiers are terminated by backslash, check for end of line in case we have invalid syntax + isExtendedId = false; + sc.ForwardSetState(SCE_VHDL_DEFAULT); } } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_VHDL_COMMENTLINEBANG) { if (sc.atLineEnd) { @@ -119,6 +124,11 @@ static void ColouriseVHDLDoc( sc.ChangeState(SCE_VHDL_STRINGEOL); sc.ForwardSetState(SCE_VHDL_DEFAULT); } + } else if (sc.state == SCE_VHDL_BLOCK_COMMENT){ + if(sc.ch == '*' && sc.chNext == '/'){ + sc.Forward(); + sc.ForwardSetState(SCE_VHDL_DEFAULT); + } } // Determine if a new state should be entered. @@ -132,8 +142,13 @@ static void ColouriseVHDLDoc( sc.SetState(SCE_VHDL_COMMENTLINEBANG); else sc.SetState(SCE_VHDL_COMMENT); + } else if (sc.Match('/', '*')){ + sc.SetState(SCE_VHDL_BLOCK_COMMENT); } else if (sc.ch == '\"') { sc.SetState(SCE_VHDL_STRING); + } else if (sc.ch == '\\') { + isExtendedId = true; + sc.SetState(SCE_VHDL_IDENTIFIER); } else if (isoperator(static_cast(sc.ch))) { sc.SetState(SCE_VHDL_OPERATOR); } @@ -155,6 +170,39 @@ static bool IsCommentLine(int line, Accessor &styler) { } return false; } +static bool IsCommentBlockStart(int line, Accessor &styler) +{ + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + char chNext = styler[i+1]; + char style = styler.StyleAt(i); + if ((style == SCE_VHDL_BLOCK_COMMENT) && (ch == '/') && (chNext == '*')) + return true; + } + return false; +} + +static bool IsCommentBlockEnd(int line, Accessor &styler) +{ + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + char chNext = styler[i+1]; + char style = styler.StyleAt(i); + if ((style == SCE_VHDL_BLOCK_COMMENT) && (ch == '*') && (chNext == '/')) + return true; + } + return false; +} + +static bool IsCommentStyle(char style) +{ + return style == SCE_VHDL_BLOCK_COMMENT || style == SCE_VHDL_COMMENT || style == SCE_VHDL_COMMENTLINEBANG; +} //============================================================================= // Folding the code @@ -167,7 +215,7 @@ static void FoldNoBoxVHDLDoc( // Decided it would be smarter to have the lexer have all keywords included. Therefore I // don't check if the style for the keywords that I use to adjust the levels. char words[] = - "architecture begin case component else elsif end entity generate loop package process record then " + "architecture begin block case component else elsif end entity generate loop package process record then " "procedure function when"; WordList keywords; keywords.Set(words); @@ -207,14 +255,14 @@ static void FoldNoBoxVHDLDoc( char chPrev = styler.SafeGetCharAt(j-1); int style = styler.StyleAt(j); int stylePrev = styler.StyleAt(j-1); - if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING)) + if ((!IsCommentStyle(style)) && (stylePrev != SCE_VHDL_STRING)) { if(IsAWordChar(chPrev) && !IsAWordChar(ch)) { end = j-1; } } - if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) + if ((!IsCommentStyle(style)) && (style != SCE_VHDL_STRING)) { if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0)) { @@ -236,7 +284,7 @@ static void FoldNoBoxVHDLDoc( { char ch = styler.SafeGetCharAt(j); int style = styler.StyleAt(j); - if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) + if ((!IsCommentStyle(style)) && (style != SCE_VHDL_STRING)) { if((ch == ';') && (strcmp(prevWord, "end") == 0)) { @@ -268,15 +316,29 @@ static void FoldNoBoxVHDLDoc( styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + if (foldComment && atEOL) { - if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler)) + if(IsCommentLine(lineCurrent, styler)) { - levelNext++; + if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler)) + { + levelNext++; + } + else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler)) + { + levelNext--; + } } - else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler)) + else { - levelNext--; + if (IsCommentBlockStart(lineCurrent, styler) && !IsCommentBlockEnd(lineCurrent, styler)) + { + levelNext++; + } + else if (IsCommentBlockEnd(lineCurrent, styler) && !IsCommentBlockStart(lineCurrent, styler)) + { + levelNext--; + } } } @@ -289,7 +351,7 @@ static void FoldNoBoxVHDLDoc( } } - if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) + if ((!IsCommentStyle(style)) && (style != SCE_VHDL_STRING)) { if((ch == ';') && (strcmp(prevWord, "end") == 0)) { @@ -301,7 +363,7 @@ static void FoldNoBoxVHDLDoc( lastStart = i; } - if(iswordchar(ch) && !iswordchar(chNext)) { + if(IsAWordChar(ch) && !IsAWordChar(chNext)) { char s[32]; unsigned int k; for(k=0; (k<31 ) && (k0 && + (chAtPos == ' ' || chAtPos == '\t' || + chAtPos == '\n' || chAtPos == '\r' || + IsCommentStyle(styleAtPos))); + + // check for a colon (':') before the instantiated units "entity", "component" or "configuration". Don't fold thereafter. + if (chAtPos != ':') + { + if (levelMinCurrentElse > levelNext) { + levelMinCurrentElse = levelNext; + } + levelNext++; + } + } } else if ( strcmp(s, "procedure") == 0 || strcmp(s, "function") == 0) @@ -338,19 +426,19 @@ static void FoldNoBoxVHDLDoc( { // This code checks to see if the procedure / function is a definition within a "package" // rather than the actual code in the body. int BracketLevel = 0; - for(int j=i+1; j levelNext) { levelMinCurrentElse = levelNext; @@ -358,7 +446,7 @@ static void FoldNoBoxVHDLDoc( levelNext++; break; } - if((BracketLevel == 0) && (LocalCh == ';')) + if((BracketLevel == 0) && (chAtPos == ';')) { break; } diff --git a/src/stc/scintilla/lexers/LexVerilog.cxx b/src/stc/scintilla/lexers/LexVerilog.cxx index ed39c2b177..f0995be240 100644 --- a/src/stc/scintilla/lexers/LexVerilog.cxx +++ b/src/stc/scintilla/lexers/LexVerilog.cxx @@ -13,6 +13,11 @@ #include #include +#include +#include +#include +#include + #include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" @@ -24,127 +29,722 @@ #include "CharacterSet.h" #include "LexerModule.h" +#include "OptionSet.h" +#include "SubStyles.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif +namespace { + // Use an unnamed namespace to protect the functions and classes from name conflicts + +struct PPDefinition { + int line; + std::string key; + std::string value; + bool isUndef; + std::string arguments; + PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false, std::string arguments_="") : + line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) { + } +}; + +class LinePPState { + int state; + int ifTaken; + int level; + bool ValidLevel() const { + return level >= 0 && level < 32; + } + int maskLevel() const { + return 1 << level; + } +public: + LinePPState() : state(0), ifTaken(0), level(-1) { + } + bool IsInactive() const { + return state != 0; + } + bool CurrentIfTaken() const { + return (ifTaken & maskLevel()) != 0; + } + void StartSection(bool on) { + level++; + if (ValidLevel()) { + if (on) { + state &= ~maskLevel(); + ifTaken |= maskLevel(); + } else { + state |= maskLevel(); + ifTaken &= ~maskLevel(); + } + } + } + void EndSection() { + if (ValidLevel()) { + state &= ~maskLevel(); + ifTaken &= ~maskLevel(); + } + level--; + } + void InvertCurrentLevel() { + if (ValidLevel()) { + state ^= maskLevel(); + ifTaken |= maskLevel(); + } + } +}; + +// Hold the preprocessor state for each line seen. +// Currently one entry per line but could become sparse with just one entry per preprocessor line. +class PPStates { + std::vector vlls; +public: + LinePPState ForLine(int line) const { + if ((line > 0) && (vlls.size() > static_cast(line))) { + return vlls[line]; + } else { + return LinePPState(); + } + } + void Add(int line, LinePPState lls) { + vlls.resize(line+1); + vlls[line] = lls; + } +}; + +// Options used for LexerVerilog +struct OptionsVerilog { + bool foldComment; + bool foldPreprocessor; + bool foldPreprocessorElse; + bool foldCompact; + bool foldAtElse; + bool foldAtModule; + bool trackPreprocessor; + bool updatePreprocessor; + bool portStyling; + bool allUppercaseDocKeyword; + OptionsVerilog() { + foldComment = false; + foldPreprocessor = false; + foldPreprocessorElse = false; + foldCompact = false; + foldAtElse = false; + foldAtModule = false; + // for backwards compatibility, preprocessor functionality is disabled by default + trackPreprocessor = false; + updatePreprocessor = false; + // for backwards compatibility, treat input/output/inout as regular keywords + portStyling = false; + // for backwards compatibility, don't treat all uppercase identifiers as documentation keywords + allUppercaseDocKeyword = false; + } +}; + +struct OptionSetVerilog : public OptionSet { + OptionSetVerilog() { + DefineProperty("fold.comment", &OptionsVerilog::foldComment, + "This option enables folding multi-line comments when using the Verilog lexer."); + DefineProperty("fold.preprocessor", &OptionsVerilog::foldPreprocessor, + "This option enables folding preprocessor directives when using the Verilog lexer."); + DefineProperty("fold.compact", &OptionsVerilog::foldCompact); + DefineProperty("fold.at.else", &OptionsVerilog::foldAtElse, + "This option enables folding on the else line of an if statement."); + DefineProperty("fold.verilog.flags", &OptionsVerilog::foldAtModule, + "This option enables folding module definitions. Typically source files " + "contain only one module definition so this option is somewhat useless."); + DefineProperty("lexer.verilog.track.preprocessor", &OptionsVerilog::trackPreprocessor, + "Set to 1 to interpret `if/`else/`endif to grey out code that is not active."); + DefineProperty("lexer.verilog.update.preprocessor", &OptionsVerilog::updatePreprocessor, + "Set to 1 to update preprocessor definitions when `define, `undef, or `undefineall found."); + DefineProperty("lexer.verilog.portstyling", &OptionsVerilog::portStyling, + "Set to 1 to style input, output, and inout ports differently from regular keywords."); + DefineProperty("lexer.verilog.allupperkeywords", &OptionsVerilog::allUppercaseDocKeyword, + "Set to 1 to style identifiers that are all uppercase as documentation keyword."); + DefineProperty("lexer.verilog.fold.preprocessor.else", &OptionsVerilog::foldPreprocessorElse, + "This option enables folding on `else and `elsif preprocessor directives."); + } +}; + +const char styleSubable[] = {0}; + +} + +class LexerVerilog : public ILexerWithSubStyles { + CharacterSet setWord; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList ppDefinitions; + PPStates vlls; + std::vector ppDefineHistory; + struct SymbolValue { + std::string value; + std::string arguments; + SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) { + } + SymbolValue &operator = (const std::string &value_) { + value = value_; + arguments.clear(); + return *this; + } + bool IsMacro() const { + return !arguments.empty(); + } + }; + typedef std::map SymbolTable; + SymbolTable preprocessorDefinitionsStart; + OptionsVerilog options; + OptionSetVerilog osVerilog; + enum { activeFlag = 0x40 }; + SubStyles subStyles; + + // states at end of line (EOL) during fold operations: + // foldExternFlag: EOL while parsing an extern function/task declaration terminated by ';' + // foldWaitDisableFlag: EOL while parsing wait or disable statement, terminated by "fork" or '(' + // typdefFlag: EOL while parsing typedef statement, terminated by ';' + enum {foldExternFlag = 0x01, foldWaitDisableFlag = 0x02, typedefFlag = 0x04}; + // map using line number as key to store fold state information + std::map foldState; + +public: + LexerVerilog() : + setWord(CharacterSet::setAlphaNum, "._", 0x80, true), + subStyles(styleSubable, 0x80, 0x40, activeFlag) { + } + virtual ~LexerVerilog() {} + int SCI_METHOD Version() const { + return lvSubStyles; + } + void SCI_METHOD Release() { + delete this; + } + const char* SCI_METHOD PropertyNames() { + return osVerilog.PropertyNames(); + } + int SCI_METHOD PropertyType(const char* name) { + return osVerilog.PropertyType(name); + } + const char* SCI_METHOD DescribeProperty(const char* name) { + return osVerilog.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char* key, const char* val) { + return osVerilog.PropertySet(&options, key, val); + } + const char* SCI_METHOD DescribeWordListSets() { + return osVerilog.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char* wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void* SCI_METHOD PrivateCall(int, void*) { + return 0; + } + int SCI_METHOD LineEndTypesSupported() { + return SC_LINE_END_TYPE_UNICODE; + } + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) { + int styleBase = subStyles.BaseStyle(MaskActive(subStyle)); + int active = subStyle & activeFlag; + return styleBase | active; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) { + return MaskActive(style); + } + void SCI_METHOD FreeSubStyles() { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() { + return activeFlag; + } + const char * SCI_METHOD GetSubStyleBases() { + return styleSubable; + } + static ILexer* LexerFactoryVerilog() { + return new LexerVerilog(); + } + static int MaskActive(int style) { + return style & ~activeFlag; + } + std::vector Tokenize(const std::string &expr) const; +}; + +int SCI_METHOD LexerVerilog::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &keywords5; + break; + case 5: + wordListN = &ppDefinitions; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + if (n == 5) { + // Rebuild preprocessorDefinitions + preprocessorDefinitionsStart.clear(); + for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) { + const char *cpDefinition = ppDefinitions.WordAt(nDefinition); + const char *cpEquals = strchr(cpDefinition, '='); + if (cpEquals) { + std::string name(cpDefinition, cpEquals - cpDefinition); + std::string val(cpEquals+1); + size_t bracket = name.find('('); + size_t bracketEnd = name.find(')'); + if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) { + // Macro + std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1); + name = name.substr(0, bracket); + preprocessorDefinitionsStart[name] = SymbolValue(val, args); + } else { + preprocessorDefinitionsStart[name] = val; + } + } else { + std::string name(cpDefinition); + std::string val("1"); + preprocessorDefinitionsStart[name] = val; + } + } + } + } + } + return firstModification; +} + static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$'); + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\''|| ch == '$'); } static inline bool IsAWordStart(const int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$'); } -static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { +static inline bool AllUpperCase(const char *a) { + while (*a) { + if (*a >= 'a' && *a <= 'z') return false; + a++; + } + return true; +} - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; +// Functor used to truncate history +struct After { + int line; + explicit After(int line_) : line(line_) {} + bool operator()(PPDefinition &p) const { + return p.line > line; + } +}; + +static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { + std::string restOfLine; + int i =0; + char ch = styler.SafeGetCharAt(start, '\n'); + int endLine = styler.LineEnd(styler.GetLine(start)); + while (((start+i) < endLine) && (ch != '\r')) { + char chNext = styler.SafeGetCharAt(start + i + 1, '\n'); + if (ch == '/' && (chNext == '/' || chNext == '*')) + break; + if (allowSpace || (ch != ' ')) + restOfLine += ch; + i++; + ch = chNext; + } + return restOfLine; +} + +static bool IsSpaceOrTab(int ch) { + return ch == ' ' || ch == '\t'; +} + +void SCI_METHOD LexerVerilog::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) +{ + LexAccessor styler(pAccess); + + const int kwOther=0, kwDot=0x100, kwInput=0x200, kwOutput=0x300, kwInout=0x400; + int lineState = kwOther; + bool continuationLine = false; + + int curLine = styler.GetLine(startPos); + if (curLine > 0) lineState = styler.GetLineState(curLine - 1); // Do not leak onto next line if (initStyle == SCE_V_STRINGEOL) initStyle = SCE_V_DEFAULT; + if ((MaskActive(initStyle) == SCE_V_PREPROCESSOR) || + (MaskActive(initStyle) == SCE_V_COMMENTLINE) || + (MaskActive(initStyle) == SCE_V_COMMENTLINEBANG)) { + // Set continuationLine if last character of previous line is '\' + if (curLine > 0) { + int endLinePrevious = styler.LineEnd(curLine - 1); + if (endLinePrevious > 0) { + continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\'; + } + } + } + StyleContext sc(startPos, length, initStyle, styler); + LinePPState preproc = vlls.ForLine(curLine); + + bool definitionsChanged = false; + + // Truncate ppDefineHistory before current line + + if (!options.updatePreprocessor) + ppDefineHistory.clear(); + + std::vector::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(curLine-1)); + if (itInvalid != ppDefineHistory.end()) { + ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); + definitionsChanged = true; + } + + SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart; + for (std::vector::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { + if (itDef->isUndef) + preprocessorDefinitions.erase(itDef->key); + else + preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments); + } + + int activitySet = preproc.IsInactive() ? activeFlag : 0; + int lineEndNext = styler.LineEnd(curLine); + bool isEscapedId = false; // true when parsing an escaped Identifier for (; sc.More(); sc.Forward()) { + if (sc.atLineStart) { + if (sc.state == SCE_V_STRING) { + // Prevent SCE_V_STRINGEOL from leaking back to previous line + sc.SetState(SCE_V_STRING); + } + if ((MaskActive(sc.state) == SCE_V_PREPROCESSOR) && (!continuationLine)) { + sc.SetState(SCE_V_DEFAULT|activitySet); + } + if (preproc.IsInactive()) { + activitySet = activeFlag; + sc.SetState(sc.state | activitySet); + } + } - if (sc.atLineStart && (sc.state == SCE_V_STRING)) { - // Prevent SCE_V_STRINGEOL from leaking back to previous line - sc.SetState(SCE_V_STRING); + if (sc.atLineEnd) { + curLine++; + lineEndNext = styler.LineEnd(curLine); + vlls.Add(curLine, preproc); + // Update the line state, so it can be seen by next line + styler.SetLineState(curLine, lineState); + isEscapedId = false; // EOL terminates an escaped Identifier } // Handle line continuation generically. if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { + if (static_cast((sc.currentPos+1)) >= lineEndNext) { + curLine++; + lineEndNext = styler.LineEnd(curLine); + vlls.Add(curLine, preproc); + // Update the line state, so it can be seen by next line + styler.SetLineState(curLine, lineState); sc.Forward(); if (sc.ch == '\r' && sc.chNext == '\n') { + // Even in UTF-8, \r and \n are separate sc.Forward(); } + continuationLine = true; + sc.Forward(); continue; } } + // for comment keyword + if (MaskActive(sc.state) == SCE_V_COMMENT_WORD && !IsAWordChar(sc.ch)) { + char s[100]; + int state = lineState & 0xff; + sc.GetCurrent(s, sizeof(s)); + if (keywords5.InList(s)) { + sc.ChangeState(SCE_V_COMMENT_WORD|activitySet); + } else { + sc.ChangeState(state|activitySet); + } + sc.SetState(state|activitySet); + } + + const bool atLineEndBeforeSwitch = sc.atLineEnd; + // Determine if the current state should terminate. - if (sc.state == SCE_V_OPERATOR) { - sc.SetState(SCE_V_DEFAULT); - } else if (sc.state == SCE_V_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_V_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_V_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_V_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_V_USER); + switch (MaskActive(sc.state)) { + case SCE_V_OPERATOR: + sc.SetState(SCE_V_DEFAULT|activitySet); + break; + case SCE_V_NUMBER: + if (!(IsAWordChar(sc.ch) || (sc.ch == '?'))) { + sc.SetState(SCE_V_DEFAULT|activitySet); } - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_PREPROCESSOR) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_COMMENT) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) { - if (sc.atLineStart) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + break; + case SCE_V_IDENTIFIER: + if (!isEscapedId &&(!IsAWordChar(sc.ch) || (sc.ch == '.'))) { + char s[100]; + lineState &= 0xff00; + sc.GetCurrent(s, sizeof(s)); + if (options.portStyling && (strcmp(s, "input") == 0)) { + lineState = kwInput; + sc.ChangeState(SCE_V_INPUT|activitySet); + } else if (options.portStyling && (strcmp(s, "output") == 0)) { + lineState = kwOutput; + sc.ChangeState(SCE_V_OUTPUT|activitySet); + } else if (options.portStyling && (strcmp(s, "inout") == 0)) { + lineState = kwInout; + sc.ChangeState(SCE_V_INOUT|activitySet); + } else if (lineState == kwInput) { + sc.ChangeState(SCE_V_INPUT|activitySet); + } else if (lineState == kwOutput) { + sc.ChangeState(SCE_V_OUTPUT|activitySet); + } else if (lineState == kwInout) { + sc.ChangeState(SCE_V_INOUT|activitySet); + } else if (lineState == kwDot) { + lineState = kwOther; + if (options.portStyling) + sc.ChangeState(SCE_V_PORT_CONNECT|activitySet); + } else if (keywords.InList(s)) { + sc.ChangeState(SCE_V_WORD|activitySet); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_V_WORD2|activitySet); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_V_WORD3|activitySet); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_V_USER|activitySet); + } else if (options.allUppercaseDocKeyword && AllUpperCase(s)) { + sc.ChangeState(SCE_V_USER|activitySet); + } + sc.SetState(SCE_V_DEFAULT|activitySet); + } + break; + case SCE_V_PREPROCESSOR: + if (!IsAWordChar(sc.ch) || sc.atLineEnd) { + sc.SetState(SCE_V_DEFAULT|activitySet); + } + break; + case SCE_V_COMMENT: + if (sc.Match('*', '/')) { sc.Forward(); + sc.ForwardSetState(SCE_V_DEFAULT|activitySet); + } else if (IsAWordStart(sc.ch)) { + lineState = sc.state | (lineState & 0xff00); + sc.SetState(SCE_V_COMMENT_WORD|activitySet); } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_V_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_V_STRINGEOL); - sc.ForwardSetState(SCE_V_DEFAULT); - } + break; + case SCE_V_COMMENTLINE: + case SCE_V_COMMENTLINEBANG: + if (sc.atLineStart) { + sc.SetState(SCE_V_DEFAULT|activitySet); + } else if (IsAWordStart(sc.ch)) { + lineState = sc.state | (lineState & 0xff00); + sc.SetState(SCE_V_COMMENT_WORD|activitySet); + } + break; + case SCE_V_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_V_DEFAULT|activitySet); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_V_STRINGEOL|activitySet); + sc.ForwardSetState(SCE_V_DEFAULT|activitySet); + } + break; + } + + if (sc.atLineEnd && !atLineEndBeforeSwitch) { + // State exit processing consumed characters up to end of line. + curLine++; + lineEndNext = styler.LineEnd(curLine); + vlls.Add(curLine, preproc); + // Update the line state, so it can be seen by next line + styler.SetLineState(curLine, lineState); + isEscapedId = false; // EOL terminates an escaped Identifier } // Determine if a new state should be entered. - if (sc.state == SCE_V_DEFAULT) { + if (MaskActive(sc.state) == SCE_V_DEFAULT) { if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_V_NUMBER); + sc.SetState(SCE_V_NUMBER|activitySet); } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_V_IDENTIFIER); + sc.SetState(SCE_V_IDENTIFIER|activitySet); } else if (sc.Match('/', '*')) { - sc.SetState(SCE_V_COMMENT); + sc.SetState(SCE_V_COMMENT|activitySet); sc.Forward(); // Eat the * so it isn't used for the end of the comment } else if (sc.Match('/', '/')) { if (sc.Match("//!")) // Nice to have a different comment style - sc.SetState(SCE_V_COMMENTLINEBANG); + sc.SetState(SCE_V_COMMENTLINEBANG|activitySet); else - sc.SetState(SCE_V_COMMENTLINE); + sc.SetState(SCE_V_COMMENTLINE|activitySet); } else if (sc.ch == '\"') { - sc.SetState(SCE_V_STRING); + sc.SetState(SCE_V_STRING|activitySet); } else if (sc.ch == '`') { - sc.SetState(SCE_V_PREPROCESSOR); + sc.SetState(SCE_V_PREPROCESSOR|activitySet); // Skip whitespace between ` and preprocessor word do { sc.Forward(); } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); if (sc.atLineEnd) { - sc.SetState(SCE_V_DEFAULT); + sc.SetState(SCE_V_DEFAULT|activitySet); + styler.SetLineState(curLine, lineState); + } else { + if (options.trackPreprocessor) { + if (sc.Match("ifdef") || sc.Match("ifndef")) { + bool isIfDef = sc.Match("ifdef"); + int i = isIfDef ? 5 : 6; + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false); + bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); + preproc.StartSection(isIfDef == foundDef); + } else if (sc.Match("else")) { + if (!preproc.CurrentIfTaken()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) { + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) { + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } + } else if (sc.Match("elsif")) { + // Ensure only one chosen out of `if .. `elsif .. `elsif .. `else .. `endif + if (!preproc.CurrentIfTaken()) { + // Similar to `ifdef + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + bool ifGood = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); + if (ifGood) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } else if (sc.Match("endif")) { + preproc.EndSection(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } else if (sc.Match("define")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + size_t startName = 0; + while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName])) + startName++; + size_t endName = startName; + while ((endName < restOfLine.length()) && setWord.Contains(static_cast(restOfLine[endName]))) + endName++; + std::string key = restOfLine.substr(startName, endName-startName); + if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) { + // Macro + size_t endArgs = endName; + while ((endArgs < restOfLine.length()) && (restOfLine[endArgs] != ')')) + endArgs++; + std::string args = restOfLine.substr(endName + 1, endArgs - endName - 1); + size_t startValue = endArgs+1; + while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) + startValue++; + std::string value; + if (startValue < restOfLine.length()) + value = restOfLine.substr(startValue); + preprocessorDefinitions[key] = SymbolValue(value, args); + ppDefineHistory.push_back(PPDefinition(curLine, key, value, false, args)); + definitionsChanged = true; + } else { + // Value + size_t startValue = endName; + while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) + startValue++; + std::string value = restOfLine.substr(startValue); + preprocessorDefinitions[key] = value; + ppDefineHistory.push_back(PPDefinition(curLine, key, value)); + definitionsChanged = true; + } + } + } else if (sc.Match("undefineall")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + // remove all preprocessor definitions + std::map::iterator itDef; + for(itDef = preprocessorDefinitions.begin(); itDef != preprocessorDefinitions.end(); ++itDef) { + ppDefineHistory.push_back(PPDefinition(curLine, itDef->first, "", true)); + } + preprocessorDefinitions.clear(); + definitionsChanged = true; + } + } else if (sc.Match("undef")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true); + std::vector tokens = Tokenize(restOfLine); + std::string key; + if (tokens.size() >= 1) { + key = tokens[0]; + preprocessorDefinitions.erase(key); + ppDefineHistory.push_back(PPDefinition(curLine, key, "", true)); + definitionsChanged = true; + } + } + } + } } + } else if (sc.ch == '\\') { + // escaped identifier, everything is ok up to whitespace + isEscapedId = true; + sc.SetState(SCE_V_IDENTIFIER|activitySet); } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '#') { - sc.SetState(SCE_V_OPERATOR); + sc.SetState(SCE_V_OPERATOR|activitySet); + if (sc.ch == '.') lineState = kwDot; + if (sc.ch == ';') lineState = kwOther; } } + if (isEscapedId && isspacechar(sc.ch)) { + isEscapedId = false; + } + } + if (definitionsChanged) { + styler.ChangeLexerState(startPos, startPos + length); } sc.Complete(); } @@ -153,7 +753,7 @@ static bool IsStreamCommentStyle(int style) { return style == SCE_V_COMMENT; } -static bool IsCommentLine(int line, Accessor &styler) { +static bool IsCommentLine(int line, LexAccessor &styler) { int pos = styler.LineStart(line); int eolPos = styler.LineStart(line + 1) - 1; for (int i = pos; i < eolPos; i++) { @@ -169,44 +769,60 @@ static bool IsCommentLine(int line, Accessor &styler) { } return false; } + // Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". -static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle, - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - // Verilog specific folding options: - // fold_at_module - - // Generally used methodology in verilog code is - // one module per file, so folding at module definition is useless. - // fold_at_brace/parenthese - - // Folding of long port lists can be convenient. - bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0; +void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) +{ + LexAccessor styler(pAccess); bool foldAtBrace = 1; bool foldAtParenthese = 1; + int lineCurrent = styler.GetLine(startPos); + // Move back one line to be compatible with LexerModule::Fold behavior, fixes problem with foldComment behavior + if (lineCurrent > 0) { + lineCurrent--; + int newStartPos = styler.LineStart(lineCurrent); + length += startPos - newStartPos; + startPos = newStartPos; + initStyle = 0; + if (startPos > 0) { + initStyle = styler.StyleAt(startPos - 1); + } + } unsigned int endPos = startPos + length; int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); int levelCurrent = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; int levelMinCurrent = levelCurrent; int levelNext = levelCurrent; char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; + int styleNext = MaskActive(styler.StyleAt(startPos)); + int style = MaskActive(initStyle); + + // restore fold state (if it exists) for prior line + int stateCurrent = 0; + std::map::iterator foldStateIterator = foldState.find(lineCurrent-1); + if (foldStateIterator != foldState.end()) { + stateCurrent = foldStateIterator->second; + } + + // remove all foldState entries after lineCurrent-1 + foldStateIterator = foldState.upper_bound(lineCurrent-1); + if (foldStateIterator != foldState.end()) { + foldState.erase(foldStateIterator, foldState.end()); + } + for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int stylePrev = style; style = styleNext; - styleNext = styler.StyleAt(i + 1); + styleNext = MaskActive(styler.StyleAt(i + 1)); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { + if (options.foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { @@ -214,7 +830,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle levelNext--; } } - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { if (!IsCommentLine(lineCurrent - 1, styler) && IsCommentLine(lineCurrent + 1, styler)) @@ -223,7 +839,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle && !IsCommentLine(lineCurrent+1, styler)) levelNext--; } - if (foldComment && (style == SCE_V_COMMENTLINE)) { + if (options.foldComment && (style == SCE_V_COMMENTLINE)) { if ((ch == '/') && (chNext == '/')) { char chNext2 = styler.SafeGetCharAt(i + 2); if (chNext2 == '{') { @@ -233,87 +849,157 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle } } } - if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { + if (options.foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { if (ch == '`') { unsigned int j = i + 1; while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { j++; } if (styler.Match(j, "if")) { + if (options.foldPreprocessorElse) { + // Measure the minimum before a begin to allow + // folding on "end else begin" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + } levelNext++; - } else if (styler.Match(j, "end")) { + } else if (options.foldPreprocessorElse && styler.Match(j, "else")) { + levelNext--; + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (options.foldPreprocessorElse && styler.Match(j, "elsif")) { + levelNext--; + // Measure the minimum before a begin to allow + // folding on "end else begin" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (styler.Match(j, "endif")) { levelNext--; } } } - if (style == SCE_V_OPERATOR) { - if (foldAtParenthese) { + if (style == SCE_V_OPERATOR) { + if (foldAtParenthese) { + if (ch == '(') { + levelNext++; + } else if (ch == ')') { + levelNext--; + } + } + // semicolons terminate external declarations + if (ch == ';') { + // extern and pure virtual declarations terminated by semicolon + if (stateCurrent & foldExternFlag) { + levelNext--; + stateCurrent &= ~foldExternFlag; + } + // wait and disable statements terminated by semicolon + if (stateCurrent & foldWaitDisableFlag) { + stateCurrent &= ~foldWaitDisableFlag; + } + // typedef statements terminated by semicolon + if (stateCurrent & typedefFlag) { + stateCurrent &= ~typedefFlag; + } + } + // wait and disable statements containing '(' will not contain "fork" keyword, special processing is not needed if (ch == '(') { - levelNext++; - } else if (ch == ')') { - levelNext--; + if (stateCurrent & foldWaitDisableFlag) { + stateCurrent &= ~foldWaitDisableFlag; + } } - } } - if (style == SCE_V_OPERATOR) { - if (foldAtBrace) { - if (ch == '{') { - levelNext++; - } else if (ch == '}') { - levelNext--; + if (style == SCE_V_OPERATOR) { + if (foldAtBrace) { + if (ch == '{') { + levelNext++; + } else if (ch == '}') { + levelNext--; + } } - } } - if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { - unsigned int j = i; - if (styler.Match(j, "case") || - styler.Match(j, "casex") || - styler.Match(j, "casez") || - styler.Match(j, "class") || - styler.Match(j, "function") || - styler.Match(j, "generate") || - styler.Match(j, "covergroup") || - styler.Match(j, "package") || - styler.Match(j, "primitive") || - styler.Match(j, "program") || - styler.Match(j, "sequence") || - styler.Match(j, "specify") || - styler.Match(j, "table") || - styler.Match(j, "task") || - styler.Match(j, "fork") || - (styler.Match(j, "module") && foldAtModule) || - styler.Match(j, "begin")) { - levelNext++; - } else if (styler.Match(j, "endcase") || - styler.Match(j, "endclass") || - styler.Match(j, "endfunction") || - styler.Match(j, "endgenerate") || - styler.Match(j, "endgroup") || - styler.Match(j, "endpackage") || - styler.Match(j, "endprimitive") || - styler.Match(j, "endprogram") || - styler.Match(j, "endsequence") || - styler.Match(j, "endspecify") || - styler.Match(j, "endtable") || - styler.Match(j, "endtask") || - styler.Match(j, "join") || - styler.Match(j, "join_any") || - styler.Match(j, "join_none") || - (styler.Match(j, "endmodule") && foldAtModule) || - (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) { - levelNext--; - } + if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { + unsigned int j = i; + if (styler.Match(j, "case") || + styler.Match(j, "casex") || + styler.Match(j, "casez") || + styler.Match(j, "function") || + styler.Match(j, "generate") || + styler.Match(j, "covergroup") || + styler.Match(j, "package") || + styler.Match(j, "primitive") || + styler.Match(j, "program") || + styler.Match(j, "sequence") || + styler.Match(j, "specify") || + styler.Match(j, "table") || + styler.Match(j, "task") || + (styler.Match(j, "module") && options.foldAtModule)) { + levelNext++; + } else if (styler.Match(j, "begin")) { + // Measure the minimum before a begin to allow + // folding on "end else begin" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (styler.Match(j, "class")) { + // class does not introduce a block when used in a typedef statement + if (!(stateCurrent & typedefFlag)) + levelNext++; + } else if (styler.Match(j, "fork")) { + // fork does not introduce a block when used in a wait or disable statement + if (stateCurrent & foldWaitDisableFlag) { + stateCurrent &= ~foldWaitDisableFlag; + } else + levelNext++; + } else if (styler.Match(j, "endcase") || + styler.Match(j, "endclass") || + styler.Match(j, "endfunction") || + styler.Match(j, "endgenerate") || + styler.Match(j, "endgroup") || + styler.Match(j, "endpackage") || + styler.Match(j, "endprimitive") || + styler.Match(j, "endprogram") || + styler.Match(j, "endsequence") || + styler.Match(j, "endspecify") || + styler.Match(j, "endtable") || + styler.Match(j, "endtask") || + styler.Match(j, "join") || + styler.Match(j, "join_any") || + styler.Match(j, "join_none") || + (styler.Match(j, "endmodule") && options.foldAtModule) || + (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j + 3)))) { + levelNext--; + } else if (styler.Match(j, "extern") || + styler.Match(j, "pure")) { + // extern and pure virtual functions/tasks are terminated by ';' not endfunction/endtask + stateCurrent |= foldExternFlag; + } else if (styler.Match(j, "disable") || + styler.Match(j, "wait")) { + // fork does not introduce a block when used in a wait or disable statement + stateCurrent |= foldWaitDisableFlag; + } else if (styler.Match(j, "typedef")) { + stateCurrent |= typedefFlag; + } } if (atEOL) { int levelUse = levelCurrent; - if (foldAtElse) { + if (options.foldAtElse||options.foldPreprocessorElse) { levelUse = levelMinCurrent; } int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) + if (visibleChars == 0 && options.foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; + if (stateCurrent) { + foldState[lineCurrent] = stateCurrent; + } if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } @@ -327,9 +1013,31 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle } } -static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - FoldNoBoxVerilogDoc(startPos, length, initStyle, styler); +std::vector LexerVerilog::Tokenize(const std::string &expr) const { + // Break into tokens + std::vector tokens; + const char *cp = expr.c_str(); + while (*cp) { + std::string word; + if (setWord.Contains(static_cast(*cp))) { + // Identifiers and numbers + while (setWord.Contains(static_cast(*cp))) { + word += *cp; + cp++; + } + } else if (IsSpaceOrTab(*cp)) { + while (IsSpaceOrTab(*cp)) { + cp++; + } + continue; + } else { + // Should handle strings, characters, and comments here + word += *cp; + cp++; + } + tokens.push_back(word); + } + return tokens; } static const char * const verilogWordLists[] = { @@ -337,9 +1045,9 @@ static const char * const verilogWordLists[] = { "Secondary keywords and identifiers", "System Tasks", "User defined tasks and identifiers", - "Unused", + "Documentation comment keywords", + "Preprocessor definitions", 0, }; - -LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists); +LexerModule lmVerilog(SCLEX_VERILOG, LexerVerilog::LexerFactoryVerilog, "verilog", verilogWordLists); diff --git a/src/stc/scintilla/lexers/LexVisualProlog.cxx b/src/stc/scintilla/lexers/LexVisualProlog.cxx index b89353dc7b..24e19e24ea 100644 --- a/src/stc/scintilla/lexers/LexVisualProlog.cxx +++ b/src/stc/scintilla/lexers/LexVisualProlog.cxx @@ -13,10 +13,10 @@ #include #include -#include #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable: 4786) @@ -396,7 +396,7 @@ void SCI_METHOD LexerVisualProlog::Lex(unsigned int startPos, int length, int in if (sc.atLineEnd) { // Update the line state, so it can be seen by next line int lineState = 0; - if (SCE_VISUALPROLOG_STRING_VERBATIM_EOL == sc.state) { + if (SCE_VISUALPROLOG_STRING_VERBATIM_EOL == sc.state) { lineState = closingQuote; } else if (SCE_VISUALPROLOG_COMMENT_BLOCK == sc.state) { lineState = nestLevel; diff --git a/src/stc/scintilla/lexlib/Accessor.cxx b/src/stc/scintilla/lexlib/Accessor.cxx index 61661626f8..f67737d4d6 100644 --- a/src/stc/scintilla/lexlib/Accessor.cxx +++ b/src/stc/scintilla/lexlib/Accessor.cxx @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include "ILexer.h" #include "Scintilla.h" diff --git a/src/stc/scintilla/lexlib/CharacterCategory.cxx b/src/stc/scintilla/lexlib/CharacterCategory.cxx index 765469a3f7..2be46c0130 100644 --- a/src/stc/scintilla/lexlib/CharacterCategory.cxx +++ b/src/stc/scintilla/lexlib/CharacterCategory.cxx @@ -3287,7 +3287,7 @@ const int nRanges = ELEMENTS(catRanges); // Initial version has 3249 entries and adds about 13K to the executable. // The array is in ascending order so can be searched using binary search. // Therefore the average call takes log2(3249) = 12 comparisons. -// For speed, it may be an useful to make a linear table for the common values, +// For speed, it may be useful to make a linear table for the common values, // possibly for 0..0xff for most Western European text or 0..0xfff for most // alphabetic languages. diff --git a/src/stc/scintilla/lexlib/CharacterSet.cxx b/src/stc/scintilla/lexlib/CharacterSet.cxx index 2f41df1166..0ab2cc0cc9 100644 --- a/src/stc/scintilla/lexlib/CharacterSet.cxx +++ b/src/stc/scintilla/lexlib/CharacterSet.cxx @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include #include "CharacterSet.h" diff --git a/src/stc/scintilla/lexlib/LexAccessor.h b/src/stc/scintilla/lexlib/LexAccessor.h index 45a3a0a93e..8e3455d0c3 100644 --- a/src/stc/scintilla/lexlib/LexAccessor.h +++ b/src/stc/scintilla/lexlib/LexAccessor.h @@ -29,11 +29,8 @@ private: int codePage; enum EncodingType encodingType; int lenDoc; - int mask; char styleBuf[bufferSize]; int validLen; - char chFlags; - char chWhile; unsigned int startSeg; int startPosStyling; int documentVersion; @@ -58,9 +55,12 @@ public: codePage(pAccess->CodePage()), encodingType(enc8bit), lenDoc(pAccess->Length()), - mask(127), validLen(0), chFlags(0), chWhile(0), + validLen(0), startSeg(0), startPosStyling(0), documentVersion(pAccess->Version()) { + // Prevent warnings by static analyzers about uninitialized buf and styleBuf. + buf[0] = 0; + styleBuf[0] = 0; switch (codePage) { case 65001: encodingType = encUnicode; @@ -111,7 +111,7 @@ public: return true; } char StyleAt(int position) const { - return static_cast(pAccess->StyleAt(position) & mask); + return static_cast(pAccess->StyleAt(position)); } int GetLine(int position) const { return pAccess->LineFromPosition(position); @@ -152,16 +152,10 @@ public: return pAccess->SetLineState(line, state); } // Style setting - void StartAt(unsigned int start, char chMask=31) { - // Store the mask specified for use with StyleAt. - mask = chMask; - pAccess->StartStyling(start, chMask); + void StartAt(unsigned int start) { + pAccess->StartStyling(start, '\377'); startPosStyling = start; } - void SetFlags(char chFlags_, char chWhile_) { - chFlags = chFlags_; - chWhile = chWhile_; - } unsigned int GetStartSegment() const { return startSeg; } @@ -182,9 +176,6 @@ public: // Too big for buffer so send directly pAccess->SetStyleFor(pos - startSeg + 1, static_cast(chAttr)); } else { - if (chAttr != chWhile) - chFlags = 0; - chAttr = static_cast(chAttr | chFlags); for (unsigned int i = startSeg; i <= pos; i++) { assert((startPosStyling + validLen) < Length()); styleBuf[validLen++] = static_cast(chAttr); diff --git a/src/stc/scintilla/lexlib/LexerBase.cxx b/src/stc/scintilla/lexlib/LexerBase.cxx index 0e86562bf9..bbef3f1593 100644 --- a/src/stc/scintilla/lexlib/LexerBase.cxx +++ b/src/stc/scintilla/lexlib/LexerBase.cxx @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include "ILexer.h" #include "Scintilla.h" diff --git a/src/stc/scintilla/lexlib/LexerModule.cxx b/src/stc/scintilla/lexlib/LexerModule.cxx index c77b317751..6cefbee778 100644 --- a/src/stc/scintilla/lexlib/LexerModule.cxx +++ b/src/stc/scintilla/lexlib/LexerModule.cxx @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include @@ -34,28 +34,24 @@ LexerModule::LexerModule(int language_, LexerFunction fnLexer_, const char *languageName_, LexerFunction fnFolder_, - const char *const wordListDescriptions_[], - int styleBits_) : + const char *const wordListDescriptions_[]) : language(language_), fnLexer(fnLexer_), fnFolder(fnFolder_), fnFactory(0), wordListDescriptions(wordListDescriptions_), - styleBits(styleBits_), languageName(languageName_) { } LexerModule::LexerModule(int language_, LexerFactoryFunction fnFactory_, const char *languageName_, - const char * const wordListDescriptions_[], - int styleBits_) : + const char * const wordListDescriptions_[]) : language(language_), fnLexer(0), fnFolder(0), fnFactory(fnFactory_), wordListDescriptions(wordListDescriptions_), - styleBits(styleBits_), languageName(languageName_) { } @@ -82,10 +78,6 @@ const char *LexerModule::GetWordListDescription(int index) const { } } -int LexerModule::GetStyleBitsNeeded() const { - return styleBits; -} - ILexer *LexerModule::Create() const { if (fnFactory) return fnFactory(); diff --git a/src/stc/scintilla/lexlib/LexerModule.h b/src/stc/scintilla/lexlib/LexerModule.h index e502541b2d..5993c0fe97 100644 --- a/src/stc/scintilla/lexlib/LexerModule.h +++ b/src/stc/scintilla/lexlib/LexerModule.h @@ -31,7 +31,6 @@ protected: LexerFunction fnFolder; LexerFactoryFunction fnFactory; const char * const * wordListDescriptions; - int styleBits; public: const char *languageName; @@ -39,13 +38,11 @@ public: LexerFunction fnLexer_, const char *languageName_=0, LexerFunction fnFolder_=0, - const char * const wordListDescriptions_[] = NULL, - int styleBits_=5); + const char * const wordListDescriptions_[] = NULL); LexerModule(int language_, LexerFactoryFunction fnFactory_, const char *languageName_, - const char * const wordListDescriptions_[] = NULL, - int styleBits_=8); + const char * const wordListDescriptions_[] = NULL); virtual ~LexerModule() { } int GetLanguage() const { return language; } @@ -54,8 +51,6 @@ public: int GetNumWordLists() const; const char *GetWordListDescription(int index) const; - int GetStyleBitsNeeded() const; - ILexer *Create() const; virtual void Lex(unsigned int startPos, int length, int initStyle, @@ -72,7 +67,12 @@ inline int Maximum(int a, int b) { // Shut up annoying Visual C++ warnings: #ifdef _MSC_VER -#pragma warning(disable: 4244 4309 4514 4710) +#pragma warning(disable: 4244 4309 4456 4457) +#endif + +// Turn off shadow warnings for lexers as may be maintained by others +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wshadow" #endif #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/lexlib/LexerNoExceptions.cxx b/src/stc/scintilla/lexlib/LexerNoExceptions.cxx index 5f31f22688..9ebae2af09 100644 --- a/src/stc/scintilla/lexlib/LexerNoExceptions.cxx +++ b/src/stc/scintilla/lexlib/LexerNoExceptions.cxx @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include "ILexer.h" #include "Scintilla.h" diff --git a/src/stc/scintilla/lexlib/LexerSimple.cxx b/src/stc/scintilla/lexlib/LexerSimple.cxx index 5489ab886e..4d0e178ca9 100644 --- a/src/stc/scintilla/lexlib/LexerSimple.cxx +++ b/src/stc/scintilla/lexlib/LexerSimple.cxx @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include diff --git a/src/stc/scintilla/lexlib/PropSetSimple.cxx b/src/stc/scintilla/lexlib/PropSetSimple.cxx index 6f4553a07c..6592d70eb3 100644 --- a/src/stc/scintilla/lexlib/PropSetSimple.cxx +++ b/src/stc/scintilla/lexlib/PropSetSimple.cxx @@ -11,11 +11,6 @@ #include #include -#ifdef _MSC_VER -// Visual C++ doesn't like unreachable code in its own headers. -#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702) -#endif - #include #include diff --git a/src/stc/scintilla/lexlib/StyleContext.cxx b/src/stc/scintilla/lexlib/StyleContext.cxx index ec0c5047ce..9429c5ba87 100644 --- a/src/stc/scintilla/lexlib/StyleContext.cxx +++ b/src/stc/scintilla/lexlib/StyleContext.cxx @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include "ILexer.h" diff --git a/src/stc/scintilla/lexlib/StyleContext.h b/src/stc/scintilla/lexlib/StyleContext.h index 9b5ce5dff8..837386cef9 100644 --- a/src/stc/scintilla/lexlib/StyleContext.h +++ b/src/stc/scintilla/lexlib/StyleContext.h @@ -66,7 +66,7 @@ public: int widthNext; StyleContext(unsigned int startPos, unsigned int length, - int initStyle, LexAccessor &styler_, char chMask=31) : + int initStyle, LexAccessor &styler_, char chMask='\377') : styler(styler_), multiByteAccess(0), endPos(startPos + length), @@ -86,7 +86,7 @@ public: if (styler.Encoding() != enc8bit) { multiByteAccess = styler.MultiByteAccess(); } - styler.StartAt(startPos, chMask); + styler.StartAt(startPos /*, chMask*/); styler.StartSegment(startPos); currentLine = styler.GetLine(startPos); lineStartNext = styler.LineStart(currentLine+1); diff --git a/src/stc/scintilla/lexlib/SubStyles.h b/src/stc/scintilla/lexlib/SubStyles.h index 5791078196..f5b15e9cfa 100644 --- a/src/stc/scintilla/lexlib/SubStyles.h +++ b/src/stc/scintilla/lexlib/SubStyles.h @@ -166,7 +166,8 @@ public: } const WordClassifier &Classifier(int baseStyle) const { - return classifiers[BlockFromBaseStyle(baseStyle)]; + const int block = BlockFromBaseStyle(baseStyle); + return classifiers[block >= 0 ? block : 0]; } }; diff --git a/src/stc/scintilla/lexlib/WordList.cxx b/src/stc/scintilla/lexlib/WordList.cxx index 10b6fe349f..be7fda5056 100644 --- a/src/stc/scintilla/lexlib/WordList.cxx +++ b/src/stc/scintilla/lexlib/WordList.cxx @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include @@ -69,6 +69,8 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa WordList::WordList(bool onlyLineEnds_) : words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) { + // Prevent warnings by static analyzers about uninitialized starts. + starts[0] = -1; } WordList::~WordList() { diff --git a/src/stc/scintilla/src/AutoComplete.cxx b/src/stc/scintilla/src/AutoComplete.cxx index d154a913a1..27eed53b99 100644 --- a/src/stc/scintilla/src/AutoComplete.cxx +++ b/src/stc/scintilla/src/AutoComplete.cxx @@ -167,7 +167,9 @@ void AutoComplete::SetList(const char *list) { char item[maxItemLen]; for (size_t i = 0; i < sortMatrix.size(); ++i) { int wordLen = IndexSort.indices[sortMatrix[i] * 2 + 2] - IndexSort.indices[sortMatrix[i] * 2]; - strncpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen); + if (wordLen > maxItemLen-2) + wordLen = maxItemLen - 2; + memcpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen); if ((i+1) == sortMatrix.size()) { // Last item so remove separator if present if ((wordLen > 0) && (item[wordLen-1] == separator)) diff --git a/src/stc/scintilla/src/AutoComplete.h b/src/stc/scintilla/src/AutoComplete.h index 6838e43062..c35fa1a0ee 100644 --- a/src/stc/scintilla/src/AutoComplete.h +++ b/src/stc/scintilla/src/AutoComplete.h @@ -65,7 +65,7 @@ public: void SetSeparator(char separator_); char GetSeparator() const; - /// The typesep character is used for seperating the word from the type + /// The typesep character is used for separating the word from the type void SetTypesep(char separator_); char GetTypesep() const; diff --git a/src/stc/scintilla/src/CallTip.cxx b/src/stc/scintilla/src/CallTip.cxx index 7dc23a4ac3..f6f3f10ea0 100644 --- a/src/stc/scintilla/src/CallTip.cxx +++ b/src/stc/scintilla/src/CallTip.cxx @@ -109,13 +109,15 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, int endSeg = ends[seg]; if (endSeg > startSeg) { if (IsArrowCharacter(s[startSeg])) { + xEnd = x + widthArrow; bool upArrow = s[startSeg] == '\001'; - rcClient.left = x; - rcClient.right = rcClient.left + widthArrow; + rcClient.left = static_cast(x); + rcClient.right = static_cast(xEnd); if (draw) { const int halfWidth = widthArrow / 2 - 3; - const int centreX = rcClient.left + widthArrow / 2 - 1; - const int centreY = (rcClient.top + rcClient.bottom) / 2; + const int quarterWidth = halfWidth / 2; + const int centreX = x + widthArrow / 2 - 1; + const int centreY = static_cast(rcClient.top + rcClient.bottom) / 2; surface->FillRectangle(rcClient, colourBG); PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1, rcClient.right - 2, rcClient.bottom - 1); @@ -123,21 +125,20 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, if (upArrow) { // Up arrow Point pts[] = { - Point(centreX - halfWidth, centreY + halfWidth / 2), - Point(centreX + halfWidth, centreY + halfWidth / 2), - Point(centreX, centreY - halfWidth + halfWidth / 2), + Point::FromInts(centreX - halfWidth, centreY + quarterWidth), + Point::FromInts(centreX + halfWidth, centreY + quarterWidth), + Point::FromInts(centreX, centreY - halfWidth + quarterWidth), }; surface->Polygon(pts, ELEMENTS(pts), colourBG, colourBG); } else { // Down arrow Point pts[] = { - Point(centreX - halfWidth, centreY - halfWidth / 2), - Point(centreX + halfWidth, centreY - halfWidth / 2), - Point(centreX, centreY + halfWidth - halfWidth / 2), + Point::FromInts(centreX - halfWidth, centreY - quarterWidth), + Point::FromInts(centreX + halfWidth, centreY - quarterWidth), + Point::FromInts(centreX, centreY + halfWidth - quarterWidth), }; surface->Polygon(pts, ELEMENTS(pts), colourBG, colourBG); } } - xEnd = rcClient.right; offsetMain = xEnd; if (upArrow) { rectUp = rcClient; @@ -147,11 +148,11 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, } else if (IsTabCharacter(s[startSeg])) { xEnd = NextTabPos(x); } else { - xEnd = x + surface->WidthText(font, s + startSeg, endSeg - startSeg); + xEnd = x + RoundXYPosition(surface->WidthText(font, s + startSeg, endSeg - startSeg)); if (draw) { - rcClient.left = x; - rcClient.right = xEnd; - surface->DrawTextTransparent(rcClient, font, ytext, + rcClient.left = static_cast(x); + rcClient.right = static_cast(xEnd); + surface->DrawTextTransparent(rcClient, font, static_cast(ytext), s+startSeg, endSeg - startSeg, highlight ? colourSel : colourUnSel); } @@ -164,16 +165,16 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, int CallTip::PaintContents(Surface *surfaceWindow, bool draw) { PRectangle rcClientPos = wCallTip.GetClientPosition(); - PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left, + PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left, rcClientPos.bottom - rcClientPos.top); - PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1); + PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1); // To make a nice small call tip window, it is only sized to fit most normal characters without accents - int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font); + int ascent = RoundXYPosition(surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font)); // For each line... // Draw the definition in three parts: before highlight, highlighted, after highlight - int ytext = rcClient.top + ascent + 1; + int ytext = static_cast(rcClient.top) + ascent + 1; rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1; const char *chunkVal = val.c_str(); bool moreChunks = true; @@ -185,8 +186,8 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) { chunkEnd = chunkVal + strlen(chunkVal); moreChunks = false; } - int chunkOffset = chunkVal - val.c_str(); - int chunkLength = chunkEnd - chunkVal; + int chunkOffset = static_cast(chunkVal - val.c_str()); + int chunkLength = static_cast(chunkEnd - chunkVal); int chunkEndOffset = chunkOffset + chunkLength; int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset); thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset); @@ -194,7 +195,7 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) { int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset); thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset); thisEndHighlight -= chunkOffset; - rcClient.top = ytext - ascent - 1; + rcClient.top = static_cast(ytext - ascent - 1); int x = insetX; // start each line at this inset @@ -217,9 +218,9 @@ void CallTip::PaintCT(Surface *surfaceWindow) { if (val.empty()) return; PRectangle rcClientPos = wCallTip.GetClientPosition(); - PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left, + PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left, rcClientPos.bottom - rcClientPos.top); - PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1); + PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1); surfaceWindow->FillRectangle(rcClient, colourBG); @@ -229,13 +230,13 @@ void CallTip::PaintCT(Surface *surfaceWindow) { #ifndef __APPLE__ // OSX doesn't put borders on "help tags" // Draw a raised border around the edges of the window - surfaceWindow->MoveTo(0, rcClientSize.bottom - 1); + surfaceWindow->MoveTo(0, static_cast(rcClientSize.bottom) - 1); surfaceWindow->PenColour(colourShade); - surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1); - surfaceWindow->LineTo(rcClientSize.right - 1, 0); + surfaceWindow->LineTo(static_cast(rcClientSize.right) - 1, static_cast(rcClientSize.bottom) - 1); + surfaceWindow->LineTo(static_cast(rcClientSize.right) - 1, 0); surfaceWindow->PenColour(colourLight); surfaceWindow->LineTo(0, 0); - surfaceWindow->LineTo(0, rcClientSize.bottom - 1); + surfaceWindow->LineTo(0, static_cast(rcClientSize.bottom) - 1); #endif } @@ -264,7 +265,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char * endHighlight = 0; inCallTipMode = true; posStartCallTip = pos; - int deviceHeight = surfaceMeasure->DeviceHeightFont(size); + XYPOSITION deviceHeight = static_cast(surfaceMeasure->DeviceHeightFont(size)); FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet); font.Create(fp); // Look for multiple lines in the text @@ -280,12 +281,12 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char * look = newline + 1; numLines++; } - lineHeight = surfaceMeasure->Height(font); + lineHeight = RoundXYPosition(surfaceMeasure->Height(font)); // The returned // rectangle is aligned to the right edge of the last arrow encountered in // the tip text, else to the tip text left edge. - int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + borderHeight * 2; + int height = lineHeight * numLines - static_cast(surfaceMeasure->InternalLeading(font)) + borderHeight * 2; delete surfaceMeasure; if (above) { return PRectangle(pt.x - offsetMain, pt.y - verticalOffset - height, pt.x + width - offsetMain, pt.y - verticalOffset); diff --git a/src/stc/scintilla/src/CaseConvert.cxx b/src/stc/scintilla/src/CaseConvert.cxx index 879f7af70d..e8f533d5cc 100644 --- a/src/stc/scintilla/src/CaseConvert.cxx +++ b/src/stc/scintilla/src/CaseConvert.cxx @@ -35,48 +35,48 @@ int symmetricCaseConversionRanges[] = { //lower, upper, range length, range pitch //++Autogenerated -- start of section automatically generated //**\(\*\n\) -97,65,26,1, -224,192,23,1, -248,216,7,1, -257,256,24,2, -314,313,8,2, -331,330,23,2, -462,461,8,2, -479,478,9,2, -505,504,20,2, -547,546,9,2, -583,582,5,2, -945,913,17,1, -963,931,9,1, -985,984,12,2, -1072,1040,32,1, -1104,1024,16,1, -1121,1120,17,2, -1163,1162,27,2, -1218,1217,7,2, -1233,1232,44,2, -1377,1329,38,1, -7681,7680,75,2, -7841,7840,48,2, -7936,7944,8,1, -7952,7960,6,1, -7968,7976,8,1, -7984,7992,8,1, -8000,8008,6,1, -8032,8040,8,1, -8560,8544,16,1, -9424,9398,26,1, -11312,11264,47,1, -11393,11392,50,2, -11520,4256,38,1, -42561,42560,23,2, -42625,42624,12,2, -42787,42786,7,2, -42803,42802,31,2, -42879,42878,5,2, -42913,42912,5,2, -65345,65313,26,1, -66600,66560,40,1, +97,65,26,1, +224,192,23,1, +248,216,7,1, +257,256,24,2, +314,313,8,2, +331,330,23,2, +462,461,8,2, +479,478,9,2, +505,504,20,2, +547,546,9,2, +583,582,5,2, +945,913,17,1, +963,931,9,1, +985,984,12,2, +1072,1040,32,1, +1104,1024,16,1, +1121,1120,17,2, +1163,1162,27,2, +1218,1217,7,2, +1233,1232,44,2, +1377,1329,38,1, +7681,7680,75,2, +7841,7840,48,2, +7936,7944,8,1, +7952,7960,6,1, +7968,7976,8,1, +7984,7992,8,1, +8000,8008,6,1, +8032,8040,8,1, +8560,8544,16,1, +9424,9398,26,1, +11312,11264,47,1, +11393,11392,50,2, +11520,4256,38,1, +42561,42560,23,2, +42625,42624,12,2, +42787,42786,7,2, +42803,42802,31,2, +42879,42878,5,2, +42913,42912,5,2, +65345,65313,26,1, +66600,66560,40,1, //--Autogenerated -- end of section automatically generated }; @@ -88,138 +88,138 @@ int symmetricCaseConversions[] = { //lower, upper //++Autogenerated -- start of section automatically generated //**1 \(\*\n\) -255,376, -307,306, -309,308, -311,310, -378,377, -380,379, -382,381, -384,579, -387,386, -389,388, -392,391, -396,395, -402,401, -405,502, -409,408, -410,573, -414,544, -417,416, -419,418, -421,420, -424,423, -429,428, -432,431, -436,435, -438,437, -441,440, -445,444, -447,503, -454,452, -457,455, -460,458, -477,398, -499,497, -501,500, -572,571, -575,11390, -576,11391, -578,577, -592,11375, -593,11373, -594,11376, -595,385, -596,390, -598,393, -599,394, -601,399, -603,400, -608,403, -611,404, -613,42893, -614,42922, -616,407, -617,406, -619,11362, -623,412, -625,11374, -626,413, -629,415, -637,11364, -640,422, -643,425, -648,430, -649,580, -650,433, -651,434, -652,581, -658,439, -881,880, -883,882, -887,886, -891,1021, -892,1022, -893,1023, -940,902, -941,904, -942,905, -943,906, -972,908, -973,910, -974,911, -983,975, -1010,1017, -1016,1015, -1019,1018, -1231,1216, -7545,42877, -7549,11363, -8017,8025, -8019,8027, -8021,8029, -8023,8031, -8048,8122, -8049,8123, -8050,8136, -8051,8137, -8052,8138, -8053,8139, -8054,8154, -8055,8155, -8056,8184, -8057,8185, -8058,8170, -8059,8171, -8060,8186, -8061,8187, -8112,8120, -8113,8121, -8144,8152, -8145,8153, -8160,8168, -8161,8169, -8165,8172, -8526,8498, -8580,8579, -11361,11360, -11365,570, -11366,574, -11368,11367, -11370,11369, -11372,11371, -11379,11378, -11382,11381, -11500,11499, -11502,11501, -11507,11506, -11559,4295, -11565,4301, -42874,42873, -42876,42875, -42892,42891, -42897,42896, -42899,42898, +255,376, +307,306, +309,308, +311,310, +378,377, +380,379, +382,381, +384,579, +387,386, +389,388, +392,391, +396,395, +402,401, +405,502, +409,408, +410,573, +414,544, +417,416, +419,418, +421,420, +424,423, +429,428, +432,431, +436,435, +438,437, +441,440, +445,444, +447,503, +454,452, +457,455, +460,458, +477,398, +499,497, +501,500, +572,571, +575,11390, +576,11391, +578,577, +592,11375, +593,11373, +594,11376, +595,385, +596,390, +598,393, +599,394, +601,399, +603,400, +608,403, +611,404, +613,42893, +614,42922, +616,407, +617,406, +619,11362, +623,412, +625,11374, +626,413, +629,415, +637,11364, +640,422, +643,425, +648,430, +649,580, +650,433, +651,434, +652,581, +658,439, +881,880, +883,882, +887,886, +891,1021, +892,1022, +893,1023, +940,902, +941,904, +942,905, +943,906, +972,908, +973,910, +974,911, +983,975, +1010,1017, +1016,1015, +1019,1018, +1231,1216, +7545,42877, +7549,11363, +8017,8025, +8019,8027, +8021,8029, +8023,8031, +8048,8122, +8049,8123, +8050,8136, +8051,8137, +8052,8138, +8053,8139, +8054,8154, +8055,8155, +8056,8184, +8057,8185, +8058,8170, +8059,8171, +8060,8186, +8061,8187, +8112,8120, +8113,8121, +8144,8152, +8145,8153, +8160,8168, +8161,8169, +8165,8172, +8526,8498, +8580,8579, +11361,11360, +11365,570, +11366,574, +11368,11367, +11370,11369, +11372,11371, +11379,11378, +11382,11381, +11500,11499, +11502,11501, +11507,11506, +11559,4295, +11565,4301, +42874,42873, +42876,42875, +42892,42891, +42897,42896, +42899,42898, //--Autogenerated -- end of section automatically generated }; diff --git a/src/stc/scintilla/src/CaseFolder.cxx b/src/stc/scintilla/src/CaseFolder.cxx index 44a94da6f5..200ac99b8e 100644 --- a/src/stc/scintilla/src/CaseFolder.cxx +++ b/src/stc/scintilla/src/CaseFolder.cxx @@ -8,9 +8,9 @@ #include #include +#include "CaseFolder.h" #include "CaseConvert.h" #include "UniConversion.h" -#include "CaseFolder.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/Catalogue.cxx b/src/stc/scintilla/src/Catalogue.cxx index 41d5d54898..b02a0108ce 100644 --- a/src/stc/scintilla/src/Catalogue.cxx +++ b/src/stc/scintilla/src/Catalogue.cxx @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include @@ -90,6 +90,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmBaan); LINK_LEXER(lmBash); LINK_LEXER(lmBatch); + LINK_LEXER(lmBibTeX); LINK_LEXER(lmBlitzBasic); LINK_LEXER(lmBullant); LINK_LEXER(lmCaml); @@ -106,6 +107,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmD); LINK_LEXER(lmDiff); LINK_LEXER(lmDMAP); + LINK_LEXER(lmDMIS); LINK_LEXER(lmECL); LINK_LEXER(lmEiffel); LINK_LEXER(lmEiffelkw); @@ -121,6 +123,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmGui4Cli); LINK_LEXER(lmHaskell); LINK_LEXER(lmHTML); + LINK_LEXER(lmIHex); LINK_LEXER(lmInno); LINK_LEXER(lmKix); LINK_LEXER(lmKVIrc); @@ -162,6 +165,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmPython); LINK_LEXER(lmR); LINK_LEXER(lmREBOL); + LINK_LEXER(lmRegistry); LINK_LEXER(lmRuby); LINK_LEXER(lmRust); LINK_LEXER(lmScriptol); @@ -171,12 +175,14 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmSpecman); LINK_LEXER(lmSpice); LINK_LEXER(lmSQL); + LINK_LEXER(lmSrec); LINK_LEXER(lmSTTXT); LINK_LEXER(lmTACL); LINK_LEXER(lmTADS3); LINK_LEXER(lmTAL); LINK_LEXER(lmTCL); LINK_LEXER(lmTCMD); + LINK_LEXER(lmTEHex); LINK_LEXER(lmTeX); LINK_LEXER(lmTxt2tags); LINK_LEXER(lmVB); diff --git a/src/stc/scintilla/src/CellBuffer.cxx b/src/stc/scintilla/src/CellBuffer.cxx index c050608656..dfa1350c05 100644 --- a/src/stc/scintilla/src/CellBuffer.cxx +++ b/src/stc/scintilla/src/CellBuffer.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include "Platform.h" @@ -144,6 +145,7 @@ UndoHistory::UndoHistory() { currentAction = 0; undoSequenceDepth = 0; savePoint = 0; + tentativePoint = -1; actions[currentAction].Create(startAction); } @@ -194,7 +196,7 @@ const char *UndoHistory::AppendAction(actionType at, int position, const char *d // Visual Studio 2013 Code Analysis wrongly believes actions can be NULL at its next reference __analysis_assume(actions); #endif - if (currentAction == savePoint) { + if ((currentAction == savePoint) || (currentAction == tentativePoint)) { currentAction++; } else if (!actions[currentAction].mayCoalesce) { // Not allowed to coalesce if this set @@ -282,6 +284,7 @@ void UndoHistory::DeleteUndoHistory() { currentAction = 0; actions[currentAction].Create(startAction); savePoint = 0; + tentativePoint = -1; } void UndoHistory::SetSavePoint() { @@ -292,6 +295,26 @@ bool UndoHistory::IsSavePoint() const { return savePoint == currentAction; } +void UndoHistory::TentativeStart() { + tentativePoint = currentAction; +} + +void UndoHistory::TentativeCommit() { + tentativePoint = -1; + // Truncate undo history + maxAction = currentAction; +} + +int UndoHistory::TentativeSteps() { + // Drop any trailing startAction + if (actions[currentAction].at == startAction && currentAction > 0) + currentAction--; + if (tentativePoint >= 0) + return currentAction - tentativePoint; + else + return -1; +} + bool UndoHistory::CanUndo() const { return (currentAction > 0) && (maxAction > 0); } @@ -356,7 +379,7 @@ char CellBuffer::CharAt(int position) const { } void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const { - if (lengthRetrieve < 0) + if (lengthRetrieve <= 0) return; if (position < 0) return; @@ -413,25 +436,24 @@ const char *CellBuffer::InsertString(int position, const char *s, int insertLeng return data; } -bool CellBuffer::SetStyleAt(int position, char styleValue, char mask) { - styleValue &= mask; +bool CellBuffer::SetStyleAt(int position, char styleValue) { char curVal = style.ValueAt(position); - if ((curVal & mask) != styleValue) { - style.SetValueAt(position, static_cast((curVal & ~mask) | styleValue)); + if (curVal != styleValue) { + style.SetValueAt(position, styleValue); return true; } else { return false; } } -bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue, char mask) { +bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue) { bool changed = false; PLATFORM_ASSERT(lengthStyle == 0 || (lengthStyle > 0 && lengthStyle + position <= style.Length())); while (lengthStyle--) { char curVal = style.ValueAt(position); - if ((curVal & mask) != styleValue) { - style.SetValueAt(position, static_cast((curVal & ~mask) | styleValue)); + if (curVal != styleValue) { + style.SetValueAt(position, styleValue); changed = true; } position++; @@ -506,6 +528,22 @@ bool CellBuffer::IsSavePoint() const { return uh.IsSavePoint(); } +void CellBuffer::TentativeStart() { + uh.TentativeStart(); +} + +void CellBuffer::TentativeCommit() { + uh.TentativeCommit(); +} + +int CellBuffer::TentativeSteps() { + return uh.TentativeSteps(); +} + +bool CellBuffer::TentativeActive() const { + return uh.TentativeActive(); +} + // Without undo void CellBuffer::InsertLine(int line, int position, bool lineStart) { @@ -749,6 +787,10 @@ const Action &CellBuffer::GetUndoStep() const { void CellBuffer::PerformUndoStep() { const Action &actionStep = uh.GetUndoStep(); if (actionStep.at == insertAction) { + if (substance.Length() < actionStep.lenData) { + throw std::runtime_error( + "CellBuffer::PerformUndoStep: deletion must be less than document length."); + } BasicDeleteChars(actionStep.position, actionStep.lenData); } else if (actionStep.at == removeAction) { BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData); diff --git a/src/stc/scintilla/src/CellBuffer.h b/src/stc/scintilla/src/CellBuffer.h index 6b719de275..5e4fc7c8ca 100644 --- a/src/stc/scintilla/src/CellBuffer.h +++ b/src/stc/scintilla/src/CellBuffer.h @@ -95,6 +95,7 @@ class UndoHistory { int currentAction; int undoSequenceDepth; int savePoint; + int tentativePoint; void EnsureUndoRoom(); @@ -117,6 +118,12 @@ public: void SetSavePoint(); bool IsSavePoint() const; + // Tentative actions are used for input composition so that it can be undone cleanly + void TentativeStart(); + void TentativeCommit(); + bool TentativeActive() const { return tentativePoint >= 0; } + int TentativeSteps(); + /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is /// called that many times. Similarly for redo. bool CanUndo() const; @@ -180,8 +187,8 @@ public: /// Setting styles for positions outside the range of the buffer is safe and has no effect. /// @return true if the style of a character is changed. - bool SetStyleAt(int position, char styleValue, char mask='\377'); - bool SetStyleFor(int position, int length, char styleValue, char mask); + bool SetStyleAt(int position, char styleValue); + bool SetStyleFor(int position, int length, char styleValue); const char *DeleteChars(int position, int deleteLength, bool &startSequence); @@ -193,6 +200,11 @@ public: void SetSavePoint(); bool IsSavePoint() const; + void TentativeStart(); + void TentativeCommit(); + bool TentativeActive() const; + int TentativeSteps(); + bool SetUndoCollection(bool collectUndo); bool IsCollectingUndo() const; void BeginUndoAction(); diff --git a/src/stc/scintilla/src/CharClassify.cxx b/src/stc/scintilla/src/CharClassify.cxx index 7e3db737e3..cc431630d8 100644 --- a/src/stc/scintilla/src/CharClassify.cxx +++ b/src/stc/scintilla/src/CharClassify.cxx @@ -14,11 +14,6 @@ using namespace Scintilla; #endif -// Shut up annoying Visual C++ warnings: -#ifdef _MSC_VER -#pragma warning(disable: 4514) -#endif - CharClassify::CharClassify() { SetDefaultCharClasses(true); } diff --git a/src/stc/scintilla/src/ContractionState.cxx b/src/stc/scintilla/src/ContractionState.cxx index 0636d90ead..7b76554209 100644 --- a/src/stc/scintilla/src/ContractionState.cxx +++ b/src/stc/scintilla/src/ContractionState.cxx @@ -76,6 +76,10 @@ int ContractionState::DisplayFromDoc(int lineDoc) const { } } +int ContractionState::DisplayLastFromDoc(int lineDoc) const { + return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1; +} + int ContractionState::DocFromDisplay(int lineDisplay) const { if (OneToOne()) { return lineDisplay; @@ -146,8 +150,8 @@ bool ContractionState::GetVisible(int lineDoc) const { } } -bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) { - if (OneToOne() && visible_) { +bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool isVisible) { + if (OneToOne() && isVisible) { return false; } else { EnsureData(); @@ -155,9 +159,9 @@ bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible Check(); if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) { for (int line = lineDocStart; line <= lineDocEnd; line++) { - if (GetVisible(line) != visible_) { - int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line); - visible->SetValueAt(line, visible_ ? 1 : 0); + if (GetVisible(line) != isVisible) { + int difference = isVisible ? heights->ValueAt(line) : -heights->ValueAt(line); + visible->SetValueAt(line, isVisible ? 1 : 0); displayLines->InsertText(line, difference); delta += difference; } @@ -187,13 +191,13 @@ bool ContractionState::GetExpanded(int lineDoc) const { } } -bool ContractionState::SetExpanded(int lineDoc, bool expanded_) { - if (OneToOne() && expanded_) { +bool ContractionState::SetExpanded(int lineDoc, bool isExpanded) { + if (OneToOne() && isExpanded) { return false; } else { EnsureData(); - if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) { - expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0); + if (isExpanded != (expanded->ValueAt(lineDoc) == 1)) { + expanded->SetValueAt(lineDoc, isExpanded ? 1 : 0); Check(); return true; } else { diff --git a/src/stc/scintilla/src/ContractionState.h b/src/stc/scintilla/src/ContractionState.h index 0309fc2691..96cbf07638 100644 --- a/src/stc/scintilla/src/ContractionState.h +++ b/src/stc/scintilla/src/ContractionState.h @@ -39,6 +39,7 @@ public: int LinesInDoc() const; int LinesDisplayed() const; int DisplayFromDoc(int lineDoc) const; + int DisplayLastFromDoc(int lineDoc) const; int DocFromDisplay(int lineDisplay) const; void InsertLine(int lineDoc); @@ -47,11 +48,11 @@ public: void DeleteLines(int lineDoc, int lineCount); bool GetVisible(int lineDoc) const; - bool SetVisible(int lineDocStart, int lineDocEnd, bool visible); + bool SetVisible(int lineDocStart, int lineDocEnd, bool isVisible); bool HiddenLines() const; bool GetExpanded(int lineDoc) const; - bool SetExpanded(int lineDoc, bool expanded); + bool SetExpanded(int lineDoc, bool isExpanded); int ContractedNext(int lineDocStart) const; int GetHeight(int lineDoc) const; diff --git a/src/stc/scintilla/src/Decoration.cxx b/src/stc/scintilla/src/Decoration.cxx index 72c7a331ff..e7610e0b6b 100644 --- a/src/stc/scintilla/src/Decoration.cxx +++ b/src/stc/scintilla/src/Decoration.cxx @@ -163,7 +163,9 @@ int DecorationList::AllOnFor(int position) const { int mask = 0; for (Decoration *deco=root; deco; deco = deco->next) { if (deco->rs.ValueAt(position)) { - mask |= 1 << deco->indicator; + if (deco->indicator < INDIC_IME) { + mask |= 1 << deco->indicator; + } } } return mask; diff --git a/src/stc/scintilla/src/Document.cxx b/src/stc/scintilla/src/Document.cxx index 1788cf74ec..7d34dace1c 100644 --- a/src/stc/scintilla/src/Document.cxx +++ b/src/stc/scintilla/src/Document.cxx @@ -8,30 +8,36 @@ #include #include #include -#include #include +#include +#include #include #include #include +#ifdef CXX11_REGEX +#include +#endif + #include "Platform.h" #include "ILexer.h" #include "Scintilla.h" +#include "CharacterSet.h" #include "SplitVector.h" #include "Partitioning.h" #include "RunStyles.h" #include "CellBuffer.h" #include "PerLine.h" #include "CharClassify.h" -#include "CharacterSet.h" #include "Decoration.h" #include "CaseFolder.h" #include "Document.h" #include "RESearch.h" #include "UniConversion.h" +#include "UnicodeFromUTF8.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -58,7 +64,7 @@ void LexInterface::Colourise(int start, int end) { int styleStart = 0; if (start > 0) - styleStart = pdoc->StyleAt(start - 1) & pdoc->stylingBitsMask; + styleStart = pdoc->StyleAt(start - 1); if (len > 0) { instance->Lex(start, len, styleStart, pdoc); @@ -90,14 +96,12 @@ Document::Document() { #endif dbcsCodePage = 0; lineEndBitSet = SC_LINE_END_TYPE_DEFAULT; - stylingBits = 5; - stylingBitsMask = 0x1F; - stylingMask = 0; endStyled = 0; styleClock = 0; enteredModification = 0; enteredStyling = 0; enteredReadOnlyCount = 0; + insertionSet = false; tabInChars = 8; indentInChars = 0; actualIndentInChars = 8; @@ -211,6 +215,65 @@ void Document::SetSavePoint() { NotifySavePoint(true); } +void Document::TentativeUndo() { + CheckReadOnly(); + if (enteredModification == 0) { + enteredModification++; + if (!cb.IsReadOnly()) { + bool startSavePoint = cb.IsSavePoint(); + bool multiLine = false; + int steps = cb.TentativeSteps(); + //Platform::DebugPrintf("Steps=%d\n", steps); + for (int step = 0; step < steps; step++) { + const int prevLinesTotal = LinesTotal(); + const Action &action = cb.GetUndoStep(); + if (action.at == removeAction) { + NotifyModified(DocModification( + SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action)); + } else if (action.at == containerAction) { + DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO); + dm.token = action.position; + NotifyModified(dm); + } else { + NotifyModified(DocModification( + SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action)); + } + cb.PerformUndoStep(); + if (action.at != containerAction) { + ModifiedAt(action.position); + } + + int modFlags = SC_PERFORMED_UNDO; + // With undo, an insertion action becomes a deletion notification + if (action.at == removeAction) { + modFlags |= SC_MOD_INSERTTEXT; + } else if (action.at == insertAction) { + modFlags |= SC_MOD_DELETETEXT; + } + if (steps > 1) + modFlags |= SC_MULTISTEPUNDOREDO; + const int linesAdded = LinesTotal() - prevLinesTotal; + if (linesAdded != 0) + multiLine = true; + if (step == steps - 1) { + modFlags |= SC_LASTSTEPINUNDOREDO; + if (multiLine) + modFlags |= SC_MULTILINEUNDOREDO; + } + NotifyModified(DocModification(modFlags, action.position, action.lenData, + linesAdded, action.data)); + } + + bool endSavePoint = cb.IsSavePoint(); + if (startSavePoint != endSavePoint) + NotifySavePoint(endSavePoint); + + cb.TentativeCommit(); + } + enteredModification--; + } +} + int Document::GetMark(int line) { return static_cast(perLineData[ldMarkers])->MarkValue(line); } @@ -278,6 +341,10 @@ int SCI_METHOD Document::LineStart(int line) const { return cb.LineStart(line); } +bool Document::IsLineStartPosition(int position) const { + return LineStart(LineFromPosition(position)) == position; +} + int SCI_METHOD Document::LineEnd(int line) const { if (line >= LinesTotal() - 1) { return LineStart(line + 1); @@ -544,7 +611,7 @@ bool Document::InGoodUTF8(int pos, int &start, int &end) const { // When lines are terminated with \r\n pairs which should be treated as one character. // When displaying DBCS text such as Japanese. // If moving, move the position in the indicated direction. -int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { +int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const { //Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir); // If out of range, just return minimum/maximum value. if (pos <= 0) @@ -700,19 +767,6 @@ bool Document::NextCharacter(int &pos, int moveDir) const { } } -static inline int UnicodeFromBytes(const unsigned char *us) { - if (us[0] < 0xC2) { - return us[0]; - } else if (us[0] < 0xE0) { - return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F); - } else if (us[0] < 0xF0) { - return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F); - } else if (us[0] < 0xF5) { - return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F); - } - return us[0]; -} - // Return -1 on out-of-bounds int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOffset) const { int pos = positionStart; @@ -733,6 +787,27 @@ int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOff return pos; } +int Document::GetRelativePositionUTF16(int positionStart, int characterOffset) const { + int pos = positionStart; + if (dbcsCodePage) { + const int increment = (characterOffset > 0) ? 1 : -1; + while (characterOffset != 0) { + const int posNext = NextPosition(pos, increment); + if (posNext == pos) + return INVALID_POSITION; + if (abs(pos-posNext) > 3) // 4 byte character = 2*UTF16. + characterOffset -= increment; + pos = posNext; + characterOffset -= increment; + } + } else { + pos = positionStart + characterOffset; + if ((pos < 0) || (pos > Length())) + return INVALID_POSITION; + } + return pos; +} + int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const { int character; int bytesInCharacter = 1; @@ -753,7 +828,7 @@ int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const { character = 0xDC80 + leadByte; } else { bytesInCharacter = utf8status & UTF8MaskWidth; - character = UnicodeFromBytes(charBytes); + character = UnicodeFromUTF8(charBytes); } } } else { @@ -880,6 +955,8 @@ void Document::CheckReadOnly() { // SetStyleAt does not change the persistent state of a document bool Document::DeleteChars(int pos, int len) { + if (pos < 0) + return false; if (len <= 0) return false; if ((pos + len) > Length()) @@ -919,37 +996,56 @@ bool Document::DeleteChars(int pos, int len) { /** * Insert a string with a length. */ -bool Document::InsertString(int position, const char *s, int insertLength) { +int Document::InsertString(int position, const char *s, int insertLength) { if (insertLength <= 0) { - return false; + return 0; + } + CheckReadOnly(); // Application may change read only state here + if (cb.IsReadOnly()) { + return 0; } - CheckReadOnly(); if (enteredModification != 0) { - return false; - } else { - enteredModification++; - if (!cb.IsReadOnly()) { - NotifyModified( - DocModification( - SC_MOD_BEFOREINSERT | SC_PERFORMED_USER, - position, insertLength, - 0, s)); - int prevLinesTotal = LinesTotal(); - bool startSavePoint = cb.IsSavePoint(); - bool startSequence = false; - const char *text = cb.InsertString(position, s, insertLength, startSequence); - if (startSavePoint && cb.IsCollectingUndo()) - NotifySavePoint(!startSavePoint); - ModifiedAt(position); - NotifyModified( - DocModification( - SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0), - position, insertLength, - LinesTotal() - prevLinesTotal, text)); - } - enteredModification--; + return 0; } - return !cb.IsReadOnly(); + enteredModification++; + insertionSet = false; + insertion.clear(); + NotifyModified( + DocModification( + SC_MOD_INSERTCHECK, + position, insertLength, + 0, s)); + if (insertionSet) { + s = insertion.c_str(); + insertLength = static_cast(insertion.length()); + } + NotifyModified( + DocModification( + SC_MOD_BEFOREINSERT | SC_PERFORMED_USER, + position, insertLength, + 0, s)); + int prevLinesTotal = LinesTotal(); + bool startSavePoint = cb.IsSavePoint(); + bool startSequence = false; + const char *text = cb.InsertString(position, s, insertLength, startSequence); + if (startSavePoint && cb.IsCollectingUndo()) + NotifySavePoint(!startSavePoint); + ModifiedAt(position); + NotifyModified( + DocModification( + SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0), + position, insertLength, + LinesTotal() - prevLinesTotal, text)); + if (insertionSet) { // Free memory as could be large + std::string().swap(insertion); + } + enteredModification--; + return insertLength; +} + +void Document::ChangeInsertion(const char *s, int length) { + insertionSet = true; + insertion.assign(s, length); } int SCI_METHOD Document::AddData(char *data, int length) { @@ -1113,22 +1209,6 @@ int Document::Redo() { return newPos; } -/** - * Insert a single character. - */ -bool Document::InsertChar(int pos, char ch) { - char chs[1]; - chs[0] = ch; - return InsertString(pos, chs, 1); -} - -/** - * Insert a null terminated string. - */ -bool Document::InsertCString(int position, const char *s) { - return InsertString(position, s, static_cast(s ? strlen(s) : 0)); -} - void Document::DelChar(int pos) { DeleteChars(pos, LenChar(pos)); } @@ -1183,7 +1263,7 @@ int SCI_METHOD Document::GetLineIndentation(int line) { return indent; } -void Document::SetLineIndentation(int line, int indent) { +int Document::SetLineIndentation(int line, int indent) { int indentOfLine = GetLineIndentation(line); if (indent < 0) indent = 0; @@ -1193,7 +1273,10 @@ void Document::SetLineIndentation(int line, int indent) { int indentPos = GetLineIndentPosition(line); UndoGroup ug(this); DeleteChars(thisLineStart, indentPos - thisLineStart); - InsertCString(thisLineStart, linebuf.c_str()); + return thisLineStart + InsertString(thisLineStart, linebuf.c_str(), + static_cast(linebuf.length())); + } else { + return GetLineIndentPosition(line); } } @@ -1232,7 +1315,7 @@ int Document::GetColumn(int pos) { return column; } -int Document::CountCharacters(int startPos, int endPos) { +int Document::CountCharacters(int startPos, int endPos) const { startPos = MovePositionOutsideChar(startPos, 1, false); endPos = MovePositionOutsideChar(endPos, -1, false); int count = 0; @@ -1246,6 +1329,21 @@ int Document::CountCharacters(int startPos, int endPos) { return count; } +int Document::CountUTF16(int startPos, int endPos) const { + startPos = MovePositionOutsideChar(startPos, 1, false); + endPos = MovePositionOutsideChar(endPos, -1, false); + int count = 0; + int i = startPos; + while (i < endPos) { + count++; + const int next = NextPosition(i, 1); + if ((next - i) > 3) + count++; + i = next; + } + return count; +} + int Document::FindColumn(int line, int column) { int position = LineStart(line); if ((line >= 0) && (line < LinesTotal())) { @@ -1325,21 +1423,21 @@ void Document::ConvertLineEnds(int eolModeSet) { } else { // CR if (eolModeSet == SC_EOL_CRLF) { - InsertString(pos + 1, "\n", 1); // Insert LF - pos++; + pos += InsertString(pos + 1, "\n", 1); // Insert LF } else if (eolModeSet == SC_EOL_LF) { - InsertString(pos, "\n", 1); // Insert LF - DeleteChars(pos + 1, 1); // Delete CR + pos += InsertString(pos, "\n", 1); // Insert LF + DeleteChars(pos, 1); // Delete CR + pos--; } } } else if (cb.CharAt(pos) == '\n') { // LF if (eolModeSet == SC_EOL_CRLF) { - InsertString(pos, "\r", 1); // Insert CR - pos++; + pos += InsertString(pos, "\r", 1); // Insert CR } else if (eolModeSet == SC_EOL_CR) { - InsertString(pos, "\r", 1); // Insert CR - DeleteChars(pos + 1, 1); // Delete LF + pos += InsertString(pos, "\r", 1); // Insert CR + DeleteChars(pos, 1); // Delete LF + pos--; } } } @@ -1521,6 +1619,25 @@ void Document::SetCaseFolder(CaseFolder *pcf_) { pcf = pcf_; } +Document::CharacterExtracted Document::ExtractCharacter(int position) const { + const unsigned char leadByte = static_cast(cb.CharAt(position)); + if (UTF8IsAscii(leadByte)) { + // Common case: ASCII character + return CharacterExtracted(leadByte, 1); + } + const int widthCharBytes = UTF8BytesOfLead[leadByte]; + unsigned char charBytes[UTF8MaxBytes] = { leadByte, 0, 0, 0 }; + for (int b=1; b(cb.CharAt(position + b)); + int utf8status = UTF8Classify(charBytes, widthCharBytes); + if (utf8status & UTF8MaskInvalid) { + // Treat as invalid and use up just one byte + return CharacterExtracted(unicodeReplacementChar, 1); + } else { + return CharacterExtracted(UnicodeFromUTF8(charBytes), utf8status & UTF8MaskWidth); + } +} + /** * Find text in document, supporting both forward and backward * searches (just pass minPos > maxPos to do a backward search) @@ -1705,13 +1822,7 @@ int Document::GetCharsOfClass(CharClassify::cc characterClass, unsigned char *bu return charClass.GetCharsOfClass(characterClass, buffer); } -void Document::SetStylingBits(int bits) { - stylingBits = bits; - stylingBitsMask = (1 << stylingBits) - 1; -} - -void SCI_METHOD Document::StartStyling(int position, char mask) { - stylingMask = mask; +void SCI_METHOD Document::StartStyling(int position, char) { endStyled = position; } @@ -1720,9 +1831,8 @@ bool SCI_METHOD Document::SetStyleFor(int length, char style) { return false; } else { enteredStyling++; - style &= stylingMask; int prevEndStyled = endStyled; - if (cb.SetStyleFor(endStyled, length, style, stylingMask)) { + if (cb.SetStyleFor(endStyled, length, style)) { DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, prevEndStyled, length); NotifyModified(mh); @@ -1743,7 +1853,7 @@ bool SCI_METHOD Document::SetStyles(int length, const char *styles) { int endMod = 0; for (int iPos = 0; iPos < length; iPos++, endStyled++) { PLATFORM_ASSERT(endStyled < Length()); - if (cb.SetStyleAt(endStyled, styles[iPos], stylingMask)) { + if (cb.SetStyleAt(endStyled, styles[iPos])) { if (!didChange) { startMod = endStyled; } @@ -2073,7 +2183,7 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) { char chSeek = BraceOpposite(chBrace); if (chSeek == '\0') return - 1; - char styBrace = static_cast(StyleAt(position) & stylingBitsMask); + char styBrace = static_cast(StyleAt(position)); int direction = -1; if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<') direction = 1; @@ -2081,7 +2191,7 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) { position = NextPosition(position, direction); while ((position >= 0) && (position < Length())) { char chAtPos = CharAt(position); - char styAtPos = static_cast(StyleAt(position) & stylingBitsMask); + char styAtPos = static_cast(StyleAt(position)); if ((position > GetEndStyled()) || (styAtPos == styBrace)) { if (chAtPos == chBrace) depth++; @@ -2119,6 +2229,61 @@ private: std::string substituted; }; +namespace { + +/** +* RESearchRange keeps track of search range. +*/ +class RESearchRange { +public: + const Document *doc; + int increment; + int startPos; + int endPos; + int lineRangeStart; + int lineRangeEnd; + int lineRangeBreak; + RESearchRange(const Document *doc_, int minPos, int maxPos) : doc(doc_) { + increment = (minPos <= maxPos) ? 1 : -1; + + // Range endpoints should not be inside DBCS characters, but just in case, move them. + startPos = doc->MovePositionOutsideChar(minPos, 1, false); + endPos = doc->MovePositionOutsideChar(maxPos, 1, false); + + lineRangeStart = doc->LineFromPosition(startPos); + lineRangeEnd = doc->LineFromPosition(endPos); + if ((increment == 1) && + (startPos >= doc->LineEnd(lineRangeStart)) && + (lineRangeStart < lineRangeEnd)) { + // the start position is at end of line or between line end characters. + lineRangeStart++; + startPos = doc->LineStart(lineRangeStart); + } else if ((increment == -1) && + (startPos <= doc->LineStart(lineRangeStart)) && + (lineRangeStart > lineRangeEnd)) { + // the start position is at beginning of line. + lineRangeStart--; + startPos = doc->LineEnd(lineRangeStart); + } + lineRangeBreak = lineRangeEnd + increment; + } + Range LineRange(int line) const { + Range range(doc->LineStart(line), doc->LineEnd(line)); + if (increment == 1) { + if (line == lineRangeStart) + range.start = startPos; + if (line == lineRangeEnd) + range.end = endPos; + } else { + if (line == lineRangeEnd) + range.start = endPos; + if (line == lineRangeStart) + range.end = startPos; + } + return range; + } +}; + // Define a way for the Regular Expression code to access the document class DocumentIndexer : public CharacterIndexer { Document *pdoc; @@ -2139,18 +2304,376 @@ public: } }; +#ifdef CXX11_REGEX + +class ByteIterator : public std::iterator { +public: + const Document *doc; + Position position; + ByteIterator(const Document *doc_ = 0, Position position_ = 0) : doc(doc_), position(position_) { + } + ByteIterator(const ByteIterator &other) { + doc = other.doc; + position = other.position; + } + ByteIterator &operator=(const ByteIterator &other) { + if (this != &other) { + doc = other.doc; + position = other.position; + } + return *this; + } + char operator*() const { + return doc->CharAt(position); + } + ByteIterator &operator++() { + position++; + return *this; + } + ByteIterator operator++(int) { + ByteIterator retVal(*this); + position++; + return retVal; + } + ByteIterator &operator--() { + position--; + return *this; + } + bool operator==(const ByteIterator &other) const { + return doc == other.doc && position == other.position; + } + bool operator!=(const ByteIterator &other) const { + return doc != other.doc || position != other.position; + } + int Pos() const { + return position; + } + int PosRoundUp() const { + return position; + } +}; + +// On Windows, wchar_t is 16 bits wide and on Unix it is 32 bits wide. +// Would be better to use sizeof(wchar_t) or similar to differentiate +// but easier for now to hard-code platforms. +// C++11 has char16_t and char32_t but neither Clang nor Visual C++ +// appear to allow specializing basic_regex over these. + +#ifdef _WIN32 +#define WCHAR_T_IS_16 1 +#else +#define WCHAR_T_IS_16 0 +#endif + +#if WCHAR_T_IS_16 + +// On Windows, report non-BMP characters as 2 separate surrogates as that +// matches wregex since it is based on wchar_t. +class UTF8Iterator : public std::iterator { + // These 3 fields determine the iterator position and are used for comparisons + const Document *doc; + Position position; + size_t characterIndex; + // Remaining fields are derived from the determining fields so are excluded in comparisons + unsigned int lenBytes; + size_t lenCharacters; + wchar_t buffered[2]; +public: + UTF8Iterator(const Document *doc_ = 0, Position position_ = 0) : + doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0) { + buffered[0] = 0; + buffered[1] = 0; + if (doc) { + ReadCharacter(); + } + } + UTF8Iterator(const UTF8Iterator &other) { + doc = other.doc; + position = other.position; + characterIndex = other.characterIndex; + lenBytes = other.lenBytes; + lenCharacters = other.lenCharacters; + buffered[0] = other.buffered[0]; + buffered[1] = other.buffered[1]; + } + UTF8Iterator &operator=(const UTF8Iterator &other) { + if (this != &other) { + doc = other.doc; + position = other.position; + characterIndex = other.characterIndex; + lenBytes = other.lenBytes; + lenCharacters = other.lenCharacters; + buffered[0] = other.buffered[0]; + buffered[1] = other.buffered[1]; + } + return *this; + } + wchar_t operator*() const { + assert(lenCharacters != 0); + return buffered[characterIndex]; + } + UTF8Iterator &operator++() { + if ((characterIndex + 1) < (lenCharacters)) { + characterIndex++; + } else { + position += lenBytes; + ReadCharacter(); + characterIndex = 0; + } + return *this; + } + UTF8Iterator operator++(int) { + UTF8Iterator retVal(*this); + if ((characterIndex + 1) < (lenCharacters)) { + characterIndex++; + } else { + position += lenBytes; + ReadCharacter(); + characterIndex = 0; + } + return retVal; + } + UTF8Iterator &operator--() { + if (characterIndex) { + characterIndex--; + } else { + position = doc->NextPosition(position, -1); + ReadCharacter(); + characterIndex = lenCharacters - 1; + } + return *this; + } + bool operator==(const UTF8Iterator &other) const { + // Only test the determining fields, not the character widths and values derived from this + return doc == other.doc && + position == other.position && + characterIndex == other.characterIndex; + } + bool operator!=(const UTF8Iterator &other) const { + // Only test the determining fields, not the character widths and values derived from this + return doc != other.doc || + position != other.position || + characterIndex != other.characterIndex; + } + int Pos() const { + return position; + } + int PosRoundUp() const { + if (characterIndex) + return position + lenBytes; // Force to end of character + else + return position; + } +private: + void ReadCharacter() { + Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position); + lenBytes = charExtracted.widthBytes; + if (charExtracted.character == unicodeReplacementChar) { + lenCharacters = 1; + buffered[0] = static_cast(charExtracted.character); + } else { + lenCharacters = UTF16FromUTF32Character(charExtracted.character, buffered); + } + } +}; + +#else + +// On Unix, report non-BMP characters as single characters + +class UTF8Iterator : public std::iterator { + const Document *doc; + Position position; +public: + UTF8Iterator(const Document *doc_=0, Position position_=0) : doc(doc_), position(position_) { + } + UTF8Iterator(const UTF8Iterator &other) { + doc = other.doc; + position = other.position; + } + UTF8Iterator &operator=(const UTF8Iterator &other) { + if (this != &other) { + doc = other.doc; + position = other.position; + } + return *this; + } + wchar_t operator*() const { + Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position); + return charExtracted.character; + } + UTF8Iterator &operator++() { + position = doc->NextPosition(position, 1); + return *this; + } + UTF8Iterator operator++(int) { + UTF8Iterator retVal(*this); + position = doc->NextPosition(position, 1); + return retVal; + } + UTF8Iterator &operator--() { + position = doc->NextPosition(position, -1); + return *this; + } + bool operator==(const UTF8Iterator &other) const { + return doc == other.doc && position == other.position; + } + bool operator!=(const UTF8Iterator &other) const { + return doc != other.doc || position != other.position; + } + int Pos() const { + return position; + } + int PosRoundUp() const { + return position; + } +}; + +#endif + +std::regex_constants::match_flag_type MatchFlags(const Document *doc, int startPos, int endPos) { + std::regex_constants::match_flag_type flagsMatch = std::regex_constants::match_default; + if (!doc->IsLineStartPosition(startPos)) + flagsMatch |= std::regex_constants::match_not_bol; + if (!doc->IsLineEndPosition(endPos)) + flagsMatch |= std::regex_constants::match_not_eol; + return flagsMatch; +} + +template +bool MatchOnLines(const Document *doc, const Regex ®exp, const RESearchRange &resr, RESearch &search) { + bool matched = false; + std::match_results match; + + // MSVC and libc++ have problems with ^ and $ matching line ends inside a range + // If they didn't then the line by line iteration could be removed for the forwards + // case and replaced with the following 4 lines: + // Iterator uiStart(doc, startPos); + // Iterator uiEnd(doc, endPos); + // flagsMatch = MatchFlags(doc, startPos, endPos); + // matched = std::regex_search(uiStart, uiEnd, match, regexp, flagsMatch); + + // Line by line. + for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) { + const Range lineRange = resr.LineRange(line); + Iterator itStart(doc, lineRange.start); + Iterator itEnd(doc, lineRange.end); + std::regex_constants::match_flag_type flagsMatch = MatchFlags(doc, lineRange.start, lineRange.end); + matched = std::regex_search(itStart, itEnd, match, regexp, flagsMatch); + // Check for the last match on this line. + if (matched) { + if (resr.increment == -1) { + while (matched) { + Iterator itNext(doc, match[0].second.PosRoundUp()); + flagsMatch = MatchFlags(doc, itNext.Pos(), lineRange.end); + std::match_results matchNext; + matched = std::regex_search(itNext, itEnd, matchNext, regexp, flagsMatch); + if (matched) { + if (match[0].first == match[0].second) { + // Empty match means failure so exit + return false; + } + match = matchNext; + } + } + matched = true; + } + break; + } + } + if (matched) { + for (size_t co = 0; co < match.size(); co++) { + search.bopat[co] = match[co].first.Pos(); + search.eopat[co] = match[co].second.PosRoundUp(); + size_t lenMatch = search.eopat[co] - search.bopat[co]; + search.pat[co].resize(lenMatch); + for (size_t iPos = 0; iPos < lenMatch; iPos++) { + search.pat[co][iPos] = doc->CharAt(iPos + search.bopat[co]); + } + } + } + return matched; +} + +long Cxx11RegexFindText(Document *doc, int minPos, int maxPos, const char *s, + bool caseSensitive, int *length, RESearch &search) { + const RESearchRange resr(doc, minPos, maxPos); + try { + //ElapsedTime et; + std::regex::flag_type flagsRe = std::regex::ECMAScript; + // Flags that apper to have no effect: + // | std::regex::collate | std::regex::extended; + if (!caseSensitive) + flagsRe = flagsRe | std::regex::icase; + + // Clear the RESearch so can fill in matches + search.Clear(); + + bool matched = false; + if (SC_CP_UTF8 == doc->dbcsCodePage) { + unsigned int lenS = static_cast(strlen(s)); + std::vector ws(lenS + 1); +#if WCHAR_T_IS_16 + size_t outLen = UTF16FromUTF8(s, lenS, &ws[0], lenS); +#else + size_t outLen = UTF32FromUTF8(s, lenS, reinterpret_cast(&ws[0]), lenS); +#endif + ws[outLen] = 0; + std::wregex regexp; +#if defined(__APPLE__) + // Using a UTF-8 locale doesn't change to Unicode over a byte buffer so '.' + // is one byte not one character. + // However, on OS X this makes wregex act as Unicode + std::locale localeU("en_US.UTF-8"); + regexp.imbue(localeU); +#endif + regexp.assign(&ws[0], flagsRe); + matched = MatchOnLines(doc, regexp, resr, search); + + } else { + std::regex regexp; + regexp.assign(s, flagsRe); + matched = MatchOnLines(doc, regexp, resr, search); + } + + int posMatch = -1; + if (matched) { + posMatch = search.bopat[0]; + *length = search.eopat[0] - search.bopat[0]; + } + // Example - search in doc/ScintillaHistory.html for + // [[:upper:]]eta[[:space:]] + // On MacBook, normally around 1 second but with locale imbued -> 14 seconds. + //double durSearch = et.Duration(true); + //Platform::DebugPrintf("Search:%9.6g \n", durSearch); + return posMatch; + } catch (std::regex_error &) { + // Failed to create regular expression + throw RegexError(); + } catch (...) { + // Failed in some other way + return -1; + } +} + +#endif + +} + long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s, bool caseSensitive, bool, bool, int flags, int *length) { - bool posix = (flags & SCFIND_POSIX) != 0; - int increment = (minPos <= maxPos) ? 1 : -1; - int startPos = minPos; - int endPos = maxPos; +#ifdef CXX11_REGEX + if (flags & SCFIND_CXX11REGEX) { + return Cxx11RegexFindText(doc, minPos, maxPos, s, + caseSensitive, length, search); + } +#endif - // Range endpoints should not be inside DBCS characters, but just in case, move them. - startPos = doc->MovePositionOutsideChar(startPos, 1, false); - endPos = doc->MovePositionOutsideChar(endPos, 1, false); + const RESearchRange resr(doc, minPos, maxPos); + + const bool posix = (flags & SCFIND_POSIX) != 0; const char *errmsg = search.Compile(s, *length, caseSensitive, posix); if (errmsg) { @@ -2160,50 +2683,34 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s // Replace first '.' with '-' in each property file variable reference: // Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\)) // Replace: $(\1-\2) - int lineRangeStart = doc->LineFromPosition(startPos); - int lineRangeEnd = doc->LineFromPosition(endPos); - if ((increment == 1) && - (startPos >= doc->LineEnd(lineRangeStart)) && - (lineRangeStart < lineRangeEnd)) { - // the start position is at end of line or between line end characters. - lineRangeStart++; - startPos = doc->LineStart(lineRangeStart); - } else if ((increment == -1) && - (startPos <= doc->LineStart(lineRangeStart)) && - (lineRangeStart > lineRangeEnd)) { - // the start position is at beginning of line. - lineRangeStart--; - startPos = doc->LineEnd(lineRangeStart); - } int pos = -1; int lenRet = 0; - char searchEnd = s[*length - 1]; - char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0'; - int lineRangeBreak = lineRangeEnd + increment; - for (int line = lineRangeStart; line != lineRangeBreak; line += increment) { + const char searchEnd = s[*length - 1]; + const char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0'; + for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) { int startOfLine = doc->LineStart(line); int endOfLine = doc->LineEnd(line); - if (increment == 1) { - if (line == lineRangeStart) { - if ((startPos != startOfLine) && (s[0] == '^')) + if (resr.increment == 1) { + if (line == resr.lineRangeStart) { + if ((resr.startPos != startOfLine) && (s[0] == '^')) continue; // Can't match start of line if start position after start of line - startOfLine = startPos; + startOfLine = resr.startPos; } - if (line == lineRangeEnd) { - if ((endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) + if (line == resr.lineRangeEnd) { + if ((resr.endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) continue; // Can't match end of line if end position before end of line - endOfLine = endPos; + endOfLine = resr.endPos; } } else { - if (line == lineRangeEnd) { - if ((endPos != startOfLine) && (s[0] == '^')) + if (line == resr.lineRangeEnd) { + if ((resr.endPos != startOfLine) && (s[0] == '^')) continue; // Can't match start of line if end position after start of line - startOfLine = endPos; + startOfLine = resr.endPos; } - if (line == lineRangeStart) { - if ((startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) + if (line == resr.lineRangeStart) { + if ((resr.startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) continue; // Can't match end of line if start position before end of line - endOfLine = startPos; + endOfLine = resr.startPos; } } @@ -2215,7 +2722,7 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s search.eopat[0] = doc->MovePositionOutsideChar(search.eopat[0], 1, false); lenRet = search.eopat[0] - search.bopat[0]; // There can be only one start of a line, so no need to look for last match in line - if ((increment == -1) && (s[0] != '^')) { + if ((resr.increment == -1) && (s[0] != '^')) { // Check for the last match on this line. int repetitions = 1000; // Break out of infinite loop while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) { diff --git a/src/stc/scintilla/src/Document.h b/src/stc/scintilla/src/Document.h index c985af499d..5e66dc2b62 100644 --- a/src/stc/scintilla/src/Document.h +++ b/src/stc/scintilla/src/Document.h @@ -39,10 +39,22 @@ public: start(start_), end(end_) { } + bool operator==(const Range &other) const { + return (start == other.start) && (end == other.end); + } + bool Valid() const { return (start != invalidPosition) && (end != invalidPosition); } + Position First() const { + return (start <= end) ? start : end; + } + + Position Last() const { + return (start > end) ? start : end; + } + // Is the position within the range? bool Contains(Position pos) const { if (start < end) { @@ -176,6 +188,10 @@ public: } }; +struct RegexError : public std::runtime_error { + RegexError() : std::runtime_error("regex failure") {} +}; + /** */ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { @@ -191,9 +207,6 @@ public: bool operator==(const WatcherWithUserData &other) const { return (watcher == other.watcher) && (userData == other.userData); } - bool operator!=(const WatcherWithUserData &other) const { - return !(*this == other); - } }; private: @@ -201,13 +214,15 @@ private: CellBuffer cb; CharClassify charClass; CaseFolder *pcf; - char stylingMask; int endStyled; int styleClock; int enteredModification; int enteredStyling; int enteredReadOnlyCount; + bool insertionSet; + std::string insertion; + std::vector watchers; // ldSize is not real data - it is for dimensions and loops @@ -221,9 +236,6 @@ public: LexInterface *pli; - int stylingBits; - int stylingBitsMask; - int eolMode; /// Can also be SC_CP_UTF8 to enable UTF-8 mode int dbcsCodePage; @@ -263,10 +275,11 @@ public: bool IsCrLf(int pos) const; int LenChar(int pos); bool InGoodUTF8(int pos, int &start, int &end) const; - int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); + int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const; int NextPosition(int pos, int moveDir) const; bool NextCharacter(int &pos, int moveDir) const; // Returns true if pos changed int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const; + int GetRelativePositionUTF16(int positionStart, int characterOffset) const; int SCI_METHOD GetCharacterAndWidth(int position, int *pWidth) const; int SCI_METHOD CodePage() const; bool SCI_METHOD IsDBCSLeadByte(char ch) const; @@ -277,7 +290,8 @@ public: void ModifiedAt(int pos); void CheckReadOnly(); bool DeleteChars(int pos, int len); - bool InsertString(int position, const char *s, int insertLength); + int InsertString(int position, const char *s, int insertLength); + void ChangeInsertion(const char *s, int length); int SCI_METHOD AddData(char *data, int length); void * SCI_METHOD ConvertToDocument(); int Undo(); @@ -294,15 +308,22 @@ public: void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); } void SetSavePoint(); bool IsSavePoint() const { return cb.IsSavePoint(); } + + void TentativeStart() { cb.TentativeStart(); } + void TentativeCommit() { cb.TentativeCommit(); } + void TentativeUndo(); + bool TentativeActive() const { return cb.TentativeActive(); } + const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); } const char *RangePointer(int position, int rangeLength) { return cb.RangePointer(position, rangeLength); } int GapPosition() const { return cb.GapPosition(); } int SCI_METHOD GetLineIndentation(int line); - void SetLineIndentation(int line, int indent); + int SetLineIndentation(int line, int indent); int GetLineIndentPosition(int line) const; int GetColumn(int position); - int CountCharacters(int startPos, int endPos); + int CountCharacters(int startPos, int endPos) const; + int CountUTF16(int startPos, int endPos) const; int FindColumn(int line, int column); void Indent(bool forwards, int lineBottom, int lineTop); static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted); @@ -310,8 +331,6 @@ public: void SetReadOnly(bool set) { cb.SetReadOnly(set); } bool IsReadOnly() const { return cb.IsReadOnly(); } - bool InsertChar(int pos, char ch); - bool InsertCString(int position, const char *s); void DelChar(int pos); void DelCharBack(int pos); @@ -332,6 +351,7 @@ public: void DeleteAllMarks(int markerNum); int LineFromHandle(int markerHandle); int SCI_METHOD LineStart(int line) const; + bool IsLineStartPosition(int position) const; int SCI_METHOD LineEnd(int line) const; int LineEndPosition(int position) const; bool IsLineEndPosition(int position) const; @@ -351,6 +371,16 @@ public: int NextWordEnd(int pos, int delta); int SCI_METHOD Length() const { return cb.Length(); } void Allocate(int newSize) { cb.Allocate(newSize); } + + struct CharacterExtracted { + unsigned int character; + unsigned int widthBytes; + CharacterExtracted(unsigned int character_, unsigned int widthBytes_) : + character(character_), widthBytes(widthBytes_) { + } + }; + CharacterExtracted ExtractCharacter(int position) const; + bool MatchesWordOptions(bool word, bool wordStart, int pos, int length) const; bool HasCaseFolder(void) const; void SetCaseFolder(CaseFolder *pcf_); @@ -361,8 +391,7 @@ public: void SetDefaultCharClasses(bool includeWordClass); void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass); - int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer); - void SetStylingBits(int bits); + int GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer); void SCI_METHOD StartStyling(int position, char mask); bool SCI_METHOD SetStyleFor(int length, char style); bool SCI_METHOD SetStyles(int length, const char *styles); @@ -393,7 +422,7 @@ public: void AnnotationSetStyles(int line, const unsigned char *styles); int AnnotationLines(int line) const; void AnnotationClearAll(); - + bool AddWatcher(DocWatcher *watcher, void *userData); bool RemoveWatcher(DocWatcher *watcher, void *userData); diff --git a/src/stc/scintilla/src/EditModel.cxx b/src/stc/scintilla/src/EditModel.cxx new file mode 100644 index 0000000000..b50ade258f --- /dev/null +++ b/src/stc/scintilla/src/EditModel.cxx @@ -0,0 +1,77 @@ +// Scintilla source code edit control +/** @file EditModel.cxx + ** Defines the editor state that must be visible to EditorView. + **/ +// Copyright 1998-2014 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "ILexer.h" +#include "Scintilla.h" + +#include "StringCopy.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "UniConversion.h" +#include "Selection.h" +#include "PositionCache.h" +#include "EditModel.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +Caret::Caret() : + active(false), on(false), period(500) {} + +EditModel::EditModel() { + inOverstrike = false; + xOffset = 0; + trackLineWidth = false; + posDrag = SelectionPosition(invalidPosition); + braces[0] = invalidPosition; + braces[1] = invalidPosition; + bracesMatchStyle = STYLE_BRACEBAD; + highlightGuideColumn = 0; + primarySelection = true; + imeInteraction = imeWindowed; + foldFlags = 0; + hotspot = Range(invalidPosition); + hoverIndicatorPos = invalidPosition; + wrapWidth = LineLayout::wrapWidthInfinite; + pdoc = new Document(); + pdoc->AddRef(); +} + +EditModel::~EditModel() { + pdoc->Release(); + pdoc = 0; +} diff --git a/src/stc/scintilla/src/EditModel.h b/src/stc/scintilla/src/EditModel.h new file mode 100644 index 0000000000..fce26bd22e --- /dev/null +++ b/src/stc/scintilla/src/EditModel.h @@ -0,0 +1,70 @@ +// Scintilla source code edit control +/** @file EditModel.h + ** Defines the editor state that must be visible to EditorView. + **/ +// Copyright 1998-2014 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef EDITMODEL_H +#define EDITMODEL_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +/** +*/ +class Caret { +public: + bool active; + bool on; + int period; + + Caret(); +}; + +class EditModel { + // Private so EditModel objects can not be copied + EditModel(const EditModel &); + EditModel &operator=(const EditModel &); + +public: + bool inOverstrike; + int xOffset; ///< Horizontal scrolled amount in pixels + bool trackLineWidth; + + SpecialRepresentations reprs; + Caret caret; + SelectionPosition posDrag; + Position braces[2]; + int bracesMatchStyle; + int highlightGuideColumn; + Selection sel; + bool primarySelection; + + enum IMEInteraction { imeWindowed, imeInline } imeInteraction; + + int foldFlags; + ContractionState cs; + // Hotspot support + Range hotspot; + int hoverIndicatorPos; + + // Wrapping support + int wrapWidth; + + Document *pdoc; + + EditModel(); + virtual ~EditModel(); + virtual int TopLineOfMain() const = 0; + virtual Point GetVisibleOriginInMain() const = 0; + virtual int LinesOnScreen() const = 0; + virtual Range GetHotSpotRange() const = 0; +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/EditView.cxx b/src/stc/scintilla/src/EditView.cxx new file mode 100644 index 0000000000..5372e3abd4 --- /dev/null +++ b/src/stc/scintilla/src/EditView.cxx @@ -0,0 +1,2117 @@ +// Scintilla source code edit control +/** @file Editor.cxx + ** Defines the appearance of the main text area of the editor window. + **/ +// Copyright 1998-2014 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "ILexer.h" +#include "Scintilla.h" + +#include "StringCopy.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "PerLine.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "UniConversion.h" +#include "Selection.h" +#include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsControlCharacter(int ch) { + // iscntrl returns true for lots of chars > 127 which are displayable + return ch >= 0 && ch < ' '; +} + +PrintParameters::PrintParameters() { + magnification = 0; + colourMode = SC_PRINT_NORMAL; + wrapState = eWrapWord; +} + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) { + if (st.multipleStyles) { + for (size_t iStyle = 0; iStyle(styles[endSegment + 1]) == style)) + endSegment++; + FontAlias fontText = vs.styles[style + styleOffset].font; + width += static_cast(surface->WidthText(fontText, text + start, + static_cast(endSegment - start + 1))); + start = endSegment + 1; + } + return width; +} + +int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) { + int widthMax = 0; + size_t start = 0; + while (start < st.length) { + size_t lenLine = st.LineLength(start); + int widthSubLine; + if (st.multipleStyles) { + widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); + } else { + FontAlias fontText = vs.styles[styleOffset + st.style].font; + widthSubLine = static_cast(surface->WidthText(fontText, + st.text + start, static_cast(lenLine))); + } + if (widthSubLine > widthMax) + widthMax = widthSubLine; + start += lenLine + 1; + } + return widthMax; +} + +void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, + const char *s, int len, DrawPhase phase) { + FontAlias fontText = style.font; + if (phase & drawBack) { + if (phase & drawText) { + // Drawing both + surface->DrawTextNoClip(rc, fontText, ybase, s, len, + style.fore, style.back); + } else { + surface->FillRectangle(rc, style.back); + } + } else if (phase & drawText) { + surface->DrawTextTransparent(rc, fontText, ybase, s, len, style.fore); + } +} + +void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, + const StyledText &st, size_t start, size_t length, DrawPhase phase) { + + if (st.multipleStyles) { + int x = static_cast(rcText.left); + size_t i = 0; + while (i < length) { + size_t end = i; + size_t style = st.styles[i + start]; + while (end < length - 1 && st.styles[start + end + 1] == style) + end++; + style += styleOffset; + FontAlias fontText = vs.styles[style].font; + const int width = static_cast(surface->WidthText(fontText, + st.text + start + i, static_cast(end - i + 1))); + PRectangle rcSegment = rcText; + rcSegment.left = static_cast(x); + rcSegment.right = static_cast(x + width + 1); + DrawTextNoClipPhase(surface, rcSegment, vs.styles[style], + rcText.top + vs.maxAscent, st.text + start + i, + static_cast(end - i + 1), phase); + x += width; + i = end + 1; + } + } else { + const size_t style = st.style + styleOffset; + DrawTextNoClipPhase(surface, rcText, vs.styles[style], + rcText.top + vs.maxAscent, st.text + start, + static_cast(length), phase); + } +} + +#ifdef SCI_NAMESPACE +} +#endif + +const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues + +EditView::EditView() { + ldTabstops = NULL; + tabWidthMinimumPixels = 2; // needed for calculating tab stops for fractional proportional fonts + hideSelection = false; + drawOverstrikeCaret = true; + bufferedDraw = true; + phasesDraw = phasesTwo; + lineWidthMaxSeen = 0; + additionalCaretsBlink = true; + additionalCaretsVisible = true; + imeCaretBlockOverride = false; + pixmapLine = 0; + pixmapIndentGuide = 0; + pixmapIndentGuideHighlight = 0; + llc.SetLevel(LineLayoutCache::llcCaret); + posCache.SetSize(0x400); + tabArrowHeight = 4; + customDrawTabArrow = NULL; + customDrawWrapMarker = NULL; +} + +EditView::~EditView() { + delete ldTabstops; + ldTabstops = NULL; +} + +bool EditView::SetTwoPhaseDraw(bool twoPhaseDraw) { + const PhasesDraw phasesDrawNew = twoPhaseDraw ? phasesTwo : phasesOne; + const bool redraw = phasesDraw != phasesDrawNew; + phasesDraw = phasesDrawNew; + return redraw; +} + +bool EditView::SetPhasesDraw(int phases) { + const PhasesDraw phasesDrawNew = static_cast(phases); + const bool redraw = phasesDraw != phasesDrawNew; + phasesDraw = phasesDrawNew; + return redraw; +} + +bool EditView::LinesOverlap() const { + return phasesDraw == phasesMultiple; +} + +void EditView::ClearAllTabstops() { + delete ldTabstops; + ldTabstops = 0; +} + +XYPOSITION EditView::NextTabstopPos(int line, XYPOSITION x, XYPOSITION tabWidth) const { + int next = GetNextTabstop(line, static_cast(x + tabWidthMinimumPixels)); + if (next > 0) + return static_cast(next); + return (static_cast((x + tabWidthMinimumPixels) / tabWidth) + 1) * tabWidth; +} + +bool EditView::ClearTabstops(int line) { + LineTabstops *lt = static_cast(ldTabstops); + return lt && lt->ClearTabstops(line); +} + +bool EditView::AddTabstop(int line, int x) { + if (!ldTabstops) { + ldTabstops = new LineTabstops(); + } + LineTabstops *lt = static_cast(ldTabstops); + return lt && lt->AddTabstop(line, x); +} + +int EditView::GetNextTabstop(int line, int x) const { + LineTabstops *lt = static_cast(ldTabstops); + if (lt) { + return lt->GetNextTabstop(line, x); + } else { + return 0; + } +} + +void EditView::LinesAddedOrRemoved(int lineOfPos, int linesAdded) { + if (ldTabstops) { + if (linesAdded > 0) { + for (int line = lineOfPos; line < lineOfPos + linesAdded; line++) { + ldTabstops->InsertLine(line); + } + } else { + for (int line = (lineOfPos + -linesAdded) - 1; line >= lineOfPos; line--) { + ldTabstops->RemoveLine(line); + } + } + } +} + +void EditView::DropGraphics(bool freeObjects) { + if (freeObjects) { + delete pixmapLine; + pixmapLine = 0; + delete pixmapIndentGuide; + pixmapIndentGuide = 0; + delete pixmapIndentGuideHighlight; + pixmapIndentGuideHighlight = 0; + } else { + if (pixmapLine) + pixmapLine->Release(); + if (pixmapIndentGuide) + pixmapIndentGuide->Release(); + if (pixmapIndentGuideHighlight) + pixmapIndentGuideHighlight->Release(); + } +} + +void EditView::AllocateGraphics(const ViewStyle &vsDraw) { + if (!pixmapLine) + pixmapLine = Surface::Allocate(vsDraw.technology); + if (!pixmapIndentGuide) + pixmapIndentGuide = Surface::Allocate(vsDraw.technology); + if (!pixmapIndentGuideHighlight) + pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology); +} + +const char *ControlCharacterString(unsigned 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 < ELEMENTS(reps)) { + return reps[ch]; + } else { + return "BAD"; + } +} + +void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { + int ydiff = static_cast(rcTab.bottom - rcTab.top) / 2; + int xhead = static_cast(rcTab.right) - 1 - ydiff; + if (xhead <= rcTab.left) { + ydiff -= static_cast(rcTab.left) - xhead - 1; + xhead = static_cast(rcTab.left) - 1; + } + if ((rcTab.left + 2) < (rcTab.right - 1)) + surface->MoveTo(static_cast(rcTab.left) + 2, ymid); + else + surface->MoveTo(static_cast(rcTab.right) - 1, ymid); + surface->LineTo(static_cast(rcTab.right) - 1, ymid); + surface->LineTo(xhead, ymid - ydiff); + surface->MoveTo(static_cast(rcTab.right) - 1, ymid); + surface->LineTo(xhead, ymid + ydiff); +} + +void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { + if (!pixmapIndentGuide->Initialised()) { + // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line + pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); + pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); + PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight); + pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back); + pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore); + pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back); + pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore); + for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) { + PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1); + pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore); + pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore); + } + } +} + +LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) { + int posLineStart = model.pdoc->LineStart(lineNumber); + int posLineEnd = model.pdoc->LineStart(lineNumber + 1); + PLATFORM_ASSERT(posLineEnd >= posLineStart); + int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret()); + return llc.Retrieve(lineNumber, lineCaret, + posLineEnd - posLineStart, model.pdoc->GetStyleClock(), + model.LinesOnScreen() + 1, model.pdoc->LinesTotal()); +} + +/** +* Fill in the LineLayout data for the given line. +* Copy the given @a line and its styles from the document into local arrays. +* Also determine the x position at which each character starts. +*/ +void EditView::LayoutLine(const EditModel &model, int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, int width) { + if (!ll) + return; + + PLATFORM_ASSERT(line < model.pdoc->LinesTotal()); + PLATFORM_ASSERT(ll->chars != NULL); + int posLineStart = model.pdoc->LineStart(line); + int posLineEnd = model.pdoc->LineStart(line + 1); + // If the line is very long, limit the treatment to a length that should fit in the viewport + if (posLineEnd >(posLineStart + ll->maxLineLength)) { + posLineEnd = posLineStart + ll->maxLineLength; + } + if (ll->validity == LineLayout::llCheckTextAndStyle) { + int lineLength = posLineEnd - posLineStart; + if (!vstyle.viewEOL) { + lineLength = model.pdoc->LineEnd(line) - posLineStart; + } + if (lineLength == ll->numCharsInLine) { + // See if chars, styles, indicators, are all the same + bool allSame = true; + // Check base line layout + char styleByte = 0; + int numCharsInLine = 0; + while (numCharsInLine < lineLength) { + int charInDoc = numCharsInLine + posLineStart; + char chDoc = model.pdoc->CharAt(charInDoc); + styleByte = model.pdoc->StyleAt(charInDoc); + allSame = allSame && + (ll->styles[numCharsInLine] == static_cast(styleByte)); + if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed) + allSame = allSame && + (ll->chars[numCharsInLine] == chDoc); + else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) + allSame = allSame && + (ll->chars[numCharsInLine] == static_cast(tolower(chDoc))); + else // Style::caseUpper + allSame = allSame && + (ll->chars[numCharsInLine] == static_cast(toupper(chDoc))); + numCharsInLine++; + } + allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled + if (allSame) { + ll->validity = LineLayout::llPositions; + } else { + ll->validity = LineLayout::llInvalid; + } + } else { + ll->validity = LineLayout::llInvalid; + } + } + if (ll->validity == LineLayout::llInvalid) { + ll->widthLine = LineLayout::wrapWidthInfinite; + ll->lines = 1; + if (vstyle.edgeState == EDGE_BACKGROUND) { + ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge); + if (ll->edgeColumn >= posLineStart) { + ll->edgeColumn -= posLineStart; + } + } else { + ll->edgeColumn = -1; + } + + // Fill base line layout + const int lineLength = posLineEnd - posLineStart; + model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength); + model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength); + int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart; + const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL; + for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) { + const unsigned char styleByte = ll->styles[styleInLine]; + ll->styles[styleInLine] = styleByte; + } + const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0; + if (vstyle.someStylesForceCase) { + for (int charInLine = 0; charInLinechars[charInLine]; + if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper) + ll->chars[charInLine] = static_cast(toupper(chDoc)); + else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower) + ll->chars[charInLine] = static_cast(tolower(chDoc)); + } + } + ll->xHighlightGuide = 0; + // Extra element at the end of the line to hold end x position and act as + ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character + ll->styles[numCharsInLine] = styleByteLast; // For eolFilled + + // Layout the line, determining the position of each character, + // with an extra element at the end for the end of the line. + ll->positions[0] = 0; + bool lastSegItalics = false; + + BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs, NULL); + while (bfLayout.More()) { + + const TextSegment ts = bfLayout.Next(); + + std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f); + if (vstyle.styles[ll->styles[ts.start]].visible) { + if (ts.representation) { + XYPOSITION representationWidth = vstyle.controlCharWidth; + if (ll->chars[ts.start] == '\t') { + // Tab is a special case of representation, taking a variable amount of space + const XYPOSITION x = ll->positions[ts.start]; + representationWidth = NextTabstopPos(line, x, vstyle.tabWidth) - ll->positions[ts.start]; + } else { + if (representationWidth <= 0.0) { + XYPOSITION positionsRepr[256]; // Should expand when needed + posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(), + static_cast(ts.representation->stringRep.length()), positionsRepr, model.pdoc); + representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding; + } + } + for (int ii = 0; ii < ts.length; ii++) + ll->positions[ts.start + 1 + ii] = representationWidth; + } else { + if ((ts.length == 1) && (' ' == ll->chars[ts.start])) { + // Over half the segments are single characters and of these about half are space characters. + ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth; + } else { + posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start, + ts.length, ll->positions + ts.start + 1, model.pdoc); + } + } + lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic); + } + + for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) { + ll->positions[posToIncrease] += ll->positions[ts.start]; + } + } + + // Small hack to make lines that end with italics not cut off the edge of the last character + if (lastSegItalics) { + ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset; + } + ll->numCharsInLine = numCharsInLine; + ll->numCharsBeforeEOL = numCharsBeforeEOL; + ll->validity = LineLayout::llPositions; + } + // Hard to cope when too narrow, so just assume there is space + if (width < 20) { + width = 20; + } + if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) { + ll->widthLine = width; + if (width == LineLayout::wrapWidthInfinite) { + ll->lines = 1; + } else if (width > ll->positions[ll->numCharsInLine]) { + // Simple common case where line does not need wrapping. + ll->lines = 1; + } else { + if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { + width -= static_cast(vstyle.aveCharWidth); // take into account the space for end wrap mark + } + XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line + if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) { + wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth; + } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) { + wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth; + } + ll->wrapIndent = wrapAddIndent; + if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED) + for (int i = 0; i < ll->numCharsInLine; i++) { + if (!IsSpaceOrTab(ll->chars[i])) { + ll->wrapIndent += ll->positions[i]; // Add line indent + break; + } + } + // Check for text width minimum + if (ll->wrapIndent > width - static_cast(vstyle.aveCharWidth) * 15) + ll->wrapIndent = wrapAddIndent; + // Check for wrapIndent minimum + if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth)) + ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual + ll->lines = 0; + // Calculate line start positions based upon width. + int lastGoodBreak = 0; + int lastLineStart = 0; + XYACCUMULATOR startOffset = 0; + int p = 0; + while (p < ll->numCharsInLine) { + if ((ll->positions[p + 1] - startOffset) >= width) { + if (lastGoodBreak == lastLineStart) { + // Try moving to start of last character + if (p > 0) { + lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) + - posLineStart; + } + if (lastGoodBreak == lastLineStart) { + // Ensure at least one character on line. + lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) + - posLineStart; + } + } + lastLineStart = lastGoodBreak; + ll->lines++; + ll->SetLineStart(ll->lines, lastGoodBreak); + startOffset = ll->positions[lastGoodBreak]; + // take into account the space for start wrap mark and indent + startOffset -= ll->wrapIndent; + p = lastGoodBreak + 1; + continue; + } + if (p > 0) { + if (vstyle.wrapState == eWrapChar) { + lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) + - posLineStart; + p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart; + continue; + } else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) { + lastGoodBreak = p; + } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) { + lastGoodBreak = p; + } + } + p++; + } + ll->lines++; + } + ll->validity = LineLayout::llLines; + } +} + +Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine, const ViewStyle &vs) { + Point pt; + if (pos.Position() == INVALID_POSITION) + return pt; + const int line = model.pdoc->LineFromPosition(pos.Position()); + const int lineVisible = model.cs.DisplayFromDoc(line); + //Platform::DebugPrintf("line=%d\n", line); + AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); + if (surface && ll) { + const int posLineStart = model.pdoc->LineStart(line); + LayoutLine(model, line, surface, vs, ll, model.wrapWidth); + const int posInLine = pos.Position() - posLineStart; + pt = ll->PointFromPosition(posInLine, vs.lineHeight); + pt.y += (lineVisible - topLine) * vs.lineHeight; + pt.x += vs.textStart - model.xOffset; + } + pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; + return pt; +} + +SelectionPosition EditView::SPositionFromLocation(Surface *surface, const EditModel &model, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const ViewStyle &vs) { + pt.x = pt.x - vs.textStart; + int visibleLine = static_cast(floor(pt.y / vs.lineHeight)); + if (!canReturnInvalid && (visibleLine < 0)) + visibleLine = 0; + const int lineDoc = model.cs.DocFromDisplay(visibleLine); + if (canReturnInvalid && (lineDoc < 0)) + return SelectionPosition(INVALID_POSITION); + if (lineDoc >= model.pdoc->LinesTotal()) + return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length()); + const int posLineStart = model.pdoc->LineStart(lineDoc); + AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); + if (surface && ll) { + LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth); + const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); + const int subLine = visibleLine - lineStartSet; + if (subLine < ll->lines) { + const Range rangeSubLine = ll->SubLineRange(subLine); + const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; + if (subLine > 0) // Wrapped + pt.x -= ll->wrapIndent; + const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition); + if (positionInLine < rangeSubLine.end) { + return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); + } + if (virtualSpace) { + const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; + const int spaceOffset = static_cast( + (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); + return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); + } else if (canReturnInvalid) { + if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) { + return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1)); + } + } else { + return SelectionPosition(rangeSubLine.end + posLineStart); + } + } + if (!canReturnInvalid) + return SelectionPosition(ll->numCharsInLine + posLineStart); + } + return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart); +} + +/** +* Find the document position corresponding to an x coordinate on a particular document line. +* Ensure is between whole characters when document is in multi-byte or UTF-8 mode. +* This method is used for rectangular selections and does not work on wrapped lines. +*/ +SelectionPosition EditView::SPositionFromLineX(Surface *surface, const EditModel &model, int lineDoc, int x, const ViewStyle &vs) { + AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); + if (surface && ll) { + const int posLineStart = model.pdoc->LineStart(lineDoc); + LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth); + const Range rangeSubLine = ll->SubLineRange(0); + const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; + const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false); + if (positionInLine < rangeSubLine.end) { + return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); + } + const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; + const int spaceOffset = static_cast( + (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); + return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); + } + return SelectionPosition(0); +} + +int EditView::DisplayFromPosition(Surface *surface, const EditModel &model, int pos, const ViewStyle &vs) { + int lineDoc = model.pdoc->LineFromPosition(pos); + int lineDisplay = model.cs.DisplayFromDoc(lineDoc); + AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); + if (surface && ll) { + LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth); + unsigned int posLineStart = model.pdoc->LineStart(lineDoc); + int posInLine = pos - posLineStart; + lineDisplay--; // To make up for first increment ahead. + for (int subLine = 0; subLine < ll->lines; subLine++) { + if (posInLine >= ll->LineStart(subLine)) { + lineDisplay++; + } + } + } + return lineDisplay; +} + +int EditView::StartEndDisplayLine(Surface *surface, const EditModel &model, int pos, bool start, const ViewStyle &vs) { + int line = model.pdoc->LineFromPosition(pos); + AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); + int posRet = INVALID_POSITION; + if (surface && ll) { + unsigned int posLineStart = model.pdoc->LineStart(line); + LayoutLine(model, line, surface, vs, ll, model.wrapWidth); + int posInLine = pos - posLineStart; + if (posInLine <= ll->maxLineLength) { + for (int subLine = 0; subLine < ll->lines; subLine++) { + if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) { + if (start) { + posRet = ll->LineStart(subLine) + posLineStart; + } else { + if (subLine == ll->lines - 1) + posRet = ll->LineStart(subLine + 1) + posLineStart; + else + posRet = ll->LineStart(subLine + 1) + posLineStart - 1; + } + } + } + } + } + return posRet; +} + +static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) { + return main ? + (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) : + vsDraw.selAdditionalBackground; +} + +static ColourDesired TextBackground(const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i) { + if (inSelection == 1) { + if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) { + return SelectionBackground(vsDraw, true, model.primarySelection); + } + } else if (inSelection == 2) { + if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) { + return SelectionBackground(vsDraw, false, model.primarySelection); + } + } else { + if ((vsDraw.edgeState == EDGE_BACKGROUND) && + (i >= ll->edgeColumn) && + (i < ll->numCharsBeforeEOL)) + return vsDraw.edgecolour; + if (inHotspot && vsDraw.hotspotColours.back.isSet) + return vsDraw.hotspotColours.back; + } + if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { + return background; + } else { + return vsDraw.styles[styleMain].back; + } +} + +void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { + Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); + PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast(rcSegment.top), start + 2, static_cast(rcSegment.bottom)); + surface->Copy(rcCopyArea, from, + highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); +} + +static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) { + if (alpha != SC_ALPHA_NOALPHA) { + surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0); + } +} + +static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment, + const char *s, ColourDesired textBack, ColourDesired textFore, bool fillBackground) { + if (fillBackground) { + surface->FillRectangle(rcSegment, textBack); + } + FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; + int normalCharHeight = static_cast(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, s, static_cast(s ? strlen(s) : 0), + textBack, textFore); +} + +void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + PRectangle rcLine, int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, + ColourOptional background) { + + const int posLineStart = model.pdoc->LineStart(line); + PRectangle rcSegment = rcLine; + + const bool lastSubLine = subLine == (ll->lines - 1); + XYPOSITION virtualSpace = 0; + if (lastSubLine) { + const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; + virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth; + } + XYPOSITION xEol = static_cast(ll->positions[lineEnd] - subLineStart); + + // Fill the virtual space and show selections within it + if (virtualSpace > 0.0f) { + rcSegment.left = xEol + xStart; + rcSegment.right = xEol + xStart + virtualSpace; + surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back); + if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) { + SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)))); + for (size_t r = 0; rEndLineStyle()].spaceWidth; + rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - + static_cast(subLineStart)+portion.start.VirtualSpace() * spaceWidth; + rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - + static_cast(subLineStart)+portion.end.VirtualSpace() * spaceWidth; + rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; + rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; + surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection)); + } + } + } + } + } + + int eolInSelection = 0; + int alpha = SC_ALPHA_NOALPHA; + if (!hideSelection) { + int posAfterLineEnd = model.pdoc->LineStart(line + 1); + eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; + alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; + } + + // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on + XYPOSITION blobsWidth = 0; + if (lastSubLine) { + for (int eolPos = ll->numCharsBeforeEOL; eolPosnumCharsInLine; eolPos++) { + rcSegment.left = xStart + ll->positions[eolPos] - static_cast(subLineStart)+virtualSpace; + rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast(subLineStart)+virtualSpace; + blobsWidth += rcSegment.Width(); + char hexits[4]; + const char *ctrlChar; + unsigned char chEOL = ll->chars[eolPos]; + int styleMain = ll->styles[eolPos]; + ColourDesired textBack = TextBackground(model, vsDraw, ll, background, eolInSelection, false, styleMain, eolPos); + if (UTF8IsAscii(chEOL)) { + ctrlChar = ControlCharacterString(chEOL); + } else { + const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos); + if (repr) { + ctrlChar = repr->stringRep.c_str(); + eolPos = ll->numCharsInLine; + } else { + sprintf(hexits, "x%2X", chEOL); + ctrlChar = hexits; + } + } + ColourDesired textFore = vsDraw.styles[styleMain].fore; + if (eolInSelection && vsDraw.selColours.fore.isSet) { + textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; + } + if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) { + if (alpha == SC_ALPHA_NOALPHA) { + surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); + } else { + surface->FillRectangle(rcSegment, textBack); + } + } else { + surface->FillRectangle(rcSegment, textBack); + } + DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, phasesDraw == phasesOne); + if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { + SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + } + } + } + + // Draw the eol-is-selected rectangle + rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; + rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; + + if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { + surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); + } else { + if (background.isSet) { + surface->FillRectangle(rcSegment, background); + } else if (line < model.pdoc->LinesTotal() - 1) { + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); + } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); + } else { + surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); + } + if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { + SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + } + } + + // Fill the remainder of the line + rcSegment.left = rcSegment.right; + if (rcSegment.left < rcLine.left) + rcSegment.left = rcLine.left; + rcSegment.right = rcLine.right; + + if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { + surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); + } else { + if (background.isSet) { + surface->FillRectangle(rcSegment, background); + } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); + } else { + surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); + } + if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { + SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + } + } + + bool drawWrapMarkEnd = false; + + if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { + if (subLine + 1 < ll->lines) { + drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0; + } + } + + if (drawWrapMarkEnd) { + PRectangle rcPlace = rcSegment; + + if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) { + rcPlace.left = xEol + xStart + virtualSpace; + rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; + } else { + // rcLine is clipped to text area + rcPlace.right = rcLine.right; + rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; + } + if (customDrawWrapMarker == NULL) { + DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); + } else { + customDrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); + } + } +} + +static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw, + const LineLayout *ll, int xStart, PRectangle rcLine, int subLine, Indicator::DrawState drawState, int value) { + const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)]; + PRectangle rcIndic( + ll->positions[startPos] + xStart - subLineStart, + rcLine.top + vsDraw.maxAscent, + ll->positions[endPos] + xStart - subLineStart, + rcLine.top + vsDraw.maxAscent + 3); + vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine, drawState, value); +} + +static void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, int xStart, PRectangle rcLine, int subLine, int lineEnd, bool under, int hoverIndicatorPos) { + // Draw decorators + const int posLineStart = model.pdoc->LineStart(line); + const int lineStart = ll->LineStart(subLine); + const int posLineEnd = posLineStart + lineEnd; + + for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { + if (under == vsDraw.indicators[deco->indicator].under) { + int startPos = posLineStart + lineStart; + if (!deco->rs.ValueAt(startPos)) { + startPos = deco->rs.EndRun(startPos); + } + while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) { + int endPos = deco->rs.EndRun(startPos); + if (endPos > posLineEnd) + endPos = posLineEnd; + const bool hover = vsDraw.indicators[deco->indicator].IsDynamic() && + ((hoverIndicatorPos >= startPos) && (hoverIndicatorPos <= endPos)); + const int value = deco->rs.ValueAt(startPos); + Indicator::DrawState drawState = hover ? Indicator::drawHover : Indicator::drawNormal; + DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, + surface, vsDraw, ll, xStart, rcLine, subLine, drawState, value); + startPos = endPos; + if (!deco->rs.ValueAt(startPos)) { + startPos = deco->rs.EndRun(startPos); + } + } + } + } + + // Use indicators to highlight matching braces + if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || + (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) { + int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator; + if (under == vsDraw.indicators[braceIndicator].under) { + Range rangeLine(posLineStart + lineStart, posLineEnd); + if (rangeLine.ContainsCharacter(model.braces[0])) { + int braceOffset = model.braces[0] - posLineStart; + if (braceOffset < ll->numCharsInLine) { + DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1); + } + } + if (rangeLine.ContainsCharacter(model.braces[1])) { + int braceOffset = model.braces[1] - posLineStart; + if (braceOffset < ll->numCharsInLine) { + DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1); + } + } + } + } +} + +static bool AnnotationBoxedOrIndented(int annotationVisible) { + return annotationVisible == ANNOTATION_BOXED || annotationVisible == ANNOTATION_INDENTED; +} + +void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) { + int indent = static_cast(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth); + PRectangle rcSegment = rcLine; + int annotationLine = subLine - ll->lines; + const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line); + if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { + if (phase & drawBack) { + surface->FillRectangle(rcSegment, vsDraw.styles[0].back); + } + rcSegment.left = static_cast(xStart); + if (model.trackLineWidth || AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { + // Only care about calculating width if tracking or need to draw indented box + int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); + if (AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { + widthAnnotation += static_cast(vsDraw.spaceWidth * 2); // Margins + rcSegment.left = static_cast(xStart + indent); + rcSegment.right = rcSegment.left + widthAnnotation; + } + if (widthAnnotation > lineWidthMaxSeen) + lineWidthMaxSeen = widthAnnotation; + } + const int annotationLines = model.pdoc->AnnotationLines(line); + size_t start = 0; + size_t lengthAnnotation = stAnnotation.LineLength(start); + int lineInAnnotation = 0; + while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) { + start += lengthAnnotation + 1; + lengthAnnotation = stAnnotation.LineLength(start); + lineInAnnotation++; + } + PRectangle rcText = rcSegment; + if ((phase & drawBack) && AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { + surface->FillRectangle(rcText, + vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); + rcText.left += vsDraw.spaceWidth; + } + DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, + stAnnotation, start, lengthAnnotation, phase); + if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) { + surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore); + surface->MoveTo(static_cast(rcSegment.left), static_cast(rcSegment.top)); + surface->LineTo(static_cast(rcSegment.left), static_cast(rcSegment.bottom)); + surface->MoveTo(static_cast(rcSegment.right), static_cast(rcSegment.top)); + surface->LineTo(static_cast(rcSegment.right), static_cast(rcSegment.bottom)); + if (subLine == ll->lines) { + surface->MoveTo(static_cast(rcSegment.left), static_cast(rcSegment.top)); + surface->LineTo(static_cast(rcSegment.right), static_cast(rcSegment.top)); + } + if (subLine == ll->lines + annotationLines - 1) { + surface->MoveTo(static_cast(rcSegment.left), static_cast(rcSegment.bottom - 1)); + surface->LineTo(static_cast(rcSegment.right), static_cast(rcSegment.bottom - 1)); + } + } + } +} + +static void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) { + + int lineStart = ll->LineStart(subLine); + int posBefore = posCaret; + int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1); + int numCharsToDraw = posAfter - posCaret; + + // Work out where the starting and ending offsets are. We need to + // see if the previous character shares horizontal space, such as a + // glyph / combining character. If so we'll need to draw that too. + int offsetFirstChar = offset; + int offsetLastChar = offset + (posAfter - posCaret); + while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) { + if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { + // The char does not share horizontal space + break; + } + // Char shares horizontal space, update the numChars to draw + // Update posBefore to point to the prev char + posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1); + numCharsToDraw = posAfter - posBefore; + offsetFirstChar = offset - (posCaret - posBefore); + } + + // See if the next character shares horizontal space, if so we'll + // need to draw that too. + if (offsetFirstChar < 0) + offsetFirstChar = 0; + numCharsToDraw = offsetLastChar - offsetFirstChar; + while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { + // Update posAfter to point to the 2nd next char, this is where + // the next character ends, and 2nd next begins. We'll need + // to compare these two + posBefore = posAfter; + posAfter = model.pdoc->MovePositionOutsideChar(posAfter + 1, 1); + offsetLastChar = offset + (posAfter - posCaret); + if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { + // The char does not share horizontal space + break; + } + // Char shares horizontal space, update the numChars to draw + numCharsToDraw = offsetLastChar - offsetFirstChar; + } + + // We now know what to draw, update the caret drawing rectangle + rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart; + rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart; + + // Adjust caret position to take into account any word wrapping symbols. + if ((ll->wrapIndent != 0) && (lineStart != 0)) { + XYPOSITION wordWrapCharWidth = ll->wrapIndent; + rcCaret.left += wordWrapCharWidth; + rcCaret.right += wordWrapCharWidth; + } + + // This character is where the caret block is, we override the colours + // (inversed) for drawing the caret here. + int styleMain = ll->styles[offsetFirstChar]; + FontAlias fontText = vsDraw.styles[styleMain].font; + surface->DrawTextClipped(rcCaret, fontText, + rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, + numCharsToDraw, vsDraw.styles[styleMain].back, + caretColour); +} + +void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int lineDoc, int xStart, PRectangle rcLine, int subLine) const { + // When drag is active it is the only caret drawn + bool drawDrag = model.posDrag.IsValid(); + if (hideSelection && !drawDrag) + return; + const int posLineStart = model.pdoc->LineStart(lineDoc); + // For each selection draw + for (size_t r = 0; (rEndLineStyle()].spaceWidth; + const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth; + if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { + XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; + if (ll->wrapIndent != 0) { + int lineStart = ll->LineStart(subLine); + if (lineStart != 0) // Wrapped + xposCaret += ll->wrapIndent; + } + bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret); + bool caretVisibleState = additionalCaretsVisible || mainCaret; + if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) && + ((model.posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) { + bool caretAtEOF = false; + bool caretAtEOL = false; + bool drawBlockCaret = false; + XYPOSITION widthOverstrikeCaret; + XYPOSITION caretWidthOffset = 0; + PRectangle rcCaret = rcLine; + + if (posCaret.Position() == model.pdoc->Length()) { // At end of document + caretAtEOF = true; + widthOverstrikeCaret = vsDraw.aveCharWidth; + } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line + caretAtEOL = true; + widthOverstrikeCaret = vsDraw.aveCharWidth; + } else { + const int widthChar = model.pdoc->LenChar(posCaret.Position()); + widthOverstrikeCaret = ll->positions[offset + widthChar] - ll->positions[offset]; + } + if (widthOverstrikeCaret < 3) // Make sure its visible + widthOverstrikeCaret = 3; + + if (xposCaret > 0) + caretWidthOffset = 0.51f; // Move back so overlaps both character cells. + xposCaret += xStart; + if (model.posDrag.IsValid()) { + /* Dragging text, use a line caret */ + rcCaret.left = static_cast(RoundXYPosition(xposCaret - caretWidthOffset)); + rcCaret.right = rcCaret.left + vsDraw.caretWidth; + } else if (model.inOverstrike && drawOverstrikeCaret) { + /* Overstrike (insert mode), use a modified bar caret */ + rcCaret.top = rcCaret.bottom - 2; + rcCaret.left = xposCaret + 1; + rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; + } else if ((vsDraw.caretStyle == CARETSTYLE_BLOCK) || imeCaretBlockOverride) { + /* Block caret */ + rcCaret.left = xposCaret; + if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) { + drawBlockCaret = true; + rcCaret.right = xposCaret + widthOverstrikeCaret; + } else { + rcCaret.right = xposCaret + vsDraw.aveCharWidth; + } + } else { + /* Line caret */ + rcCaret.left = static_cast(RoundXYPosition(xposCaret - caretWidthOffset)); + rcCaret.right = rcCaret.left + vsDraw.caretWidth; + } + ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour; + if (drawBlockCaret) { + DrawBlockCaret(surface, model, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour); + } else { + surface->FillRectangle(rcCaret, caretColour); + } + } + } + if (drawDrag) + break; + } +} + +static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, + int xStart, PRectangle rcLine, ColourOptional background, DrawWrapMarkerFn customDrawWrapMarker) { + // default bgnd here.. + surface->FillRectangle(rcLine, background.isSet ? background : + vsDraw.styles[STYLE_DEFAULT].back); + + if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) { + + // draw continuation rect + PRectangle rcPlace = rcLine; + + rcPlace.left = static_cast(xStart); + rcPlace.right = rcPlace.left + ll->wrapIndent; + + if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT) + rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; + else + rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; + + if (customDrawWrapMarker == NULL) { + DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); + } else { + customDrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); + } + } +} + +void EditView::DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + PRectangle rcLine, Range lineRange, int posLineStart, int xStart, + int subLine, ColourOptional background) const { + + const bool selBackDrawn = vsDraw.SelectionBackgroundDrawn(); + bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. + const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; + // Does not take margin into account but not significant + const int xStartVisible = static_cast(subLineStart)-xStart; + + BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, NULL); + + const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background.isSet; + + // Background drawing loop + while (bfBack.More()) { + + const TextSegment ts = bfBack.Next(); + const int i = ts.end() - 1; + const int iDoc = i + posLineStart; + + PRectangle rcSegment = rcLine; + rcSegment.left = ll->positions[ts.start] + xStart - static_cast(subLineStart); + rcSegment.right = ll->positions[ts.end()] + xStart - static_cast(subLineStart); + // Only try to 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.Intersects(rcLine)) { + // Clip to line rectangle, since may have a huge position which will not work with some platforms + if (rcSegment.left < rcLine.left) + rcSegment.left = rcLine.left; + if (rcSegment.right > rcLine.right) + rcSegment.right = rcLine.right; + + const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); + const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); + ColourDesired textBack = TextBackground(model, vsDraw, ll, background, inSelection, + inHotspot, ll->styles[i], i); + if (ts.representation) { + if (ll->chars[i] == '\t') { + // Tab display + if (drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) + textBack = vsDraw.whitespaceColours.back; + } else { + // Blob display + inIndentation = false; + } + surface->FillRectangle(rcSegment, textBack); + } else { + // Normal text display + surface->FillRectangle(rcSegment, textBack); + if (vsDraw.viewWhitespace != wsInvisible || + (inIndentation && vsDraw.viewIndentationGuides == ivReal)) { + for (int cpos = 0; cpos <= i - ts.start; cpos++) { + if (ll->chars[cpos + ts.start] == ' ') { + if (drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { + PRectangle rcSpace( + ll->positions[cpos + ts.start] + xStart - static_cast(subLineStart), + rcSegment.top, + ll->positions[cpos + ts.start + 1] + xStart - static_cast(subLineStart), + rcSegment.bottom); + surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back); + } + } else { + inIndentation = false; + } + } + } + } + } else if (rcSegment.left > rcLine.right) { + break; + } + } +} + +static void DrawEdgeLine(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, + Range lineRange, int xStart) { + if (vsDraw.edgeState == EDGE_LINE) { + PRectangle rcSegment = rcLine; + int edgeX = static_cast(vsDraw.theEdge * vsDraw.spaceWidth); + rcSegment.left = static_cast(edgeX + xStart); + if ((ll->wrapIndent != 0) && (lineRange.start != 0)) + rcSegment.left -= ll->wrapIndent; + rcSegment.right = rcSegment.left + 1; + surface->FillRectangle(rcSegment, vsDraw.edgecolour); + } +} + +// Draw underline mark as part of background if not transparent +static void DrawMarkUnderline(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, + int line, PRectangle rcLine) { + int marks = model.pdoc->GetMark(line); + for (int markBit = 0; (markBit < 32) && marks; markBit++) { + if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) && + (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { + PRectangle rcUnderline = rcLine; + rcUnderline.top = rcUnderline.bottom - 2; + surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back); + } + marks >>= 1; + } +} +static void DrawTranslucentSelection(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, PRectangle rcLine, int subLine, Range lineRange, int xStart) { + if ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA)) { + const int posLineStart = model.pdoc->LineStart(line); + const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; + // For each selection draw + int virtualSpaces = 0; + if (subLine == (ll->lines - 1)) { + virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)); + } + SelectionPosition posStart(posLineStart + lineRange.start); + SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces); + SelectionSegment virtualSpaceRange(posStart, posEnd); + for (size_t r = 0; r < model.sel.Count(); r++) { + int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; + if (alpha != SC_ALPHA_NOALPHA) { + SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); + if (!portion.Empty()) { + const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; + PRectangle rcSegment = rcLine; + rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - + static_cast(subLineStart)+portion.start.VirtualSpace() * spaceWidth; + rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - + static_cast(subLineStart)+portion.end.VirtualSpace() * spaceWidth; + if ((ll->wrapIndent != 0) && (lineRange.start != 0)) { + if ((portion.start.Position() - posLineStart) == lineRange.start && model.sel.Range(r).ContainsCharacter(portion.start.Position() - 1)) + rcSegment.left -= static_cast(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here + } + rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; + rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; + if (rcSegment.right > rcLine.left) + SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha); + } + } + } + } +} + +// Draw any translucent whole line states +static void DrawTranslucentLineState(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, PRectangle rcLine) { + if ((model.caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) { + SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLineBackground, vsDraw.caretLineAlpha); + } + int marks = model.pdoc->GetMark(line); + for (int markBit = 0; (markBit < 32) && marks; markBit++) { + if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) { + SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); + } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) { + PRectangle rcUnderline = rcLine; + rcUnderline.top = rcUnderline.bottom - 2; + SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); + } + marks >>= 1; + } + if (vsDraw.maskInLine) { + int marksMasked = model.pdoc->GetMark(line) & vsDraw.maskInLine; + if (marksMasked) { + for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) { + if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) { + SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); + } + marksMasked >>= 1; + } + } + } +} + +void EditView::DrawForeground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int lineVisible, PRectangle rcLine, Range lineRange, int posLineStart, int xStart, + int subLine, ColourOptional background) { + + const bool selBackDrawn = vsDraw.SelectionBackgroundDrawn(); + const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background.isSet; + bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. + + const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; + const XYPOSITION indentWidth = model.pdoc->IndentSize() * vsDraw.spaceWidth; + + // Does not take margin into account but not significant + const int xStartVisible = static_cast(subLineStart)-xStart; + + // Foreground drawing loop + BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, + (((phasesDraw == phasesOne) && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs, &vsDraw); + + while (bfFore.More()) { + + const TextSegment ts = bfFore.Next(); + const int i = ts.end() - 1; + const int iDoc = i + posLineStart; + + PRectangle rcSegment = rcLine; + rcSegment.left = ll->positions[ts.start] + xStart - static_cast(subLineStart); + rcSegment.right = ll->positions[ts.end()] + xStart - static_cast(subLineStart); + // Only try to 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.Intersects(rcLine)) { + int styleMain = ll->styles[i]; + ColourDesired textFore = vsDraw.styles[styleMain].fore; + FontAlias textFont = vsDraw.styles[styleMain].font; + //hotspot foreground + const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); + if (inHotspot) { + if (vsDraw.hotspotColours.fore.isSet) + textFore = vsDraw.hotspotColours.fore; + } + if (vsDraw.indicatorsSetFore > 0) { + // At least one indicator sets the text colour so see if it applies to this segment + for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { + const int indicatorValue = deco->rs.ValueAt(ts.start + posLineStart); + if (indicatorValue) { + const Indicator &indicator = vsDraw.indicators[deco->indicator]; + const bool hover = indicator.IsDynamic() && + ((model.hoverIndicatorPos >= ts.start + posLineStart) && + (model.hoverIndicatorPos <= ts.end() + posLineStart)); + if (hover) { + if (indicator.sacHover.style == INDIC_TEXTFORE) { + textFore = indicator.sacHover.fore; + } + } else { + if (indicator.sacNormal.style == INDIC_TEXTFORE) { + if (indicator.Flags() & SC_INDICFLAG_VALUEFORE) + textFore = indicatorValue & SC_INDICVALUEMASK; + else + textFore = indicator.sacNormal.fore; + } + } + } + } + } + const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); + if (inSelection && (vsDraw.selColours.fore.isSet)) { + textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; + } + ColourDesired textBack = TextBackground(model, vsDraw, ll, background, inSelection, inHotspot, styleMain, i); + if (ts.representation) { + if (ll->chars[i] == '\t') { + // Tab display + if (phasesDraw == phasesOne) { + if (drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) + textBack = vsDraw.whitespaceColours.back; + surface->FillRectangle(rcSegment, textBack); + } + if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { + for (int indentCount = static_cast((ll->positions[i] + epsilon) / indentWidth); + indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth; + indentCount++) { + if (indentCount > 0) { + int xIndent = static_cast(indentCount * indentWidth); + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, + (ll->xHighlightGuide == xIndent)); + } + } + } + if (vsDraw.viewWhitespace != wsInvisible) { + if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { + if (vsDraw.whitespaceColours.fore.isSet) + textFore = vsDraw.whitespaceColours.fore; + surface->PenColour(textFore); + PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight, + rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); + if (customDrawTabArrow == NULL) + DrawTabArrow(surface, rcTab, static_cast(rcSegment.top + vsDraw.lineHeight / 2)); + else + customDrawTabArrow(surface, rcTab, static_cast(rcSegment.top + vsDraw.lineHeight / 2)); + } + } + } else { + inIndentation = false; + if (vsDraw.controlCharSymbol >= 32) { + // 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. + FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; + char cc[2] = { static_cast(vsDraw.controlCharSymbol), '\0' }; + surface->DrawTextNoClip(rcSegment, ctrlCharsFont, + rcSegment.top + vsDraw.maxAscent, + cc, 1, textBack, textFore); + } else { + DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), + textBack, textFore, phasesDraw == phasesOne); + } + } + } else { + // Normal text display + if (vsDraw.styles[styleMain].visible) { + if (phasesDraw != phasesOne) { + surface->DrawTextTransparent(rcSegment, textFont, + rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, + i - ts.start + 1, textFore); + } else { + surface->DrawTextNoClip(rcSegment, textFont, + rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, + i - ts.start + 1, textFore, textBack); + } + } + if (vsDraw.viewWhitespace != wsInvisible || + (inIndentation && vsDraw.viewIndentationGuides != ivNone)) { + for (int cpos = 0; cpos <= i - ts.start; cpos++) { + if (ll->chars[cpos + ts.start] == ' ') { + if (vsDraw.viewWhitespace != wsInvisible) { + if (vsDraw.whitespaceColours.fore.isSet) + textFore = vsDraw.whitespaceColours.fore; + if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { + XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2; + if ((phasesDraw == phasesOne) && drawWhitespaceBackground && + (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { + textBack = vsDraw.whitespaceColours.back; + PRectangle rcSpace( + ll->positions[cpos + ts.start] + xStart - static_cast(subLineStart), + rcSegment.top, + ll->positions[cpos + ts.start + 1] + xStart - static_cast(subLineStart), + rcSegment.bottom); + surface->FillRectangle(rcSpace, textBack); + } + PRectangle rcDot(xmid + xStart - static_cast(subLineStart), + rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f); + rcDot.right = rcDot.left + vsDraw.whitespaceSize; + rcDot.bottom = rcDot.top + vsDraw.whitespaceSize; + surface->FillRectangle(rcDot, textFore); + } + } + if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { + for (int indentCount = static_cast((ll->positions[cpos + ts.start] + epsilon) / indentWidth); + indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth; + indentCount++) { + if (indentCount > 0) { + int xIndent = static_cast(indentCount * indentWidth); + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, + (ll->xHighlightGuide == xIndent)); + } + } + } + } else { + inIndentation = false; + } + } + } + } + if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) { + PRectangle rcUL = rcSegment; + rcUL.top = rcUL.top + vsDraw.maxAscent + 1; + rcUL.bottom = rcUL.top + 1; + if (vsDraw.hotspotColours.fore.isSet) + surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore); + else + surface->FillRectangle(rcUL, textFore); + } else if (vsDraw.styles[styleMain].underline) { + PRectangle rcUL = rcSegment; + rcUL.top = rcUL.top + vsDraw.maxAscent + 1; + rcUL.bottom = rcUL.top + 1; + surface->FillRectangle(rcUL, textFore); + } + } else if (rcSegment.left > rcLine.right) { + break; + } + } +} + +void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, int lineVisible, PRectangle rcLine, int xStart, int subLine) { + if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth) + && (subLine == 0)) { + const int posLineStart = model.pdoc->LineStart(line); + int indentSpace = model.pdoc->GetLineIndentation(line); + int xStartText = static_cast(ll->positions[model.pdoc->GetLineIndentPosition(line) - posLineStart]); + + // Find the most recent line with some text + + int lineLastWithText = line; + while (lineLastWithText > Platform::Maximum(line - 20, 0) && model.pdoc->IsWhiteLine(lineLastWithText)) { + lineLastWithText--; + } + if (lineLastWithText < line) { + xStartText = 100000; // Don't limit to visible indentation on empty line + // This line is empty, so use indentation of last line with text + int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText); + int isFoldHeader = model.pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG; + if (isFoldHeader) { + // Level is one more level than parent + indentLastWithText += model.pdoc->IndentSize(); + } + if (vsDraw.viewIndentationGuides == ivLookForward) { + // In viLookForward mode, previous line only used if it is a fold header + if (isFoldHeader) { + indentSpace = Platform::Maximum(indentSpace, indentLastWithText); + } + } else { // viLookBoth + indentSpace = Platform::Maximum(indentSpace, indentLastWithText); + } + } + + int lineNextWithText = line; + while (lineNextWithText < Platform::Minimum(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) { + lineNextWithText++; + } + if (lineNextWithText > line) { + xStartText = 100000; // Don't limit to visible indentation on empty line + // This line is empty, so use indentation of first next line with text + indentSpace = Platform::Maximum(indentSpace, + model.pdoc->GetLineIndentation(lineNextWithText)); + } + + for (int indentPos = model.pdoc->IndentSize(); indentPos < indentSpace; indentPos += model.pdoc->IndentSize()) { + int xIndent = static_cast(indentPos * vsDraw.spaceWidth); + if (xIndent < xStartText) { + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcLine, + (ll->xHighlightGuide == xIndent)); + } + } + } +} + +void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, int lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) { + + if (subLine >= ll->lines) { + DrawAnnotation(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, phase); + return; // No further drawing + } + + // See if something overrides the line background color. + const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); + + const int posLineStart = model.pdoc->LineStart(line); + + const Range lineRange = ll->SubLineRange(subLine); + const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; + + if ((ll->wrapIndent != 0) && (subLine > 0)) { + if (phase & drawBack) { + DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background, customDrawWrapMarker); + } + xStart += static_cast(ll->wrapIndent); + } + + if ((phasesDraw != phasesOne) && (phase & drawBack)) { + DrawBackground(surface, model, vsDraw, ll, rcLine, lineRange, posLineStart, xStart, + subLine, background); + DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end, + xStart, subLine, subLineStart, background); + } + + if (phase & drawIndicatorsBack) { + DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, true, model.hoverIndicatorPos); + DrawEdgeLine(surface, vsDraw, ll, rcLine, lineRange, xStart); + DrawMarkUnderline(surface, model, vsDraw, line, rcLine); + } + + if (phase & drawText) { + DrawForeground(surface, model, vsDraw, ll, lineVisible, rcLine, lineRange, posLineStart, xStart, + subLine, background); + } + + if (phase & drawIndentationGuides) { + DrawIndentGuidesOverEmpty(surface, model, vsDraw, ll, line, lineVisible, rcLine, xStart, subLine); + } + + if (phase & drawIndicatorsFore) { + DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, false, model.hoverIndicatorPos); + } + + // End of the drawing of the current line + if (phasesDraw == phasesOne) { + DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end, + xStart, subLine, subLineStart, background); + } + + if (!hideSelection && (phase & drawSelectionTranslucent)) { + DrawTranslucentSelection(surface, model, vsDraw, ll, line, rcLine, subLine, lineRange, xStart); + } + + if (phase & drawLineTranslucent) { + DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine); + } +} + +static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, int line, PRectangle rcLine) { + bool expanded = model.cs.GetExpanded(line); + const int level = model.pdoc->GetLevel(line); + const int levelNext = model.pdoc->GetLevel(line + 1); + if ((level & SC_FOLDLEVELHEADERFLAG) && + ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) { + // Paint the line above the fold + if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) + || + (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { + PRectangle rcFoldLine = rcLine; + rcFoldLine.bottom = rcFoldLine.top + 1; + surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); + } + // Paint the line below the fold + if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) + || + (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { + PRectangle rcFoldLine = rcLine; + rcFoldLine.top = rcFoldLine.bottom - 1; + surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); + } + } +} + +void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectangle rcArea, + PRectangle rcClient, const ViewStyle &vsDraw) { + // Allow text at start of line to overlap 1 pixel into the margin as this displays + // serifs and italic stems for aliased text. + const int leftTextOverlap = ((model.xOffset == 0) && (vsDraw.leftMarginWidth > 0)) ? 1 : 0; + + // Do the painting + if (rcArea.right > vsDraw.textStart - leftTextOverlap) { + + Surface *surface = surfaceWindow; + if (bufferedDraw) { + surface = pixmapLine; + PLATFORM_ASSERT(pixmapLine->Initialised()); + } + surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage); + surface->SetDBCSMode(model.pdoc->dbcsCodePage); + + const Point ptOrigin = model.GetVisibleOriginInMain(); + + const int screenLinePaintFirst = static_cast(rcArea.top) / vsDraw.lineHeight; + const int xStart = vsDraw.textStart - model.xOffset + static_cast(ptOrigin.x); + + SelectionPosition posCaret = model.sel.RangeMain().caret; + if (model.posDrag.IsValid()) + posCaret = model.posDrag; + const int lineCaret = model.pdoc->LineFromPosition(posCaret.Position()); + + PRectangle rcTextArea = rcClient; + if (vsDraw.marginInside) { + rcTextArea.left += vsDraw.textStart; + rcTextArea.right -= vsDraw.rightMarginWidth; + } else { + rcTextArea = rcArea; + } + + // Remove selection margin from drawing area so text will not be drawn + // on it in unbuffered mode. + if (!bufferedDraw && vsDraw.marginInside) { + PRectangle rcClipText = rcTextArea; + rcClipText.left -= leftTextOverlap; + surfaceWindow->SetClip(rcClipText); + } + + // Loop on visible lines + //double durLayout = 0.0; + //double durPaint = 0.0; + //double durCopy = 0.0; + //ElapsedTime etWhole; + + const bool bracesIgnoreStyle = ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || + (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))); + + int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times + AutoLineLayout ll(llc, 0); + std::vector phases; + if ((phasesDraw == phasesMultiple) && !bufferedDraw) { + for (DrawPhase phase = drawBack; phase <= drawCarets; phase = static_cast(phase * 2)) { + phases.push_back(phase); + } + } else { + phases.push_back(drawAll); + } + for (std::vector::iterator it = phases.begin(); it != phases.end(); ++it) { + int ypos = 0; + if (!bufferedDraw) + ypos += screenLinePaintFirst * vsDraw.lineHeight; + int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; + int visibleLine = model.TopLineOfMain() + screenLinePaintFirst; + while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) { + + const int lineDoc = model.cs.DocFromDisplay(visibleLine); + // Only visible lines should be handled by the code within the loop + PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); + const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); + const int subLine = visibleLine - lineStartSet; + + // Copy this line and its styles from the document into local arrays + // and determine the x position at which each character starts. + //ElapsedTime et; + if (lineDoc != lineDocPrevious) { + ll.Set(0); + ll.Set(RetrieveLineLayout(lineDoc, model)); + LayoutLine(model, lineDoc, surface, vsDraw, ll, model.wrapWidth); + lineDocPrevious = lineDoc; + } + //durLayout += et.Duration(true); + + if (ll) { + ll->containsCaret = !hideSelection && (lineDoc == lineCaret); + ll->hotspot = model.GetHotSpotRange(); + + PRectangle rcLine = rcTextArea; + rcLine.top = static_cast(ypos); + rcLine.bottom = static_cast(ypos + vsDraw.lineHeight); + + Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1)); + + // Highlight the current braces if any + ll->SetBracesHighlight(rangeLine, model.braces, static_cast(model.bracesMatchStyle), + static_cast(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle); + + if (leftTextOverlap && bufferedDraw) { + PRectangle rcSpacer = rcLine; + rcSpacer.right = rcSpacer.left; + rcSpacer.left -= 1; + surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back); + } + + DrawLine(surface, model, vsDraw, ll, lineDoc, visibleLine, xStart, rcLine, subLine, *it); + //durPaint += et.Duration(true); + + // Restore the previous styles for the brace highlights in case layout is in cache. + ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle); + + if (*it & drawFoldLines) { + DrawFoldLines(surface, model, vsDraw, lineDoc, rcLine); + } + + if (*it & drawCarets) { + DrawCarets(surface, model, vsDraw, ll, lineDoc, xStart, rcLine, subLine); + } + + if (bufferedDraw) { + Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0); + PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen, + static_cast(rcClient.right - vsDraw.rightMarginWidth), + yposScreen + vsDraw.lineHeight); + surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); + } + + lineWidthMaxSeen = Platform::Maximum( + lineWidthMaxSeen, static_cast(ll->positions[ll->numCharsInLine])); + //durCopy += et.Duration(true); + } + + if (!bufferedDraw) { + ypos += vsDraw.lineHeight; + } + + yposScreen += vsDraw.lineHeight; + visibleLine++; + } + } + ll.Set(0); + //if (durPaint < 0.00000001) + // durPaint = 0.00000001; + + // Right column limit indicator + PRectangle rcBeyondEOF = (vsDraw.marginInside) ? rcClient : rcArea; + rcBeyondEOF.left = static_cast(vsDraw.textStart); + rcBeyondEOF.right = rcBeyondEOF.right - ((vsDraw.marginInside) ? vsDraw.rightMarginWidth : 0); + rcBeyondEOF.top = static_cast((model.cs.LinesDisplayed() - model.TopLineOfMain()) * vsDraw.lineHeight); + if (rcBeyondEOF.top < rcBeyondEOF.bottom) { + surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.styles[STYLE_DEFAULT].back); + if (vsDraw.edgeState == EDGE_LINE) { + int edgeX = static_cast(vsDraw.theEdge * vsDraw.spaceWidth); + rcBeyondEOF.left = static_cast(edgeX + xStart); + rcBeyondEOF.right = rcBeyondEOF.left + 1; + surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.edgecolour); + } + } + //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); + + //Platform::DebugPrintf( + //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n", + //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); + } +} + +// Space (3 space characters) between line numbers and text when printing. +#define lineNumberPrintSpace " " + +ColourDesired InvertedLight(ColourDesired orig) { + unsigned int r = orig.GetRed(); + unsigned int g = orig.GetGreen(); + unsigned int b = orig.GetBlue(); + unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye + unsigned int il = 0xff - l; + if (l == 0) + return ColourDesired(0xff, 0xff, 0xff); + r = r * il / l; + g = g * il / l; + b = b * il / l; + return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); +} + +long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, + const EditModel &model, const ViewStyle &vs) { + // Can't use measurements cached for screen + posCache.Clear(); + + ViewStyle vsPrint(vs); + vsPrint.technology = SC_TECHNOLOGY_DEFAULT; + + // 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 <= SC_MAX_MARGIN; margin++) { + if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) { + lineNumberIndex = margin; + } else { + vsPrint.ms[margin].width = 0; + } + } + vsPrint.fixedColumnWidth = 0; + vsPrint.zoomLevel = printParameters.magnification; + // Don't show indentation guides + // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT + vsPrint.viewIndentationGuides = ivNone; + // Don't show the selection when printing + vsPrint.selColours.back.isSet = false; + vsPrint.selColours.fore.isSet = false; + vsPrint.selAlpha = SC_ALPHA_NOALPHA; + vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA; + vsPrint.whitespaceColours.back.isSet = false; + vsPrint.whitespaceColours.fore.isSet = false; + vsPrint.showCaretLineBackground = false; + vsPrint.alwaysShowCaretLineBackground = false; + // Don't highlight matching braces using indicators + vsPrint.braceHighlightIndicatorSet = false; + vsPrint.braceBadLightIndicatorSet = false; + + // Set colours for printing according to users settings + for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) { + if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) { + vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); + vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); + } else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) { + vsPrint.styles[sty].fore = ColourDesired(0, 0, 0); + vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); + } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) { + vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); + } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { + if (sty <= STYLE_DEFAULT) { + vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); + } + } + } + // White background for the line numbers + vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff); + + // Printing uses different margins, so reset screen margins + vsPrint.leftMarginWidth = 0; + vsPrint.rightMarginWidth = 0; + + vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); + // Determining width must happen after fonts have been realised in Refresh + int lineNumberWidth = 0; + if (lineNumberIndex >= 0) { + lineNumberWidth = static_cast(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, + "99999" lineNumberPrintSpace, 5 + static_cast(strlen(lineNumberPrintSpace)))); + vsPrint.ms[lineNumberIndex].width = lineNumberWidth; + vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); // Recalculate fixedColumnWidth + } + + int linePrintStart = model.pdoc->LineFromPosition(static_cast(pfr->chrg.cpMin)); + int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1; + if (linePrintLast < linePrintStart) + linePrintLast = linePrintStart; + int linePrintMax = model.pdoc->LineFromPosition(static_cast(pfr->chrg.cpMax)); + 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 = model.pdoc->Length(); + if (linePrintLast < model.pdoc->LinesTotal()) + endPosPrint = model.pdoc->LineStart(linePrintLast + 1); + + // Ensure we are styled to where we are formatting. + model.pdoc->EnsureStyledTo(endPosPrint); + + int xStart = vsPrint.fixedColumnWidth + pfr->rc.left; + int ypos = pfr->rc.top; + + int lineDoc = linePrintStart; + + int nPrintPos = static_cast(pfr->chrg.cpMin); + int visibleLine = 0; + int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; + if (printParameters.wrapState == eWrapNone) + widthPrint = LineLayout::wrapWidthInfinite; + + while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) { + + // When printing, the hdc and hdcTarget may be the same, so + // changing the state of surfaceMeasure may change the underlying + // state of surface. Therefore, any cached state is discarded before + // using each surface. + surfaceMeasure->FlushCachedState(); + + // Copy this line and its styles from the document into local arrays + // and determine the x position at which each character starts. + LineLayout ll(model.pdoc->LineStart(lineDoc + 1) - model.pdoc->LineStart(lineDoc) + 1); + LayoutLine(model, lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint); + + ll.containsCaret = false; + + PRectangle rcLine = PRectangle::FromInts( + pfr->rc.left, + ypos, + pfr->rc.right - 1, + ypos + vsPrint.lineHeight); + + // When document line is wrapped over multiple display lines, find where + // to start printing from to ensure a particular position is on the first + // line of the page. + if (visibleLine == 0) { + int startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc); + for (int iwl = 0; iwl < ll.lines - 1; iwl++) { + if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) { + visibleLine = -iwl; + } + } + + if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) { + visibleLine = -(ll.lines - 1); + } + } + + if (draw && lineNumberWidth && + (ypos + vsPrint.lineHeight <= pfr->rc.bottom) && + (visibleLine >= 0)) { + char number[100]; + sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1); + PRectangle rcNumber = rcLine; + rcNumber.right = rcNumber.left + lineNumberWidth; + // Right justify + rcNumber.left = rcNumber.right - surfaceMeasure->WidthText( + vsPrint.styles[STYLE_LINENUMBER].font, number, static_cast(strlen(number))); + surface->FlushCachedState(); + surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, + static_cast(ypos + vsPrint.maxAscent), number, static_cast(strlen(number)), + vsPrint.styles[STYLE_LINENUMBER].fore, + vsPrint.styles[STYLE_LINENUMBER].back); + } + + // Draw the line + surface->FlushCachedState(); + + for (int iwl = 0; iwl < ll.lines; iwl++) { + if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) { + if (visibleLine >= 0) { + if (draw) { + rcLine.top = static_cast(ypos); + rcLine.bottom = static_cast(ypos + vsPrint.lineHeight); + DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xStart, rcLine, iwl, drawAll); + } + ypos += vsPrint.lineHeight; + } + visibleLine++; + if (iwl == ll.lines - 1) + nPrintPos = model.pdoc->LineStart(lineDoc + 1); + else + nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl); + } + } + + ++lineDoc; + } + + // Clear cache so measurements are not used for screen + posCache.Clear(); + + return nPrintPos; +} diff --git a/src/stc/scintilla/src/EditView.h b/src/stc/scintilla/src/EditView.h new file mode 100644 index 0000000000..79a88657ae --- /dev/null +++ b/src/stc/scintilla/src/EditView.h @@ -0,0 +1,174 @@ +// Scintilla source code edit control +/** @file EditView.h + ** Defines the appearance of the main text area of the editor window. + **/ +// Copyright 1998-2014 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef EDITVIEW_H +#define EDITVIEW_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +struct PrintParameters { + int magnification; + int colourMode; + WrapMode wrapState; + PrintParameters(); +}; + +/** +* The view may be drawn in separate phases. +*/ +enum DrawPhase { + drawBack = 0x1, + drawIndicatorsBack = 0x2, + drawText = 0x4, + drawIndentationGuides = 0x8, + drawIndicatorsFore = 0x10, + drawSelectionTranslucent = 0x20, + drawLineTranslucent = 0x40, + drawFoldLines = 0x80, + drawCarets = 0x100, + drawAll = 0x1FF +}; + +bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st); +int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st); +void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, + const char *s, int len, DrawPhase phase); +void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, + const StyledText &st, size_t start, size_t length, DrawPhase phase); + +typedef void (*DrawTabArrowFn)(Surface *surface, PRectangle rcTab, int ymid); + +/** +* EditView draws the main text area. +*/ +class EditView { +public: + PrintParameters printParameters; + PerLine *ldTabstops; + int tabWidthMinimumPixels; + + bool hideSelection; + bool drawOverstrikeCaret; + + /** 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; + /** In phasesTwo mode, drawing is performed in two phases, first the background + * and then the foreground. This avoids chopping off characters that overlap the next run. + * In multiPhaseDraw mode, drawing is performed in multiple phases with each phase drawing + * one feature over the whole drawing area, instead of within one line. This allows text to + * overlap from one line to the next. */ + enum PhasesDraw { phasesOne, phasesTwo, phasesMultiple }; + PhasesDraw phasesDraw; + + int lineWidthMaxSeen; + + bool additionalCaretsBlink; + bool additionalCaretsVisible; + + bool imeCaretBlockOverride; + + Surface *pixmapLine; + Surface *pixmapIndentGuide; + Surface *pixmapIndentGuideHighlight; + + LineLayoutCache llc; + PositionCache posCache; + + int tabArrowHeight; // draw arrow heads this many pixels above/below line midpoint + /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native + * DrawTabArrow function for drawing tab characters. Allow those platforms to + * override it instead of creating a new method in the Surface class that + * existing platforms must implement as empty. */ + DrawTabArrowFn customDrawTabArrow; + DrawWrapMarkerFn customDrawWrapMarker; + + EditView(); + virtual ~EditView(); + + bool SetTwoPhaseDraw(bool twoPhaseDraw); + bool SetPhasesDraw(int phases); + bool LinesOverlap() const; + + void ClearAllTabstops(); + XYPOSITION NextTabstopPos(int line, XYPOSITION x, XYPOSITION tabWidth) const; + bool ClearTabstops(int line); + bool AddTabstop(int line, int x); + int GetNextTabstop(int line, int x) const; + void LinesAddedOrRemoved(int lineOfPos, int linesAdded); + + void DropGraphics(bool freeObjects); + void AllocateGraphics(const ViewStyle &vsDraw); + void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); + + LineLayout *RetrieveLineLayout(int lineNumber, const EditModel &model); + void LayoutLine(const EditModel &model, int line, Surface *surface, const ViewStyle &vstyle, + LineLayout *ll, int width = LineLayout::wrapWidthInfinite); + + Point LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine, const ViewStyle &vs); + SelectionPosition SPositionFromLocation(Surface *surface, const EditModel &model, Point pt, bool canReturnInvalid, + bool charPosition, bool virtualSpace, const ViewStyle &vs); + SelectionPosition SPositionFromLineX(Surface *surface, const EditModel &model, int lineDoc, int x, const ViewStyle &vs); + int DisplayFromPosition(Surface *surface, const EditModel &model, int pos, const ViewStyle &vs); + int StartEndDisplayLine(Surface *surface, const EditModel &model, int pos, bool start, const ViewStyle &vs); + + void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); + void DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, + int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, + ColourOptional background); + void DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase); + void DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line, + int xStart, PRectangle rcLine, int subLine) const; + void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, + Range lineRange, int posLineStart, int xStart, + int subLine, ColourOptional background) const; + void DrawForeground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int lineVisible, + PRectangle rcLine, Range lineRange, int posLineStart, int xStart, + int subLine, ColourOptional background); + void DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, + int line, int lineVisible, PRectangle rcLine, int xStart, int subLine); + void DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line, + int lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase); + void PaintText(Surface *surfaceWindow, const EditModel &model, PRectangle rcArea, PRectangle rcClient, + const ViewStyle &vsDraw); + long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, + const EditModel &model, const ViewStyle &vs); +}; + +/** +* Convenience class to ensure LineLayout objects are always disposed. +*/ +class AutoLineLayout { + LineLayoutCache &llc; + LineLayout *ll; + AutoLineLayout &operator=(const AutoLineLayout &); +public: + AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {} + ~AutoLineLayout() { + llc.Dispose(ll); + ll = 0; + } + LineLayout *operator->() const { + return ll; + } + operator LineLayout *() const { + return ll; + } + void Set(LineLayout *ll_) { + llc.Dispose(ll); + ll = ll_; + } +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/Editor.cxx b/src/stc/scintilla/src/Editor.cxx index 2075e7b5b5..77d9ce5e74 100644 --- a/src/stc/scintilla/src/Editor.cxx +++ b/src/stc/scintilla/src/Editor.cxx @@ -8,10 +8,11 @@ #include #include #include -#include -#include #include +#include +#include +#include #include #include #include @@ -29,6 +30,7 @@ #include "RunStyles.h" #include "ContractionState.h" #include "CellBuffer.h" +#include "PerLine.h" #include "KeyMap.h" #include "Indicator.h" #include "XPM.h" @@ -42,6 +44,9 @@ #include "UniConversion.h" #include "Selection.h" #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" #include "Editor.h" #ifdef SCI_NAMESPACE @@ -79,25 +84,13 @@ static bool IsLastStep(const DocModification &mh) { && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0; } -Caret::Caret() : - active(false), on(false), period(500) {} - Timer::Timer() : ticking(false), ticksToWait(0), tickerID(0) {} Idler::Idler() : state(false), idlerID(0) {} -static int RoundXYPosition(XYPOSITION xyPos) { - return int(xyPos+0.5); -} - -static inline bool IsControlCharacter(int ch) { - // iscntrl returns true for lots of chars > 127 which are displayable - return ch >= 0 && ch < ' '; -} - -static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) { +static inline bool IsAllSpacesOrTabs(const char *s, unsigned int len) { for (unsigned int i = 0; i < len; i++) { // This is safe because IsSpaceOrTab() will return false for null terminators if (!IsSpaceOrTab(s[i])) @@ -106,32 +99,21 @@ static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) { return true; } -PrintParameters::PrintParameters() { - magnification = 0; - colourMode = SC_PRINT_NORMAL; - wrapState = eWrapWord; -} - Editor::Editor() { ctrlID = 0; stylesValid = false; technology = SC_TECHNOLOGY_DEFAULT; - scaleRGBAImage = 100; + scaleRGBAImage = 100.0f; cursorMode = SC_CURSORNORMAL; hasFocus = false; - hideSelection = false; - inOverstrike = false; - drawOverstrikeCaret = true; errorStatus = 0; mouseDownCaptures = true; - bufferedDraw = true; - twoPhaseDraw = true; - lastClickTime = 0; + doubleClickCloseThreshold = Point(3, 3); dwellDelay = SC_TIME_FOREVER; ticksToDwell = SC_TIME_FOREVER; dwelling = false; @@ -139,7 +121,6 @@ Editor::Editor() { ptMouseLast.y = 0; inDragDrop = ddNone; dropWentOutside = false; - posDrag = SelectionPosition(invalidPosition); posDrop = SelectionPosition(invalidPosition); hotSpotClickPos = INVALID_POSITION; selectionType = selChar; @@ -151,8 +132,6 @@ Editor::Editor() { wordSelectAnchorEndPos = 0; wordSelectInitialCaretPos = -1; - primarySelection = true; - caretXPolicy = CARET_SLOP | CARET_EVEN; caretXSlop = 50; @@ -164,12 +143,9 @@ Editor::Editor() { searchAnchor = 0; - xOffset = 0; xCaretMargin = 50; horizontalScrollBarVisible = true; scrollWidth = 2000; - trackLineWidth = false; - lineWidthMaxSeen = 0; verticalScrollBarVisible = true; endAtLastLine = true; caretSticky = SC_CARETSTICKY_OFF; @@ -178,17 +154,8 @@ Editor::Editor() { multipleSelection = false; additionalSelectionTyping = false; multiPasteMode = SC_MULTIPASTE_ONCE; - additionalCaretsBlink = true; - additionalCaretsVisible = true; virtualSpaceOptions = SCVS_NONE; - pixmapLine = 0; - pixmapSelMargin = 0; - pixmapSelPattern = 0; - pixmapSelPatternOffset1 = 0; - pixmapIndentGuide = 0; - pixmapIndentGuideHighlight = 0; - targetStart = 0; targetEnd = 0; searchFlags = 0; @@ -200,10 +167,6 @@ Editor::Editor() { needUpdateUI = 0; ContainerNeedsUpdate(SC_UPDATE_CONTENT); - braces[0] = invalidPosition; - braces[1] = invalidPosition; - bracesMatchStyle = STYLE_BRACEBAD; - highlightGuideColumn = 0; paintState = notPainting; paintAbandonedByStyling = false; @@ -212,31 +175,18 @@ Editor::Editor() { modEventMask = SC_MODEVENTMASKALL; - pdoc = new Document(); - pdoc->AddRef(); pdoc->AddWatcher(this, 0); recordingMacro = false; - foldFlags = 0; foldAutomatic = 0; - wrapWidth = LineLayout::wrapWidthInfinite; - convertPastes = true; - hsStart = -1; - hsEnd = -1; - - llc.SetLevel(LineLayoutCache::llcCaret); - posCache.SetSize(0x400); - SetRepresentations(); } Editor::~Editor() { pdoc->RemoveWatcher(this, 0); - pdoc->Release(); - pdoc = 0; DropGraphics(true); } @@ -289,48 +239,13 @@ void Editor::SetRepresentations() { } void Editor::DropGraphics(bool freeObjects) { - if (freeObjects) { - delete pixmapLine; - pixmapLine = 0; - delete pixmapSelMargin; - pixmapSelMargin = 0; - delete pixmapSelPattern; - pixmapSelPattern = 0; - delete pixmapSelPatternOffset1; - pixmapSelPatternOffset1 = 0; - delete pixmapIndentGuide; - pixmapIndentGuide = 0; - delete pixmapIndentGuideHighlight; - pixmapIndentGuideHighlight = 0; - } else { - if (pixmapLine) - pixmapLine->Release(); - if (pixmapSelMargin) - pixmapSelMargin->Release(); - if (pixmapSelPattern) - pixmapSelPattern->Release(); - if (pixmapSelPatternOffset1) - pixmapSelPatternOffset1->Release(); - if (pixmapIndentGuide) - pixmapIndentGuide->Release(); - if (pixmapIndentGuideHighlight) - pixmapIndentGuideHighlight->Release(); - } + marginView.DropGraphics(freeObjects); + view.DropGraphics(freeObjects); } void Editor::AllocateGraphics() { - if (!pixmapLine) - pixmapLine = Surface::Allocate(technology); - if (!pixmapSelMargin) - pixmapSelMargin = Surface::Allocate(technology); - if (!pixmapSelPattern) - pixmapSelPattern = Surface::Allocate(technology); - if (!pixmapSelPatternOffset1) - pixmapSelPatternOffset1 = Surface::Allocate(technology); - if (!pixmapIndentGuide) - pixmapIndentGuide = Surface::Allocate(technology); - if (!pixmapIndentGuideHighlight) - pixmapIndentGuideHighlight = Surface::Allocate(technology); + marginView.AllocateGraphics(vs); + view.AllocateGraphics(vs); } void Editor::InvalidateStyleData() { @@ -338,8 +253,8 @@ void Editor::InvalidateStyleData() { vs.technology = technology; DropGraphics(false); AllocateGraphics(); - llc.Invalidate(LineLayout::llInvalid); - posCache.Clear(); + view.llc.Invalidate(LineLayout::llInvalid); + view.posCache.Clear(); } void Editor::InvalidateStyleRedraw() { @@ -360,11 +275,11 @@ void Editor::RefreshStyleData() { } } -Point Editor::GetVisibleOriginInMain() { +Point Editor::GetVisibleOriginInMain() const { return Point(0,0); } -Point Editor::DocumentPointFromView(Point ptView) { +Point Editor::DocumentPointFromView(Point ptView) const { Point ptDocument = ptView; if (wMargin.GetID()) { Point ptOrigin = GetVisibleOriginInMain(); @@ -384,29 +299,30 @@ int Editor::TopLineOfMain() const { return topLine; } -PRectangle Editor::GetClientRectangle() { - return wMain.GetClientPosition(); +PRectangle Editor::GetClientRectangle() const { + Window &win = const_cast(wMain); + return win.GetClientPosition(); } PRectangle Editor::GetClientDrawingRectangle() { return GetClientRectangle(); } -PRectangle Editor::GetTextRectangle() { +PRectangle Editor::GetTextRectangle() const { PRectangle rc = GetClientRectangle(); rc.left += vs.textStart; rc.right -= vs.rightMarginWidth; return rc; } -int Editor::LinesOnScreen() { +int Editor::LinesOnScreen() const { PRectangle rcClient = GetClientRectangle(); - int htClient = rcClient.bottom - rcClient.top; + int htClient = static_cast(rcClient.bottom - rcClient.top); //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1); return htClient / vs.lineHeight; } -int Editor::LinesToScroll() { +int Editor::LinesToScroll() const { int retVal = LinesOnScreen() - 1; if (retVal < 1) return 1; @@ -414,7 +330,7 @@ int Editor::LinesToScroll() { return retVal; } -int Editor::MaxScrollPos() { +int Editor::MaxScrollPos() const { //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n", //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1); int retVal = cs.LinesDisplayed(); @@ -430,45 +346,6 @@ int Editor::MaxScrollPos() { } } -const char *ControlCharacterString(unsigned 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 < ELEMENTS(reps)) { - return reps[ch]; - } else { - return "BAD"; - } -} - -/** - * Convenience class to ensure LineLayout objects are always disposed. - */ -class AutoLineLayout { - LineLayoutCache &llc; - LineLayout *ll; - AutoLineLayout &operator=(const AutoLineLayout &); -public: - AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {} - ~AutoLineLayout() { - llc.Dispose(ll); - ll = 0; - } - LineLayout *operator->() const { - return ll; - } - operator LineLayout *() const { - return ll; - } - void Set(LineLayout *ll_) { - llc.Dispose(ll); - ll = ll_; - } -}; - SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const { if (sp.Position() < 0) { return SelectionPosition(0); @@ -483,25 +360,9 @@ SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const } Point Editor::LocationFromPosition(SelectionPosition pos) { - Point pt; RefreshStyleData(); - if (pos.Position() == INVALID_POSITION) - return pt; - const int line = pdoc->LineFromPosition(pos.Position()); - const int lineVisible = cs.DisplayFromDoc(line); - //Platform::DebugPrintf("line=%d\n", line); AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(line)); - if (surface && ll) { - const int posLineStart = pdoc->LineStart(line); - LayoutLine(line, surface, vs, ll, wrapWidth); - const int posInLine = pos.Position() - posLineStart; - pt = ll->PointFromPosition(posInLine, vs.lineHeight); - pt.y += (lineVisible - topLine) * vs.lineHeight; - pt.x += vs.textStart - xOffset; - } - pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; - return pt; + return view.LocationFromPosition(surface, *this, pos, topLine, vs); } Point Editor::LocationFromPosition(int pos) { @@ -510,28 +371,18 @@ Point Editor::LocationFromPosition(int pos) { int Editor::XFromPosition(int pos) { Point pt = LocationFromPosition(pos); - return pt.x - vs.textStart + xOffset; + return static_cast(pt.x) - vs.textStart + xOffset; } int Editor::XFromPosition(SelectionPosition sp) { Point pt = LocationFromPosition(sp); - return pt.x - vs.textStart + xOffset; -} - -int Editor::LineFromLocation(Point pt) const { - return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine); -} - -void Editor::SetTopLine(int topLineNew) { - if ((topLine != topLineNew) && (topLineNew >= 0)) { - topLine = topLineNew; - ContainerNeedsUpdate(SC_UPDATE_V_SCROLL); - } - posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine)); + return static_cast(pt.x) - vs.textStart + xOffset; } SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) { RefreshStyleData(); + AutoSurface surface(this); + if (canReturnInvalid) { PRectangle rcClient = GetTextRectangle(); // May be in scroll view coordinates so translate back to main view @@ -545,48 +396,7 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, return SelectionPosition(INVALID_POSITION); } pt = DocumentPointFromView(pt); - pt.x = pt.x - vs.textStart; - int visibleLine = floor(pt.y / vs.lineHeight); - if (!canReturnInvalid && (visibleLine < 0)) - visibleLine = 0; - const int lineDoc = cs.DocFromDisplay(visibleLine); - if (canReturnInvalid && (lineDoc < 0)) - return SelectionPosition(INVALID_POSITION); - if (lineDoc >= pdoc->LinesTotal()) - return SelectionPosition(canReturnInvalid ? INVALID_POSITION : pdoc->Length()); - const int posLineStart = pdoc->LineStart(lineDoc); - AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc)); - if (surface && ll) { - LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - const int lineStartSet = cs.DisplayFromDoc(lineDoc); - const int subLine = visibleLine - lineStartSet; - if (subLine < ll->lines) { - const Range rangeSubLine = ll->SubLineRange(subLine); - const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; - if (subLine > 0) // Wrapped - pt.x -= ll->wrapIndent; - const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition); - if (positionInLine < rangeSubLine.end) { - return SelectionPosition(pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); - } - if (virtualSpace) { - const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; - const int spaceOffset = (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / - spaceWidth; - return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); - } else if (canReturnInvalid) { - if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) { - return SelectionPosition(pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1)); - } - } else { - return SelectionPosition(rangeSubLine.end + posLineStart); - } - } - if (!canReturnInvalid) - return SelectionPosition(ll->numCharsInLine + posLineStart); - } - return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart); + return view.SPositionFromLocation(surface, *this, pt, canReturnInvalid, charPosition, virtualSpace, vs); } int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) { @@ -594,37 +404,35 @@ int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosit } /** - * Find the document position corresponding to an x coordinate on a particular document line. - * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. - * This method is used for rectangular selections and does not work on wrapped lines. - */ +* Find the document position corresponding to an x coordinate on a particular document line. +* Ensure is between whole characters when document is in multi-byte or UTF-8 mode. +* This method is used for rectangular selections and does not work on wrapped lines. +*/ SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) { RefreshStyleData(); if (lineDoc >= pdoc->LinesTotal()) return SelectionPosition(pdoc->Length()); //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc)); - if (surface && ll) { - const int posLineStart = pdoc->LineStart(lineDoc); - LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - const Range rangeSubLine = ll->SubLineRange(0); - const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; - const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false); - if (positionInLine < rangeSubLine.end) { - return SelectionPosition(pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); - } - const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; - const int spaceOffset = (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth; - return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); - } - return SelectionPosition(0); + return view.SPositionFromLineX(surface, *this, lineDoc, x, vs); } int Editor::PositionFromLineX(int lineDoc, int x) { return SPositionFromLineX(lineDoc, x).Position(); } +int Editor::LineFromLocation(Point pt) const { + return cs.DocFromDisplay(static_cast(pt.y) / vs.lineHeight + topLine); +} + +void Editor::SetTopLine(int topLineNew) { + if ((topLine != topLineNew) && (topLineNew >= 0)) { + topLine = topLineNew; + ContainerNeedsUpdate(SC_UPDATE_V_SCROLL); + } + posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine)); +} + /** * If painting then abandon the painting because a wider redraw is needed. * @return true if calling code should stop drawing. @@ -679,8 +487,7 @@ void Editor::RedrawSelMargin(int line, bool allAfter) { PRectangle rcSelMargin = GetClientRectangle(); rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth; if (line != -1) { - int position = pdoc->LineStart(line); - PRectangle rcLine = RectangleFromRange(position, position); + PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line)), 0); // Inflate line rectangle if there are image markers with height larger than line height if (vs.largestMarkerHeight > vs.lineHeight) { @@ -710,31 +517,25 @@ void Editor::RedrawSelMargin(int line, bool allAfter) { } } -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 lineDocMax = pdoc->LineFromPosition(maxPos); - int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1; - PRectangle rcClient = GetTextRectangle(); +PRectangle Editor::RectangleFromRange(Range r, int overlap) { + const int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(r.First())); + const int maxLine = cs.DisplayLastFromDoc(pdoc->LineFromPosition(r.Last())); + const PRectangle rcClientDrawing = GetClientDrawingRectangle(); PRectangle rc; const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0; - rc.left = vs.textStart - leftTextOverlap; - rc.top = (minLine - TopLineOfMain()) * vs.lineHeight; - if (rc.top < rcClient.top) - rc.top = rcClient.top; - rc.right = rcClient.right; - rc.bottom = (maxLine - TopLineOfMain() + 1) * vs.lineHeight; + rc.left = static_cast(vs.textStart - leftTextOverlap); + rc.top = static_cast((minLine - TopLineOfMain()) * vs.lineHeight - overlap); + if (rc.top < rcClientDrawing.top) + rc.top = rcClientDrawing.top; + // Extend to right of prepared area if any to prevent artifacts from caret line highlight + rc.right = rcClientDrawing.right; + rc.bottom = static_cast((maxLine - TopLineOfMain() + 1) * vs.lineHeight + overlap); return rc; } void Editor::InvalidateRange(int start, int end) { - RedrawRect(RectangleFromRange(start, end)); + RedrawRect(RectangleFromRange(Range(start, end), view.LinesOverlap() ? vs.lineOverlap : 0)); } int Editor::CurrentPosition() const { @@ -829,8 +630,9 @@ void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition ancho sel.RangeMain() = rangeNew; SetRectangularRange(); ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); - if (highlightDelimiter.NeedsDrawing(currentLine)) { + if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); } QueueIdleWork(WorkNeeded::workUpdateUI); @@ -856,8 +658,9 @@ void Editor::SetSelection(SelectionPosition currentPos_) { SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor); } ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); - if (highlightDelimiter.NeedsDrawing(currentLine)) { + if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); } QueueIdleWork(WorkNeeded::workUpdateUI); @@ -877,8 +680,9 @@ void Editor::SetEmptySelection(SelectionPosition currentPos_) { sel.RangeMain() = rangeNew; SetRectangularRange(); ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); - if (highlightDelimiter.NeedsDrawing(currentLine)) { + if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); } QueueIdleWork(WorkNeeded::workUpdateUI); @@ -895,9 +699,8 @@ bool Editor::RangeContainsProtected(int start, int end) const { start = end; end = t; } - int mask = pdoc->stylingBitsMask; for (int pos = start; pos < end; pos++) { - if (vs.styles[pdoc->StyleAt(pos) & mask].IsProtected()) + if (vs.styles[pdoc->StyleAt(pos)].IsProtected()) return true; } } @@ -926,17 +729,16 @@ SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int mov if (posMoved != pos.Position()) pos.SetPosition(posMoved); if (vs.ProtectionActive()) { - int mask = pdoc->stylingBitsMask; if (moveDir > 0) { - if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()) { + if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1)].IsProtected()) { while ((pos.Position() < pdoc->Length()) && - (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected())) + (vs.styles[pdoc->StyleAt(pos.Position())].IsProtected())) pos.Add(1); } } else if (moveDir < 0) { - if (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()) { + if (vs.styles[pdoc->StyleAt(pos.Position())].IsProtected()) { while ((pos.Position() > 0) && - (vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected())) + (vs.styles[pdoc->StyleAt(pos.Position() - 1)].IsProtected())) pos.Add(-1); } } @@ -990,7 +792,7 @@ int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, b } } - if (highlightDelimiter.NeedsDrawing(currentLine)) { + if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); } return 0; @@ -1033,7 +835,7 @@ Point Editor::PointMainCaret() { */ void Editor::SetLastXChosen() { Point pt = PointMainCaret(); - lastXChosen = pt.x + xOffset; + lastXChosen = static_cast(pt.x) + xOffset; } void Editor::ScrollTo(int line, bool moveThumb) { @@ -1096,7 +898,7 @@ void Editor::VerticalCentreCaret() { // Avoid 64 bit compiler warnings. // Scintilla does not support text buffers larger than 2**31 static int istrlen(const char *s) { - return static_cast(strlen(s)); + return static_cast(s ? strlen(s) : 0); } void Editor::MoveSelectedLines(int lineDelta) { @@ -1150,13 +952,13 @@ void Editor::MoveSelectedLines(int lineDelta) { const char *eol = StringFromEOLMode(pdoc->eolMode); if (currentLine + lineDelta >= pdoc->LinesTotal()) - pdoc->InsertCString(pdoc->Length(), eol); + pdoc->InsertString(pdoc->Length(), eol, istrlen(eol)); GoToLine(currentLine + lineDelta); - pdoc->InsertCString(CurrentPosition(), selectedText.Data()); + selectionLength = pdoc->InsertString(CurrentPosition(), selectedText.Data(), selectionLength); if (appendEol) { - pdoc->InsertCString(CurrentPosition() + selectionLength, eol); - selectionLength += istrlen(eol); + const int lengthInserted = pdoc->InsertString(CurrentPosition() + selectionLength, eol, istrlen(eol)); + selectionLength += lengthInserted; } SetSelection(CurrentPosition(), CurrentPosition() + selectionLength); } @@ -1174,35 +976,21 @@ void Editor::MoveCaretInsideView(bool ensureVisible) { Point pt = PointMainCaret(); if (pt.y < rcClient.top) { MovePositionTo(SPositionFromLocation( - Point(lastXChosen - xOffset, rcClient.top), + Point::FromInts(lastXChosen - xOffset, static_cast(rcClient.top)), false, false, UserVirtualSpace()), Selection::noSel, ensureVisible); } else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) { - int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight; + int yOfLastLineFullyDisplayed = static_cast(rcClient.top) + (LinesOnScreen() - 1) * vs.lineHeight; MovePositionTo(SPositionFromLocation( - Point(lastXChosen - xOffset, rcClient.top + yOfLastLineFullyDisplayed), + Point::FromInts(lastXChosen - xOffset, static_cast(rcClient.top) + yOfLastLineFullyDisplayed), false, false, UserVirtualSpace()), Selection::noSel, ensureVisible); } } int Editor::DisplayFromPosition(int pos) { - int lineDoc = pdoc->LineFromPosition(pos); - int lineDisplay = cs.DisplayFromDoc(lineDoc); AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc)); - if (surface && ll) { - LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - unsigned int posLineStart = pdoc->LineStart(lineDoc); - int posInLine = pos - posLineStart; - lineDisplay--; // To make up for first increment ahead. - for (int subLine = 0; subLine < ll->lines; subLine++) { - if (posInLine >= ll->LineStart(subLine)) { - lineDisplay++; - } - } - } - return lineDisplay; + return view.DisplayFromPosition(surface, *this, pos, vs); } /** @@ -1229,7 +1017,7 @@ so the caret can move in the same direction longer before the policy is applied If even is not set, instead of having symmetrical UZs, the left and bottom UZs are extended up to right and top UZs respectively. -This way, we favour the displaying of useful information: the begining of lines, +This way, we favour the displaying of useful information: the beginning of lines, where most code reside, and the lines after the caret, eg. the body of a function. | | | | | @@ -1370,7 +1158,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran // Horizontal positioning if ((options & xysHorizontal) && !Wrapping()) { - const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2; + const int halfScreen = Platform::Maximum(static_cast(rcClient.Width()) - 4, 4) / 2; const bool bSlop = (caretXPolicy & CARET_SLOP) != 0; const bool bStrict = (caretXPolicy & CARET_STRICT) != 0; const bool bJump = (caretXPolicy & CARET_JUMPS) != 0; @@ -1391,7 +1179,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran if (bEven) { xMarginL = xMarginR; } else { - xMarginL = rcClient.Width() - xMarginR - 4; + xMarginL = static_cast(rcClient.Width()) - xMarginR - 4; } } if (bJump && bEven) { @@ -1406,7 +1194,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran newXY.xOffset -= xMoveL; } else { // Move just enough to allow to display the caret - newXY.xOffset -= (rcClient.left + xMarginL) - pt.x; + newXY.xOffset -= static_cast((rcClient.left + xMarginL) - pt.x); } } else if (pt.x >= rcClient.right - xMarginR) { // Caret is on the right of the display @@ -1414,7 +1202,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran newXY.xOffset += xMoveR; } else { // Move just enough to allow to display the caret - newXY.xOffset += pt.x - (rcClient.right - xMarginR) + 1; + newXY.xOffset += static_cast(pt.x - (rcClient.right - xMarginR) + 1); } } } else { // Not strict @@ -1423,7 +1211,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran if (bEven) { xMoveL = xMoveR; } else { - xMoveL = rcClient.Width() - xMoveR - 4; + xMoveL = static_cast(rcClient.Width()) - xMoveR - 4; } if (pt.x < rcClient.left) { // Caret is on the left of the display @@ -1439,32 +1227,32 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran // Strict or going out of display if (bEven) { // Center caret - newXY.xOffset += pt.x - rcClient.left - halfScreen; + newXY.xOffset += static_cast(pt.x - rcClient.left - halfScreen); } else { // Put caret on right - newXY.xOffset += pt.x - rcClient.right + 1; + newXY.xOffset += static_cast(pt.x - rcClient.right + 1); } } else { // Move just enough to allow to display the caret if (pt.x < rcClient.left) { // Caret is on the left of the display if (bEven) { - newXY.xOffset -= rcClient.left - pt.x; + newXY.xOffset -= static_cast(rcClient.left - pt.x); } else { - newXY.xOffset += pt.x - rcClient.right + 1; + newXY.xOffset += static_cast(pt.x - rcClient.right) + 1; } } else if (pt.x >= rcClient.right) { // Caret is on the right of the display - newXY.xOffset += pt.x - rcClient.right + 1; + newXY.xOffset += static_cast(pt.x - rcClient.right) + 1; } } } // In case of a jump (find result) largely out of display, adjust the offset to display the caret if (pt.x + xOffset < rcClient.left + newXY.xOffset) { - newXY.xOffset = pt.x + xOffset - rcClient.left - 2; + newXY.xOffset = static_cast(pt.x + xOffset - rcClient.left) - 2; } else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) { - newXY.xOffset = pt.x + xOffset - rcClient.right + 2; - if (vs.caretStyle == CARETSTYLE_BLOCK) { + newXY.xOffset = static_cast(pt.x + xOffset - rcClient.right) + 2; + if ((vs.caretStyle == CARETSTYLE_BLOCK) || view.imeCaretBlockOverride) { // Ensure we can see a good portion of the block caret newXY.xOffset += static_cast(vs.aveCharWidth); } @@ -1472,14 +1260,14 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &ran if (!(range.caret == range.anchor)) { if (ptAnchor.x < pt.x) { // Shift to left to show anchor or as much of range as possible - int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1; - int minOffset = pt.x + xOffset - rcClient.right + 1; + int maxOffset = static_cast(ptAnchor.x + xOffset - rcClient.left) - 1; + int minOffset = static_cast(pt.x + xOffset - rcClient.right) + 1; newXY.xOffset = std::min(newXY.xOffset, maxOffset); newXY.xOffset = std::max(newXY.xOffset, minOffset); } else { // Shift to right to show anchor or as much of range as possible - int minOffset = ptAnchor.x + xOffset - rcClient.right + 1; - int maxOffset = pt.x + xOffset - rcClient.left - 1; + int minOffset = static_cast(ptAnchor.x + xOffset - rcClient.right) + 1; + int maxOffset = static_cast(pt.x + xOffset - rcClient.left) - 1; newXY.xOffset = std::max(newXY.xOffset, minOffset); newXY.xOffset = std::min(newXY.xOffset, maxOffset); } @@ -1505,7 +1293,7 @@ void Editor::SetXYScroll(XYScrollPosition newXY) { PRectangle rcText = GetTextRectangle(); if (horizontalScrollBarVisible && rcText.Width() + xOffset > scrollWidth) { - scrollWidth = xOffset + rcText.Width(); + scrollWidth = xOffset + static_cast(rcText.Width()); SetScrollBars(); } } @@ -1529,19 +1317,44 @@ void Editor::ShowCaretAtCurrentPosition() { if (hasFocus) { caret.active = true; caret.on = true; - SetTicking(true); + if (FineTickerAvailable()) { + FineTickerCancel(tickCaret); + if (caret.period > 0) + FineTickerStart(tickCaret, caret.period, caret.period/10); + } else { + SetTicking(true); + } } else { caret.active = false; caret.on = false; + if (FineTickerAvailable()) { + FineTickerCancel(tickCaret); + } } InvalidateCaret(); } void Editor::DropCaret() { caret.active = false; + if (FineTickerAvailable()) { + FineTickerCancel(tickCaret); + } InvalidateCaret(); } +void Editor::CaretSetPeriod(int period) { + if (caret.period != period) { + caret.period = period; + caret.on = true; + if (FineTickerAvailable()) { + FineTickerCancel(tickCaret); + if ((caret.active) && (caret.period > 0)) + FineTickerStart(tickCaret, caret.period, caret.period/10); + } + InvalidateCaret(); + } +} + void Editor::InvalidateCaret() { if (posDrag.IsValid()) { InvalidateRange(posDrag.Position(), posDrag.Position() + 1); @@ -1563,7 +1376,7 @@ bool Editor::Wrapping() const { void Editor::NeedWrapping(int docLineStart, int docLineEnd) { //Platform::DebugPrintf("\nNeedWrapping: %0d..%0d\n", docLineStart, docLineEnd); if (wrapPending.AddRange(docLineStart, docLineEnd)) { - llc.Invalidate(LineLayout::llPositions); + view.llc.Invalidate(LineLayout::llPositions); } // Wrap lines during idle. if (Wrapping() && wrapPending.NeedsWrap()) { @@ -1572,10 +1385,10 @@ void Editor::NeedWrapping(int docLineStart, int docLineEnd) { } bool Editor::WrapOneLine(Surface *surface, int lineToWrap) { - AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap)); + AutoLineLayout ll(view.llc, view.RetrieveLineLayout(lineToWrap, *this)); int linesWrapped = 1; if (ll) { - LayoutLine(lineToWrap, surface, vs, ll, wrapWidth); + view.LayoutLine(*this, lineToWrap, surface, vs, ll, wrapWidth); linesWrapped = ll->lines; } return cs.SetHeight(lineToWrap, linesWrapped + @@ -1641,9 +1454,9 @@ bool Editor::WrapLines(enum wrapScope ws) { if (lineToWrap < lineToWrapEnd) { PRectangle rcTextArea = GetClientRectangle(); - rcTextArea.left = vs.textStart; + rcTextArea.left = static_cast(vs.textStart); rcTextArea.right -= vs.rightMarginWidth; - wrapWidth = rcTextArea.Width(); + wrapWidth = static_cast(rcTextArea.Width()); RefreshStyleData(); AutoSurface surface(this); if (surface) { @@ -1686,8 +1499,8 @@ void Editor::LinesJoin() { pdoc->DelChar(pos); if (prevNonWS) { // Ensure at least one space separating previous lines - pdoc->InsertChar(pos, ' '); - targetEnd++; + const int lengthInserted = pdoc->InsertString(pos, " ", 1); + targetEnd += lengthInserted; } } else { prevNonWS = pdoc->CharAt(pos) != ' '; @@ -1710,7 +1523,7 @@ void Editor::LinesSplit(int pixelWidth) { if (!RangeContainsProtected(targetStart, targetEnd)) { if (pixelWidth == 0) { PRectangle rcText = GetTextRectangle(); - pixelWidth = rcText.Width(); + pixelWidth = static_cast(rcText.Width()); } int lineStart = pdoc->LineFromPosition(targetStart); int lineEnd = pdoc->LineFromPosition(targetEnd); @@ -1718,16 +1531,18 @@ void Editor::LinesSplit(int pixelWidth) { UndoGroup ug(pdoc); for (int line = lineStart; line <= lineEnd; line++) { AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(line)); + AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this)); if (surface && ll) { unsigned int posLineStart = pdoc->LineStart(line); - LayoutLine(line, surface, vs, ll, pixelWidth); + view.LayoutLine(*this, line, surface, vs, ll, pixelWidth); + int lengthInsertedTotal = 0; for (int subLine = 1; subLine < ll->lines; subLine++) { - pdoc->InsertCString( - static_cast(posLineStart + (subLine - 1) * strlen(eol) + + const int lengthInserted = pdoc->InsertString( + static_cast(posLineStart + lengthInsertedTotal + ll->LineStart(subLine)), - eol); - targetEnd += static_cast(strlen(eol)); + eol, istrlen(eol)); + targetEnd += lengthInserted; + lengthInsertedTotal += lengthInserted; } } lineEnd = pdoc->LineFromPosition(targetEnd); @@ -1735,95 +1550,6 @@ void Editor::LinesSplit(int pixelWidth) { } } -int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) const { - if (vs.markers[markerCheck].markType == SC_MARK_EMPTY) - return markerDefault; - return markerCheck; -} - -bool ValidStyledText(ViewStyle &vs, size_t styleOffset, const StyledText &st) { - if (st.multipleStyles) { - for (size_t iStyle=0; iStyle(styles[endSegment+1]) == style)) - endSegment++; - width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, - static_cast(endSegment - start + 1)); - start = endSegment + 1; - } - return width; -} - -static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, const StyledText &st) { - int widthMax = 0; - size_t start = 0; - while (start < st.length) { - size_t lenLine = st.LineLength(start); - int widthSubLine; - if (st.multipleStyles) { - widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); - } else { - widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font, - st.text + start, static_cast(lenLine)); - } - if (widthSubLine > widthMax) - widthMax = widthSubLine; - start += lenLine + 1; - } - return widthMax; -} - -void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent, - const StyledText &st, size_t start, size_t length) { - - if (st.multipleStyles) { - int x = rcText.left; - size_t i = 0; - while (i < length) { - size_t end = i; - int style = st.styles[i + start]; - while (end < length-1 && st.styles[start+end+1] == style) - end++; - style += styleOffset; - int width = surface->WidthText(vs.styles[style].font, - st.text + start + i, static_cast(end - i + 1)); - PRectangle rcSegment = rcText; - rcSegment.left = x; - rcSegment.right = x + width + 1; - surface->DrawTextNoClip(rcSegment, vs.styles[style].font, - ascent, st.text + start + i, - static_cast(end - i + 1), - vs.styles[style].fore, - vs.styles[style].back); - x += width; - i = end + 1; - } - } else { - size_t style = st.style + styleOffset; - surface->DrawTextNoClip(rcText, vs.styles[style].font, - rcText.top + vs.maxAscent, st.text + start, - static_cast(length), - vs.styles[style].fore, - vs.styles[style].back); - } -} - void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { if (vs.fixedColumnWidth == 0) return; @@ -1832,18 +1558,25 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { RefreshStyleData(); RefreshPixMaps(surfWindow); + // On GTK+ with Ubuntu overlay scroll bars, the surface may have been finished + // at this point. The Initialised call checks for this case and sets the status + // to be bad which avoids crashes in following calls. + if (!surfWindow->Initialised()) { + return; + } + PRectangle rcMargin = GetClientRectangle(); Point ptOrigin = GetVisibleOriginInMain(); rcMargin.Move(0, -ptOrigin.y); rcMargin.left = 0; - rcMargin.right = vs.fixedColumnWidth; + rcMargin.right = static_cast(vs.fixedColumnWidth); if (!rc.Intersects(rcMargin)) return; Surface *surface; - if (bufferedDraw) { - surface = pixmapSelMargin; + if (view.bufferedDraw) { + surface = marginView.pixmapSelMargin; } else { surface = surfWindow; } @@ -1854,1643 +1587,27 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { if (rcMargin.top < rc.top) rcMargin.top = rc.top; - PRectangle rcSelMargin = rcMargin; - rcSelMargin.right = rcMargin.left; - if (rcSelMargin.bottom < rc.bottom) - rcSelMargin.bottom = rc.bottom; + marginView.PaintMargin(surface, topLine, rc, rcMargin, *this, vs); - for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { - if (vs.ms[margin].width > 0) { - - rcSelMargin.left = rcSelMargin.right; - rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width; - - if (vs.ms[margin].style != SC_MARGIN_NUMBER) { - if (vs.ms[margin].mask & SC_MASK_FOLDERS) { - // Required because of special way brush is created for selection margin - // Ensure patterns line up when scrolling with separate margin view - // by choosing correctly aligned variant. - bool invertPhase = static_cast(ptOrigin.y) & 1; - surface->FillRectangle(rcSelMargin, - invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1); - } else { - ColourDesired colour; - switch (vs.ms[margin].style) { - case SC_MARGIN_BACK: - colour = vs.styles[STYLE_DEFAULT].back; - break; - case SC_MARGIN_FORE: - colour = vs.styles[STYLE_DEFAULT].fore; - break; - default: - colour = vs.styles[STYLE_LINENUMBER].back; - break; - } - surface->FillRectangle(rcSelMargin, colour); - } - } else { - surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back); - } - - const int lineStartPaint = (rcMargin.top + ptOrigin.y) / vs.lineHeight; - int visibleLine = TopLineOfMain() + lineStartPaint; - int yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y; - // Work out whether the top line is whitespace located after a - // lessening of fold level which implies a 'fold tail' but which should not - // be displayed until the last of a sequence of whitespace. - bool needWhiteClosure = false; - if (vs.ms[margin].mask & SC_MASK_FOLDERS) { - int level = pdoc->GetLevel(cs.DocFromDisplay(visibleLine)); - if (level & SC_FOLDLEVELWHITEFLAG) { - int lineBack = cs.DocFromDisplay(visibleLine); - int levelPrev = level; - while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { - lineBack--; - levelPrev = pdoc->GetLevel(lineBack); - } - if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { - if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) - needWhiteClosure = true; - } - } - if (highlightDelimiter.isEnabled) { - int lastLine = cs.DocFromDisplay(topLine + LinesOnScreen()) + 1; - pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lastLine); - } - } - - // Old code does not know about new markers needed to distinguish all cases - int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, - SC_MARKNUM_FOLDEROPEN); - int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND, - SC_MARKNUM_FOLDER); - - while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rc.bottom) { - - PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed()); - int lineDoc = cs.DocFromDisplay(visibleLine); - PLATFORM_ASSERT(cs.GetVisible(lineDoc)); - bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc); - bool lastSubLine = visibleLine == (cs.DisplayFromDoc(lineDoc + 1) - 1); - - int marks = pdoc->GetMark(lineDoc); - if (!firstSubLine) - marks = 0; - - bool headWithTail = false; - - if (vs.ms[margin].mask & SC_MASK_FOLDERS) { - // Decide which fold indicator should be displayed - int level = pdoc->GetLevel(lineDoc); - int levelNext = pdoc->GetLevel(lineDoc + 1); - int levelNum = level & SC_FOLDLEVELNUMBERMASK; - int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; - if (level & SC_FOLDLEVELHEADERFLAG) { - if (firstSubLine) { - if (levelNum < levelNextNum) { - if (cs.GetExpanded(lineDoc)) { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDEROPEN; - else - marks |= 1 << folderOpenMid; - } else { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDER; - else - marks |= 1 << folderEnd; - } - } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } else { - if (levelNum < levelNextNum) { - if (cs.GetExpanded(lineDoc)) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } - needWhiteClosure = false; - int firstFollowupLine = cs.DocFromDisplay(cs.DisplayFromDoc(lineDoc + 1)); - int firstFollowupLineLevel = pdoc->GetLevel(firstFollowupLine); - int secondFollowupLineLevelNum = pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK; - if (!cs.GetExpanded(lineDoc)) { - if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) && - (levelNum > secondFollowupLineLevelNum)) - needWhiteClosure = true; - - if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine)) - headWithTail = true; - } - } else if (level & SC_FOLDLEVELWHITEFLAG) { - if (needWhiteClosure) { - if (levelNext & SC_FOLDLEVELWHITEFLAG) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } else if (levelNextNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; - needWhiteClosure = false; - } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; - needWhiteClosure = false; - } - } else if (levelNum > SC_FOLDLEVELBASE) { - if (levelNextNum < levelNum) { - if (levelNextNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; - } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; - } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } - } else if (levelNum > SC_FOLDLEVELBASE) { - if (levelNextNum < levelNum) { - needWhiteClosure = false; - if (levelNext & SC_FOLDLEVELWHITEFLAG) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - needWhiteClosure = true; - } else if (lastSubLine) { - if (levelNextNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; - } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; - } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } - } - - marks &= vs.ms[margin].mask; - - PRectangle rcMarker = rcSelMargin; - rcMarker.top = yposScreen; - rcMarker.bottom = yposScreen + vs.lineHeight; - if (vs.ms[margin].style == SC_MARGIN_NUMBER) { - if (firstSubLine) { - char number[100] = ""; - if (lineDoc >= 0) - sprintf(number, "%d", lineDoc + 1); - if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) { - int lev = pdoc->GetLevel(lineDoc); - sprintf(number, "%c%c %03X %03X", - (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_', - (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_', - lev & SC_FOLDLEVELNUMBERMASK, - lev >> 16 - ); - } - PRectangle rcNumber = rcMarker; - // Right justify - XYPOSITION width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number)); - XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding; - rcNumber.left = xpos; - surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font, - rcNumber.top + vs.maxAscent, number, istrlen(number), - vs.styles[STYLE_LINENUMBER].fore, - vs.styles[STYLE_LINENUMBER].back); - } else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) { - PRectangle rcWrapMarker = rcMarker; - rcWrapMarker.right -= 3; - rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth; - DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); - } - } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { - if (firstSubLine) { - const StyledText stMargin = pdoc->MarginStyledText(lineDoc); - if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { - surface->FillRectangle(rcMarker, - vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back); - if (vs.ms[margin].style == SC_MARGIN_RTEXT) { - int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin); - rcMarker.left = rcMarker.right - width - 3; - } - DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent, - stMargin, 0, stMargin.length); - } - } - } - - if (marks) { - for (int markBit = 0; (markBit < 32) && marks; markBit++) { - if (marks & 1) { - LineMarker::typeOfFold tFold = LineMarker::undefined; - if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { - if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { - tFold = LineMarker::body; - } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { - if (firstSubLine) { - tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head; - } else { - if (cs.GetExpanded(lineDoc) || headWithTail) { - tFold = LineMarker::body; - } else { - tFold = LineMarker::undefined; - } - } - } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { - tFold = LineMarker::tail; - } - } - vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font, tFold, vs.ms[margin].style); - } - marks >>= 1; - } - } - - visibleLine++; - yposScreen += vs.lineHeight; - } - } + if (view.bufferedDraw) { + surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *marginView.pixmapSelMargin); } - - PRectangle rcBlankMargin = rcMargin; - rcBlankMargin.left = rcSelMargin.right; - surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back); - - if (bufferedDraw) { - surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *pixmapSelMargin); - } -} - -void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { - int ydiff = (rcTab.bottom - rcTab.top) / 2; - int xhead = rcTab.right - 1 - ydiff; - if (xhead <= rcTab.left) { - ydiff -= rcTab.left - xhead - 1; - xhead = rcTab.left - 1; - } - 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); -} - -LineLayout *Editor::RetrieveLineLayout(int lineNumber) { - int posLineStart = pdoc->LineStart(lineNumber); - int posLineEnd = pdoc->LineStart(lineNumber + 1); - PLATFORM_ASSERT(posLineEnd >= posLineStart); - int lineCaret = pdoc->LineFromPosition(sel.MainCaret()); - return llc.Retrieve(lineNumber, lineCaret, - posLineEnd - posLineStart, pdoc->GetStyleClock(), - LinesOnScreen() + 1, pdoc->LinesTotal()); -} - -/** - * Fill in the LineLayout data for the given line. - * Copy the given @a line and its styles from the document into local arrays. - * Also determine the x position at which each character starts. - */ -void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width) { -//void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width, Document *pdoc, PositionCache &posCache, SpecialRepresentations &reprs) { - if (!ll) - return; - - PLATFORM_ASSERT(line < pdoc->LinesTotal()); - PLATFORM_ASSERT(ll->chars != NULL); - int posLineStart = pdoc->LineStart(line); - int posLineEnd = pdoc->LineStart(line + 1); - // If the line is very long, limit the treatment to a length that should fit in the viewport - if (posLineEnd > (posLineStart + ll->maxLineLength)) { - posLineEnd = posLineStart + ll->maxLineLength; - } - if (ll->validity == LineLayout::llCheckTextAndStyle) { - int lineLength = posLineEnd - posLineStart; - if (!vstyle.viewEOL) { - lineLength = pdoc->LineEnd(line) - posLineStart; - } - if (lineLength == ll->numCharsInLine) { - // See if chars, styles, indicators, are all the same - bool allSame = true; - const int styleMask = pdoc->stylingBitsMask; - // Check base line layout - char styleByte = 0; - int numCharsInLine = 0; - while (numCharsInLine < lineLength) { - int charInDoc = numCharsInLine + posLineStart; - char chDoc = pdoc->CharAt(charInDoc); - styleByte = pdoc->StyleAt(charInDoc); - allSame = allSame && - (ll->styles[numCharsInLine] == static_cast(styleByte & styleMask)); - allSame = allSame && - (ll->indicators[numCharsInLine] == static_cast(styleByte & ~styleMask)); - if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed) - allSame = allSame && - (ll->chars[numCharsInLine] == chDoc); - else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) - allSame = allSame && - (ll->chars[numCharsInLine] == static_cast(tolower(chDoc))); - else // Style::caseUpper - allSame = allSame && - (ll->chars[numCharsInLine] == static_cast(toupper(chDoc))); - numCharsInLine++; - } - allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled - if (allSame) { - ll->validity = LineLayout::llPositions; - } else { - ll->validity = LineLayout::llInvalid; - } - } else { - ll->validity = LineLayout::llInvalid; - } - } - if (ll->validity == LineLayout::llInvalid) { - ll->widthLine = LineLayout::wrapWidthInfinite; - ll->lines = 1; - if (vstyle.edgeState == EDGE_BACKGROUND) { - ll->edgeColumn = pdoc->FindColumn(line, vstyle.theEdge); - if (ll->edgeColumn >= posLineStart) { - ll->edgeColumn -= posLineStart; - } - } else { - ll->edgeColumn = -1; - } - - char styleByte; - const int styleMask = pdoc->stylingBitsMask; - ll->styleBitsSet = 0; - // Fill base line layout - const int lineLength = posLineEnd - posLineStart; - pdoc->GetCharRange(ll->chars, posLineStart, lineLength); - pdoc->GetStyleRange(ll->styles, posLineStart, lineLength); - int numCharsBeforeEOL = pdoc->LineEnd(line) - posLineStart; - const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL; - for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) { - styleByte = ll->styles[styleInLine]; - ll->styleBitsSet |= styleByte; - ll->styles[styleInLine] = static_cast(styleByte & styleMask); - ll->indicators[styleInLine] = static_cast(styleByte & ~styleMask); - } - styleByte = static_cast(((lineLength > 0) ? ll->styles[lineLength-1] : 0) & styleMask); - if (vstyle.someStylesForceCase) { - for (int charInLine = 0; charInLinechars[charInLine]; - if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper) - ll->chars[charInLine] = static_cast(toupper(chDoc)); - else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower) - ll->chars[charInLine] = static_cast(tolower(chDoc)); - } - } - ll->xHighlightGuide = 0; - // Extra element at the end of the line to hold end x position and act as - ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character - ll->styles[numCharsInLine] = styleByte; // For eolFilled - ll->indicators[numCharsInLine] = 0; - - // Layout the line, determining the position of each character, - // with an extra element at the end for the end of the line. - ll->positions[0] = 0; - bool lastSegItalics = false; - - BreakFinder bfLayout(ll, 0, numCharsInLine, posLineStart, 0, false, pdoc, &reprs); - while (bfLayout.More()) { - - const TextSegment ts = bfLayout.Next(); - - std::fill(&ll->positions[ts.start+1], &ll->positions[ts.end()+1], 0.0f); - if (vstyle.styles[ll->styles[ts.start]].visible) { - if (ts.representation) { - XYPOSITION representationWidth = vstyle.controlCharWidth; - if (ll->chars[ts.start] == '\t') { - // Tab is a special case of representation, taking a variable amount of space - representationWidth = - ((static_cast((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start]; - } else { - if (representationWidth <= 0.0) { - XYPOSITION positionsRepr[256]; // Should expand when needed - posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(), - static_cast(ts.representation->stringRep.length()), positionsRepr, pdoc); - representationWidth = positionsRepr[ts.representation->stringRep.length()-1] + vstyle.ctrlCharPadding; - } - } - for (int ii=0; ii < ts.length; ii++) - ll->positions[ts.start + 1 + ii] = representationWidth; - } else { - if ((ts.length == 1) && (' ' == ll->chars[ts.start])) { - // Over half the segments are single characters and of these about half are space characters. - ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth; - } else { - posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start, - ts.length, ll->positions + ts.start + 1, pdoc); - } - } - lastSegItalics = (!ts.representation) && ((ll->chars[ts.end()-1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic); - } - - for (int posToIncrease = ts.start+1; posToIncrease <= ts.end(); posToIncrease++) { - ll->positions[posToIncrease] += ll->positions[ts.start]; - } - } - - // Small hack to make lines that end with italics not cut off the edge of the last character - if (lastSegItalics) { - ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset; - } - ll->numCharsInLine = numCharsInLine; - ll->numCharsBeforeEOL = numCharsBeforeEOL; - ll->validity = LineLayout::llPositions; - } - // Hard to cope when too narrow, so just assume there is space - if (width < 20) { - width = 20; - } - if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) { - ll->widthLine = width; - if (width == LineLayout::wrapWidthInfinite) { - ll->lines = 1; - } else if (width > ll->positions[ll->numCharsInLine]) { - // Simple common case where line does not need wrapping. - ll->lines = 1; - } else { - if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { - width -= static_cast(vstyle.aveCharWidth); // take into account the space for end wrap mark - } - XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line - if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) { - wrapAddIndent = pdoc->IndentSize() * vstyle.spaceWidth; - } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) { - wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth; - } - ll->wrapIndent = wrapAddIndent; - if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED) - for (int i = 0; i < ll->numCharsInLine; i++) { - if (!IsSpaceOrTab(ll->chars[i])) { - ll->wrapIndent += ll->positions[i]; // Add line indent - break; - } - } - // Check for text width minimum - if (ll->wrapIndent > width - static_cast(vstyle.aveCharWidth) * 15) - ll->wrapIndent = wrapAddIndent; - // Check for wrapIndent minimum - if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth)) - ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual - ll->lines = 0; - // Calculate line start positions based upon width. - int lastGoodBreak = 0; - int lastLineStart = 0; - XYACCUMULATOR startOffset = 0; - int p = 0; - while (p < ll->numCharsInLine) { - if ((ll->positions[p + 1] - startOffset) >= width) { - if (lastGoodBreak == lastLineStart) { - // Try moving to start of last character - if (p > 0) { - lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1) - - posLineStart; - } - if (lastGoodBreak == lastLineStart) { - // Ensure at least one character on line. - lastGoodBreak = pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) - - posLineStart; - } - } - lastLineStart = lastGoodBreak; - ll->lines++; - ll->SetLineStart(ll->lines, lastGoodBreak); - startOffset = ll->positions[lastGoodBreak]; - // take into account the space for start wrap mark and indent - startOffset -= ll->wrapIndent; - p = lastGoodBreak + 1; - continue; - } - if (p > 0) { - if (vstyle.wrapState == eWrapChar) { - lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1) - - posLineStart; - p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart; - continue; - } else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) { - lastGoodBreak = p; - } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) { - lastGoodBreak = p; - } - } - p++; - } - ll->lines++; - } - ll->validity = LineLayout::llLines; - } -} - -ColourDesired Editor::SelectionBackground(ViewStyle &vsDraw, bool main) const { - return main ? - (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) : - vsDraw.selAdditionalBackground; -} - -ColourDesired Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground, - ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) const { - if (inSelection == 1) { - if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) { - return SelectionBackground(vsDraw, true); - } - } else if (inSelection == 2) { - if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) { - return SelectionBackground(vsDraw, false); - } - } else { - if ((vsDraw.edgeState == EDGE_BACKGROUND) && - (i >= ll->edgeColumn) && - (i < ll->numCharsBeforeEOL)) - return vsDraw.edgecolour; - if (inHotspot && vsDraw.hotspotColours.back.isSet) - return vsDraw.hotspotColours.back; - } - if (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { - return background; - } else { - return vsDraw.styles[styleMain].back; - } -} - -void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { - Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); - PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom); - surface->Copy(rcCopyArea, from, - highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); -} - -void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace, - bool isEndMarker, ColourDesired wrapColour) { - surface->PenColour(wrapColour); - - enum { xa = 1 }; // gap before start - int w = rcPlace.right - rcPlace.left - xa - 1; - - bool xStraight = isEndMarker; // x-mirrored symbol for start marker - - int x0 = xStraight ? rcPlace.left : rcPlace.right - 1; - int y0 = rcPlace.top; - - int dy = (rcPlace.bottom - rcPlace.top) / 5; - int y = (rcPlace.bottom - rcPlace.top) / 2 + dy; - - struct Relative { - Surface *surface; - int xBase; - int xDir; - int yBase; - int yDir; - void MoveTo(int xRelative, int yRelative) { - surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative); - } - void LineTo(int xRelative, int yRelative) { - surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative); - } - }; - Relative rel = {surface, x0, xStraight ? 1 : -1, y0, 1}; - - // arrow head - rel.MoveTo(xa, y); - rel.LineTo(xa + 2*w / 3, y - dy); - rel.MoveTo(xa, y); - rel.LineTo(xa + 2*w / 3, y + dy); - - // arrow body - rel.MoveTo(xa, y); - rel.LineTo(xa + w, y); - rel.LineTo(xa + w, y - 2 * dy); - rel.LineTo(xa - 1, // on windows lineto is exclusive endpoint, perhaps GTK not... - y - 2 * dy); -} - -static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) { - if (alpha != SC_ALPHA_NOALPHA) { - surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0); - } -} - -void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment, - const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) { - if (!twoPhaseDraw) { - surface->FillRectangle(rcSegment, textBack); - } - Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; - 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, s, istrlen(s), - textBack, textFore); -} - -void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, - int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, - bool overrideBackground, ColourDesired background, - bool drawWrapMarkEnd, ColourDesired wrapColour) { - - const int posLineStart = pdoc->LineStart(line); - const int styleMask = pdoc->stylingBitsMask; - PRectangle rcSegment = rcLine; - - const bool lastSubLine = subLine == (ll->lines - 1); - XYPOSITION virtualSpace = 0; - if (lastSubLine) { - const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; - virtualSpace = sel.VirtualSpaceFor(pdoc->LineEnd(line)) * spaceWidth; - } - XYPOSITION xEol = ll->positions[lineEnd] - subLineStart; - - // Fill the virtual space and show selections within it - if (virtualSpace) { - rcSegment.left = xEol + xStart; - rcSegment.right = xEol + xStart + virtualSpace; - surface->FillRectangle(rcSegment, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); - if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) { - SelectionSegment virtualSpaceRange(SelectionPosition(pdoc->LineEnd(line)), SelectionPosition(pdoc->LineEnd(line), sel.VirtualSpaceFor(pdoc->LineEnd(line)))); - for (size_t r=0; rEndLineStyle()].spaceWidth; - rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth; - rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth; - rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; - rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == sel.Main())); - } - } - } - } - } - - int eolInSelection = 0; - int alpha = SC_ALPHA_NOALPHA; - if (!hideSelection) { - int posAfterLineEnd = pdoc->LineStart(line + 1); - eolInSelection = (subLine == (ll->lines - 1)) ? sel.InSelectionForEOL(posAfterLineEnd) : 0; - alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; - } - - // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on - XYPOSITION blobsWidth = 0; - if (lastSubLine) { - for (int eolPos=ll->numCharsBeforeEOL; eolPosnumCharsInLine; eolPos++) { - rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace; - rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace; - blobsWidth += rcSegment.Width(); - char hexits[4]; - const char *ctrlChar; - unsigned char chEOL = ll->chars[eolPos]; - int styleMain = ll->styles[eolPos]; - ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll); - if (UTF8IsAscii(chEOL)) { - ctrlChar = ControlCharacterString(chEOL); - } else { - Representation *repr = reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos); - if (repr) { - ctrlChar = repr->stringRep.c_str(); - eolPos = ll->numCharsInLine; - } else { - sprintf(hexits, "x%2X", chEOL); - ctrlChar = hexits; - } - } - ColourDesired textFore = vsDraw.styles[styleMain].fore; - if (eolInSelection && vsDraw.selColours.fore.isSet) { - textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; - } - if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1)) { - if (alpha == SC_ALPHA_NOALPHA) { - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); - } else { - surface->FillRectangle(rcSegment, textBack); - } - } else { - surface->FillRectangle(rcSegment, textBack); - } - DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw); - if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); - } - } - } - - // Draw the eol-is-selected rectangle - rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; - rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; - - if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); - } else { - if (overrideBackground) { - surface->FillRectangle(rcSegment, background); - } else if (line < pdoc->LinesTotal() - 1) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); - } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); - } else { - surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); - } - if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); - } - } - - // Fill the remainder of the line - rcSegment.left = rcSegment.right; - if (rcSegment.left < rcLine.left) - rcSegment.left = rcLine.left; - rcSegment.right = rcLine.right; - - if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); - } else { - if (overrideBackground) { - surface->FillRectangle(rcSegment, background); - } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); - } else { - surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); - } - if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); - } - } - - if (drawWrapMarkEnd) { - PRectangle rcPlace = rcSegment; - - if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) { - rcPlace.left = xEol + xStart + virtualSpace; - rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; - } else { - // rcLine is clipped to text area - rcPlace.right = rcLine.right; - rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; - } - DrawWrapMarker(surface, rcPlace, true, wrapColour); - } -} - -void Editor::DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw, - int xStart, PRectangle rcLine, LineLayout *ll, int subLine) { - const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)]; - PRectangle rcIndic( - ll->positions[startPos] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent, - ll->positions[endPos] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent + 3); - vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine); -} - -void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) { - // Draw decorators - const int posLineStart = pdoc->LineStart(line); - const int lineStart = ll->LineStart(subLine); - const int posLineEnd = posLineStart + lineEnd; - - if (!under) { - // Draw indicators - // foreach indicator... - for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) { - if (!(mask & ll->styleBitsSet)) { - mask <<= 1; - continue; - } - int startPos = -1; - // foreach style pos in line... - for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) { - // look for starts... - if (startPos < 0) { - // NOT in indicator run, looking for START - if (indicPos < lineEnd && (ll->indicators[indicPos] & mask)) - startPos = indicPos; - } - // ... or ends - if (startPos >= 0) { - // IN indicator run, looking for END - if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) { - // AT end of indicator run, DRAW it! - DrawIndicator(indicnum, startPos, indicPos, surface, vsDraw, xStart, rcLine, ll, subLine); - // RESET control var - startPos = -1; - } - } - } - mask <<= 1; - } - } - - for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { - if (under == vsDraw.indicators[deco->indicator].under) { - int startPos = posLineStart + lineStart; - if (!deco->rs.ValueAt(startPos)) { - startPos = deco->rs.EndRun(startPos); - } - while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) { - int endPos = deco->rs.EndRun(startPos); - if (endPos > posLineEnd) - endPos = posLineEnd; - DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, - surface, vsDraw, xStart, rcLine, ll, subLine); - startPos = endPos; - if (!deco->rs.ValueAt(startPos)) { - startPos = deco->rs.EndRun(startPos); - } - } - } - } - - // Use indicators to highlight matching braces - if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) || - (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) { - int braceIndicator = (bracesMatchStyle == STYLE_BRACELIGHT) ? vs.braceHighlightIndicator : vs.braceBadLightIndicator; - if (under == vsDraw.indicators[braceIndicator].under) { - Range rangeLine(posLineStart + lineStart, posLineEnd); - if (rangeLine.ContainsCharacter(braces[0])) { - int braceOffset = braces[0] - posLineStart; - if (braceOffset < ll->numCharsInLine) { - DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); - } - } - if (rangeLine.ContainsCharacter(braces[1])) { - int braceOffset = braces[1] - posLineStart; - if (braceOffset < ll->numCharsInLine) { - DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); - } - } - } - } -} - -void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine) { - int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth; - PRectangle rcSegment = rcLine; - int annotationLine = subLine - ll->lines; - const StyledText stAnnotation = pdoc->AnnotationStyledText(line); - if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { - surface->FillRectangle(rcSegment, vsDraw.styles[0].back); - rcSegment.left = xStart; - if (trackLineWidth || (vs.annotationVisible == ANNOTATION_BOXED)) { - // Only care about calculating width if tracking or need to draw box - int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); - if (vs.annotationVisible == ANNOTATION_BOXED) { - widthAnnotation += vsDraw.spaceWidth * 2; // Margins - } - if (widthAnnotation > lineWidthMaxSeen) - lineWidthMaxSeen = widthAnnotation; - if (vs.annotationVisible == ANNOTATION_BOXED) { - rcSegment.left = xStart + indent; - rcSegment.right = rcSegment.left + widthAnnotation; - } - } - const int annotationLines = pdoc->AnnotationLines(line); - size_t start = 0; - size_t lengthAnnotation = stAnnotation.LineLength(start); - int lineInAnnotation = 0; - while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) { - start += lengthAnnotation + 1; - lengthAnnotation = stAnnotation.LineLength(start); - lineInAnnotation++; - } - PRectangle rcText = rcSegment; - if (vs.annotationVisible == ANNOTATION_BOXED) { - surface->FillRectangle(rcText, - vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); - rcText.left += vsDraw.spaceWidth; - } - DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent, - stAnnotation, start, lengthAnnotation); - if (vs.annotationVisible == ANNOTATION_BOXED) { - surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore); - surface->MoveTo(rcSegment.left, rcSegment.top); - surface->LineTo(rcSegment.left, rcSegment.bottom); - surface->MoveTo(rcSegment.right, rcSegment.top); - surface->LineTo(rcSegment.right, rcSegment.bottom); - if (subLine == ll->lines) { - surface->MoveTo(rcSegment.left, rcSegment.top); - surface->LineTo(rcSegment.right, rcSegment.top); - } - if (subLine == ll->lines+annotationLines-1) { - surface->MoveTo(rcSegment.left, rcSegment.bottom - 1); - surface->LineTo(rcSegment.right, rcSegment.bottom - 1); - } - } - } -} - -void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine) { - - if (subLine >= ll->lines) { - DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine); - return; // No further drawing - } - - 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; - - // See if something overrides the line background color: Either if caret is on the line - // and background color is set for that, or if a marker is defined that forces its background - // color onto the line, or if a marker is defined but has no selection margin in which to - // display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order - // with the earlier taking precedence. When multiple markers cause background override, - // the color for the highest numbered one is used. - bool overrideBackground = false; - ColourDesired background; - if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) { - overrideBackground = true; - background = vsDraw.caretLineBackground; - } - if (!overrideBackground) { - int marks = pdoc->GetMark(line); - for (int markBit = 0; (markBit < 32) && marks; markBit++) { - if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) && - (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - background = vsDraw.markers[markBit].back; - overrideBackground = true; - } - marks >>= 1; - } - } - if (!overrideBackground) { - if (vsDraw.maskInLine) { - int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine; - if (marksMasked) { - for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) { - if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) && - (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - overrideBackground = true; - background = vsDraw.markers[markBit].back; - } - marksMasked >>= 1; - } - } - } - } - - const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) && - (!overrideBackground) && (vsDraw.whitespaceColours.back.isSet); - - bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. - const XYPOSITION indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth; - const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues - - const int posLineStart = pdoc->LineStart(line); - - const int startseg = ll->LineStart(subLine); - const XYACCUMULATOR subLineStart = ll->positions[startseg]; - int lineStart = 0; - int lineEnd = 0; - if (subLine < ll->lines) { - lineStart = ll->LineStart(subLine); - lineEnd = ll->LineStart(subLine + 1); - if (subLine == ll->lines - 1) { - lineEnd = ll->numCharsBeforeEOL; - } - } - - const ColourDesired wrapColour = vsDraw.WrapColour(); - - bool drawWrapMarkEnd = false; - - if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { - if (subLine + 1 < ll->lines) { - drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0; - } - } - - if (ll->wrapIndent != 0) { - - bool continuedWrapLine = false; - if (subLine < ll->lines) { - continuedWrapLine = ll->LineStart(subLine) != 0; - } - - if (continuedWrapLine) { - // draw continuation rect - PRectangle rcPlace = rcSegment; - - rcPlace.left = ll->positions[startseg] + xStart - subLineStart; - rcPlace.right = rcPlace.left + ll->wrapIndent; - - // default bgnd here.. - surface->FillRectangle(rcSegment, overrideBackground ? background : - vsDraw.styles[STYLE_DEFAULT].back); - - // main line style would be below but this would be inconsistent with end markers - // also would possibly not be the style at wrap point - //int styleMain = ll->styles[lineStart]; - //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back); - - if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) { - - if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT) - rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; - else - rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; - - DrawWrapMarker(surface, rcPlace, false, wrapColour); - } - - xStart += static_cast(ll->wrapIndent); - } - } - - const bool selBackDrawn = vsDraw.selColours.back.isSet && - ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)); - - // Does not take margin into account but not significant - const int xStartVisible = static_cast(subLineStart) - xStart; - - ll->psel = &sel; - - if (twoPhaseDraw) { - BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible, selBackDrawn, pdoc, &reprs); - - // Background drawing loop - while (bfBack.More()) { - - const TextSegment ts = bfBack.Next(); - const int i = ts.end() - 1; - const int iDoc = i + posLineStart; - - rcSegment.left = ll->positions[ts.start] + xStart - subLineStart; - rcSegment.right = ll->positions[ts.end()] + xStart - subLineStart; - // Only try to 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.Intersects(rcLine)) { - // Clip to line rectangle, since may have a huge position which will not work with some platforms - if (rcSegment.left < rcLine.left) - rcSegment.left = rcLine.left; - if (rcSegment.right > rcLine.right) - rcSegment.right = rcLine.right; - - const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc); - const bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd); - ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, - inHotspot, ll->styles[i], i, ll); - if (ts.representation) { - if (ll->chars[i] == '\t') { - // Tab display - if (drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceColours.back; - } else { - // Blob display - inIndentation = false; - } - surface->FillRectangle(rcSegment, textBack); - } else { - // Normal text display - surface->FillRectangle(rcSegment, textBack); - if (vsDraw.viewWhitespace != wsInvisible || - (inIndentation && vsDraw.viewIndentationGuides == ivReal)) { - for (int cpos = 0; cpos <= i - ts.start; cpos++) { - if (ll->chars[cpos + ts.start] == ' ') { - if (drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { - PRectangle rcSpace(ll->positions[cpos + ts.start] + xStart - subLineStart, - rcSegment.top, - ll->positions[cpos + ts.start + 1] + xStart - subLineStart, - rcSegment.bottom); - surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back); - } - } else { - inIndentation = false; - } - } - } - } - } else if (rcSegment.left > rcLine.right) { - break; - } - } - - DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd, - xStart, subLine, subLineStart, overrideBackground, background, - drawWrapMarkEnd, wrapColour); - } - - DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, true); - - if (vsDraw.edgeState == EDGE_LINE) { - int edgeX = vsDraw.theEdge * vsDraw.spaceWidth; - rcSegment.left = edgeX + xStart; - if ((ll->wrapIndent != 0) && (lineStart != 0)) - rcSegment.left -= ll->wrapIndent; - rcSegment.right = rcSegment.left + 1; - surface->FillRectangle(rcSegment, vsDraw.edgecolour); - } - - // Draw underline mark as part of background if not transparent - int marks = pdoc->GetMark(line); - int markBit; - for (markBit = 0; (markBit < 32) && marks; markBit++) { - if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) && - (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - PRectangle rcUnderline = rcLine; - rcUnderline.top = rcUnderline.bottom - 2; - surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back); - } - marks >>= 1; - } - - inIndentation = subLine == 0; // Do not handle indentation except on first subline. - // Foreground drawing loop - BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible, - ((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), pdoc, &reprs); - - while (bfFore.More()) { - - const TextSegment ts = bfFore.Next(); - const int i = ts.end() - 1; - const int iDoc = i + posLineStart; - - rcSegment.left = ll->positions[ts.start] + xStart - subLineStart; - rcSegment.right = ll->positions[ts.end()] + xStart - subLineStart; - // Only try to 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.Intersects(rcLine)) { - int styleMain = ll->styles[i]; - ColourDesired textFore = vsDraw.styles[styleMain].fore; - Font &textFont = vsDraw.styles[styleMain].font; - //hotspot foreground - if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) { - if (vsDraw.hotspotColours.fore.isSet) - textFore = vsDraw.hotspotColours.fore; - } - const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc); - if (inSelection && (vsDraw.selColours.fore.isSet)) { - textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; - } - const bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd); - ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll); - if (ts.representation) { - if (ll->chars[i] == '\t') { - // Tab display - if (!twoPhaseDraw) { - if (drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceColours.back; - surface->FillRectangle(rcSegment, textBack); - } - if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { - for (int indentCount = (ll->positions[i] + epsilon) / indentWidth; - indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth; - indentCount++) { - if (indentCount > 0) { - int xIndent = indentCount * indentWidth; - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, - (ll->xHighlightGuide == xIndent)); - } - } - } - if (vsDraw.viewWhitespace != wsInvisible) { - if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - if (vsDraw.whitespaceColours.fore.isSet) - textFore = vsDraw.whitespaceColours.fore; - 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); - } - } - } else { - inIndentation = false; - if (vsDraw.controlCharSymbol >= 32) { - char cc[2] = { static_cast(vsDraw.controlCharSymbol), '\0' }; - surface->DrawTextNoClip(rcSegment, ctrlCharsFont, - rcSegment.top + vsDraw.maxAscent, - cc, 1, textBack, textFore); - } else { - DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw); - } - } - } else { - // Normal text display - if (vsDraw.styles[styleMain].visible) { - if (twoPhaseDraw) { - surface->DrawTextTransparent(rcSegment, textFont, - rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, - i - ts.start + 1, textFore); - } else { - surface->DrawTextNoClip(rcSegment, textFont, - rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, - i - ts.start + 1, textFore, textBack); - } - } - if (vsDraw.viewWhitespace != wsInvisible || - (inIndentation && vsDraw.viewIndentationGuides != ivNone)) { - for (int cpos = 0; cpos <= i - ts.start; cpos++) { - if (ll->chars[cpos + ts.start] == ' ') { - if (vsDraw.viewWhitespace != wsInvisible) { - if (vsDraw.whitespaceColours.fore.isSet) - textFore = vsDraw.whitespaceColours.fore; - if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2; - if (!twoPhaseDraw && drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { - textBack = vsDraw.whitespaceColours.back; - PRectangle rcSpace(ll->positions[cpos + ts.start] + xStart - subLineStart, - rcSegment.top, - ll->positions[cpos + ts.start + 1] + xStart - subLineStart, - rcSegment.bottom); - surface->FillRectangle(rcSpace, textBack); - } - PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0); - rcDot.right = rcDot.left + vs.whitespaceSize; - rcDot.bottom = rcDot.top + vs.whitespaceSize; - surface->FillRectangle(rcDot, textFore); - } - } - if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { - for (int indentCount = (ll->positions[cpos + ts.start] + epsilon) / indentWidth; - indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth; - indentCount++) { - if (indentCount > 0) { - int xIndent = indentCount * indentWidth; - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, - (ll->xHighlightGuide == xIndent)); - } - } - } - } else { - inIndentation = false; - } - } - } - } - if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd) { - PRectangle rcUL = rcSegment; - rcUL.top = rcUL.top + vsDraw.maxAscent + 1; - rcUL.bottom = rcUL.top + 1; - if (vsDraw.hotspotColours.fore.isSet) - surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore); - else - surface->FillRectangle(rcUL, textFore); - } else if (vsDraw.styles[styleMain].underline) { - PRectangle rcUL = rcSegment; - rcUL.top = rcUL.top + vsDraw.maxAscent + 1; - rcUL.bottom = rcUL.top + 1; - surface->FillRectangle(rcUL, textFore); - } - } else if (rcSegment.left > rcLine.right) { - break; - } - } - if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth) - && (subLine == 0)) { - int indentSpace = pdoc->GetLineIndentation(line); - int xStartText = ll->positions[pdoc->GetLineIndentPosition(line) - posLineStart]; - - // Find the most recent line with some text - - int lineLastWithText = line; - while (lineLastWithText > Platform::Maximum(line-20, 0) && pdoc->IsWhiteLine(lineLastWithText)) { - lineLastWithText--; - } - if (lineLastWithText < line) { - xStartText = 100000; // Don't limit to visible indentation on empty line - // This line is empty, so use indentation of last line with text - int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText); - int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG; - if (isFoldHeader) { - // Level is one more level than parent - indentLastWithText += pdoc->IndentSize(); - } - if (vsDraw.viewIndentationGuides == ivLookForward) { - // In viLookForward mode, previous line only used if it is a fold header - if (isFoldHeader) { - indentSpace = Platform::Maximum(indentSpace, indentLastWithText); - } - } else { // viLookBoth - indentSpace = Platform::Maximum(indentSpace, indentLastWithText); - } - } - - int lineNextWithText = line; - while (lineNextWithText < Platform::Minimum(line+20, pdoc->LinesTotal()) && pdoc->IsWhiteLine(lineNextWithText)) { - lineNextWithText++; - } - if (lineNextWithText > line) { - xStartText = 100000; // Don't limit to visible indentation on empty line - // This line is empty, so use indentation of first next line with text - indentSpace = Platform::Maximum(indentSpace, - pdoc->GetLineIndentation(lineNextWithText)); - } - - for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) { - int xIndent = indentPos * vsDraw.spaceWidth; - if (xIndent < xStartText) { - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, - (ll->xHighlightGuide == xIndent)); - } - } - } - - DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false); - - // End of the drawing of the current line - if (!twoPhaseDraw) { - DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd, - xStart, subLine, subLineStart, overrideBackground, background, - drawWrapMarkEnd, wrapColour); - } - if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) { - // For each selection draw - int virtualSpaces = 0; - if (subLine == (ll->lines - 1)) { - virtualSpaces = sel.VirtualSpaceFor(pdoc->LineEnd(line)); - } - SelectionPosition posStart(posLineStart + lineStart); - SelectionPosition posEnd(posLineStart + lineEnd, virtualSpaces); - SelectionSegment virtualSpaceRange(posStart, posEnd); - for (size_t r=0; rEndLineStyle()].spaceWidth; - rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth; - rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth; - if ((ll->wrapIndent != 0) && (lineStart != 0)) { - if ((portion.start.Position() - posLineStart) == lineStart && sel.Range(r).ContainsCharacter(portion.start.Position() - 1)) - rcSegment.left -= static_cast(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here - } - rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; - rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; - if (rcSegment.right > rcLine.left) - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == sel.Main()), alpha); - } - } - } - } - - // Draw any translucent whole line states - rcSegment = rcLine; - if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) { - SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground, vsDraw.caretLineAlpha); - } - marks = pdoc->GetMark(line); - for (markBit = 0; (markBit < 32) && marks; markBit++) { - if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) { - SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); - } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) { - PRectangle rcUnderline = rcSegment; - rcUnderline.top = rcUnderline.bottom - 2; - SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); - } - marks >>= 1; - } - if (vsDraw.maskInLine) { - int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine; - if (marksMasked) { - for (markBit = 0; (markBit < 32) && marksMasked; markBit++) { - if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) { - SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); - } - marksMasked >>= 1; - } - } - } -} - -void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, - int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) { - - int lineStart = ll->LineStart(subLine); - int posBefore = posCaret; - int posAfter = MovePositionOutsideChar(posCaret + 1, 1); - int numCharsToDraw = posAfter - posCaret; - - // Work out where the starting and ending offsets are. We need to - // see if the previous character shares horizontal space, such as a - // glyph / combining character. If so we'll need to draw that too. - int offsetFirstChar = offset; - int offsetLastChar = offset + (posAfter - posCaret); - while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) { - if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { - // The char does not share horizontal space - break; - } - // Char shares horizontal space, update the numChars to draw - // Update posBefore to point to the prev char - posBefore = MovePositionOutsideChar(posBefore - 1, -1); - numCharsToDraw = posAfter - posBefore; - offsetFirstChar = offset - (posCaret - posBefore); - } - - // See if the next character shares horizontal space, if so we'll - // need to draw that too. - if (offsetFirstChar < 0) - offsetFirstChar = 0; - numCharsToDraw = offsetLastChar - offsetFirstChar; - while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { - // Update posAfter to point to the 2nd next char, this is where - // the next character ends, and 2nd next begins. We'll need - // to compare these two - posBefore = posAfter; - posAfter = MovePositionOutsideChar(posAfter + 1, 1); - offsetLastChar = offset + (posAfter - posCaret); - if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { - // The char does not share horizontal space - break; - } - // Char shares horizontal space, update the numChars to draw - numCharsToDraw = offsetLastChar - offsetFirstChar; - } - - // We now know what to draw, update the caret drawing rectangle - rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart; - rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[lineStart] + xStart; - - // Adjust caret position to take into account any word wrapping symbols. - if ((ll->wrapIndent != 0) && (lineStart != 0)) { - XYPOSITION wordWrapCharWidth = ll->wrapIndent; - rcCaret.left += wordWrapCharWidth; - rcCaret.right += wordWrapCharWidth; - } - - // This character is where the caret block is, we override the colours - // (inversed) for drawing the caret here. - int styleMain = ll->styles[offsetFirstChar]; - surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font, - rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, - numCharsToDraw, vsDraw.styles[styleMain].back, - caretColour); } void Editor::RefreshPixMaps(Surface *surfaceWindow) { - if (!pixmapSelPattern->Initialised()) { - const int patternSize = 8; - pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID()); - pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID()); - // This complex procedure is to reproduce the checkerboard 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, patternSize, patternSize); + view.RefreshPixMaps(surfaceWindow, wMain.GetID(), vs); + marginView.RefreshPixMaps(surfaceWindow, wMain.GetID(), vs); + if (view.bufferedDraw) { + PRectangle rcClient = GetClientRectangle(); + if (!view.pixmapLine->Initialised()) { - // Initialize default colours based on the chrome colour scheme. Typically the highlight is white. - ColourDesired colourFMFill = vs.selbar; - ColourDesired colourFMStripes = vs.selbarlight; - - if (!(vs.selbarlight == ColourDesired(0xff, 0xff, 0xff))) { - // User has chosen an unusual chrome colour scheme so just use the highlight edge colour. - // (Typically, the highlight colour is white.) - colourFMFill = vs.selbarlight; - } - - if (vs.foldmarginColour.isSet) { - // override default fold margin colour - colourFMFill = vs.foldmarginColour; - } - if (vs.foldmarginHighlightColour.isSet) { - // override default fold margin highlight colour - colourFMStripes = vs.foldmarginHighlightColour; - } - - pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); - pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes); - for (int y = 0; y < patternSize; y++) { - for (int x = y % 2; x < patternSize; x+=2) { - PRectangle rcPixel(x, y, x+1, y+1); - pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes); - pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill); - } - } - } - - if (!pixmapIndentGuide->Initialised()) { - // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line - pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID()); - pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID()); - PRectangle rcIG(0, 0, 1, vs.lineHeight); - pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back); - pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore); - pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back); - pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore); - for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) { - PRectangle rcPixel(0, stripe, 1, stripe+1); - pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore); - pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore); - } - } - - if (bufferedDraw) { - if (!pixmapLine->Initialised()) { - PRectangle rcClient = GetClientRectangle(); - pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight, + view.pixmapLine->InitPixMap(static_cast(rcClient.Width()), vs.lineHeight, surfaceWindow, wMain.GetID()); - pixmapSelMargin->InitPixMap(vs.fixedColumnWidth, - rcClient.Height(), surfaceWindow, wMain.GetID()); } - } -} - -void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine) { - // When drag is active it is the only caret drawn - bool drawDrag = posDrag.IsValid(); - if (hideSelection && !drawDrag) - return; - const int posLineStart = pdoc->LineStart(lineDoc); - // For each selection draw - for (size_t r=0; (rEndLineStyle()].spaceWidth; - const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth; - if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { - XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; - if (ll->wrapIndent != 0) { - int lineStart = ll->LineStart(subLine); - if (lineStart != 0) // Wrapped - xposCaret += ll->wrapIndent; - } - bool caretBlinkState = (caret.active && caret.on) || (!additionalCaretsBlink && !mainCaret); - bool caretVisibleState = additionalCaretsVisible || mainCaret; - if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) && - ((posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) { - bool caretAtEOF = false; - bool caretAtEOL = false; - bool drawBlockCaret = false; - XYPOSITION widthOverstrikeCaret; - XYPOSITION caretWidthOffset = 0; - PRectangle rcCaret = rcLine; - - if (posCaret.Position() == pdoc->Length()) { // At end of document - caretAtEOF = true; - widthOverstrikeCaret = vsDraw.aveCharWidth; - } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line - caretAtEOL = true; - widthOverstrikeCaret = vsDraw.aveCharWidth; - } else { - widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset]; - } - if (widthOverstrikeCaret < 3) // Make sure its visible - widthOverstrikeCaret = 3; - - if (xposCaret > 0) - caretWidthOffset = 0.51f; // Move back so overlaps both character cells. - xposCaret += xStart; - if (posDrag.IsValid()) { - /* Dragging text, use a line caret */ - rcCaret.left = RoundXYPosition(xposCaret - caretWidthOffset); - rcCaret.right = rcCaret.left + vsDraw.caretWidth; - } else if (inOverstrike && drawOverstrikeCaret) { - /* Overstrike (insert mode), use a modified bar caret */ - rcCaret.top = rcCaret.bottom - 2; - rcCaret.left = xposCaret + 1; - rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; - } else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) { - /* Block caret */ - rcCaret.left = xposCaret; - if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) { - drawBlockCaret = true; - rcCaret.right = xposCaret + widthOverstrikeCaret; - } else { - rcCaret.right = xposCaret + vsDraw.aveCharWidth; - } - } else { - /* Line caret */ - rcCaret.left = RoundXYPosition(xposCaret - caretWidthOffset); - rcCaret.right = rcCaret.left + vsDraw.caretWidth; - } - ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour; - if (drawBlockCaret) { - DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour); - } else { - surface->FillRectangle(rcCaret, caretColour); - } - } + if (!marginView.pixmapSelMargin->Initialised()) { + marginView.pixmapSelMargin->InitPixMap(vs.fixedColumnWidth, + static_cast(rcClient.Height()), surfaceWindow, wMain.GetID()); } - if (drawDrag) - break; } } @@ -3509,18 +1626,9 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { StyleToPositionInView(PositionAfterArea(rcArea)); PRectangle rcClient = GetClientRectangle(); - Point ptOrigin = GetVisibleOriginInMain(); //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n", // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - int screenLinePaintFirst = rcArea.top / vs.lineHeight; - - int xStart = vs.textStart - xOffset + ptOrigin.x; - int ypos = 0; - if (!bufferedDraw) - ypos += screenLinePaintFirst * vs.lineHeight; - int yposScreen = screenLinePaintFirst * vs.lineHeight; - if (NotifyUpdateUI()) { RefreshStyleData(); RefreshPixMaps(surfaceWindow); @@ -3535,9 +1643,9 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { } RefreshPixMaps(surfaceWindow); // In case pixmaps invalidated by scrollbar change } - PLATFORM_ASSERT(pixmapSelPattern->Initialised()); + PLATFORM_ASSERT(marginView.pixmapSelPattern->Initialised()); - if (!bufferedDraw) + if (!view.bufferedDraw) surfaceWindow->SetClip(rcArea); if (paintState != paintAbandoned) { @@ -3571,194 +1679,19 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { } return; } - //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); - // Allow text at start of line to overlap 1 pixel into the margin as this displays - // serifs and italic stems for aliased text. - const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0; + view.PaintText(surfaceWindow, *this, rcArea, rcClient, vs); - // Do the painting - if (rcArea.right > vs.textStart - leftTextOverlap) { - - Surface *surface = surfaceWindow; - if (bufferedDraw) { - surface = pixmapLine; - PLATFORM_ASSERT(pixmapLine->Initialised()); - } - surface->SetUnicodeMode(IsUnicodeMode()); - surface->SetDBCSMode(CodePage()); - - int visibleLine = TopLineOfMain() + screenLinePaintFirst; - - SelectionPosition posCaret = sel.RangeMain().caret; - if (posDrag.IsValid()) - posCaret = posDrag; - int lineCaret = pdoc->LineFromPosition(posCaret.Position()); - - PRectangle rcTextArea = rcClient; - if (vs.marginInside) { - rcTextArea.left += vs.textStart; - rcTextArea.right -= vs.rightMarginWidth; - } else { - rcTextArea = rcArea; - } - - // Remove selection margin from drawing area so text will not be drawn - // on it in unbuffered mode. - if (!bufferedDraw && vs.marginInside) { - PRectangle rcClipText = rcTextArea; - rcClipText.left -= leftTextOverlap; - surfaceWindow->SetClip(rcClipText); - } - - // Loop on visible lines - //double durLayout = 0.0; - //double durPaint = 0.0; - //double durCopy = 0.0; - //ElapsedTime etWhole; - int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times - AutoLineLayout ll(llc, 0); - while (visibleLine < cs.LinesDisplayed() && yposScreen < rcArea.bottom) { - - int lineDoc = cs.DocFromDisplay(visibleLine); - // Only visible lines should be handled by the code within the loop - PLATFORM_ASSERT(cs.GetVisible(lineDoc)); - int lineStartSet = cs.DisplayFromDoc(lineDoc); - int subLine = visibleLine - lineStartSet; - - // Copy this line and its styles from the document into local arrays - // and determine the x position at which each character starts. - //ElapsedTime et; - if (lineDoc != lineDocPrevious) { - ll.Set(0); - ll.Set(RetrieveLineLayout(lineDoc)); - LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - lineDocPrevious = lineDoc; - } - //durLayout += et.Duration(true); - - if (ll) { - ll->containsCaret = lineDoc == lineCaret; - if (hideSelection) { - ll->containsCaret = false; - } - - GetHotSpotRange(ll->hsStart, ll->hsEnd); - - PRectangle rcLine = rcTextArea; - rcLine.top = ypos; - rcLine.bottom = ypos + vs.lineHeight; - - bool bracesIgnoreStyle = false; - if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) || - (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) { - bracesIgnoreStyle = true; - } - Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1)); - // Highlight the current braces if any - ll->SetBracesHighlight(rangeLine, braces, static_cast(bracesMatchStyle), - highlightGuideColumn * vs.spaceWidth, bracesIgnoreStyle); - - if (leftTextOverlap && bufferedDraw) { - PRectangle rcSpacer = rcLine; - rcSpacer.right = rcSpacer.left; - rcSpacer.left -= 1; - surface->FillRectangle(rcSpacer, vs.styles[STYLE_DEFAULT].back); - } - - // Draw the line - DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine); - //durPaint += et.Duration(true); - - // Restore the previous styles for the brace highlights in case layout is in cache. - ll->RestoreBracesHighlight(rangeLine, braces, bracesIgnoreStyle); - - bool expanded = cs.GetExpanded(lineDoc); - const int level = pdoc->GetLevel(lineDoc); - const int levelNext = pdoc->GetLevel(lineDoc + 1); - if ((level & SC_FOLDLEVELHEADERFLAG) && - ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) { - // Paint the line above the fold - if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) - || - (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { - PRectangle rcFoldLine = rcLine; - rcFoldLine.bottom = rcFoldLine.top + 1; - surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore); - } - // Paint the line below the fold - if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) - || - (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { - PRectangle rcFoldLine = rcLine; - rcFoldLine.top = rcFoldLine.bottom - 1; - surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore); - } - } - - DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine); - - if (bufferedDraw) { - Point from(vs.textStart-leftTextOverlap, 0); - PRectangle rcCopyArea(vs.textStart-leftTextOverlap, yposScreen, - rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight); - surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); - } - - lineWidthMaxSeen = Platform::Maximum( - lineWidthMaxSeen, ll->positions[ll->numCharsInLine]); - //durCopy += et.Duration(true); - } - - if (!bufferedDraw) { - ypos += vs.lineHeight; - } - - yposScreen += vs.lineHeight; - visibleLine++; - - //gdk_flush(); - } - ll.Set(0); - //if (durPaint < 0.00000001) - // durPaint = 0.00000001; - - // Right column limit indicator - PRectangle rcBeyondEOF = (vs.marginInside) ? rcClient : rcArea; - rcBeyondEOF.left = vs.textStart; - rcBeyondEOF.right = rcBeyondEOF.right - ((vs.marginInside) ? vs.rightMarginWidth : 0); - rcBeyondEOF.top = (cs.LinesDisplayed() - TopLineOfMain()) * vs.lineHeight; - if (rcBeyondEOF.top < rcBeyondEOF.bottom) { - surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back); - if (vs.edgeState == EDGE_LINE) { - int edgeX = vs.theEdge * vs.spaceWidth; - rcBeyondEOF.left = edgeX + xStart; - rcBeyondEOF.right = rcBeyondEOF.left + 1; - surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour); + if (horizontalScrollBarVisible && trackLineWidth && (view.lineWidthMaxSeen > scrollWidth)) { + if (FineTickerAvailable()) { + scrollWidth = view.lineWidthMaxSeen; + if (!FineTickerRunning(tickWiden)) { + FineTickerStart(tickWiden, 50, 5); } } - //Platform::DebugPrintf( - //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n", - //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); - NotifyPainted(); } -} -// Space (3 space characters) between line numbers and text when printing. -#define lineNumberPrintSpace " " - -ColourDesired InvertedLight(ColourDesired orig) { - unsigned int r = orig.GetRed(); - unsigned int g = orig.GetGreen(); - unsigned int b = orig.GetBlue(); - unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye - unsigned int il = 0xff - l; - if (l == 0) - return ColourDesired(0xff, 0xff, 0xff); - r = r * il / l; - g = g * il / l; - b = b * il / l; - return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); + NotifyPainted(); } // This is mostly copied from the Paint method but with some things omitted @@ -3775,191 +1708,14 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { if (!surfaceMeasure) { return 0; } - - // Can't use measurements cached for screen - posCache.Clear(); - - ViewStyle vsPrint(vs); - vsPrint.technology = SC_TECHNOLOGY_DEFAULT; - - // 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 <= SC_MAX_MARGIN; margin++) { - if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) { - lineNumberIndex = margin; - } else { - vsPrint.ms[margin].width = 0; - } - } - vsPrint.fixedColumnWidth = 0; - vsPrint.zoomLevel = printParameters.magnification; - // Don't show indentation guides - // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT - vsPrint.viewIndentationGuides = ivNone; - // Don't show the selection when printing - vsPrint.selColours.back.isSet = false; - vsPrint.selColours.fore.isSet = false; - vsPrint.selAlpha = SC_ALPHA_NOALPHA; - vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA; - vsPrint.whitespaceColours.back.isSet = false; - vsPrint.whitespaceColours.fore.isSet = false; - vsPrint.showCaretLineBackground = false; - vsPrint.alwaysShowCaretLineBackground = false; - // Don't highlight matching braces using indicators - vsPrint.braceHighlightIndicatorSet = false; - vsPrint.braceBadLightIndicatorSet = false; - - // Set colours for printing according to users settings - for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) { - if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) { - vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); - vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); - } else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) { - vsPrint.styles[sty].fore = ColourDesired(0, 0, 0); - vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); - } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) { - vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); - } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { - if (sty <= STYLE_DEFAULT) { - vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); - } - } - } - // White background for the line numbers - vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff); - - // Printing uses different margins, so reset screen margins - vsPrint.leftMarginWidth = 0; - vsPrint.rightMarginWidth = 0; - - vsPrint.Refresh(*surfaceMeasure, pdoc->tabInChars); - // Determining width must hapen after fonts have been realised in Refresh - int lineNumberWidth = 0; - if (lineNumberIndex >= 0) { - lineNumberWidth = surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, - "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace)); - vsPrint.ms[lineNumberIndex].width = lineNumberWidth; - vsPrint.Refresh(*surfaceMeasure, pdoc->tabInChars); // Recalculate fixedColumnWidth - } - - 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); - 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); - - // Ensure we are styled to where we are formatting. - pdoc->EnsureStyledTo(endPosPrint); - - int xStart = vsPrint.fixedColumnWidth + pfr->rc.left; - int ypos = pfr->rc.top; - - int lineDoc = linePrintStart; - - int nPrintPos = pfr->chrg.cpMin; - int visibleLine = 0; - int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; - if (printParameters.wrapState == eWrapNone) - widthPrint = LineLayout::wrapWidthInfinite; - - while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) { - - // When printing, the hdc and hdcTarget may be the same, so - // changing the state of surfaceMeasure may change the underlying - // state of surface. Therefore, any cached state is discarded before - // using each surface. - surfaceMeasure->FlushCachedState(); - - // Copy this line and its styles from the document into local arrays - // and determine the x position at which each character starts. - LineLayout ll(pdoc->LineStart(lineDoc+1)-pdoc->LineStart(lineDoc)+1); - LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint); - - ll.containsCaret = false; - - PRectangle rcLine; - rcLine.left = pfr->rc.left; - rcLine.top = ypos; - rcLine.right = pfr->rc.right - 1; - rcLine.bottom = ypos + vsPrint.lineHeight; - - // When document line is wrapped over multiple display lines, find where - // to start printing from to ensure a particular position is on the first - // line of the page. - if (visibleLine == 0) { - int startWithinLine = nPrintPos - pdoc->LineStart(lineDoc); - for (int iwl = 0; iwl < ll.lines - 1; iwl++) { - if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) { - visibleLine = -iwl; - } - } - - if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) { - visibleLine = -(ll.lines - 1); - } - } - - if (draw && lineNumberWidth && - (ypos + vsPrint.lineHeight <= pfr->rc.bottom) && - (visibleLine >= 0)) { - char number[100]; - sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1); - PRectangle rcNumber = rcLine; - rcNumber.right = rcNumber.left + lineNumberWidth; - // Right justify - rcNumber.left = rcNumber.right - surfaceMeasure->WidthText( - vsPrint.styles[STYLE_LINENUMBER].font, number, istrlen(number)); - surface->FlushCachedState(); - surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, - ypos + vsPrint.maxAscent, number, istrlen(number), - vsPrint.styles[STYLE_LINENUMBER].fore, - vsPrint.styles[STYLE_LINENUMBER].back); - } - - // Draw the line - surface->FlushCachedState(); - - for (int iwl = 0; iwl < ll.lines; iwl++) { - if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) { - if (visibleLine >= 0) { - if (draw) { - rcLine.top = ypos; - rcLine.bottom = ypos + vsPrint.lineHeight; - DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl); - } - ypos += vsPrint.lineHeight; - } - visibleLine++; - if (iwl == ll.lines - 1) - nPrintPos = pdoc->LineStart(lineDoc + 1); - else - nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl); - } - } - - ++lineDoc; - } - - // Clear cache so measurements are not used for screen - posCache.Clear(); - - return nPrintPos; + return view.FormatRange(draw, pfr, surface, surfaceMeasure, *this, vs); } int Editor::TextWidth(int style, const char *text) { RefreshStyleData(); AutoSurface surface(this); if (surface) { - return surface->WidthText(vs.styles[style].font, text, istrlen(text)); + return static_cast(surface->WidthText(vs.styles[style].font, text, istrlen(text))); } else { return 1; } @@ -3997,7 +1753,7 @@ void Editor::ChangeSize() { SetScrollBars(); if (Wrapping()) { PRectangle rcTextArea = GetClientRectangle(); - rcTextArea.left = vs.textStart; + rcTextArea.left = static_cast(vs.textStart); rcTextArea.right -= vs.rightMarginWidth; if (wrapWidth != rcTextArea.Width()) { NeedWrapping(); @@ -4009,8 +1765,8 @@ void Editor::ChangeSize() { int Editor::InsertSpace(int position, unsigned int spaces) { if (spaces > 0) { std::string spaceText(spaces, ' '); - pdoc->InsertString(position, spaceText.c_str(), spaces); - position += spaces; + const int lengthInserted = pdoc->InsertString(position, spaceText.c_str(), spaces); + position += lengthInserted; } return position; } @@ -4035,17 +1791,20 @@ static bool cmpSelPtrs(const SelectionRange *a, const SelectionRange *b) { } // AddCharUTF inserts an array of bytes which may or may not be in UTF-8. -void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { +void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { FilterSelections(); { UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike); + // Vector elements point into selection in order to change selection. std::vector selPtrs; for (size_t r = 0; r < sel.Count(); r++) { selPtrs.push_back(&sel.Range(r)); } + // Order selections by position in document. std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs); + // Loop in reverse to avoid disturbing positions of selections yet to be processed. for (std::vector::reverse_iterator rit = selPtrs.rbegin(); rit != selPtrs.rend(); ++rit) { SelectionRange *currentSel = *rit; @@ -4069,9 +1828,10 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { } } positionInsert = InsertSpace(positionInsert, currentSel->caret.VirtualSpace()); - if (pdoc->InsertString(positionInsert, s, len)) { - currentSel->caret.SetPosition(positionInsert + len); - currentSel->anchor.SetPosition(positionInsert + len); + const int lengthInserted = pdoc->InsertString(positionInsert, s, len); + if (lengthInserted > 0) { + currentSel->caret.SetPosition(positionInsert + lengthInserted); + currentSel->anchor.SetPosition(positionInsert + lengthInserted); } currentSel->ClearVirtualSpace(); // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information @@ -4112,28 +1872,9 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid // characters representing themselves. } else { - // Unroll 1 to 3 byte UTF-8 sequences. See reference data at: - // http://www.cl.cam.ac.uk/~mgk25/unicode.html - // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt - if (byte < 0xE0) { - int byte2 = static_cast(s[1]); - if ((byte2 & 0xC0) == 0x80) { - // Two-byte-character lead-byte followed by a trail-byte. - byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F)); - } - // A two-byte-character lead-byte not followed by trail-byte - // represents itself. - } else if (byte < 0xF0) { - int byte2 = static_cast(s[1]); - int byte3 = static_cast(s[2]); - if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) { - // Three-byte-character lead byte followed by two trail bytes. - byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | - (byte3 & 0x3F)); - } - // A three-byte-character lead-byte not followed by two trail-bytes - // represents itself. - } + unsigned int utf32[1] = { 0 }; + UTF32FromUTF8(s, len, utf32, ELEMENTS(utf32)); + byte = utf32[0]; } NotifyChar(byte); } @@ -4143,11 +1884,20 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { } } -void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) { +void Editor::FillVirtualSpace() { + const bool tmpOverstrike = inOverstrike; + inOverstrike = false; // not allow to be deleted twice. + AddCharUTF("", 0); + inOverstrike = tmpOverstrike; +} + +void Editor::InsertPaste(const char *text, int len) { if (multiPasteMode == SC_MULTIPASTE_ONCE) { + SelectionPosition selStart = sel.Start(); selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace())); - if (pdoc->InsertString(selStart.Position(), text, len)) { - SetEmptySelection(selStart.Position() + len); + const int lengthInserted = pdoc->InsertString(selStart.Position(), text, len); + if (lengthInserted > 0) { + SetEmptySelection(selStart.Position() + lengthInserted); } } else { // SC_MULTIPASTE_EACH @@ -4165,9 +1915,10 @@ void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) } } positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace()); - if (pdoc->InsertString(positionInsert, text, len)) { - sel.Range(r).caret.SetPosition(positionInsert + len); - sel.Range(r).anchor.SetPosition(positionInsert + len); + const int lengthInserted = pdoc->InsertString(positionInsert, text, len); + if (lengthInserted > 0) { + sel.Range(r).caret.SetPosition(positionInsert + lengthInserted); + sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted); } sel.Range(r).ClearVirtualSpace(); } @@ -4175,6 +1926,35 @@ void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) } } +void Editor::InsertPasteShape(const char *text, int len, PasteShape shape) { + std::string convertedText; + if (convertPastes) { + // Convert line endings of the paste into our local line-endings mode + convertedText = Document::TransformLineEnds(text, len, pdoc->eolMode); + len = static_cast(convertedText.length()); + text = convertedText.c_str(); + } + if (shape == pasteRectangular) { + PasteRectangular(sel.Start(), text, len); + } else { + if (shape == pasteLine) { + int insertPos = pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())); + int lengthInserted = pdoc->InsertString(insertPos, text, len); + // add the newline if necessary + if ((len > 0) && (text[len - 1] != '\n' && text[len - 1] != '\r')) { + const char *endline = StringFromEOLMode(pdoc->eolMode); + int length = static_cast(strlen(endline)); + lengthInserted += pdoc->InsertString(insertPos + lengthInserted, endline, length); + } + if (sel.MainCaret() == insertPos) { + SetEmptySelection(sel.MainCaret() + lengthInserted); + } + } else { + InsertPaste(text, len); + } + } +} + void Editor::ClearSelection(bool retainMultipleSelections) { if (!sel.IsRectangular() && !retainMultipleSelections) FilterSelections(); @@ -4192,6 +1972,7 @@ void Editor::ClearSelection(bool retainMultipleSelections) { ThinRectangularRange(); sel.RemoveDuplicates(); ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); } void Editor::ClearAll() { @@ -4206,6 +1987,9 @@ void Editor::ClearAll() { pdoc->MarginClearAll(); } } + + view.ClearAllTabstops(); + sel.Clear(); SetTopLine(0); SetVerticalScrollPos(); @@ -4226,6 +2010,7 @@ void Editor::ClearDocumentStyle() { pdoc->StartStyling(0, '\377'); pdoc->SetStyleFor(pdoc->Length(), 0); cs.ShowAll(); + SetAnnotationHeights(0, pdoc->LinesTotal()); pdoc->ClearLevels(); } @@ -4263,22 +2048,23 @@ void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) { line++; if (line >= pdoc->LinesTotal()) { if (pdoc->eolMode != SC_EOL_LF) - pdoc->InsertChar(pdoc->Length(), '\r'); + pdoc->InsertString(pdoc->Length(), "\r", 1); if (pdoc->eolMode != SC_EOL_CR) - pdoc->InsertChar(pdoc->Length(), '\n'); + pdoc->InsertString(pdoc->Length(), "\n", 1); } // Pad the end of lines with spaces if required sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert)); if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) { while (XFromPosition(sel.MainCaret()) < xInsert) { - pdoc->InsertChar(sel.MainCaret(), ' '); - sel.RangeMain().caret.Add(1); + assert(pdoc); + const int lengthInserted = pdoc->InsertString(sel.MainCaret(), " ", 1); + sel.RangeMain().caret.Add(lengthInserted); } } prevCr = ptr[i] == '\r'; } else { - pdoc->InsertString(sel.MainCaret(), ptr + i, 1); - sel.RangeMain().caret.Add(1); + const int lengthInserted = pdoc->InsertString(sel.MainCaret(), ptr + i, 1); + sel.RangeMain().caret.Add(lengthInserted); prevCr = false; } } @@ -4319,6 +2105,7 @@ void Editor::Clear() { ClearSelection(); } sel.RemoveDuplicates(); + ShowCaretAtCurrentPosition(); // Avoid blinking } void Editor::SelectAll() { @@ -4346,15 +2133,8 @@ void Editor::Redo() { } } -void Editor::DelChar() { - if (!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1)) { - pdoc->DelChar(sel.MainCaret()); - } - // Avoid blinking during rapid typing: - ShowCaretAtCurrentPosition(); -} - void Editor::DelCharBack(bool allowLineStartDeletion) { + RefreshStyleData(); if (!sel.IsRectangular()) FilterSelections(); if (sel.IsRectangular()) @@ -4374,14 +2154,12 @@ void Editor::DelCharBack(bool allowLineStartDeletion) { UndoGroup ugInner(pdoc, !ug.Needed()); int indentation = pdoc->GetLineIndentation(lineCurrentPos); int indentationStep = pdoc->IndentSize(); - if (indentation % indentationStep == 0) { - pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); - } else { - pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep)); - } + int indentationChange = indentation % indentationStep; + if (indentationChange == 0) + indentationChange = indentationStep; + const int posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationChange); // SetEmptySelection - sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos), - pdoc->GetLineIndentPosition(lineCurrentPos)); + sel.Range(r) = SelectionRange(posSelect); } else { pdoc->DelCharBack(sel.Range(r).caret.Position()); } @@ -4603,8 +2381,8 @@ void Editor::NotifyDwelling(Point pt, bool state) { SCNotification scn = {}; scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND; scn.position = PositionFromLocation(pt, true); - scn.x = pt.x + vs.ExternalMarginWidth(); - scn.y = pt.y; + scn.x = static_cast(pt.x + vs.ExternalMarginWidth()); + scn.y = static_cast(pt.y); NotifyParent(scn); } @@ -4627,7 +2405,7 @@ void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) { void Editor::CheckModificationForWrap(DocModification mh) { if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) { - llc.Invalidate(LineLayout::llCheckTextAndStyle); + view.llc.Invalidate(LineLayout::llCheckTextAndStyle); int lineDoc = pdoc->LineFromPosition(mh.position); int lines = Platform::Maximum(0, mh.linesAdded); if (Wrapping()) { @@ -4676,6 +2454,9 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { Redraw(); } } + if (mh.modificationType & SC_MOD_CHANGETABSTOPS) { + Redraw(); + } if (mh.modificationType & SC_MOD_LEXERSTATE) { if (paintState == painting) { CheckForChangeOutsidePaint( @@ -4697,7 +2478,7 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { } } if (mh.modificationType & SC_MOD_CHANGESTYLE) { - llc.Invalidate(LineLayout::llCheckTextAndStyle); + view.llc.Invalidate(LineLayout::llCheckTextAndStyle); } } else { // Move selection and brace highlights @@ -4739,6 +2520,7 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { } else { cs.DeleteLines(lineOfPos, -mh.linesAdded); } + view.LinesAddedOrRemoved(lineOfPos, mh.linesAdded); } if (mh.modificationType & SC_MOD_CHANGEANNOTATION) { int lineDoc = pdoc->LineFromPosition(mh.position); @@ -4778,7 +2560,7 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) { if (mh.modificationType & SC_MOD_CHANGEFOLD) { // Fold changes can affect the drawing of following lines so redraw whole margin - RedrawSelMargin(highlightDelimiter.isEnabled ? -1 : mh.line-1, true); + RedrawSelMargin(marginView.highlightDelimiter.isEnabled ? -1 : mh.line - 1, true); } else { RedrawSelMargin(mh.line); } @@ -4970,17 +2752,17 @@ void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) { int topStutterLine = topLine + caretYSlop; int bottomStutterLine = pdoc->LineFromPosition(PositionFromLocation( - Point(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll()))) + Point::FromInts(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll()))) - caretYSlop - 1; if (stuttered && (direction < 0 && currentLine > topStutterLine)) { topLineNew = topLine; - newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * caretYSlop), + newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * caretYSlop), false, false, UserVirtualSpace()); } else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) { topLineNew = topLine; - newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)), + newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)), false, false, UserVirtualSpace()); } else { @@ -4989,7 +2771,7 @@ void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) { topLineNew = Platform::Clamp( topLine + direction * LinesToScroll(), 0, MaxScrollPos()); newPos = SPositionFromLocation( - Point(lastXChosen - xOffset, pt.y + direction * (vs.lineHeight * LinesToScroll())), + Point::FromInts(lastXChosen - xOffset, static_cast(pt.y) + direction * (vs.lineHeight * LinesToScroll())), false, false, UserVirtualSpace()); } @@ -5029,12 +2811,13 @@ void Editor::ChangeCaseOfSelection(int caseMapping) { pdoc->DeleteChars( static_cast(currentNoVS.Start().Position() + firstDifference), static_cast(rangeBytes - firstDifference - endDifferenceText)); - pdoc->InsertString( + const int lengthChange = static_cast(lastDifferenceMapped - firstDifference + 1); + const int lengthInserted = pdoc->InsertString( static_cast(currentNoVS.Start().Position() + firstDifference), sMapped.c_str() + firstDifference, - static_cast(lastDifferenceMapped - firstDifference + 1)); + lengthChange); // Automatic movement changes selection so reset to exactly the same as it was. - int diffSizes = static_cast(sMapped.size() - sText.size()); + int diffSizes = static_cast(sMapped.size() - sText.size()) + lengthInserted - lengthChange; if (diffSizes != 0) { if (current.anchor > current.caret) current.anchor.Add(diffSizes); @@ -5051,19 +2834,23 @@ void Editor::LineTranspose() { int line = pdoc->LineFromPosition(sel.MainCaret()); if (line > 0) { UndoGroup ug(pdoc); - int startPrev = pdoc->LineStart(line - 1); - int endPrev = pdoc->LineEnd(line - 1); - int start = pdoc->LineStart(line); - int end = pdoc->LineEnd(line); - std::string line1 = RangeText(startPrev, endPrev); - int len1 = endPrev - startPrev; - std::string line2 = RangeText(start, end); - int len2 = end - start; - pdoc->DeleteChars(start, len2); - pdoc->DeleteChars(startPrev, len1); - pdoc->InsertString(startPrev, line2.c_str(), len2); - pdoc->InsertString(start - len1 + len2, line1.c_str(), len1); - MovePositionTo(SelectionPosition(start - len1 + len2)); + + const int startPrevious = pdoc->LineStart(line - 1); + const std::string linePrevious = RangeText(startPrevious, pdoc->LineEnd(line - 1)); + + int startCurrent = pdoc->LineStart(line); + const std::string lineCurrent = RangeText(startCurrent, pdoc->LineEnd(line)); + + pdoc->DeleteChars(startCurrent, static_cast(lineCurrent.length())); + pdoc->DeleteChars(startPrevious, static_cast(linePrevious.length())); + startCurrent -= static_cast(linePrevious.length()); + + startCurrent += pdoc->InsertString(startPrevious, lineCurrent.c_str(), + static_cast(lineCurrent.length())); + pdoc->InsertString(startCurrent, linePrevious.c_str(), + static_cast(linePrevious.length())); + // Move caret to start of current line + MovePositionTo(SelectionPosition(startCurrent)); } } @@ -5087,9 +2874,10 @@ void Editor::Duplicate(bool forLine) { end = SelectionPosition(pdoc->LineEnd(line)); } std::string text = RangeText(start.Position(), end.Position()); + int lengthInserted = eolLen; if (forLine) - pdoc->InsertString(end.Position(), eol, eolLen); - pdoc->InsertString(end.Position() + eolLen, text.c_str(), SelectionRange(end, start).Length()); + lengthInserted = pdoc->InsertString(end.Position(), eol, eolLen); + pdoc->InsertString(end.Position() + lengthInserted, text.c_str(), static_cast(text.length())); } if (sel.Count() && sel.IsRectangular()) { SelectionPosition last = sel.Last(); @@ -5128,12 +2916,12 @@ void Editor::NewLine() { } else if (pdoc->eolMode == SC_EOL_CR) { eol = "\r"; } // else SC_EOL_LF -> "\n" already set - bool inserted = pdoc->InsertCString(sel.MainCaret(), eol); + const int insertLength = pdoc->InsertString(sel.MainCaret(), eol, istrlen(eol)); // Want to end undo group before NotifyChar as applications often modify text here if (needGroupUndo) pdoc->EndUndoAction(); - if (inserted) { - SetEmptySelection(sel.MainCaret() + istrlen(eol)); + if (insertLength > 0) { + SetEmptySelection(sel.MainCaret() + insertLength); while (*eol) { NotifyChar(*eol); if (recordingMacro) { @@ -5168,7 +2956,7 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) { if (vs.annotationVisible) { int lineDoc = pdoc->LineFromPosition(caretToUse.Position()); Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); - int subLine = (pt.y - ptStartLine.y) / vs.lineHeight; + int subLine = static_cast(pt.y - ptStartLine.y) / vs.lineHeight; if (direction < 0 && subLine == 0) { int lineDisplay = cs.DisplayFromDoc(lineDoc); @@ -5180,9 +2968,9 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) { } } - int newY = pt.y + (1 + skipLines) * direction * vs.lineHeight; + int newY = static_cast(pt.y) + (1 + skipLines) * direction * vs.lineHeight; SelectionPosition posNew = SPositionFromLocation( - Point(lastXChosen - xOffset, newY), false, false, UserVirtualSpace()); + Point::FromInts(lastXChosen - xOffset, newY), false, false, UserVirtualSpace()); if (direction < 0) { // Line wrapping may lead to a location on the same line, so @@ -5225,29 +3013,8 @@ void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) { int Editor::StartEndDisplayLine(int pos, bool start) { RefreshStyleData(); - int line = pdoc->LineFromPosition(pos); AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(line)); - int posRet = INVALID_POSITION; - if (surface && ll) { - unsigned int posLineStart = pdoc->LineStart(line); - LayoutLine(line, surface, vs, ll, wrapWidth); - int posInLine = pos - posLineStart; - if (posInLine <= ll->maxLineLength) { - for (int subLine = 0; subLine < ll->lines; subLine++) { - if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) { - if (start) { - posRet = ll->LineStart(subLine) + posLineStart; - } else { - if (subLine == ll->lines - 1) - posRet = ll->LineStart(subLine + 1) + posLineStart; - else - posRet = ll->LineStart(subLine + 1) + posLineStart - 1; - } - } - } - } - } + int posRet = view.StartEndDisplayLine(surface, *this, pos, start, vs); if (posRet == INVALID_POSITION) { return pos; } else { @@ -5511,7 +3278,6 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_EDITTOGGLEOVERTYPE: inOverstrike = !inOverstrike; - DropCaret(); ShowCaretAtCurrentPosition(); ContainerNeedsUpdate(SC_UPDATE_CONTENT); NotifyUpdateUI(); @@ -5611,6 +3377,7 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_DELWORDRIGHT: { UndoGroup ug(pdoc); + InvalidateSelection(sel.RangeMain(), true); sel.RangeMain().caret = SelectionPosition( InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); sel.RangeMain().anchor = sel.RangeMain().caret; @@ -5620,6 +3387,7 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_DELWORDRIGHTEND: { UndoGroup ug(pdoc); + InvalidateSelection(sel.RangeMain(), true); sel.RangeMain().caret = SelectionPosition( InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1); @@ -5755,7 +3523,7 @@ int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) { if (msg) { if (consumed) *consumed = true; - return WndProc(msg, 0, 0); + return static_cast(WndProc(msg, 0, 0)); } else { if (consumed) *consumed = false; @@ -5781,21 +3549,22 @@ void Editor::Indent(bool forwards) { pdoc->tabIndents) { int indentation = pdoc->GetLineIndentation(lineCurrentPos); int indentationStep = pdoc->IndentSize(); - pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep - indentation % indentationStep); - sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos)); + const int posSelect = pdoc->SetLineIndentation( + lineCurrentPos, indentation + indentationStep - indentation % indentationStep); + sel.Range(r) = SelectionRange(posSelect); } else { if (pdoc->useTabs) { - pdoc->InsertChar(caretPosition, '\t'); - sel.Range(r) = SelectionRange(caretPosition+1); + const int lengthInserted = pdoc->InsertString(caretPosition, "\t", 1); + sel.Range(r) = SelectionRange(caretPosition + lengthInserted); } else { int numSpaces = (pdoc->tabInChars) - (pdoc->GetColumn(caretPosition) % (pdoc->tabInChars)); if (numSpaces < 1) numSpaces = pdoc->tabInChars; - for (int i = 0; i < numSpaces; i++) { - pdoc->InsertChar(caretPosition + i, ' '); - } - sel.Range(r) = SelectionRange(caretPosition+numSpaces); + const std::string spaceText(numSpaces, ' '); + const int lengthInserted = pdoc->InsertString(caretPosition, spaceText.c_str(), + static_cast(spaceText.length())); + sel.Range(r) = SelectionRange(caretPosition + lengthInserted); } } } else { @@ -5803,8 +3572,8 @@ void Editor::Indent(bool forwards) { pdoc->tabIndents) { int indentation = pdoc->GetLineIndentation(lineCurrentPos); int indentationStep = pdoc->IndentSize(); - pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); - sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos)); + const int posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); + sel.Range(r) = SelectionRange(posSelect); } else { int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) * pdoc->tabInChars; @@ -5869,18 +3638,26 @@ long Editor::FindText( int lengthFound = istrlen(ft->lpstrText); if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); - int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - wParam, - &lengthFound); - if (pos != -1) { - ft->chrgText.cpMin = pos; - ft->chrgText.cpMax = pos + lengthFound; + try { + long pos = pdoc->FindText( + static_cast(ft->chrg.cpMin), + static_cast(ft->chrg.cpMax), + ft->lpstrText, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, + static_cast(wParam), + &lengthFound); + if (pos != -1) { + ft->chrgText.cpMin = pos; + ft->chrgText.cpMax = pos + lengthFound; + } + return static_cast(pos); + } catch (RegexError &) { + errorStatus = SC_STATUS_WARN_REGEX; + return -1; } - return pos; } /** @@ -5910,29 +3687,34 @@ long Editor::SearchText( sptr_t lParam) { ///< The text to search for. const char *txt = reinterpret_cast(lParam); - int pos; + long pos; int lengthFound = istrlen(txt); if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); - if (iMessage == SCI_SEARCHNEXT) { - pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - wParam, - &lengthFound); - } else { - pos = pdoc->FindText(searchAnchor, 0, txt, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - wParam, - &lengthFound); + try { + if (iMessage == SCI_SEARCHNEXT) { + pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, + static_cast(wParam), + &lengthFound); + } else { + pos = pdoc->FindText(searchAnchor, 0, txt, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, + static_cast(wParam), + &lengthFound); + } + } catch (RegexError &) { + errorStatus = SC_STATUS_WARN_REGEX; + return -1; } if (pos != -1) { - SetSelection(pos, pos + lengthFound); + SetSelection(static_cast(pos), static_cast(pos + lengthFound)); } return pos; @@ -5964,18 +3746,23 @@ long Editor::SearchInTarget(const char *text, int length) { if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); - int pos = pdoc->FindText(targetStart, targetEnd, text, - (searchFlags & SCFIND_MATCHCASE) != 0, - (searchFlags & SCFIND_WHOLEWORD) != 0, - (searchFlags & SCFIND_WORDSTART) != 0, - (searchFlags & SCFIND_REGEXP) != 0, - searchFlags, - &lengthFound); - if (pos != -1) { - targetStart = pos; - targetEnd = pos + lengthFound; + try { + long pos = pdoc->FindText(targetStart, targetEnd, text, + (searchFlags & SCFIND_MATCHCASE) != 0, + (searchFlags & SCFIND_WHOLEWORD) != 0, + (searchFlags & SCFIND_WORDSTART) != 0, + (searchFlags & SCFIND_REGEXP) != 0, + searchFlags, + &lengthFound); + if (pos != -1) { + targetStart = static_cast(pos); + targetEnd = static_cast(pos + lengthFound); + } + return pos; + } catch (RegexError &) { + errorStatus = SC_STATUS_WARN_REGEX; + return -1; } - return pos; } void Editor::GoToLine(int lineNo) { @@ -5988,10 +3775,10 @@ void Editor::GoToLine(int lineNo) { EnsureCaretVisible(); } -static bool Close(Point pt1, Point pt2) { - if (abs(pt1.x - pt2.x) > 3) +static bool Close(Point pt1, Point pt2, Point threshold) { + if (std::abs(pt1.x - pt2.x) > threshold.x) return false; - if (abs(pt1.y - pt2.y) > 3) + if (std::abs(pt1.y - pt2.y) > threshold.y) return false; return true; } @@ -6067,7 +3854,13 @@ void Editor::SetDragPosition(SelectionPosition newPos) { } if (!(posDrag == newPos)) { caret.on = true; - SetTicking(true); + if (FineTickerAvailable()) { + FineTickerCancel(tickCaret); + if ((caret.active) && (caret.period > 0) && (newPos.Position() < 0)) + FineTickerStart(tickCaret, caret.period, caret.period/10); + } else { + SetTicking(true); + } InvalidateCaret(); posDrag = newPos; InvalidateCaret(); @@ -6082,8 +3875,8 @@ void Editor::DisplayCursor(Window::Cursor c) { } bool Editor::DragThreshold(Point ptStart, Point ptNow) { - int xMove = ptStart.x - ptNow.x; - int yMove = ptStart.y - ptNow.y; + int xMove = static_cast(ptStart.x - ptNow.x); + int yMove = static_cast(ptStart.y - ptNow.y); int distanceSquared = xMove * xMove + yMove * yMove; return distanceSquared > 16; } @@ -6134,16 +3927,20 @@ void Editor::DropAt(SelectionPosition position, const char *value, size_t length } position = positionAfterDeletion; + std::string convertedText = Document::TransformLineEnds(value, lengthValue, pdoc->eolMode); + if (rectangular) { - PasteRectangular(position, value, static_cast(lengthValue)); + PasteRectangular(position, convertedText.c_str(), static_cast(convertedText.length())); // Should try to select new rectangle but it may not be a rectangle now so just select the drop position SetEmptySelection(position); } else { position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position()); position = SelectionPosition(InsertSpace(position.Position(), position.VirtualSpace())); - if (pdoc->InsertString(position.Position(), value, static_cast(lengthValue))) { + const int lengthInserted = pdoc->InsertString( + position.Position(), convertedText.c_str(), static_cast(convertedText.length())); + if (lengthInserted > 0) { SelectionPosition posAfterInsertion = position; - posAfterInsertion.Add(static_cast(lengthValue)); + posAfterInsertion.Add(lengthInserted); SetSelection(posAfterInsertion, position); } } @@ -6194,13 +3991,13 @@ bool Editor::PointInSelection(Point pt) { return false; } -bool Editor::PointInSelMargin(Point pt) { +bool Editor::PointInSelMargin(Point pt) const { // Really means: "Point in a margin" if (vs.fixedColumnWidth > 0) { // There is a margin PRectangle rcSelMargin = GetClientRectangle(); - rcSelMargin.right = vs.textStart - vs.leftMarginWidth; - rcSelMargin.left = vs.textStart - vs.fixedColumnWidth; - return rcSelMargin.Contains(pt); + rcSelMargin.right = static_cast(vs.textStart - vs.leftMarginWidth); + rcSelMargin.left = static_cast(vs.textStart - vs.fixedColumnWidth); + return rcSelMargin.ContainsWholePixel(pt); } else { return false; } @@ -6287,6 +4084,12 @@ void Editor::DwellEnd(bool mouseMoved) { dwelling = false; NotifyDwelling(ptMouseLast, dwelling); } + if (FineTickerAvailable()) { + FineTickerCancel(tickDwell); + if (mouseMoved && (dwellDelay < SC_TIME_FOREVER)) { + //FineTickerStart(tickDwell, dwellDelay, dwellDelay/10); + } + } } void Editor::MouseLeave() { @@ -6303,6 +4106,7 @@ static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) { } void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) { + SetHoverIndicatorPoint(pt); //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop); ptMouseLast = pt; const bool ctrl = (modifiers & SCI_CTRL) != 0; @@ -6331,9 +4135,12 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie if (shift && !inSelMargin) { SetSelection(newPos); } - if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) { + if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick, doubleClickCloseThreshold)) { //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); SetMouseCapture(true); + if (FineTickerAvailable()) { + FineTickerStart(tickScroll, 100, 10); + } if (!ctrl || !multipleSelection || (selectionType != selChar && selectionType != selWord)) SetEmptySelection(newPos.Position()); bool doubleClick = false; @@ -6355,7 +4162,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie doubleClick = true; } else if (selectionType == selWord) { // Since we ended up here, we're inside a *triple* click, which should always select - // whole line irregardless of word wrap being enabled or not. + // whole line regardless of word wrap being enabled or not. selectionType = selWholeLine; } else { selectionType = selChar; @@ -6430,6 +4237,9 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie SetDragPosition(SelectionPosition(invalidPosition)); SetMouseCapture(true); + if (FineTickerAvailable()) { + FineTickerStart(tickScroll, 100, 10); + } } else { if (PointIsHotspot(pt)) { NotifyHotSpotClicked(newCharPos.Position(), modifiers); @@ -6442,6 +4252,9 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie inDragDrop = ddNone; } SetMouseCapture(true); + if (FineTickerAvailable()) { + FineTickerStart(tickScroll, 100, 10); + } if (inDragDrop != ddInitial) { SetDragPosition(SelectionPosition(invalidPosition)); if (!shift) { @@ -6473,7 +4286,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie } lastClickTime = curTime; lastClick = pt; - lastXChosen = pt.x + xOffset; + lastXChosen = static_cast(pt.x) + xOffset; ShowCaretAtCurrentPosition(); } @@ -6482,7 +4295,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b } bool Editor::PositionIsHotspot(int position) const { - return vs.styles[pdoc->StyleAt(position) & pdoc->stylingBitsMask].hotspot; + return vs.styles[static_cast(pdoc->StyleAt(position))].hotspot; } bool Editor::PointIsHotspot(Point pt) { @@ -6492,6 +4305,36 @@ bool Editor::PointIsHotspot(Point pt) { return PositionIsHotspot(pos); } +void Editor::SetHoverIndicatorPosition(int position) { + int hoverIndicatorPosPrev = hoverIndicatorPos; + hoverIndicatorPos = INVALID_POSITION; + if (vs.indicatorsDynamic == 0) + return; + if (position != INVALID_POSITION) { + for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { + if (vs.indicators[deco->indicator].IsDynamic()) { + if (pdoc->decorations.ValueAt(deco->indicator, position)) { + hoverIndicatorPos = position; + } + } + } + } + if (hoverIndicatorPosPrev != hoverIndicatorPos) { + if (hoverIndicatorPosPrev != INVALID_POSITION) + InvalidateRange(hoverIndicatorPosPrev, hoverIndicatorPosPrev + 1); + if (hoverIndicatorPos != INVALID_POSITION) + InvalidateRange(hoverIndicatorPos, hoverIndicatorPos + 1); + } +} + +void Editor::SetHoverIndicatorPoint(Point pt) { + if (vs.indicatorsDynamic == 0) { + SetHoverIndicatorPosition(INVALID_POSITION); + } else { + SetHoverIndicatorPosition(PositionFromLocation(pt, true, true)); + } +} + void Editor::SetHotSpotRange(Point *pt) { if (pt) { int pos = PositionFromLocation(*pt, false, true); @@ -6499,35 +4342,28 @@ void Editor::SetHotSpotRange(Point *pt) { // If we don't limit this to word characters then the // range can encompass more than the run range and then // the underline will not be drawn properly. - int hsStart_ = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine); - int hsEnd_ = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine); + Range hsNew; + hsNew.start = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine); + hsNew.end = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine); // Only invalidate the range if the hotspot range has changed... - if (hsStart_ != hsStart || hsEnd_ != hsEnd) { - if (hsStart != -1) { - InvalidateRange(hsStart, hsEnd); + if (!(hsNew == hotspot)) { + if (hotspot.Valid()) { + InvalidateRange(hotspot.start, hotspot.end); } - hsStart = hsStart_; - hsEnd = hsEnd_; - InvalidateRange(hsStart, hsEnd); + hotspot = hsNew; + InvalidateRange(hotspot.start, hotspot.end); } } else { - if (hsStart != -1) { - int hsStart_ = hsStart; - int hsEnd_ = hsEnd; - hsStart = -1; - hsEnd = -1; - InvalidateRange(hsStart_, hsEnd_); - } else { - hsStart = -1; - hsEnd = -1; + if (hotspot.Valid()) { + InvalidateRange(hotspot.start, hotspot.end); } + hotspot = Range(invalidPosition); } } -void Editor::GetHotSpotRange(int &hsStart_, int &hsEnd_) const { - hsStart_ = hsStart; - hsEnd_ = hsEnd; +Range Editor::GetHotSpotRange() const { + return hotspot; } void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { @@ -6542,6 +4378,9 @@ void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { if (inDragDrop == ddInitial) { if (DragThreshold(ptMouseLast, pt)) { SetMouseCapture(false); + if (FineTickerAvailable()) { + FineTickerCancel(tickScroll); + } SetDragPosition(movePos); CopySelectionRange(&drag); StartDrag(); @@ -6550,6 +4389,12 @@ void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { } ptMouseLast = pt; + PRectangle rcClient = GetClientRectangle(); + Point ptOrigin = GetVisibleOriginInMain(); + rcClient.Move(0, -ptOrigin.y); + if (FineTickerAvailable() && (dwellDelay < SC_TIME_FOREVER) && rcClient.Contains(pt)) { + FineTickerStart(tickDwell, dwellDelay, dwellDelay/10); + } //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); if (HaveMouseCapture()) { @@ -6601,9 +4446,6 @@ void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { } // Autoscroll - PRectangle rcClient = GetClientRectangle(); - Point ptOrigin = GetVisibleOriginInMain(); - rcClient.Move(0, -ptOrigin.y); int lineMove = DisplayFromPosition(movePos.Position()); if (pt.y > rcClient.bottom) { ScrollTo(lineMove - LinesOnScreen() + 1); @@ -6614,7 +4456,7 @@ void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { } EnsureCaretVisible(false, false, true); - if (hsStart != -1 && !PointIsHotspot(pt)) + if (hotspot.Valid() && !PointIsHotspot(pt)) SetHotSpotRange(NULL); if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt,true,true) != hotSpotClickPos) { @@ -6635,12 +4477,18 @@ void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { // Display regular (drag) cursor over selection if (PointInSelection(pt) && !SelectionEmpty()) { DisplayCursor(Window::cursorArrow); - } else if (PointIsHotspot(pt)) { - DisplayCursor(Window::cursorHand); - SetHotSpotRange(&pt); } else { - DisplayCursor(Window::cursorText); - SetHotSpotRange(NULL); + SetHoverIndicatorPoint(pt); + if (PointIsHotspot(pt)) { + DisplayCursor(Window::cursorHand); + SetHotSpotRange(&pt); + } else { + if (hoverIndicatorPos != invalidPosition) + DisplayCursor(Window::cursorHand); + else + DisplayCursor(Window::cursorText); + SetHotSpotRange(NULL); + } } } } @@ -6653,6 +4501,8 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop); SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular())); + if (hoverIndicatorPos != INVALID_POSITION) + InvalidateRange(newPos.Position(), newPos.Position() + 1); newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position()); if (inDragDrop == ddInitial) { inDragDrop = ddNone; @@ -6675,26 +4525,36 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { } ptMouseLast = pt; SetMouseCapture(false); + if (FineTickerAvailable()) { + FineTickerCancel(tickScroll); + } NotifyIndicatorClick(false, newPos.Position(), 0); if (inDragDrop == ddDragging) { SelectionPosition selStart = SelectionStart(); SelectionPosition selEnd = SelectionEnd(); if (selStart < selEnd) { if (drag.Length()) { + const int length = static_cast(drag.Length()); if (ctrl) { - if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast(drag.Length()))) { - SetSelection(newPos.Position(), newPos.Position() + static_cast(drag.Length())); + const int lengthInserted = pdoc->InsertString( + newPos.Position(), drag.Data(), length); + if (lengthInserted > 0) { + SetSelection(newPos.Position(), newPos.Position() + lengthInserted); } } else if (newPos < selStart) { pdoc->DeleteChars(selStart.Position(), static_cast(drag.Length())); - if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast(drag.Length()))) { - SetSelection(newPos.Position(), newPos.Position() + static_cast(drag.Length())); + const int lengthInserted = pdoc->InsertString( + newPos.Position(), drag.Data(), length); + if (lengthInserted > 0) { + SetSelection(newPos.Position(), newPos.Position() + lengthInserted); } } else if (newPos > selEnd) { pdoc->DeleteChars(selStart.Position(), static_cast(drag.Length())); newPos.Add(-static_cast(drag.Length())); - if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast(drag.Length()))) { - SetSelection(newPos.Position(), newPos.Position() + static_cast(drag.Length())); + const int lengthInserted = pdoc->InsertString( + newPos.Position(), drag.Data(), length); + if (lengthInserted > 0) { + SetSelection(newPos.Position(), newPos.Position() + lengthInserted); } } else { SetEmptySelection(newPos.Position()); @@ -6718,7 +4578,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { SetRectangularRange(); lastClickTime = curTime; lastClick = pt; - lastXChosen = pt.x + xOffset; + lastXChosen = static_cast(pt.x) + xOffset; if (sel.selType == Selection::selStream) { SetLastXChosen(); } @@ -6744,8 +4604,8 @@ void Editor::Tick() { } } } - if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) { - scrollWidth = lineWidthMaxSeen; + if (horizontalScrollBarVisible && trackLineWidth && (view.lineWidthMaxSeen > scrollWidth)) { + scrollWidth = view.lineWidthMaxSeen; SetScrollBars(); } if ((dwellDelay < SC_TIME_FOREVER) && @@ -6776,7 +4636,7 @@ bool Editor::Idle() { // Add more idle things to do here, but make sure idleDone is // set correctly before the function returns. returning - // false will stop calling this idle funtion until SetIdle() is + // false will stop calling this idle function until SetIdle() is // called again. idleDone = wrappingDone; // && thatDone && theOtherThingDone... @@ -6784,22 +4644,80 @@ bool Editor::Idle() { return !idleDone; } +void Editor::SetTicking(bool) { + // SetTicking is deprecated. In the past it was pure virtual and was overridden in each + // derived platform class but fine grained timers should now be implemented. + // Either way, execution should not arrive here so assert failure. + assert(false); +} + +void Editor::TickFor(TickReason reason) { + switch (reason) { + case tickCaret: + caret.on = !caret.on; + if (caret.active) { + InvalidateCaret(); + } + break; + case tickScroll: + // Auto scroll + ButtonMove(ptMouseLast); + break; + case tickWiden: + SetScrollBars(); + FineTickerCancel(tickWiden); + break; + case tickDwell: + if ((!HaveMouseCapture()) && + (ptMouseLast.y >= 0)) { + dwelling = true; + NotifyDwelling(ptMouseLast, dwelling); + } + FineTickerCancel(tickDwell); + break; + default: + // tickPlatform handled by subclass + break; + } +} + +bool Editor::FineTickerAvailable() { + return false; +} + +// FineTickerStart is be overridden by subclasses that support fine ticking so +// this method should never be called. +bool Editor::FineTickerRunning(TickReason) { + assert(false); + return false; +} + +// FineTickerStart is be overridden by subclasses that support fine ticking so +// this method should never be called. +void Editor::FineTickerStart(TickReason, int, int) { + assert(false); +} + +// FineTickerCancel is be overridden by subclasses that support fine ticking so +// this method should never be called. +void Editor::FineTickerCancel(TickReason) { + assert(false); +} + void Editor::SetFocusState(bool focusState) { hasFocus = focusState; NotifyFocus(hasFocus); - if (hasFocus) { - ShowCaretAtCurrentPosition(); - } else { + if (!hasFocus) { CancelModes(); - DropCaret(); } + ShowCaretAtCurrentPosition(); } int Editor::PositionAfterArea(PRectangle rcArea) const { // The start of the document line after the display line after the area // This often means that the line after a modification is restyled which helps // detect multiline comment additions and heals single line comments - int lineAfter = TopLineOfMain() + (rcArea.bottom - 1) / vs.lineHeight + 1; + int lineAfter = TopLineOfMain() + static_cast(rcArea.bottom - 1) / vs.lineHeight + 1; if (lineAfter < cs.LinesDisplayed()) return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1); else @@ -6853,7 +4771,7 @@ bool Editor::PaintContainsMargin() { return false; } PRectangle rcSelMargin = GetClientRectangle(); - rcSelMargin.right = vs.textStart; + rcSelMargin.right = static_cast(vs.textStart); return PaintContains(rcSelMargin); } @@ -6863,7 +4781,7 @@ void Editor::CheckForChangeOutsidePaint(Range r) { if (!r.Valid()) return; - PRectangle rcRange = RectangleFromRange(r.start, r.end); + PRectangle rcRange = RectangleFromRange(r, 0); PRectangle rcText = GetTextRectangle(); if (rcRange.top < rcText.top) { rcRange.top = rcText.top; @@ -6900,14 +4818,15 @@ void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) { void Editor::SetAnnotationHeights(int start, int end) { if (vs.annotationVisible) { + RefreshStyleData(); bool changedHeight = false; for (int line=start; lineLinesTotal(); line++) { int linesWrapped = 1; if (Wrapping()) { AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(line)); + AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this)); if (surface && ll) { - LayoutLine(line, surface, vs, ll, wrapWidth); + view.LayoutLine(*this, line, surface, vs, ll, wrapWidth); linesWrapped = ll->lines; } } @@ -6947,9 +4866,14 @@ void Editor::SetDocPointer(Document *document) { cs.Clear(); cs.InsertLines(0, pdoc->LinesTotal() - 1); SetAnnotationHeights(0, pdoc->LinesTotal()); - llc.Deallocate(); + view.llc.Deallocate(); NeedWrapping(); + hotspot = Range(invalidPosition); + hoverIndicatorPos = invalidPosition; + + view.ClearAllTabstops(); + pdoc->AddWatcher(this, 0); SetScrollBars(); Redraw(); @@ -7242,8 +5166,8 @@ int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) { if (targetStart != targetEnd) pdoc->DeleteChars(targetStart, targetEnd - targetStart); targetEnd = targetStart; - pdoc->InsertString(targetStart, text, length); - targetEnd = targetStart + length; + const int lengthInserted = pdoc->InsertString(targetStart, text, length); + targetEnd = targetStart + lengthInserted; return length; } @@ -7260,10 +5184,10 @@ int Editor::CodePage() const { int Editor::WrapCount(int line) { AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(line)); + AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this)); if (surface && ll) { - LayoutLine(line, surface, vs, ll, wrapWidth); + view.LayoutLine(*this, line, surface, vs, ll, wrapWidth); return ll->lines; } else { return 1; @@ -7278,16 +5202,16 @@ void Editor::AddStyledText(char *buffer, int appendLength) { for (i = 0; i < textLength; i++) { text[i] = buffer[i*2]; } - pdoc->InsertString(CurrentPosition(), text.c_str(), textLength); + const int lengthInserted = pdoc->InsertString(CurrentPosition(), text.c_str(), textLength); for (i = 0; i < textLength; i++) { text[i] = buffer[i*2+1]; } - pdoc->StartStyling(CurrentPosition(), static_cast(0xff)); + pdoc->StartStyling(CurrentPosition(), static_cast(0xff)); pdoc->SetStyles(textLength, text.c_str()); - SetEmptySelection(sel.MainCaret() + textLength); + SetEmptySelection(sel.MainCaret() + lengthInserted); } -static bool ValidMargin(unsigned long wParam) { +static bool ValidMargin(uptr_t wParam) { return wParam <= SC_MAX_MARGIN; } @@ -7299,16 +5223,16 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.EnsureStyle(wParam); switch (iMessage) { case SCI_STYLESETFORE: - vs.styles[wParam].fore = ColourDesired(lParam); + vs.styles[wParam].fore = ColourDesired(static_cast(lParam)); break; case SCI_STYLESETBACK: - vs.styles[wParam].back = ColourDesired(lParam); + vs.styles[wParam].back = ColourDesired(static_cast(lParam)); break; case SCI_STYLESETBOLD: vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL; break; case SCI_STYLESETWEIGHT: - vs.styles[wParam].weight = lParam; + vs.styles[wParam].weight = static_cast(lParam); break; case SCI_STYLESETITALIC: vs.styles[wParam].italic = lParam != 0; @@ -7317,14 +5241,14 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].eolFilled = lParam != 0; break; case SCI_STYLESETSIZE: - vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER; + vs.styles[wParam].size = static_cast(lParam * SC_FONT_SIZE_MULTIPLIER); break; case SCI_STYLESETSIZEFRACTIONAL: - vs.styles[wParam].size = lParam; + vs.styles[wParam].size = static_cast(lParam); break; case SCI_STYLESETFONT: if (lParam != 0) { - vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam)); + vs.SetStyleFontName(static_cast(wParam), CharPtrFromSPtr(lParam)); } break; case SCI_STYLESETUNDERLINE: @@ -7334,7 +5258,7 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].caseForce = static_cast(lParam); break; case SCI_STYLESETCHARACTERSET: - vs.styles[wParam].characterSet = lParam; + vs.styles[wParam].characterSet = static_cast(lParam); pdoc->SetCaseFolder(NULL); break; case SCI_STYLESETVISIBLE: @@ -7401,7 +5325,7 @@ sptr_t Editor::StringResult(sptr_t lParam, const char *val) { sptr_t Editor::BytesResult(sptr_t lParam, const unsigned char *val, size_t len) { // No NUL termination: len is number of valid/displayed bytes - if (lParam) { + if ((lParam) && (len > 0)) { char *ptr = CharPtrFromSPtr(lParam); if (val) memcpy(ptr, val, len); @@ -7439,7 +5363,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { UndoGroup ug(pdoc); pdoc->DeleteChars(0, pdoc->Length()); SetEmptySelection(0); - pdoc->InsertCString(0, CharPtrFromSPtr(lParam)); + const char *text = CharPtrFromSPtr(lParam); + pdoc->InsertString(0, text, istrlen(text)); return 1; } @@ -7472,11 +5397,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_COPYRANGE: - CopyRangeToClipboard(wParam, lParam); + CopyRangeToClipboard(static_cast(wParam), static_cast(lParam)); break; case SCI_COPYTEXT: - CopyText(wParam, CharPtrFromSPtr(lParam)); + CopyText(static_cast(wParam), CharPtrFromSPtr(lParam)); break; case SCI_PASTE: @@ -7509,12 +5434,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return topLine; case SCI_SETFIRSTVISIBLELINE: - ScrollTo(wParam); + ScrollTo(static_cast(wParam)); break; case SCI_GETLINE: { // Risk of overwriting the end of the buffer - int lineStart = pdoc->LineStart(wParam); - int lineEnd = pdoc->LineStart(wParam + 1); + int lineStart = pdoc->LineStart(static_cast(wParam)); + int lineEnd = pdoc->LineStart(static_cast(wParam + 1)); if (lParam == 0) { return lineEnd - lineStart; } @@ -7571,7 +5496,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_LINEFROMPOSITION: if (static_cast(wParam) < 0) return 0; - return pdoc->LineFromPosition(wParam); + return pdoc->LineFromPosition(static_cast(wParam)); case SCI_POSITIONFROMLINE: if (static_cast(wParam) < 0) @@ -7582,14 +5507,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return -1; //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway... // return -1; - return pdoc->LineStart(wParam); + return pdoc->LineStart(static_cast(wParam)); // Replacement of the old Scintilla interpretation of EM_LINELENGTH case SCI_LINELENGTH: if ((static_cast(wParam) < 0) || (static_cast(wParam) > pdoc->LineFromPosition(pdoc->Length()))) return 0; - return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam); + return pdoc->LineStart(static_cast(wParam) + 1) - pdoc->LineStart(static_cast(wParam)); case SCI_REPLACESEL: { if (lParam == 0) @@ -7597,26 +5522,32 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { UndoGroup ug(pdoc); ClearSelection(); char *replacement = CharPtrFromSPtr(lParam); - pdoc->InsertCString(sel.MainCaret(), replacement); - SetEmptySelection(sel.MainCaret() + istrlen(replacement)); + const int lengthInserted = pdoc->InsertString( + sel.MainCaret(), replacement, istrlen(replacement)); + SetEmptySelection(sel.MainCaret() + lengthInserted); EnsureCaretVisible(); } break; case SCI_SETTARGETSTART: - targetStart = wParam; + targetStart = static_cast(wParam); break; case SCI_GETTARGETSTART: return targetStart; case SCI_SETTARGETEND: - targetEnd = wParam; + targetEnd = static_cast(wParam); break; case SCI_GETTARGETEND: return targetEnd; + case SCI_SETTARGETRANGE: + targetStart = static_cast(wParam); + targetEnd = static_cast(lParam); + break; + case SCI_TARGETFROMSELECTION: if (sel.MainCaret() < sel.MainAnchor()) { targetStart = sel.MainCaret(); @@ -7627,44 +5558,49 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } break; + case SCI_GETTARGETTEXT: { + std::string text = RangeText(targetStart, targetEnd); + return BytesResult(lParam, reinterpret_cast(text.c_str()), text.length()); + } + case SCI_REPLACETARGET: PLATFORM_ASSERT(lParam); - return ReplaceTarget(false, CharPtrFromSPtr(lParam), wParam); + return ReplaceTarget(false, CharPtrFromSPtr(lParam), static_cast(wParam)); case SCI_REPLACETARGETRE: PLATFORM_ASSERT(lParam); - return ReplaceTarget(true, CharPtrFromSPtr(lParam), wParam); + return ReplaceTarget(true, CharPtrFromSPtr(lParam), static_cast(wParam)); case SCI_SEARCHINTARGET: PLATFORM_ASSERT(lParam); - return SearchInTarget(CharPtrFromSPtr(lParam), wParam); + return SearchInTarget(CharPtrFromSPtr(lParam), static_cast(wParam)); case SCI_SETSEARCHFLAGS: - searchFlags = wParam; + searchFlags = static_cast(wParam); break; case SCI_GETSEARCHFLAGS: return searchFlags; case SCI_GETTAG: - return GetTag(CharPtrFromSPtr(lParam), wParam); + return GetTag(CharPtrFromSPtr(lParam), static_cast(wParam)); case SCI_POSITIONBEFORE: - return pdoc->MovePositionOutsideChar(wParam - 1, -1, true); + return pdoc->MovePositionOutsideChar(static_cast(wParam) - 1, -1, true); case SCI_POSITIONAFTER: - return pdoc->MovePositionOutsideChar(wParam + 1, 1, true); + return pdoc->MovePositionOutsideChar(static_cast(wParam) + 1, 1, true); case SCI_POSITIONRELATIVE: - return Platform::Clamp(pdoc->GetRelativePosition(wParam, lParam), 0, pdoc->Length()); + return Platform::Clamp(pdoc->GetRelativePosition(static_cast(wParam), static_cast(lParam)), 0, pdoc->Length()); case SCI_LINESCROLL: - ScrollTo(topLine + lParam); - HorizontalScrollTo(xOffset + static_cast(wParam) * vs.spaceWidth); + ScrollTo(topLine + static_cast(lParam)); + HorizontalScrollTo(xOffset + static_cast(wParam)* static_cast(vs.spaceWidth)); return 1; case SCI_SETXOFFSET: - xOffset = wParam; + xOffset = static_cast(wParam); ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); SetHorizontalScrollPos(); Redraw(); @@ -7695,17 +5631,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (lParam < 0) { return 0; } else { - Point pt = LocationFromPosition(lParam); + Point pt = LocationFromPosition(static_cast(lParam)); // Convert to view-relative - return pt.x - vs.textStart + vs.fixedColumnWidth; + return static_cast(pt.x) - vs.textStart + vs.fixedColumnWidth; } case SCI_POINTYFROMPOSITION: if (lParam < 0) { return 0; } else { - Point pt = LocationFromPosition(lParam); - return pt.y; + Point pt = LocationFromPosition(static_cast(lParam)); + return static_cast(pt.y); } case SCI_FINDTEXT: @@ -7715,19 +5651,19 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (lParam == 0) return 0; Sci_TextRange *tr = reinterpret_cast(lParam); - int cpMax = tr->chrg.cpMax; + int cpMax = static_cast(tr->chrg.cpMax); if (cpMax == -1) cpMax = pdoc->Length(); PLATFORM_ASSERT(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); + int len = static_cast(cpMax - tr->chrg.cpMin); // No -1 as cpMin and cpMax are referring to inter character positions + pdoc->GetCharRange(tr->lpstrText, static_cast(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: - hideSelection = wParam != 0; + view.hideSelection = wParam != 0; Redraw(); break; @@ -7741,13 +5677,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.rightMarginWidth; case SCI_SETMARGINLEFT: - lastXChosen += lParam - vs.leftMarginWidth; - vs.leftMarginWidth = lParam; + lastXChosen += static_cast(lParam) - vs.leftMarginWidth; + vs.leftMarginWidth = static_cast(lParam); InvalidateStyleRedraw(); break; case SCI_SETMARGINRIGHT: - vs.rightMarginWidth = lParam; + vs.rightMarginWidth = static_cast(lParam); InvalidateStyleRedraw(); break; @@ -7756,33 +5692,39 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_ADDTEXT: { if (lParam == 0) return 0; - pdoc->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam), wParam); - SetEmptySelection(sel.MainCaret() + wParam); + const int lengthInserted = pdoc->InsertString( + CurrentPosition(), CharPtrFromSPtr(lParam), static_cast(wParam)); + SetEmptySelection(sel.MainCaret() + lengthInserted); return 0; } case SCI_ADDSTYLEDTEXT: if (lParam) - AddStyledText(CharPtrFromSPtr(lParam), wParam); + AddStyledText(CharPtrFromSPtr(lParam), static_cast(wParam)); return 0; case SCI_INSERTTEXT: { if (lParam == 0) return 0; - int insertPos = wParam; + int insertPos = static_cast(wParam); if (static_cast(wParam) == -1) insertPos = CurrentPosition(); int newCurrent = CurrentPosition(); char *sz = CharPtrFromSPtr(lParam); - pdoc->InsertCString(insertPos, sz); + const int lengthInserted = pdoc->InsertString(insertPos, sz, istrlen(sz)); if (newCurrent > insertPos) - newCurrent += istrlen(sz); + newCurrent += lengthInserted; SetEmptySelection(newCurrent); return 0; } + case SCI_CHANGEINSERTION: + PLATFORM_ASSERT(lParam); + pdoc->ChangeInsertion(CharPtrFromSPtr(lParam), static_cast(wParam)); + return 0; + case SCI_APPENDTEXT: - pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), wParam); + pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), static_cast(wParam)); return 0; case SCI_CLEARALL: @@ -7790,7 +5732,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return 0; case SCI_DELETERANGE: - pdoc->DeleteChars(wParam, lParam); + pdoc->DeleteChars(static_cast(wParam), static_cast(lParam)); return 0; case SCI_CLEARDOCUMENTSTYLE: @@ -7816,7 +5758,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return caret.period; case SCI_SETCARETPERIOD: - caret.period = wParam; + CaretSetPeriod(static_cast(wParam)); break; case SCI_GETWORDCHARS: @@ -7858,19 +5800,19 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->Length(); case SCI_ALLOCATE: - pdoc->Allocate(wParam); + pdoc->Allocate(static_cast(wParam)); break; case SCI_GETCHARAT: - return pdoc->CharAt(wParam); + return pdoc->CharAt(static_cast(wParam)); case SCI_SETCURRENTPOS: if (sel.IsRectangular()) { - sel.Rectangular().caret.SetPosition(wParam); + sel.Rectangular().caret.SetPosition(static_cast(wParam)); SetRectangularRange(); Redraw(); } else { - SetSelection(wParam, sel.MainAnchor()); + SetSelection(static_cast(wParam), sel.MainAnchor()); } break; @@ -7879,11 +5821,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETANCHOR: if (sel.IsRectangular()) { - sel.Rectangular().anchor.SetPosition(wParam); + sel.Rectangular().anchor.SetPosition(static_cast(wParam)); SetRectangularRange(); Redraw(); } else { - SetSelection(sel.MainCaret(), wParam); + SetSelection(sel.MainCaret(), static_cast(wParam)); } break; @@ -7891,49 +5833,49 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor(); case SCI_SETSELECTIONSTART: - SetSelection(Platform::Maximum(sel.MainCaret(), wParam), wParam); + SetSelection(Platform::Maximum(sel.MainCaret(), static_cast(wParam)), static_cast(wParam)); break; case SCI_GETSELECTIONSTART: return sel.LimitsForRectangularElseMain().start.Position(); case SCI_SETSELECTIONEND: - SetSelection(wParam, Platform::Minimum(sel.MainAnchor(), wParam)); + SetSelection(static_cast(wParam), Platform::Minimum(sel.MainAnchor(), static_cast(wParam))); break; case SCI_GETSELECTIONEND: return sel.LimitsForRectangularElseMain().end.Position(); case SCI_SETEMPTYSELECTION: - SetEmptySelection(wParam); + SetEmptySelection(static_cast(wParam)); break; case SCI_SETPRINTMAGNIFICATION: - printParameters.magnification = wParam; + view.printParameters.magnification = static_cast(wParam); break; case SCI_GETPRINTMAGNIFICATION: - return printParameters.magnification; + return view.printParameters.magnification; case SCI_SETPRINTCOLOURMODE: - printParameters.colourMode = wParam; + view.printParameters.colourMode = static_cast(wParam); break; case SCI_GETPRINTCOLOURMODE: - return printParameters.colourMode; + return view.printParameters.colourMode; case SCI_SETPRINTWRAPMODE: - printParameters.wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone; + view.printParameters.wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone; break; case SCI_GETPRINTWRAPMODE: - return printParameters.wrapState; + return view.printParameters.wrapState; case SCI_GETSTYLEAT: if (static_cast(wParam) >= pdoc->Length()) return 0; else - return pdoc->StyleAt(wParam); + return pdoc->StyleAt(static_cast(wParam)); case SCI_REDO: Redo(); @@ -7952,9 +5894,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return 0; Sci_TextRange *tr = reinterpret_cast(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); + for (long iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) { + tr->lpstrText[iPlace++] = pdoc->CharAt(static_cast(iChar)); + tr->lpstrText[iPlace++] = pdoc->StyleAt(static_cast(iChar)); } tr->lpstrText[iPlace] = '\0'; tr->lpstrText[iPlace + 1] = '\0'; @@ -7965,10 +5907,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0; case SCI_MARKERLINEFROMHANDLE: - return pdoc->LineFromHandle(wParam); + return pdoc->LineFromHandle(static_cast(wParam)); case SCI_MARKERDELETEHANDLE: - pdoc->DeleteMarkFromHandle(wParam); + pdoc->DeleteMarkFromHandle(static_cast(wParam)); break; case SCI_GETVIEWWS: @@ -7988,27 +5930,27 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_POSITIONFROMPOINT: - return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam), + return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), false, false); case SCI_POSITIONFROMPOINTCLOSE: - return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam), + return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), true, false); case SCI_CHARPOSITIONFROMPOINT: - return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam), + return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), false, true); case SCI_CHARPOSITIONFROMPOINTCLOSE: - return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam), + return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), true, true); case SCI_GOTOLINE: - GoToLine(wParam); + GoToLine(static_cast(wParam)); break; case SCI_GOTOPOS: - SetEmptySelection(wParam); + SetEmptySelection(static_cast(wParam)); EnsureCaretVisible(); break; @@ -8036,11 +5978,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->eolMode; case SCI_SETEOLMODE: - pdoc->eolMode = wParam; + pdoc->eolMode = static_cast(wParam); break; case SCI_SETLINEENDTYPESALLOWED: - if (pdoc->SetLineEndTypesAllowed(wParam)) { + if (pdoc->SetLineEndTypesAllowed(static_cast(wParam))) { cs.Clear(); cs.InsertLines(0, pdoc->LinesTotal() - 1); SetAnnotationHeights(0, pdoc->LinesTotal()); @@ -8055,32 +5997,40 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->GetLineEndTypesActive(); case SCI_STARTSTYLING: - pdoc->StartStyling(wParam, static_cast(lParam)); + pdoc->StartStyling(static_cast(wParam), static_cast(lParam)); break; case SCI_SETSTYLING: - pdoc->SetStyleFor(wParam, static_cast(lParam)); + pdoc->SetStyleFor(static_cast(wParam), static_cast(lParam)); break; case SCI_SETSTYLINGEX: // Specify a complete styling buffer if (lParam == 0) return 0; - pdoc->SetStyles(wParam, CharPtrFromSPtr(lParam)); + pdoc->SetStyles(static_cast(wParam), CharPtrFromSPtr(lParam)); break; case SCI_SETBUFFEREDDRAW: - bufferedDraw = wParam != 0; + view.bufferedDraw = wParam != 0; break; case SCI_GETBUFFEREDDRAW: - return bufferedDraw; + return view.bufferedDraw; case SCI_GETTWOPHASEDRAW: - return twoPhaseDraw; + return view.phasesDraw == EditView::phasesTwo; case SCI_SETTWOPHASEDRAW: - twoPhaseDraw = wParam != 0; - InvalidateStyleRedraw(); + if (view.SetTwoPhaseDraw(wParam != 0)) + InvalidateStyleRedraw(); + break; + + case SCI_GETPHASESDRAW: + return view.phasesDraw; + + case SCI_SETPHASESDRAW: + if (view.SetPhasesDraw(static_cast(wParam))) + InvalidateStyleRedraw(); break; case SCI_SETFONTQUALITY: @@ -8094,7 +6044,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETTABWIDTH: if (wParam > 0) { - pdoc->tabInChars = wParam; + pdoc->tabInChars = static_cast(wParam); if (pdoc->indentInChars == 0) pdoc->actualIndentInChars = pdoc->tabInChars; } @@ -8104,8 +6054,25 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETTABWIDTH: return pdoc->tabInChars; + case SCI_CLEARTABSTOPS: + if (view.ClearTabstops(static_cast(wParam))) { + DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, 0, static_cast(wParam)); + NotifyModified(pdoc, mh, NULL); + } + break; + + case SCI_ADDTABSTOP: + if (view.AddTabstop(static_cast(wParam), static_cast(lParam))) { + DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, 0, static_cast(wParam)); + NotifyModified(pdoc, mh, NULL); + } + break; + + case SCI_GETNEXTTABSTOP: + return view.GetNextTabstop(static_cast(wParam), static_cast(lParam)); + case SCI_SETINDENT: - pdoc->indentInChars = wParam; + pdoc->indentInChars = static_cast(wParam); if (pdoc->indentInChars != 0) pdoc->actualIndentInChars = pdoc->indentInChars; else @@ -8125,14 +6092,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->useTabs; case SCI_SETLINEINDENTATION: - pdoc->SetLineIndentation(wParam, lParam); + pdoc->SetLineIndentation(static_cast(wParam), static_cast(lParam)); break; case SCI_GETLINEINDENTATION: - return pdoc->GetLineIndentation(wParam); + return pdoc->GetLineIndentation(static_cast(wParam)); case SCI_GETLINEINDENTPOSITION: - return pdoc->GetLineIndentPosition(wParam); + return pdoc->GetLineIndentPosition(static_cast(wParam)); case SCI_SETTABINDENTS: pdoc->tabIndents = wParam != 0; @@ -8149,7 +6116,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->backspaceUnindents; case SCI_SETMOUSEDWELLTIME: - dwellDelay = wParam; + dwellDelay = static_cast(wParam); ticksToDwell = dwellDelay; break; @@ -8157,13 +6124,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return dwellDelay; case SCI_WORDSTARTPOSITION: - return pdoc->ExtendWordSelect(wParam, -1, lParam != 0); + return pdoc->ExtendWordSelect(static_cast(wParam), -1, lParam != 0); case SCI_WORDENDPOSITION: - return pdoc->ExtendWordSelect(wParam, 1, lParam != 0); + return pdoc->ExtendWordSelect(static_cast(wParam), 1, lParam != 0); case SCI_SETWRAPMODE: - if (vs.SetWrapState(wParam)) { + if (vs.SetWrapState(static_cast(wParam))) { xOffset = 0; ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); InvalidateStyleRedraw(); @@ -8175,7 +6142,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.wrapState; case SCI_SETWRAPVISUALFLAGS: - if (vs.SetWrapVisualFlags(wParam)) { + if (vs.SetWrapVisualFlags(static_cast(wParam))) { InvalidateStyleRedraw(); ReconfigureScrollBars(); } @@ -8185,7 +6152,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.wrapVisualFlags; case SCI_SETWRAPVISUALFLAGSLOCATION: - if (vs.SetWrapVisualFlagsLocation(wParam)) { + if (vs.SetWrapVisualFlagsLocation(static_cast(wParam))) { InvalidateStyleRedraw(); } break; @@ -8194,7 +6161,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.wrapVisualFlagsLocation; case SCI_SETWRAPSTARTINDENT: - if (vs.SetWrapVisualStartIndent(wParam)) { + if (vs.SetWrapVisualStartIndent(static_cast(wParam))) { InvalidateStyleRedraw(); ReconfigureScrollBars(); } @@ -8204,7 +6171,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.wrapVisualStartIndent; case SCI_SETWRAPINDENTMODE: - if (vs.SetWrapIndentMode(wParam)) { + if (vs.SetWrapIndentMode(static_cast(wParam))) { InvalidateStyleRedraw(); ReconfigureScrollBars(); } @@ -8214,24 +6181,24 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.wrapIndentMode; case SCI_SETLAYOUTCACHE: - llc.SetLevel(wParam); + view.llc.SetLevel(static_cast(wParam)); break; case SCI_GETLAYOUTCACHE: - return llc.GetLevel(); + return view.llc.GetLevel(); case SCI_SETPOSITIONCACHE: - posCache.SetSize(wParam); + view.posCache.SetSize(wParam); break; case SCI_GETPOSITIONCACHE: - return posCache.GetSize(); + return view.posCache.GetSize(); case SCI_SETSCROLLWIDTH: PLATFORM_ASSERT(wParam > 0); if ((wParam > 0) && (wParam != static_cast(scrollWidth))) { - lineWidthMaxSeen = 0; - scrollWidth = wParam; + view.lineWidthMaxSeen = 0; + scrollWidth = static_cast(wParam); SetScrollBars(); } break; @@ -8251,15 +6218,16 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_LINESSPLIT: - LinesSplit(wParam); + LinesSplit(static_cast(wParam)); break; case SCI_TEXTWIDTH: PLATFORM_ASSERT(wParam < vs.styles.size()); PLATFORM_ASSERT(lParam); - return TextWidth(wParam, CharPtrFromSPtr(lParam)); + return TextWidth(static_cast(wParam), CharPtrFromSPtr(lParam)); case SCI_TEXTHEIGHT: + RefreshStyleData(); return vs.lineHeight; case SCI_SETENDATLASTLINE: @@ -8276,7 +6244,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETCARETSTICKY: PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE); if (wParam <= SC_CARETSTICKY_WHITESPACE) { - caretSticky = wParam; + caretSticky = static_cast(wParam); } break; @@ -8288,10 +6256,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_GETCOLUMN: - return pdoc->GetColumn(wParam); + return pdoc->GetColumn(static_cast(wParam)); case SCI_FINDCOLUMN: - return pdoc->FindColumn(wParam, lParam); + return pdoc->FindColumn(static_cast(wParam), static_cast(lParam)); case SCI_SETHSCROLLBAR : if (horizontalScrollBarVisible != (wParam != 0)) { @@ -8327,7 +6295,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETHIGHLIGHTGUIDE: if ((highlightGuideColumn != static_cast(wParam)) || (wParam > 0)) { - highlightGuideColumn = wParam; + highlightGuideColumn = static_cast(wParam); Redraw(); } break; @@ -8336,11 +6304,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return highlightGuideColumn; case SCI_GETLINEENDPOSITION: - return pdoc->LineEnd(wParam); + return pdoc->LineEnd(static_cast(wParam)); case SCI_SETCODEPAGE: - if (ValidCodePage(wParam)) { - if (pdoc->SetDBCSCodePage(wParam)) { + if (ValidCodePage(static_cast(wParam))) { + if (pdoc->SetDBCSCodePage(static_cast(wParam))) { cs.Clear(); cs.InsertLines(0, pdoc->LinesTotal() - 1); SetAnnotationHeights(0, pdoc->LinesTotal()); @@ -8353,6 +6321,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCODEPAGE: return pdoc->dbcsCodePage; + case SCI_SETIMEINTERACTION: + imeInteraction = static_cast(wParam); + break; + + case SCI_GETIMEINTERACTION: + return imeInteraction; + #ifdef INCLUDE_DEPRECATED_FEATURES case SCI_SETUSEPALETTE: InvalidateStyleRedraw(); @@ -8365,7 +6340,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { // Marker definition and setting case SCI_MARKERDEFINE: if (wParam <= MARKER_MAX) { - vs.markers[wParam].markType = lParam; + vs.markers[wParam].markType = static_cast(lParam); vs.CalcLargestMarkerHeight(); } InvalidateStyleData(); @@ -8380,42 +6355,42 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_MARKERSETFORE: if (wParam <= MARKER_MAX) - vs.markers[wParam].fore = ColourDesired(lParam); + vs.markers[wParam].fore = ColourDesired(static_cast(lParam)); InvalidateStyleData(); RedrawSelMargin(); break; case SCI_MARKERSETBACKSELECTED: if (wParam <= MARKER_MAX) - vs.markers[wParam].backSelected = ColourDesired(lParam); + vs.markers[wParam].backSelected = ColourDesired(static_cast(lParam)); InvalidateStyleData(); RedrawSelMargin(); break; case SCI_MARKERENABLEHIGHLIGHT: - highlightDelimiter.isEnabled = wParam == 1; + marginView.highlightDelimiter.isEnabled = wParam == 1; RedrawSelMargin(); break; case SCI_MARKERSETBACK: if (wParam <= MARKER_MAX) - vs.markers[wParam].back = ColourDesired(lParam); + vs.markers[wParam].back = ColourDesired(static_cast(lParam)); InvalidateStyleData(); RedrawSelMargin(); break; case SCI_MARKERSETALPHA: if (wParam <= MARKER_MAX) - vs.markers[wParam].alpha = lParam; + vs.markers[wParam].alpha = static_cast(lParam); InvalidateStyleRedraw(); break; case SCI_MARKERADD: { - int markerID = pdoc->AddMark(wParam, lParam); + int markerID = pdoc->AddMark(static_cast(wParam), static_cast(lParam)); return markerID; } case SCI_MARKERADDSET: if (lParam != 0) - pdoc->AddMarkSet(wParam, lParam); + pdoc->AddMarkSet(static_cast(wParam), static_cast(lParam)); break; case SCI_MARKERDELETE: - pdoc->DeleteMark(wParam, lParam); + pdoc->DeleteMark(static_cast(wParam), static_cast(lParam)); break; case SCI_MARKERDELETEALL: @@ -8423,13 +6398,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_MARKERGET: - return pdoc->GetMark(wParam); + return pdoc->GetMark(static_cast(wParam)); case SCI_MARKERNEXT: - return pdoc->MarkerNext(wParam, lParam); + return pdoc->MarkerNext(static_cast(wParam), static_cast(lParam)); case SCI_MARKERPREVIOUS: { - for (int iLine = wParam; iLine >= 0; iLine--) { + for (int iLine = static_cast(wParam); iLine >= 0; iLine--) { if ((pdoc->GetMark(iLine) & lParam) != 0) return iLine; } @@ -8446,20 +6421,20 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_RGBAIMAGESETWIDTH: - sizeRGBAImage.x = wParam; + sizeRGBAImage.x = static_cast(wParam); break; case SCI_RGBAIMAGESETHEIGHT: - sizeRGBAImage.y = wParam; + sizeRGBAImage.y = static_cast(wParam); break; case SCI_RGBAIMAGESETSCALE: - scaleRGBAImage = wParam; + scaleRGBAImage = static_cast(wParam); break; case SCI_MARKERDEFINERGBAIMAGE: if (wParam <= MARKER_MAX) { - vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0, reinterpret_cast(lParam)); + vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0f, reinterpret_cast(lParam)); vs.CalcLargestMarkerHeight(); } InvalidateStyleData(); @@ -8468,7 +6443,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETMARGINTYPEN: if (ValidMargin(wParam)) { - vs.ms[wParam].style = lParam; + vs.ms[wParam].style = static_cast(lParam); InvalidateStyleRedraw(); } break; @@ -8483,8 +6458,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (ValidMargin(wParam)) { // Short-circuit if the width is unchanged, to avoid unnecessary redraw. if (vs.ms[wParam].width != lParam) { - lastXChosen += lParam - vs.ms[wParam].width; - vs.ms[wParam].width = lParam; + lastXChosen += static_cast(lParam) - vs.ms[wParam].width; + vs.ms[wParam].width = static_cast(lParam); InvalidateStyleRedraw(); } } @@ -8498,7 +6473,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETMARGINMASKN: if (ValidMargin(wParam)) { - vs.ms[wParam].mask = lParam; + vs.ms[wParam].mask = static_cast(lParam); InvalidateStyleRedraw(); } break; @@ -8524,7 +6499,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETMARGINCURSORN: if (ValidMargin(wParam)) - vs.ms[wParam].cursor = lParam; + vs.ms[wParam].cursor = static_cast(lParam); break; case SCI_GETMARGINCURSORN: @@ -8578,18 +6553,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { InvalidateStyleRedraw(); break; case SCI_SETSTYLEBITS: - vs.EnsureStyle((1 << wParam) - 1); - pdoc->SetStylingBits(wParam); + vs.EnsureStyle(0xff); break; case SCI_GETSTYLEBITS: - return pdoc->stylingBits; + return 8; case SCI_SETLINESTATE: - return pdoc->SetLineState(wParam, lParam); + return pdoc->SetLineState(static_cast(wParam), static_cast(lParam)); case SCI_GETLINESTATE: - return pdoc->GetLineState(wParam); + return pdoc->GetLineState(static_cast(wParam)); case SCI_GETMAXLINESTATE: return pdoc->GetMaxLineState(); @@ -8610,114 +6584,114 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCARETLINEBACK: return vs.caretLineBackground.AsLong(); case SCI_SETCARETLINEBACK: - vs.caretLineBackground = wParam; + vs.caretLineBackground = static_cast(wParam); InvalidateStyleRedraw(); break; case SCI_GETCARETLINEBACKALPHA: return vs.caretLineAlpha; case SCI_SETCARETLINEBACKALPHA: - vs.caretLineAlpha = wParam; + vs.caretLineAlpha = static_cast(wParam); InvalidateStyleRedraw(); break; // Folding messages case SCI_VISIBLEFROMDOCLINE: - return cs.DisplayFromDoc(wParam); + return cs.DisplayFromDoc(static_cast(wParam)); case SCI_DOCLINEFROMVISIBLE: - return cs.DocFromDisplay(wParam); + return cs.DocFromDisplay(static_cast(wParam)); case SCI_WRAPCOUNT: - return WrapCount(wParam); + return WrapCount(static_cast(wParam)); case SCI_SETFOLDLEVEL: { - int prev = pdoc->SetLevel(wParam, lParam); - if (prev != lParam) + int prev = pdoc->SetLevel(static_cast(wParam), static_cast(lParam)); + if (prev != static_cast(lParam)) RedrawSelMargin(); return prev; } case SCI_GETFOLDLEVEL: - return pdoc->GetLevel(wParam); + return pdoc->GetLevel(static_cast(wParam)); case SCI_GETLASTCHILD: - return pdoc->GetLastChild(wParam, lParam); + return pdoc->GetLastChild(static_cast(wParam), static_cast(lParam)); case SCI_GETFOLDPARENT: - return pdoc->GetFoldParent(wParam); + return pdoc->GetFoldParent(static_cast(wParam)); case SCI_SHOWLINES: - cs.SetVisible(wParam, lParam, true); + cs.SetVisible(static_cast(wParam), static_cast(lParam), true); SetScrollBars(); Redraw(); break; case SCI_HIDELINES: if (wParam > 0) - cs.SetVisible(wParam, lParam, false); + cs.SetVisible(static_cast(wParam), static_cast(lParam), false); SetScrollBars(); Redraw(); break; case SCI_GETLINEVISIBLE: - return cs.GetVisible(wParam); + return cs.GetVisible(static_cast(wParam)); case SCI_GETALLLINESVISIBLE: return cs.HiddenLines() ? 0 : 1; case SCI_SETFOLDEXPANDED: - SetFoldExpanded(wParam, lParam != 0); + SetFoldExpanded(static_cast(wParam), lParam != 0); break; case SCI_GETFOLDEXPANDED: - return cs.GetExpanded(wParam); + return cs.GetExpanded(static_cast(wParam)); case SCI_SETAUTOMATICFOLD: - foldAutomatic = wParam; + foldAutomatic = static_cast(wParam); break; case SCI_GETAUTOMATICFOLD: return foldAutomatic; case SCI_SETFOLDFLAGS: - foldFlags = wParam; + foldFlags = static_cast(wParam); Redraw(); break; case SCI_TOGGLEFOLD: - FoldLine(wParam, SC_FOLDACTION_TOGGLE); + FoldLine(static_cast(wParam), SC_FOLDACTION_TOGGLE); break; case SCI_FOLDLINE: - FoldLine(wParam, lParam); + FoldLine(static_cast(wParam), static_cast(lParam)); break; case SCI_FOLDCHILDREN: - FoldExpand(wParam, lParam, pdoc->GetLevel(wParam)); + FoldExpand(static_cast(wParam), static_cast(lParam), pdoc->GetLevel(static_cast(wParam))); break; case SCI_FOLDALL: - FoldAll(wParam); + FoldAll(static_cast(wParam)); break; case SCI_EXPANDCHILDREN: - FoldExpand(wParam, SC_FOLDACTION_EXPAND, lParam); + FoldExpand(static_cast(wParam), SC_FOLDACTION_EXPAND, static_cast(lParam)); break; case SCI_CONTRACTEDFOLDNEXT: - return ContractedFoldNext(wParam); + return ContractedFoldNext(static_cast(wParam)); case SCI_ENSUREVISIBLE: - EnsureLineVisible(wParam, false); + EnsureLineVisible(static_cast(wParam), false); break; case SCI_ENSUREVISIBLEENFORCEPOLICY: - EnsureLineVisible(wParam, true); + EnsureLineVisible(static_cast(wParam), true); break; case SCI_SCROLLRANGE: - ScrollRange(SelectionRange(lParam, wParam)); + ScrollRange(SelectionRange(static_cast(wParam), static_cast(lParam))); break; case SCI_SEARCHANCHOR: @@ -8729,18 +6703,18 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return SearchText(iMessage, wParam, lParam); case SCI_SETXCARETPOLICY: - caretXPolicy = wParam; - caretXSlop = lParam; + caretXPolicy = static_cast(wParam); + caretXSlop = static_cast(lParam); break; case SCI_SETYCARETPOLICY: - caretYPolicy = wParam; - caretYSlop = lParam; + caretYPolicy = static_cast(wParam); + caretYSlop = static_cast(lParam); break; case SCI_SETVISIBLEPOLICY: - visiblePolicy = wParam; - visibleSlop = lParam; + visiblePolicy = static_cast(wParam); + visibleSlop = static_cast(lParam); break; case SCI_LINESONSCREEN: @@ -8748,19 +6722,19 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETSELFORE: vs.selColours.fore = ColourOptional(wParam, lParam); - vs.selAdditionalForeground = ColourDesired(lParam); + vs.selAdditionalForeground = ColourDesired(static_cast(lParam)); InvalidateStyleRedraw(); break; case SCI_SETSELBACK: vs.selColours.back = ColourOptional(wParam, lParam); - vs.selAdditionalBackground = ColourDesired(lParam); + vs.selAdditionalBackground = ColourDesired(static_cast(lParam)); InvalidateStyleRedraw(); break; case SCI_SETSELALPHA: - vs.selAlpha = wParam; - vs.selAdditionalAlpha = wParam; + vs.selAlpha = static_cast(wParam); + vs.selAdditionalAlpha = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -8786,7 +6760,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_SETCARETFORE: - vs.caretcolour = ColourDesired(wParam); + vs.caretcolour = ColourDesired(static_cast(wParam)); InvalidateStyleRedraw(); break; @@ -8795,7 +6769,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETCARETSTYLE: if (wParam <= CARETSTYLE_BLOCK) - vs.caretStyle = wParam; + vs.caretStyle = static_cast(wParam); else /* Default to the line caret */ vs.caretStyle = CARETSTYLE_LINE; @@ -8811,7 +6785,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { else if (wParam >= 3) vs.caretWidth = 3; else - vs.caretWidth = wParam; + vs.caretWidth = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -8819,13 +6793,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.caretWidth; case SCI_ASSIGNCMDKEY: - kmap.AssignCmdKey(Platform::LowShortFromLong(wParam), - Platform::HighShortFromLong(wParam), lParam); + kmap.AssignCmdKey(Platform::LowShortFromLong(static_cast(wParam)), + Platform::HighShortFromLong(static_cast(wParam)), static_cast(lParam)); break; case SCI_CLEARCMDKEY: - kmap.AssignCmdKey(Platform::LowShortFromLong(wParam), - Platform::HighShortFromLong(wParam), SCI_NULL); + kmap.AssignCmdKey(Platform::LowShortFromLong(static_cast(wParam)), + Platform::HighShortFromLong(static_cast(wParam)), SCI_NULL); break; case SCI_CLEARALLCMDKEYS: @@ -8834,23 +6808,55 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICSETSTYLE: if (wParam <= INDIC_MAX) { - vs.indicators[wParam].style = lParam; + vs.indicators[wParam].sacNormal.style = static_cast(lParam); + vs.indicators[wParam].sacHover.style = static_cast(lParam); InvalidateStyleRedraw(); } break; case SCI_INDICGETSTYLE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0; + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.style : 0; case SCI_INDICSETFORE: if (wParam <= INDIC_MAX) { - vs.indicators[wParam].fore = ColourDesired(lParam); + vs.indicators[wParam].sacNormal.fore = ColourDesired(static_cast(lParam)); + vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast(lParam)); InvalidateStyleRedraw(); } break; case SCI_INDICGETFORE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.AsLong() : 0; + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.fore.AsLong() : 0; + + case SCI_INDICSETHOVERSTYLE: + if (wParam <= INDIC_MAX) { + vs.indicators[wParam].sacHover.style = static_cast(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(lParam)); + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETHOVERFORE: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.fore.AsLong() : 0; + + case SCI_INDICSETFLAGS: + if (wParam <= INDIC_MAX) { + vs.indicators[wParam].SetFlags(static_cast(lParam)); + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETFLAGS: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].Flags() : 0; case SCI_INDICSETUNDER: if (wParam <= INDIC_MAX) { @@ -8864,7 +6870,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICSETALPHA: if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) { - vs.indicators[wParam].fillAlpha = lParam; + vs.indicators[wParam].fillAlpha = static_cast(lParam); InvalidateStyleRedraw(); } break; @@ -8874,7 +6880,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICSETOUTLINEALPHA: if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) { - vs.indicators[wParam].outlineAlpha = lParam; + vs.indicators[wParam].outlineAlpha = static_cast(lParam); InvalidateStyleRedraw(); } break; @@ -8883,35 +6889,35 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0; case SCI_SETINDICATORCURRENT: - pdoc->decorations.SetCurrentIndicator(wParam); + pdoc->decorations.SetCurrentIndicator(static_cast(wParam)); break; case SCI_GETINDICATORCURRENT: return pdoc->decorations.GetCurrentIndicator(); case SCI_SETINDICATORVALUE: - pdoc->decorations.SetCurrentValue(wParam); + pdoc->decorations.SetCurrentValue(static_cast(wParam)); break; case SCI_GETINDICATORVALUE: return pdoc->decorations.GetCurrentValue(); case SCI_INDICATORFILLRANGE: - pdoc->DecorationFillRange(wParam, pdoc->decorations.GetCurrentValue(), lParam); + pdoc->DecorationFillRange(static_cast(wParam), pdoc->decorations.GetCurrentValue(), static_cast(lParam)); break; case SCI_INDICATORCLEARRANGE: - pdoc->DecorationFillRange(wParam, 0, lParam); + pdoc->DecorationFillRange(static_cast(wParam), 0, static_cast(lParam)); break; case SCI_INDICATORALLONFOR: - return pdoc->decorations.AllOnFor(wParam); + return pdoc->decorations.AllOnFor(static_cast(wParam)); case SCI_INDICATORVALUEAT: - return pdoc->decorations.ValueAt(wParam, lParam); + return pdoc->decorations.ValueAt(static_cast(wParam), static_cast(lParam)); case SCI_INDICATORSTART: - return pdoc->decorations.Start(wParam, lParam); + return pdoc->decorations.Start(static_cast(wParam), static_cast(lParam)); case SCI_INDICATOREND: - return pdoc->decorations.End(wParam, lParam); + return pdoc->decorations.End(static_cast(wParam), static_cast(lParam)); case SCI_LINEDOWN: case SCI_LINEDOWNEXTEND: @@ -9008,13 +7014,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return KeyCommand(iMessage); case SCI_BRACEHIGHLIGHT: - SetBraceHighlight(static_cast(wParam), lParam, STYLE_BRACELIGHT); + SetBraceHighlight(static_cast(wParam), static_cast(lParam), STYLE_BRACELIGHT); break; case SCI_BRACEHIGHLIGHTINDICATOR: if (lParam >= 0 && lParam <= INDIC_MAX) { vs.braceHighlightIndicatorSet = wParam != 0; - vs.braceHighlightIndicator = lParam; + vs.braceHighlightIndicator = static_cast(lParam); } break; @@ -9025,14 +7031,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_BRACEBADLIGHTINDICATOR: if (lParam >= 0 && lParam <= INDIC_MAX) { vs.braceBadLightIndicatorSet = wParam != 0; - vs.braceBadLightIndicator = lParam; + vs.braceBadLightIndicator = static_cast(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(wParam, lParam); + return pdoc->BraceMatch(static_cast(wParam), static_cast(lParam)); case SCI_GETVIEWEOL: return vs.viewEOL; @@ -9043,7 +7049,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_SETZOOM: - vs.zoomLevel = wParam; + vs.zoomLevel = static_cast(wParam); InvalidateStyleRedraw(); NotifyZoom(); break; @@ -9055,7 +7061,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.theEdge; case SCI_SETEDGECOLUMN: - vs.theEdge = wParam; + vs.theEdge = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9063,7 +7069,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.edgeState; case SCI_SETEDGEMODE: - vs.edgeState = wParam; + vs.edgeState = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9071,7 +7077,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.edgecolour.AsLong(); case SCI_SETEDGECOLOUR: - vs.edgecolour = ColourDesired(wParam); + vs.edgecolour = ColourDesired(static_cast(wParam)); InvalidateStyleRedraw(); break; @@ -9100,25 +7106,25 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_CREATELOADER: { Document *doc = new Document(); doc->AddRef(); - doc->Allocate(wParam); + doc->Allocate(static_cast(wParam)); doc->SetUndoCollection(false); return reinterpret_cast(static_cast(doc)); } case SCI_SETMODEVENTMASK: - modEventMask = wParam; + modEventMask = static_cast(wParam); return 0; case SCI_GETMODEVENTMASK: return modEventMask; case SCI_CONVERTEOLS: - pdoc->ConvertLineEnds(wParam); + pdoc->ConvertLineEnds(static_cast(wParam)); SetSelection(sel.MainCaret(), sel.MainAnchor()); // Ensure selection inside document return 0; case SCI_SETLENGTHFORENCODE: - lengthForEncode = wParam; + lengthForEncode = static_cast(wParam); return 0; case SCI_SELECTIONISRECTANGLE: @@ -9164,8 +7170,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } case SCI_GETLINESELSTARTPOSITION: case SCI_GETLINESELENDPOSITION: { - SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(wParam)), - SelectionPosition(pdoc->LineEnd(wParam))); + SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(static_cast(wParam))), + SelectionPosition(pdoc->LineEnd(static_cast(wParam)))); for (size_t r=0; r(wParam); break; case SCI_GETSTATUS: @@ -9204,7 +7210,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return mouseDownCaptures; case SCI_SETCURSOR: - cursorMode = wParam; + cursorMode = static_cast(wParam); DisplayCursor(Window::cursorText); break; @@ -9212,7 +7218,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return cursorMode; case SCI_SETCONTROLCHARSYMBOL: - vs.controlCharSymbol = wParam; + vs.controlCharSymbol = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9224,7 +7230,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_GETREPRESENTATION: { - Representation *repr = reprs.RepresentationFromCharacter( + const Representation *repr = reprs.RepresentationFromCharacter( reinterpret_cast(wParam), UTF8MaxBytes); if (repr) { return StringResult(lParam, repr->stringRep.c_str()); @@ -9301,13 +7307,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return reinterpret_cast(pdoc->BufferPointer()); case SCI_GETRANGEPOINTER: - return reinterpret_cast(pdoc->RangePointer(wParam, lParam)); + return reinterpret_cast(pdoc->RangePointer(static_cast(wParam), static_cast(lParam))); case SCI_GETGAPPOSITION: return pdoc->GapPosition(); case SCI_SETEXTRAASCENT: - vs.extraAscent = wParam; + vs.extraAscent = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9315,7 +7321,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.extraAscent; case SCI_SETEXTRADESCENT: - vs.extraDescent = wParam; + vs.extraDescent = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9323,7 +7329,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.extraDescent; case SCI_MARGINSETSTYLEOFFSET: - vs.marginStyleOffset = wParam; + vs.marginStyleOffset = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9331,36 +7337,36 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.marginStyleOffset; case SCI_SETMARGINOPTIONS: - marginOptions = wParam; + marginOptions = static_cast(wParam); break; case SCI_GETMARGINOPTIONS: return marginOptions; case SCI_MARGINSETTEXT: - pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam)); + pdoc->MarginSetText(static_cast(wParam), CharPtrFromSPtr(lParam)); break; case SCI_MARGINGETTEXT: { - const StyledText st = pdoc->MarginStyledText(wParam); + const StyledText st = pdoc->MarginStyledText(static_cast(wParam)); return BytesResult(lParam, reinterpret_cast(st.text), st.length); } case SCI_MARGINSETSTYLE: - pdoc->MarginSetStyle(wParam, lParam); + pdoc->MarginSetStyle(static_cast(wParam), static_cast(lParam)); break; case SCI_MARGINGETSTYLE: { - const StyledText st = pdoc->MarginStyledText(wParam); + const StyledText st = pdoc->MarginStyledText(static_cast(wParam)); return st.style; } case SCI_MARGINSETSTYLES: - pdoc->MarginSetStyles(wParam, reinterpret_cast(lParam)); + pdoc->MarginSetStyles(static_cast(wParam), reinterpret_cast(lParam)); break; case SCI_MARGINGETSTYLES: { - const StyledText st = pdoc->MarginStyledText(wParam); + const StyledText st = pdoc->MarginStyledText(static_cast(wParam)); return BytesResult(lParam, st.styles, st.length); } @@ -9369,48 +7375,48 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_ANNOTATIONSETTEXT: - pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam)); + pdoc->AnnotationSetText(static_cast(wParam), CharPtrFromSPtr(lParam)); break; case SCI_ANNOTATIONGETTEXT: { - const StyledText st = pdoc->AnnotationStyledText(wParam); + const StyledText st = pdoc->AnnotationStyledText(static_cast(wParam)); return BytesResult(lParam, reinterpret_cast(st.text), st.length); } case SCI_ANNOTATIONGETSTYLE: { - const StyledText st = pdoc->AnnotationStyledText(wParam); + const StyledText st = pdoc->AnnotationStyledText(static_cast(wParam)); return st.style; } case SCI_ANNOTATIONSETSTYLE: - pdoc->AnnotationSetStyle(wParam, lParam); + pdoc->AnnotationSetStyle(static_cast(wParam), static_cast(lParam)); break; case SCI_ANNOTATIONSETSTYLES: - pdoc->AnnotationSetStyles(wParam, reinterpret_cast(lParam)); + pdoc->AnnotationSetStyles(static_cast(wParam), reinterpret_cast(lParam)); break; case SCI_ANNOTATIONGETSTYLES: { - const StyledText st = pdoc->AnnotationStyledText(wParam); + const StyledText st = pdoc->AnnotationStyledText(static_cast(wParam)); return BytesResult(lParam, st.styles, st.length); } case SCI_ANNOTATIONGETLINES: - return pdoc->AnnotationLines(wParam); + return pdoc->AnnotationLines(static_cast(wParam)); case SCI_ANNOTATIONCLEARALL: pdoc->AnnotationClearAll(); break; case SCI_ANNOTATIONSETVISIBLE: - SetAnnotationVisible(wParam); + SetAnnotationVisible(static_cast(wParam)); break; case SCI_ANNOTATIONGETVISIBLE: return vs.annotationVisible; case SCI_ANNOTATIONSETSTYLEOFFSET: - vs.annotationStyleOffset = wParam; + vs.annotationStyleOffset = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9422,10 +7428,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_ALLOCATEEXTENDEDSTYLES: - return vs.AllocateExtendedStyles(wParam); + return vs.AllocateExtendedStyles(static_cast(wParam)); case SCI_ADDUNDOACTION: - pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE); + pdoc->AddUndoAction(static_cast(wParam), lParam & UNDO_MAY_COALESCE); break; case SCI_SETMOUSESELECTIONRECTANGULARSWITCH: @@ -9452,27 +7458,27 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return additionalSelectionTyping; case SCI_SETMULTIPASTE: - multiPasteMode = wParam; + multiPasteMode = static_cast(wParam); break; case SCI_GETMULTIPASTE: return multiPasteMode; case SCI_SETADDITIONALCARETSBLINK: - additionalCaretsBlink = wParam != 0; + view.additionalCaretsBlink = wParam != 0; InvalidateCaret(); break; case SCI_GETADDITIONALCARETSBLINK: - return additionalCaretsBlink; + return view.additionalCaretsBlink; case SCI_SETADDITIONALCARETSVISIBLE: - additionalCaretsVisible = wParam != 0; + view.additionalCaretsVisible = wParam != 0; InvalidateCaret(); break; case SCI_GETADDITIONALCARETSVISIBLE: - return additionalCaretsVisible; + return view.additionalCaretsVisible; case SCI_GETSELECTIONS: return sel.Count(); @@ -9486,22 +7492,22 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_SETSELECTION: - sel.SetSelection(SelectionRange(wParam, lParam)); + sel.SetSelection(SelectionRange(static_cast(wParam), static_cast(lParam))); Redraw(); break; case SCI_ADDSELECTION: - sel.AddSelection(SelectionRange(wParam, lParam)); + sel.AddSelection(SelectionRange(static_cast(wParam), static_cast(lParam))); Redraw(); break; case SCI_DROPSELECTIONN: - sel.DropSelection(wParam); + sel.DropSelection(static_cast(wParam)); Redraw(); break; case SCI_SETMAINSELECTION: - sel.SetMain(wParam); + sel.SetMain(static_cast(wParam)); Redraw(); break; @@ -9509,7 +7515,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.Main(); case SCI_SETSELECTIONNCARET: - sel.Range(wParam).caret.SetPosition(lParam); + sel.Range(wParam).caret.SetPosition(static_cast(lParam)); Redraw(); break; @@ -9517,14 +7523,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.Range(wParam).caret.Position(); case SCI_SETSELECTIONNANCHOR: - sel.Range(wParam).anchor.SetPosition(lParam); + sel.Range(wParam).anchor.SetPosition(static_cast(lParam)); Redraw(); break; case SCI_GETSELECTIONNANCHOR: return sel.Range(wParam).anchor.Position(); case SCI_SETSELECTIONNCARETVIRTUALSPACE: - sel.Range(wParam).caret.SetVirtualSpace(lParam); + sel.Range(wParam).caret.SetVirtualSpace(static_cast(lParam)); Redraw(); break; @@ -9532,7 +7538,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.Range(wParam).caret.VirtualSpace(); case SCI_SETSELECTIONNANCHORVIRTUALSPACE: - sel.Range(wParam).anchor.SetVirtualSpace(lParam); + sel.Range(wParam).anchor.SetVirtualSpace(static_cast(lParam)); Redraw(); break; @@ -9540,7 +7546,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.Range(wParam).anchor.VirtualSpace(); case SCI_SETSELECTIONNSTART: - sel.Range(wParam).anchor.SetPosition(lParam); + sel.Range(wParam).anchor.SetPosition(static_cast(lParam)); Redraw(); break; @@ -9548,7 +7554,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.Range(wParam).Start().Position(); case SCI_SETSELECTIONNEND: - sel.Range(wParam).caret.SetPosition(lParam); + sel.Range(wParam).caret.SetPosition(static_cast(lParam)); Redraw(); break; @@ -9559,7 +7565,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (!sel.IsRectangular()) sel.Clear(); sel.selType = Selection::selRectangle; - sel.Rectangular().caret.SetPosition(wParam); + sel.Rectangular().caret.SetPosition(static_cast(wParam)); SetRectangularRange(); Redraw(); break; @@ -9571,7 +7577,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (!sel.IsRectangular()) sel.Clear(); sel.selType = Selection::selRectangle; - sel.Rectangular().anchor.SetPosition(wParam); + sel.Rectangular().anchor.SetPosition(static_cast(wParam)); SetRectangularRange(); Redraw(); break; @@ -9583,7 +7589,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (!sel.IsRectangular()) sel.Clear(); sel.selType = Selection::selRectangle; - sel.Rectangular().caret.SetVirtualSpace(wParam); + sel.Rectangular().caret.SetVirtualSpace(static_cast(wParam)); SetRectangularRange(); Redraw(); break; @@ -9595,7 +7601,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (!sel.IsRectangular()) sel.Clear(); sel.selType = Selection::selRectangle; - sel.Rectangular().anchor.SetVirtualSpace(wParam); + sel.Rectangular().anchor.SetVirtualSpace(static_cast(wParam)); SetRectangularRange(); Redraw(); break; @@ -9604,24 +7610,24 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return sel.Rectangular().anchor.VirtualSpace(); case SCI_SETVIRTUALSPACEOPTIONS: - virtualSpaceOptions = wParam; + virtualSpaceOptions = static_cast(wParam); break; case SCI_GETVIRTUALSPACEOPTIONS: return virtualSpaceOptions; case SCI_SETADDITIONALSELFORE: - vs.selAdditionalForeground = ColourDesired(wParam); + vs.selAdditionalForeground = ColourDesired(static_cast(wParam)); InvalidateStyleRedraw(); break; case SCI_SETADDITIONALSELBACK: - vs.selAdditionalBackground = ColourDesired(wParam); + vs.selAdditionalBackground = ColourDesired(static_cast(wParam)); InvalidateStyleRedraw(); break; case SCI_SETADDITIONALSELALPHA: - vs.selAdditionalAlpha = wParam; + vs.selAdditionalAlpha = static_cast(wParam); InvalidateStyleRedraw(); break; @@ -9629,7 +7635,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.selAdditionalAlpha; case SCI_SETADDITIONALCARETFORE: - vs.additionalCaretColour = ColourDesired(wParam); + vs.additionalCaretColour = ColourDesired(static_cast(wParam)); InvalidateStyleRedraw(); break; @@ -9647,11 +7653,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_CHANGELEXERSTATE: - pdoc->ChangeLexerState(wParam, lParam); + pdoc->ChangeLexerState(static_cast(wParam), static_cast(lParam)); break; case SCI_SETIDENTIFIER: - SetCtrlID(wParam); + SetCtrlID(static_cast(wParam)); break; case SCI_GETIDENTIFIER: @@ -9665,7 +7671,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return technology; case SCI_COUNTCHARACTERS: - return pdoc->CountCharacters(wParam, lParam); + return pdoc->CountCharacters(static_cast(wParam), static_cast(lParam)); default: return DefWndProc(iMessage, wParam, lParam); diff --git a/src/stc/scintilla/src/Editor.h b/src/stc/scintilla/src/Editor.h index 8f6ef6828f..1fc907ac72 100644 --- a/src/stc/scintilla/src/Editor.h +++ b/src/stc/scintilla/src/Editor.h @@ -12,17 +12,6 @@ namespace Scintilla { #endif -/** - */ -class Caret { -public: - bool active; - bool on; - int period; - - Caret(); -}; - /** */ class Timer { @@ -47,7 +36,7 @@ public: /** * When platform has a way to generate an event before painting, - * accumulate needed styling range and other work items in + * accumulate needed styling range and other work items in * WorkNeeded to avoid unnecessary work inside paint handler */ class WorkNeeded { @@ -160,16 +149,9 @@ struct WrapPending { } }; -struct PrintParameters { - int magnification; - int colourMode; - WrapMode wrapState; - PrintParameters(); -}; - /** */ -class Editor : public DocWatcher { +class Editor : public EditModel, public DocWatcher { // Private so Editor objects can not be copied Editor(const Editor &); Editor &operator=(const Editor &); @@ -189,32 +171,17 @@ protected: // ScintillaBase subclass needs access to much of Editor Point sizeRGBAImage; float scaleRGBAImage; - PrintParameters printParameters; + MarginView marginView; + EditView view; int cursorMode; - // Highlight current folding block - HighlightDelimiter highlightDelimiter; - bool hasFocus; - bool hideSelection; - bool inOverstrike; - bool drawOverstrikeCaret; bool mouseDownCaptures; - /** 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; - /** In twoPhaseDraw mode, drawing is performed in two phases, first the background - * and then the foreground. This avoids chopping off characters that overlap the next run. */ - bool twoPhaseDraw; - - int xOffset; ///< Horizontal scrolled amount in pixels int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret bool horizontalScrollBarVisible; int scrollWidth; - bool trackLineWidth; - int lineWidthMaxSeen; bool verticalScrollBarVisible; bool endAtLastLine; int caretSticky; @@ -223,25 +190,11 @@ protected: // ScintillaBase subclass needs access to much of Editor bool multipleSelection; bool additionalSelectionTyping; int multiPasteMode; - bool additionalCaretsBlink; - bool additionalCaretsVisible; int virtualSpaceOptions; - Surface *pixmapLine; - Surface *pixmapSelMargin; - Surface *pixmapSelPattern; - Surface *pixmapSelPatternOffset1; - Surface *pixmapIndentGuide; - Surface *pixmapIndentGuideHighlight; - - LineLayoutCache llc; - PositionCache posCache; - SpecialRepresentations reprs; - KeyMap kmap; - Caret caret; Timer timer; Timer autoScrollTimer; enum { autoScrollDelay = 200 }; @@ -250,6 +203,7 @@ protected: // ScintillaBase subclass needs access to much of Editor Point lastClick; unsigned int lastClickTime; + Point doubleClickCloseThreshold; int dwellDelay; int ticksToDwell; bool dwelling; @@ -257,7 +211,6 @@ protected: // ScintillaBase subclass needs access to much of Editor Point ptMouseLast; enum { ddNone, ddInitial, ddDragging } inDragDrop; bool dropWentOutside; - SelectionPosition posDrag; SelectionPosition posDrop; int hotSpotClickPos; int lastXChosen; @@ -274,9 +227,6 @@ protected: // ScintillaBase subclass needs access to much of Editor int lengthForEncode; int needUpdateUI; - Position braces[2]; - int bracesMatchStyle; - int highlightGuideColumn; enum { notPainting, painting, paintAbandoned } paintState; bool paintAbandonedByStyling; @@ -288,8 +238,6 @@ protected: // ScintillaBase subclass needs access to much of Editor int modEventMask; SelectionText drag; - Selection sel; - bool primarySelection; int caretXPolicy; int caretXSlop; ///< Ensure this many pixels visible on both sides of caret @@ -304,22 +252,13 @@ protected: // ScintillaBase subclass needs access to much of Editor bool recordingMacro; - int foldFlags; int foldAutomatic; - ContractionState cs; - - // Hotspot support - int hsStart; - int hsEnd; // Wrapping support - int wrapWidth; WrapPending wrapPending; bool convertPastes; - Document *pdoc; - Editor(); virtual ~Editor(); virtual void Initialise() = 0; @@ -334,34 +273,34 @@ protected: // ScintillaBase subclass needs access to much of Editor // The top left visible point in main window coordinates. Will be 0,0 except for // scroll views where it will be equivalent to the current scroll position. - virtual Point GetVisibleOriginInMain(); - Point DocumentPointFromView(Point ptView); // Convert a point from view space to document + virtual Point GetVisibleOriginInMain() const; + Point DocumentPointFromView(Point ptView) const; // Convert a point from view space to document int TopLineOfMain() const; // Return the line at Main's y coordinate 0 - virtual PRectangle GetClientRectangle(); + virtual PRectangle GetClientRectangle() const; virtual PRectangle GetClientDrawingRectangle(); - PRectangle GetTextRectangle(); + PRectangle GetTextRectangle() const; - int LinesOnScreen(); - int LinesToScroll(); - int MaxScrollPos(); + virtual int LinesOnScreen() const; + int LinesToScroll() const; + int MaxScrollPos() const; SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const; Point LocationFromPosition(SelectionPosition pos); Point LocationFromPosition(int pos); int XFromPosition(int pos); int XFromPosition(SelectionPosition sp); SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true); - int PositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false); + int PositionFromLocation(Point pt, bool canReturnInvalid = false, bool charPosition = false); SelectionPosition SPositionFromLineX(int lineDoc, int x); int PositionFromLineX(int line, int x); int LineFromLocation(Point pt) const; void SetTopLine(int topLineNew); - bool AbandonPaint(); + virtual bool AbandonPaint(); virtual void RedrawRect(PRectangle rc); virtual void DiscardOverdraw(); virtual void Redraw(); void RedrawSelMargin(int line=-1, bool allAfter=false); - PRectangle RectangleFromRange(int start, int end); + PRectangle RectangleFromRange(Range r, int overlap); void InvalidateRange(int start, int end); bool UserVirtualSpace() const { @@ -384,8 +323,8 @@ protected: // ScintillaBase subclass needs access to much of Editor bool SelectionContainsProtected(); int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const; SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const; - int MovePositionTo(SelectionPosition newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true); - int MovePositionTo(int newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true); + int MovePositionTo(SelectionPosition newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true); + int MovePositionTo(int newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true); SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir); SelectionPosition MovePositionSoVisible(int pos, int moveDir); Point PointMainCaret(); @@ -420,6 +359,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void ScrollRange(SelectionRange range); void ShowCaretAtCurrentPosition(); void DropCaret(); + void CaretSetPeriod(int period); void InvalidateCaret(); virtual void UpdateSystemCaret(); @@ -431,31 +371,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void LinesJoin(); void LinesSplit(int pixelWidth); - int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) const; void PaintSelMargin(Surface *surface, PRectangle &rc); - LineLayout *RetrieveLineLayout(int lineNumber); - void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, - int width=LineLayout::wrapWidthInfinite); - ColourDesired SelectionBackground(ViewStyle &vsDraw, bool main) const; - ColourDesired TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) const; - void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); - static void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); - void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, - int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, - bool overrideBackground, ColourDesired background, - bool drawWrapMark, ColourDesired wrapColour); - static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw, - int xStart, PRectangle rcLine, LineLayout *ll, int subLine); - void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under); - void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine); - void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine); - void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, - int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour); - void DrawCarets(Surface *surface, ViewStyle &vsDraw, int line, int xStart, - PRectangle rcLine, LineLayout *ll, int subLine); void RefreshPixMaps(Surface *surfaceWindow); void Paint(Surface *surfaceWindow, PRectangle rcArea); long FormatRange(bool draw, Sci_RangeToFormat *pfr); @@ -471,9 +387,12 @@ protected: // ScintillaBase subclass needs access to much of Editor void FilterSelections(); int InsertSpace(int position, unsigned int spaces); void AddChar(char ch); - virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); - void InsertPaste(SelectionPosition selStart, const char *text, int len); - void ClearSelection(bool retainMultipleSelections=false); + virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false); + void FillVirtualSpace(); + void InsertPaste(const char *text, int len); + enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 }; + void InsertPasteShape(const char *text, int len, PasteShape shape); + void ClearSelection(bool retainMultipleSelections = false); void ClearAll(); void ClearDocumentStyle(); void Cut(); @@ -486,7 +405,6 @@ protected: // ScintillaBase subclass needs access to much of Editor void SelectAll(); void Undo(); void Redo(); - void DelChar(); void DelCharBack(bool allowLineStartDeletion); virtual void ClaimSelection() = 0; @@ -529,7 +447,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); void ContainerNeedsUpdate(int flags); - void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false); + void PageMove(int direction, Selection::selTypes selt=Selection::noSel, bool stuttered = false); enum { cmSame, cmUpper, cmLower }; virtual std::string CaseMapString(const std::string &s, int caseMapping); void ChangeCaseOfSelection(int caseMapping); @@ -537,8 +455,8 @@ protected: // ScintillaBase subclass needs access to much of Editor void Duplicate(bool forLine); virtual void CancelModes(); void NewLine(); - void CursorUpOrDown(int direction, Selection::selTypes sel=Selection::noSel); - void ParaUpOrDown(int direction, Selection::selTypes sel=Selection::noSel); + void CursorUpOrDown(int direction, Selection::selTypes selt=Selection::noSel); + void ParaUpOrDown(int direction, Selection::selTypes selt=Selection::noSel); int StartEndDisplayLine(int pos, bool start); virtual int KeyCommand(unsigned int iMessage); virtual int KeyDefault(int /* key */, int /*modifiers*/); @@ -568,7 +486,7 @@ protected: // ScintillaBase subclass needs access to much of Editor /** PositionInSelection returns true if position in selection. */ bool PositionInSelection(int pos); bool PointInSelection(Point pt); - bool PointInSelMargin(Point pt); + bool PointInSelMargin(Point pt) const; Window::Cursor GetMarginCursor(Point pt) const; void TrimAndSetSelection(int currentPos_, int anchor_); void LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine); @@ -583,7 +501,13 @@ protected: // ScintillaBase subclass needs access to much of Editor void Tick(); bool Idle(); - virtual void SetTicking(bool on) = 0; + virtual void SetTicking(bool on); + enum TickReason { tickCaret, tickScroll, tickWiden, tickDwell, tickPlatform }; + virtual void TickFor(TickReason reason); + virtual bool FineTickerAvailable(); + virtual bool FineTickerRunning(TickReason reason); + virtual void FineTickerStart(TickReason reason, int millis, int tolerance); + virtual void FineTickerCancel(TickReason reason); virtual bool SetIdle(bool) { return false; } virtual void SetMouseCapture(bool on) = 0; virtual bool HaveMouseCapture() = 0; @@ -620,7 +544,9 @@ protected: // ScintillaBase subclass needs access to much of Editor bool PositionIsHotspot(int position) const; bool PointIsHotspot(Point pt); void SetHotSpotRange(Point *pt); - void GetHotSpotRange(int &hsStart, int &hsEnd) const; + Range GetHotSpotRange() const; + void SetHoverIndicatorPosition(int position); + void SetHoverIndicatorPoint(Point pt); int CodePage() const; virtual bool ValidCodePage(int /* codePage */) const { return true; } diff --git a/src/stc/scintilla/src/ExternalLexer.cxx b/src/stc/scintilla/src/ExternalLexer.cxx index 6823208892..25d83ceb8b 100644 --- a/src/stc/scintilla/src/ExternalLexer.cxx +++ b/src/stc/scintilla/src/ExternalLexer.cxx @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include diff --git a/src/stc/scintilla/src/Indicator.cxx b/src/stc/scintilla/src/Indicator.cxx index ac7435156f..62df0b7161 100644 --- a/src/stc/scintilla/src/Indicator.cxx +++ b/src/stc/scintilla/src/Indicator.cxx @@ -11,8 +11,8 @@ #include "Platform.h" #include "Scintilla.h" -#include "XPM.h" #include "Indicator.h" +#include "XPM.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -20,17 +20,24 @@ using namespace Scintilla; static PRectangle PixelGridAlign(const PRectangle &rc) { // Move left and right side to nearest pixel to avoid blurry visuals - return PRectangle(int(rc.left + 0.5), rc.top, int(rc.right + 0.5), rc.bottom); + return PRectangle::FromInts(int(rc.left + 0.5), int(rc.top), int(rc.right + 0.5), int(rc.bottom)); } -void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) { - surface->PenColour(fore); - int ymid = (rc.bottom + rc.top) / 2; - if (style == INDIC_SQUIGGLE) { +void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, DrawState drawState, int value) const { + StyleAndColour sacDraw = sacNormal; + if (Flags() & SC_INDICFLAG_VALUEFORE) { + sacDraw.fore = value & SC_INDICVALUEMASK; + } + if (drawState == drawHover) { + sacDraw = sacHover; + } + surface->PenColour(sacDraw.fore); + int ymid = static_cast(rc.bottom + rc.top) / 2; + if (sacDraw.style == INDIC_SQUIGGLE) { int x = int(rc.left+0.5); int xLast = int(rc.right+0.5); int y = 0; - surface->MoveTo(x, rc.top + y); + surface->MoveTo(x, static_cast(rc.top) + y); while (x < xLast) { if ((x + 2) > xLast) { if (xLast > x) @@ -40,41 +47,41 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r x += 2; y = 2 - y; } - surface->LineTo(x, rc.top + y); + surface->LineTo(x, static_cast(rc.top) + y); } - } else if (style == INDIC_SQUIGGLEPIXMAP) { + } else if (sacDraw.style == INDIC_SQUIGGLEPIXMAP) { PRectangle rcSquiggle = PixelGridAlign(rc); - int width = Platform::Minimum(4000, rcSquiggle.Width()); + int width = Platform::Minimum(4000, static_cast(rcSquiggle.Width())); RGBAImage image(width, 3, 1.0, 0); enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f }; for (int x = 0; x < width; x++) { if (x%2) { // Two halfway columns have a full pixel in middle flanked by light pixels - image.SetPixel(x, 0, fore, alphaSide); - image.SetPixel(x, 1, fore, alphaFull); - image.SetPixel(x, 2, fore, alphaSide); + image.SetPixel(x, 0, sacDraw.fore, alphaSide); + image.SetPixel(x, 1, sacDraw.fore, alphaFull); + image.SetPixel(x, 2, sacDraw.fore, alphaSide); } else { // Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre - image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull); - image.SetPixel(x, 1, fore, alphaSide2); + image.SetPixel(x, (x % 4) ? 0 : 2, sacDraw.fore, alphaFull); + image.SetPixel(x, 1, sacDraw.fore, alphaSide2); } } surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels()); - } else if (style == INDIC_SQUIGGLELOW) { - surface->MoveTo(rc.left, rc.top); - int x = rc.left + 3; + } else if (sacDraw.style == INDIC_SQUIGGLELOW) { + surface->MoveTo(static_cast(rc.left), static_cast(rc.top)); + int x = static_cast(rc.left) + 3; int y = 0; while (x < rc.right) { - surface->LineTo(x-1, rc.top + y); + surface->LineTo(x - 1, static_cast(rc.top) + y); y = 1 - y; - surface->LineTo(x, rc.top + y); + surface->LineTo(x, static_cast(rc.top) + y); x += 3; } - 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; + surface->LineTo(static_cast(rc.right), static_cast(rc.top) + y); // Finish the line + } else if (sacDraw.style == INDIC_TT) { + surface->MoveTo(static_cast(rc.left), ymid); + int x = static_cast(rc.left) + 5; while (x < rc.right) { surface->LineTo(x, ymid); surface->MoveTo(x-3, ymid); @@ -83,81 +90,91 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r surface->MoveTo(x, ymid); x += 5; } - surface->LineTo(rc.right, ymid); // Finish the line + surface->LineTo(static_cast(rc.right), ymid); // Finish the line if (x - 3 <= rc.right) { surface->MoveTo(x-3, ymid); surface->LineTo(x-3, ymid+2); } - } else if (style == INDIC_DIAGONAL) { - int x = rc.left; + } else if (sacDraw.style == INDIC_DIAGONAL) { + int x = static_cast(rc.left); while (x < rc.right) { - surface->MoveTo(x, rc.top+2); + surface->MoveTo(x, static_cast(rc.top) + 2); int endX = x+3; - int endY = rc.top - 1; + int endY = static_cast(rc.top) - 1; if (endX > rc.right) { - endY += endX - rc.right; - endX = rc.right; + endY += endX - static_cast(rc.right); + endX = static_cast(rc.right); } surface->LineTo(endX, endY); x += 4; } - } else if (style == INDIC_STRIKE) { - surface->MoveTo(rc.left, rc.top - 4); - surface->LineTo(rc.right, rc.top - 4); - } else if (style == INDIC_HIDDEN) { + } else if (sacDraw.style == INDIC_STRIKE) { + surface->MoveTo(static_cast(rc.left), static_cast(rc.top) - 4); + surface->LineTo(static_cast(rc.right), static_cast(rc.top) - 4); + } else if ((sacDraw.style == INDIC_HIDDEN) || (sacDraw.style == INDIC_TEXTFORE)) { // Draw nothing - } else if (style == INDIC_BOX) { - surface->MoveTo(rc.left, ymid+1); - surface->LineTo(rc.right, ymid+1); - surface->LineTo(rc.right, rcLine.top+1); - surface->LineTo(rc.left, rcLine.top+1); - surface->LineTo(rc.left, ymid+1); - } else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) { + } else if (sacDraw.style == INDIC_BOX) { + surface->MoveTo(static_cast(rc.left), ymid + 1); + surface->LineTo(static_cast(rc.right), ymid + 1); + surface->LineTo(static_cast(rc.right), static_cast(rcLine.top) + 1); + surface->LineTo(static_cast(rc.left), static_cast(rcLine.top) + 1); + surface->LineTo(static_cast(rc.left), ymid + 1); + } else if (sacDraw.style == INDIC_ROUNDBOX || + sacDraw.style == INDIC_STRAIGHTBOX || + sacDraw.style == INDIC_FULLBOX) { PRectangle rcBox = rcLine; - rcBox.top = rcLine.top + 1; + if (sacDraw.style != INDIC_FULLBOX) + rcBox.top = rcLine.top + 1; rcBox.left = rc.left; rcBox.right = rc.right; - surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0); - } else if (style == INDIC_DOTBOX) { + surface->AlphaRectangle(rcBox, (sacDraw.style == INDIC_ROUNDBOX) ? 1 : 0, + sacDraw.fore, fillAlpha, sacDraw.fore, outlineAlpha, 0); + } else if (sacDraw.style == INDIC_DOTBOX) { PRectangle rcBox = PixelGridAlign(rc); rcBox.top = rcLine.top + 1; rcBox.bottom = rcLine.bottom; // Cap width at 4000 to avoid large allocations when mistakes made - int width = Platform::Minimum(rcBox.Width(), 4000); - RGBAImage image(width, rcBox.Height(), 1.0, 0); + int width = Platform::Minimum(static_cast(rcBox.Width()), 4000); + RGBAImage image(width, static_cast(rcBox.Height()), 1.0, 0); // Draw horizontal lines top and bottom for (int x=0; x(rcBox.Height()); y += static_cast(rcBox.Height()) - 1) { + image.SetPixel(x, y, sacDraw.fore, ((x + y) % 2) ? outlineAlpha : fillAlpha); } } // Draw vertical lines left and right - for (int y=1; y(rcBox.Height()); y++) { for (int x=0; xDrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels()); - } else if (style == INDIC_DASH) { - int x = rc.left; + } else if (sacDraw.style == INDIC_DASH) { + int x = static_cast(rc.left); while (x < rc.right) { surface->MoveTo(x, ymid); - surface->LineTo(Platform::Minimum(x + 4, rc.right), ymid); + surface->LineTo(Platform::Minimum(x + 4, static_cast(rc.right)), ymid); x += 7; } - } else if (style == INDIC_DOTS) { - int x = rc.left; - while (x < rc.right) { - PRectangle rcDot(x, ymid, x+1, ymid+1); - surface->FillRectangle(rcDot, fore); + } else if (sacDraw.style == INDIC_DOTS) { + int x = static_cast(rc.left); + while (x < static_cast(rc.right)) { + PRectangle rcDot = PRectangle::FromInts(x, ymid, x + 1, ymid + 1); + surface->FillRectangle(rcDot, sacDraw.fore); x += 2; } - } else if (style == INDIC_COMPOSITIONTHICK) { + } else if (sacDraw.style == INDIC_COMPOSITIONTHICK) { PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom); - surface->FillRectangle(rcComposition, fore); + surface->FillRectangle(rcComposition, sacDraw.fore); + } else if (sacDraw.style == INDIC_COMPOSITIONTHIN) { + PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom-1); + surface->FillRectangle(rcComposition, sacDraw.fore); } else { // Either INDIC_PLAIN or unknown - surface->MoveTo(rc.left, ymid); - surface->LineTo(rc.right, ymid); + surface->MoveTo(static_cast(rc.left), ymid); + surface->LineTo(static_cast(rc.right), ymid); } } +void Indicator::SetFlags(int attributes_) { + attributes = attributes_; +} diff --git a/src/stc/scintilla/src/Indicator.h b/src/stc/scintilla/src/Indicator.h index 0284a855bc..c22ec71c64 100644 --- a/src/stc/scintilla/src/Indicator.h +++ b/src/stc/scintilla/src/Indicator.h @@ -12,18 +12,45 @@ namespace Scintilla { #endif +struct StyleAndColour { + int style; + ColourDesired fore; + StyleAndColour() : style(INDIC_PLAIN), fore(0, 0, 0) { + } + StyleAndColour(int style_, ColourDesired fore_ = ColourDesired(0, 0, 0)) : style(style_), fore(fore_) { + } + bool operator==(const StyleAndColour &other) const { + return (style == other.style) && (fore == other.fore); + } +}; + /** */ class Indicator { public: - int style; + enum DrawState { drawNormal, drawHover }; + StyleAndColour sacNormal; + StyleAndColour sacHover; bool under; - ColourDesired fore; int fillAlpha; int outlineAlpha; - Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30), outlineAlpha(50) { + int attributes; + Indicator() : under(false), fillAlpha(30), outlineAlpha(50), attributes(0) { } - void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine); + Indicator(int style_, ColourDesired fore_=ColourDesired(0,0,0), bool under_=false, int fillAlpha_=30, int outlineAlpha_=50) : + sacNormal(style_, fore_), sacHover(style_, fore_), under(under_), fillAlpha(fillAlpha_), outlineAlpha(outlineAlpha_), attributes(0) { + } + void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, DrawState drawState, int value) const; + bool IsDynamic() const { + return !(sacNormal == sacHover); + } + bool OverridesTextFore() const { + return sacNormal.style == INDIC_TEXTFORE || sacHover.style == INDIC_TEXTFORE; + } + int Flags() const { + return attributes; + } + void SetFlags(int attributes_); }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/LineMarker.cxx b/src/stc/scintilla/src/LineMarker.cxx index 708e6a320d..98e75ca52e 100644 --- a/src/stc/scintilla/src/LineMarker.cxx +++ b/src/stc/scintilla/src/LineMarker.cxx @@ -37,58 +37,63 @@ void LineMarker::SetXPM(const char *const *linesForm) { void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) { delete image; - image = new RGBAImage(sizeRGBAImage.x, sizeRGBAImage.y, scale, pixelsRGBAImage); + image = new RGBAImage(static_cast(sizeRGBAImage.x), static_cast(sizeRGBAImage.y), scale, pixelsRGBAImage); markType = SC_MARK_RGBAIMAGE; } static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { - PRectangle rc; - rc.left = centreX - armSize; - rc.top = centreY - armSize; - rc.right = centreX + armSize + 1; - rc.bottom = centreY + armSize + 1; + PRectangle rc = PRectangle::FromInts( + centreX - armSize, + centreY - armSize, + centreX + armSize + 1, + centreY + armSize + 1); surface->RectangleDraw(rc, back, fore); } static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { - PRectangle rcCircle; - rcCircle.left = centreX - armSize; - rcCircle.top = centreY - armSize; - rcCircle.right = centreX + armSize + 1; - rcCircle.bottom = centreY + armSize + 1; + PRectangle rcCircle = PRectangle::FromInts( + centreX - armSize, + centreY - armSize, + centreX + armSize + 1, + centreY + armSize + 1); surface->Ellipse(rcCircle, back, fore); } static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { - PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1); + PRectangle rcV = PRectangle::FromInts(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1); surface->FillRectangle(rcV, fore); - PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1); + PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1); surface->FillRectangle(rcH, fore); } static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { - PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1); + PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1); surface->FillRectangle(rcH, fore); } -void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) { - ColourDesired head = back; - ColourDesired body = back; - ColourDesired tail = back; +void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const { + if (customDraw != NULL) { + customDraw(surface, rcWhole, fontForCharacter, tFold, marginStyle, this); + return; + } + + ColourDesired colourHead = back; + ColourDesired colourBody = back; + ColourDesired colourTail = back; switch (tFold) { case LineMarker::head : case LineMarker::headWithTail : - head = backSelected; - tail = backSelected; + colourHead = backSelected; + colourTail = backSelected; break; case LineMarker::body : - head = backSelected; - body = backSelected; + colourHead = backSelected; + colourBody = backSelected; break; case LineMarker::tail : - body = backSelected; - tail = backSelected; + colourBody = backSelected; + colourTail = backSelected; break; default : // LineMarker::undefined @@ -102,9 +107,9 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac if ((markType == SC_MARK_RGBAIMAGE) && (image)) { // Make rectangle just large enough to fit image centred on centre of rcWhole PRectangle rcImage; - rcImage.top = static_cast(((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2); + rcImage.top = ((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2; rcImage.bottom = rcImage.top + image->GetScaledHeight(); - rcImage.left = static_cast(((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2); + rcImage.left = ((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2; rcImage.right = rcImage.left + image->GetScaledWidth(); surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels()); return; @@ -113,17 +118,17 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac PRectangle rc = rcWhole; rc.top++; rc.bottom--; - int minDim = Platform::Minimum(rc.Width(), rc.Height()); + int minDim = Platform::Minimum(static_cast(rc.Width()), static_cast(rc.Height())); minDim--; // Ensure does not go beyond edge - int centreX = floor((rc.right + rc.left) / 2.0); - int centreY = floor((rc.bottom + rc.top) / 2.0); + int centreX = static_cast(floor((rc.right + rc.left) / 2.0)); + int centreY = static_cast(floor((rc.bottom + rc.top) / 2.0)); int dimOn2 = minDim / 2; int dimOn4 = minDim / 4; int blobSize = dimOn2-1; int armSize = dimOn2-2; if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) { // On textual margins move marker to the left to try to avoid overlapping the text - centreX = rc.left + dimOn2 + 1; + centreX = static_cast(rc.left) + dimOn2 + 1; } if (markType == SC_MARK_ROUNDRECT) { PRectangle rcRounded = rc; @@ -131,51 +136,51 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac rcRounded.right = rc.right - 1; surface->RoundedRectangle(rcRounded, fore, back); } else if (markType == SC_MARK_CIRCLE) { - PRectangle rcCircle; - rcCircle.left = centreX - dimOn2; - rcCircle.top = centreY - dimOn2; - rcCircle.right = centreX + dimOn2; - rcCircle.bottom = centreY + dimOn2; + PRectangle rcCircle = PRectangle::FromInts( + centreX - dimOn2, + centreY - dimOn2, + centreX + dimOn2, + centreY + dimOn2); surface->Ellipse(rcCircle, fore, back); } else if (markType == SC_MARK_ARROW) { Point pts[] = { - Point(centreX - dimOn4, centreY - dimOn2), - Point(centreX - dimOn4, centreY + dimOn2), - Point(centreX + dimOn2 - dimOn4, centreY), + Point::FromInts(centreX - dimOn4, centreY - dimOn2), + Point::FromInts(centreX - dimOn4, centreY + dimOn2), + Point::FromInts(centreX + dimOn2 - dimOn4, centreY), }; surface->Polygon(pts, ELEMENTS(pts), fore, back); } else if (markType == SC_MARK_ARROWDOWN) { Point pts[] = { - Point(centreX - dimOn2, centreY - dimOn4), - Point(centreX + dimOn2, centreY - dimOn4), - Point(centreX, centreY + dimOn2 - dimOn4), + Point::FromInts(centreX - dimOn2, centreY - dimOn4), + Point::FromInts(centreX + dimOn2, centreY - dimOn4), + Point::FromInts(centreX, centreY + dimOn2 - dimOn4), }; surface->Polygon(pts, ELEMENTS(pts), fore, back); } else if (markType == SC_MARK_PLUS) { 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), + Point::FromInts(centreX - armSize, centreY - 1), + Point::FromInts(centreX - 1, centreY - 1), + Point::FromInts(centreX - 1, centreY - armSize), + Point::FromInts(centreX + 1, centreY - armSize), + Point::FromInts(centreX + 1, centreY - 1), + Point::FromInts(centreX + armSize, centreY -1), + Point::FromInts(centreX + armSize, centreY +1), + Point::FromInts(centreX + 1, centreY + 1), + Point::FromInts(centreX + 1, centreY + armSize), + Point::FromInts(centreX - 1, centreY + armSize), + Point::FromInts(centreX - 1, centreY + 1), + Point::FromInts(centreX - armSize, centreY + 1), }; surface->Polygon(pts, ELEMENTS(pts), fore, back); } else if (markType == SC_MARK_MINUS) { Point pts[] = { - Point(centreX - armSize, centreY - 1), - Point(centreX + armSize, centreY -1), - Point(centreX + armSize, centreY +1), - Point(centreX - armSize, centreY + 1), + Point::FromInts(centreX - armSize, centreY - 1), + Point::FromInts(centreX + armSize, centreY -1), + Point::FromInts(centreX + armSize, centreY +1), + Point::FromInts(centreX - armSize, centreY + 1), }; surface->Polygon(pts, ELEMENTS(pts), fore, back); @@ -192,69 +197,69 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac // An invisible marker so don't draw anything } else if (markType == SC_MARK_VLINE) { - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); - surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); } else if (markType == SC_MARK_LCORNER) { - surface->PenColour(tail); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourTail); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY); - surface->LineTo(rc.right - 1, centreY); + surface->LineTo(static_cast(rc.right) - 1, centreY); } else if (markType == SC_MARK_TCORNER) { - surface->PenColour(tail); + surface->PenColour(colourTail); surface->MoveTo(centreX, centreY); - surface->LineTo(rc.right - 1, centreY); + surface->LineTo(static_cast(rc.right) - 1, centreY); - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY + 1); - surface->PenColour(head); - surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(colourHead); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); } else if (markType == SC_MARK_LCORNERCURVE) { - surface->PenColour(tail); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourTail); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY-3); surface->LineTo(centreX+3, centreY); - surface->LineTo(rc.right - 1, centreY); + surface->LineTo(static_cast(rc.right) - 1, centreY); } else if (markType == SC_MARK_TCORNERCURVE) { - surface->PenColour(tail); + surface->PenColour(colourTail); surface->MoveTo(centreX, centreY-3); surface->LineTo(centreX+3, centreY); - surface->LineTo(rc.right - 1, centreY); + surface->LineTo(static_cast(rc.right) - 1, centreY); - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY-2); - surface->PenColour(head); - surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(colourHead); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); } else if (markType == SC_MARK_BOXPLUS) { - DrawBox(surface, centreX, centreY, blobSize, fore, head); - DrawPlus(surface, centreX, centreY, blobSize, tail); + DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); + DrawPlus(surface, centreX, centreY, blobSize, colourTail); } else if (markType == SC_MARK_BOXPLUSCONNECTED) { if (tFold == LineMarker::headWithTail) - surface->PenColour(tail); + surface->PenColour(colourTail); else - surface->PenColour(body); + surface->PenColour(colourBody); surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY - blobSize); - DrawBox(surface, centreX, centreY, blobSize, fore, head); - DrawPlus(surface, centreX, centreY, blobSize, tail); + DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); + DrawPlus(surface, centreX, centreY, blobSize, colourTail); if (tFold == LineMarker::body) { - surface->PenColour(tail); + surface->PenColour(colourTail); surface->MoveTo(centreX + 1, centreY + blobSize); surface->LineTo(centreX + blobSize + 1, centreY + blobSize); @@ -265,27 +270,27 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac surface->LineTo(centreX + blobSize + 1, centreY - blobSize); } } else if (markType == SC_MARK_BOXMINUS) { - DrawBox(surface, centreX, centreY, blobSize, fore, head); - DrawMinus(surface, centreX, centreY, blobSize, tail); + DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); + DrawMinus(surface, centreX, centreY, blobSize, colourTail); - surface->PenColour(head); + surface->PenColour(colourHead); surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); } else if (markType == SC_MARK_BOXMINUSCONNECTED) { - DrawBox(surface, centreX, centreY, blobSize, fore, head); - DrawMinus(surface, centreX, centreY, blobSize, tail); + DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); + DrawMinus(surface, centreX, centreY, blobSize, colourTail); - surface->PenColour(head); + surface->PenColour(colourHead); surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY - blobSize); if (tFold == LineMarker::body) { - surface->PenColour(tail); + surface->PenColour(colourTail); surface->MoveTo(centreX + 1, centreY + blobSize); surface->LineTo(centreX + blobSize + 1, centreY + blobSize); @@ -296,43 +301,43 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac surface->LineTo(centreX + blobSize + 1, centreY - blobSize); } } else if (markType == SC_MARK_CIRCLEPLUS) { - DrawCircle(surface, centreX, centreY, blobSize, fore, head); - DrawPlus(surface, centreX, centreY, blobSize, tail); + DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); + DrawPlus(surface, centreX, centreY, blobSize, colourTail); } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) { if (tFold == LineMarker::headWithTail) - surface->PenColour(tail); + surface->PenColour(colourTail); else - surface->PenColour(body); + surface->PenColour(colourBody); surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY - blobSize); - DrawCircle(surface, centreX, centreY, blobSize, fore, head); - DrawPlus(surface, centreX, centreY, blobSize, tail); + DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); + DrawPlus(surface, centreX, centreY, blobSize, colourTail); } else if (markType == SC_MARK_CIRCLEMINUS) { - surface->PenColour(head); + surface->PenColour(colourHead); surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); - DrawCircle(surface, centreX, centreY, blobSize, fore, head); - DrawMinus(surface, centreX, centreY, blobSize, tail); + DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); + DrawMinus(surface, centreX, centreY, blobSize, colourTail); } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) { - surface->PenColour(head); + surface->PenColour(colourHead); surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, static_cast(rcWhole.bottom)); - surface->PenColour(body); - surface->MoveTo(centreX, rcWhole.top); + surface->PenColour(colourBody); + surface->MoveTo(centreX, static_cast(rcWhole.top)); surface->LineTo(centreX, centreY - blobSize); - DrawCircle(surface, centreX, centreY, blobSize, fore, head); - DrawMinus(surface, centreX, centreY, blobSize, tail); + DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); + DrawMinus(surface, centreX, centreY, blobSize, colourTail); } else if (markType >= SC_MARK_CHARACTER) { char character[1]; @@ -344,11 +349,11 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac character, 1, fore, back); } else if (markType == SC_MARK_DOTDOTDOT) { - int right = centreX - 6; + XYPOSITION right = static_cast(centreX - 6); for (int b=0; b<3; b++) { PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2); surface->FillRectangle(rcBlob, fore); - right += 5; + right += 5.0f; } } else if (markType == SC_MARK_ARROWS) { surface->PenColour(fore); @@ -363,14 +368,14 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac } } else if (markType == 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), + Point::FromInts(centreX, centreY + dimOn2), + Point::FromInts(centreX + dimOn2, centreY), + Point::FromInts(centreX, centreY - dimOn2), + Point::FromInts(centreX, centreY - dimOn4), + Point::FromInts(centreX - dimOn4, centreY - dimOn4), + Point::FromInts(centreX - dimOn4, centreY + dimOn4), + Point::FromInts(centreX, centreY + dimOn4), + Point::FromInts(centreX, centreY + dimOn2), }; surface->Polygon(pts, ELEMENTS(pts), fore, back); } else if (markType == SC_MARK_LEFTRECT) { @@ -380,11 +385,11 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac } else if (markType == SC_MARK_BOOKMARK) { int halfHeight = minDim / 3; Point pts[] = { - Point(rc.left, centreY-halfHeight), - Point(rc.right-3, centreY-halfHeight), - Point(rc.right-3-halfHeight, centreY), - Point(rc.right-3, centreY+halfHeight), - Point(rc.left, centreY+halfHeight), + Point::FromInts(static_cast(rc.left), centreY-halfHeight), + Point::FromInts(static_cast(rc.right) - 3, centreY - halfHeight), + Point::FromInts(static_cast(rc.right) - 3 - halfHeight, centreY), + Point::FromInts(static_cast(rc.right) - 3, centreY + halfHeight), + Point::FromInts(static_cast(rc.left), centreY + halfHeight), }; surface->Polygon(pts, ELEMENTS(pts), fore, back); } else { // SC_MARK_FULLRECT diff --git a/src/stc/scintilla/src/LineMarker.h b/src/stc/scintilla/src/LineMarker.h index c8c9e10a19..6a5fe74924 100644 --- a/src/stc/scintilla/src/LineMarker.h +++ b/src/stc/scintilla/src/LineMarker.h @@ -12,6 +12,8 @@ namespace Scintilla { #endif +typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, int tFold, int marginStyle, const void *lineMarker); + /** */ class LineMarker { @@ -25,6 +27,11 @@ public: int alpha; XPM *pxpm; RGBAImage *image; + /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native + * Draw function for drawing line markers. Allow those platforms to override + * it instead of creating a new method(s) in the Surface class that existing + * platforms must implement as empty. */ + DrawLineMarkerFn customDraw; LineMarker() { markType = SC_MARK_CIRCLE; fore = ColourDesired(0,0,0); @@ -33,6 +40,7 @@ public: alpha = SC_ALPHA_NOALPHA; pxpm = NULL; image = NULL; + customDraw = NULL; } LineMarker(const LineMarker &) { // Defined to avoid pxpm being blindly copied, not as a complete copy constructor @@ -43,6 +51,7 @@ public: alpha = SC_ALPHA_NOALPHA; pxpm = NULL; image = NULL; + customDraw = NULL; } ~LineMarker() { delete pxpm; @@ -60,13 +69,14 @@ public: pxpm = NULL; delete image; image = NULL; + customDraw = NULL; } return *this; } void SetXPM(const char *textForm); void SetXPM(const char *const *linesForm); void SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage); - void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold, int marginStyle); + void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const; }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/MarginView.cxx b/src/stc/scintilla/src/MarginView.cxx new file mode 100644 index 0000000000..a6fc1f40b3 --- /dev/null +++ b/src/stc/scintilla/src/MarginView.cxx @@ -0,0 +1,470 @@ +// Scintilla source code edit control +/** @file MarginView.cxx + ** Defines the appearance of the editor margin. + **/ +// Copyright 1998-2014 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "ILexer.h" +#include "Scintilla.h" + +#include "StringCopy.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "UniConversion.h" +#include "Selection.h" +#include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +void DrawWrapMarker(Surface *surface, PRectangle rcPlace, + bool isEndMarker, ColourDesired wrapColour) { + surface->PenColour(wrapColour); + + enum { xa = 1 }; // gap before start + int w = static_cast(rcPlace.right - rcPlace.left) - xa - 1; + + bool xStraight = isEndMarker; // x-mirrored symbol for start marker + + int x0 = static_cast(xStraight ? rcPlace.left : rcPlace.right - 1); + int y0 = static_cast(rcPlace.top); + + int dy = static_cast(rcPlace.bottom - rcPlace.top) / 5; + int y = static_cast(rcPlace.bottom - rcPlace.top) / 2 + dy; + + struct Relative { + Surface *surface; + int xBase; + int xDir; + int yBase; + int yDir; + void MoveTo(int xRelative, int yRelative) { + surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative); + } + void LineTo(int xRelative, int yRelative) { + surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative); + } + }; + Relative rel = { surface, x0, xStraight ? 1 : -1, y0, 1 }; + + // arrow head + rel.MoveTo(xa, y); + rel.LineTo(xa + 2 * w / 3, y - dy); + rel.MoveTo(xa, y); + rel.LineTo(xa + 2 * w / 3, y + dy); + + // arrow body + rel.MoveTo(xa, y); + rel.LineTo(xa + w, y); + rel.LineTo(xa + w, y - 2 * dy); + rel.LineTo(xa - 1, // on windows lineto is exclusive endpoint, perhaps GTK not... + y - 2 * dy); +} + +MarginView::MarginView() { + pixmapSelMargin = 0; + pixmapSelPattern = 0; + pixmapSelPatternOffset1 = 0; + wrapMarkerPaddingRight = 3; + customDrawWrapMarker = NULL; +} + +void MarginView::DropGraphics(bool freeObjects) { + if (freeObjects) { + delete pixmapSelMargin; + pixmapSelMargin = 0; + delete pixmapSelPattern; + pixmapSelPattern = 0; + delete pixmapSelPatternOffset1; + pixmapSelPatternOffset1 = 0; + } else { + if (pixmapSelMargin) + pixmapSelMargin->Release(); + if (pixmapSelPattern) + pixmapSelPattern->Release(); + if (pixmapSelPatternOffset1) + pixmapSelPatternOffset1->Release(); + } +} + +void MarginView::AllocateGraphics(const ViewStyle &vsDraw) { + if (!pixmapSelMargin) + pixmapSelMargin = Surface::Allocate(vsDraw.technology); + if (!pixmapSelPattern) + pixmapSelPattern = Surface::Allocate(vsDraw.technology); + if (!pixmapSelPatternOffset1) + pixmapSelPatternOffset1 = Surface::Allocate(vsDraw.technology); +} + +void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { + if (!pixmapSelPattern->Initialised()) { + const int patternSize = 8; + pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid); + pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid); + // This complex procedure is to reproduce the checkerboard 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 = PRectangle::FromInts(0, 0, patternSize, patternSize); + + // Initialize default colours based on the chrome colour scheme. Typically the highlight is white. + ColourDesired colourFMFill = vsDraw.selbar; + ColourDesired colourFMStripes = vsDraw.selbarlight; + + if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) { + // User has chosen an unusual chrome colour scheme so just use the highlight edge colour. + // (Typically, the highlight colour is white.) + colourFMFill = vsDraw.selbarlight; + } + + if (vsDraw.foldmarginColour.isSet) { + // override default fold margin colour + colourFMFill = vsDraw.foldmarginColour; + } + if (vsDraw.foldmarginHighlightColour.isSet) { + // override default fold margin highlight colour + colourFMStripes = vsDraw.foldmarginHighlightColour; + } + + pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); + pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes); + for (int y = 0; y < patternSize; y++) { + for (int x = y % 2; x < patternSize; x += 2) { + PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1); + pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes); + pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill); + } + } + } +} + +static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) { + if (vs.markers[markerCheck].markType == SC_MARK_EMPTY) + return markerDefault; + return markerCheck; +} + +void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin, + const EditModel &model, const ViewStyle &vs) { + + PRectangle rcSelMargin = rcMargin; + rcSelMargin.right = rcMargin.left; + if (rcSelMargin.bottom < rc.bottom) + rcSelMargin.bottom = rc.bottom; + + Point ptOrigin = model.GetVisibleOriginInMain(); + FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font; + for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { + if (vs.ms[margin].width > 0) { + + rcSelMargin.left = rcSelMargin.right; + rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width; + + if (vs.ms[margin].style != SC_MARGIN_NUMBER) { + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + // Required because of special way brush is created for selection margin + // Ensure patterns line up when scrolling with separate margin view + // by choosing correctly aligned variant. + bool invertPhase = static_cast(ptOrigin.y) & 1; + surface->FillRectangle(rcSelMargin, + invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1); + } else { + ColourDesired colour; + switch (vs.ms[margin].style) { + case SC_MARGIN_BACK: + colour = vs.styles[STYLE_DEFAULT].back; + break; + case SC_MARGIN_FORE: + colour = vs.styles[STYLE_DEFAULT].fore; + break; + default: + colour = vs.styles[STYLE_LINENUMBER].back; + break; + } + surface->FillRectangle(rcSelMargin, colour); + } + } else { + surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back); + } + + const int lineStartPaint = static_cast(rcMargin.top + ptOrigin.y) / vs.lineHeight; + int visibleLine = model.TopLineOfMain() + lineStartPaint; + int yposScreen = lineStartPaint * vs.lineHeight - static_cast(ptOrigin.y); + // Work out whether the top line is whitespace located after a + // lessening of fold level which implies a 'fold tail' but which should not + // be displayed until the last of a sequence of whitespace. + bool needWhiteClosure = false; + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + int level = model.pdoc->GetLevel(model.cs.DocFromDisplay(visibleLine)); + if (level & SC_FOLDLEVELWHITEFLAG) { + int lineBack = model.cs.DocFromDisplay(visibleLine); + int levelPrev = level; + while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { + lineBack--; + levelPrev = model.pdoc->GetLevel(lineBack); + } + if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { + if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) + needWhiteClosure = true; + } + } + if (highlightDelimiter.isEnabled) { + int lastLine = model.cs.DocFromDisplay(topLine + model.LinesOnScreen()) + 1; + model.pdoc->GetHighlightDelimiters(highlightDelimiter, model.pdoc->LineFromPosition(model.sel.MainCaret()), lastLine); + } + } + + // Old code does not know about new markers needed to distinguish all cases + const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, + SC_MARKNUM_FOLDEROPEN, vs); + const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND, + SC_MARKNUM_FOLDER, vs); + + while ((visibleLine < model.cs.LinesDisplayed()) && yposScreen < rc.bottom) { + + PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed()); + const int lineDoc = model.cs.DocFromDisplay(visibleLine); + PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); + const int firstVisibleLine = model.cs.DisplayFromDoc(lineDoc); + const int lastVisibleLine = model.cs.DisplayLastFromDoc(lineDoc); + const bool firstSubLine = visibleLine == firstVisibleLine; + const bool lastSubLine = visibleLine == lastVisibleLine; + + int marks = model.pdoc->GetMark(lineDoc); + if (!firstSubLine) + marks = 0; + + bool headWithTail = false; + + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + // Decide which fold indicator should be displayed + const int level = model.pdoc->GetLevel(lineDoc); + const int levelNext = model.pdoc->GetLevel(lineDoc + 1); + const int levelNum = level & SC_FOLDLEVELNUMBERMASK; + const int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; + if (level & SC_FOLDLEVELHEADERFLAG) { + if (firstSubLine) { + if (levelNum < levelNextNum) { + if (model.cs.GetExpanded(lineDoc)) { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDEROPEN; + else + marks |= 1 << folderOpenMid; + } else { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDER; + else + marks |= 1 << folderEnd; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } else { + if (levelNum < levelNextNum) { + if (model.cs.GetExpanded(lineDoc)) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } + needWhiteClosure = false; + const int firstFollowupLine = model.cs.DocFromDisplay(model.cs.DisplayFromDoc(lineDoc + 1)); + const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine); + const int secondFollowupLineLevelNum = model.pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK; + if (!model.cs.GetExpanded(lineDoc)) { + if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) && + (levelNum > secondFollowupLineLevelNum)) + needWhiteClosure = true; + + if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine)) + headWithTail = true; + } + } else if (level & SC_FOLDLEVELWHITEFLAG) { + if (needWhiteClosure) { + if (levelNext & SC_FOLDLEVELWHITEFLAG) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } else if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + needWhiteClosure = false; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + needWhiteClosure = false; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + if (levelNextNum < levelNum) { + if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + } + } else { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } + } else if (levelNum > SC_FOLDLEVELBASE) { + if (levelNextNum < levelNum) { + needWhiteClosure = false; + if (levelNext & SC_FOLDLEVELWHITEFLAG) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + needWhiteClosure = true; + } else if (lastSubLine) { + if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + } + } else { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } else { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } + } + + marks &= vs.ms[margin].mask; + + PRectangle rcMarker = rcSelMargin; + rcMarker.top = static_cast(yposScreen); + rcMarker.bottom = static_cast(yposScreen + vs.lineHeight); + if (vs.ms[margin].style == SC_MARGIN_NUMBER) { + if (firstSubLine) { + char number[100] = ""; + if (lineDoc >= 0) + sprintf(number, "%d", lineDoc + 1); + if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) { + if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) { + int lev = model.pdoc->GetLevel(lineDoc); + sprintf(number, "%c%c %03X %03X", + (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_', + (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_', + lev & SC_FOLDLEVELNUMBERMASK, + lev >> 16 + ); + } else { + int state = model.pdoc->GetLineState(lineDoc); + sprintf(number, "%0X", state); + } + } + PRectangle rcNumber = rcMarker; + // Right justify + XYPOSITION width = surface->WidthText(fontLineNumber, number, static_cast(strlen(number))); + XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding; + rcNumber.left = xpos; + DrawTextNoClipPhase(surface, rcNumber, vs.styles[STYLE_LINENUMBER], + rcNumber.top + vs.maxAscent, number, static_cast(strlen(number)), drawAll); + } else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) { + PRectangle rcWrapMarker = rcMarker; + rcWrapMarker.right -= wrapMarkerPaddingRight; + rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth; + if (customDrawWrapMarker == NULL) { + DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); + } else { + customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); + } + } + } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { + const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc); + if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { + if (firstSubLine) { + surface->FillRectangle(rcMarker, + vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back); + if (vs.ms[margin].style == SC_MARGIN_RTEXT) { + int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin); + rcMarker.left = rcMarker.right - width - 3; + } + DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, + stMargin, 0, stMargin.length, drawAll); + } else { + // if we're displaying annotation lines, color the margin to match the associated document line + const int annotationLines = model.pdoc->AnnotationLines(lineDoc); + if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) { + surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back); + } + } + } + } + + if (marks) { + for (int markBit = 0; (markBit < 32) && marks; markBit++) { + if (marks & 1) { + LineMarker::typeOfFold tFold = LineMarker::undefined; + if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { + if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { + tFold = LineMarker::body; + } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { + if (firstSubLine) { + tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head; + } else { + if (model.cs.GetExpanded(lineDoc) || headWithTail) { + tFold = LineMarker::body; + } else { + tFold = LineMarker::undefined; + } + } + } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { + tFold = LineMarker::tail; + } + } + vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, tFold, vs.ms[margin].style); + } + marks >>= 1; + } + } + + visibleLine++; + yposScreen += vs.lineHeight; + } + } + } + + PRectangle rcBlankMargin = rcMargin; + rcBlankMargin.left = rcSelMargin.right; + surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back); +} + +#ifdef SCI_NAMESPACE +} +#endif + diff --git a/src/stc/scintilla/src/MarginView.h b/src/stc/scintilla/src/MarginView.h new file mode 100644 index 0000000000..ff55646767 --- /dev/null +++ b/src/stc/scintilla/src/MarginView.h @@ -0,0 +1,50 @@ +// Scintilla source code edit control +/** @file MarginView.h + ** Defines the appearance of the editor margin. + **/ +// Copyright 1998-2014 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef MARGINVIEW_H +#define MARGINVIEW_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); + +typedef void (*DrawWrapMarkerFn)(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); + +/** +* MarginView draws the margins. +*/ +class MarginView { +public: + Surface *pixmapSelMargin; + Surface *pixmapSelPattern; + Surface *pixmapSelPatternOffset1; + // Highlight current folding block + HighlightDelimiter highlightDelimiter; + + int wrapMarkerPaddingRight; // right-most pixel padding of wrap markers + /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native + * DrawWrapMarker function for drawing wrap markers. Allow those platforms to + * override it instead of creating a new method in the Surface class that + * existing platforms must implement as empty. */ + DrawWrapMarkerFn customDrawWrapMarker; + + MarginView(); + + void DropGraphics(bool freeObjects); + void AllocateGraphics(const ViewStyle &vsDraw); + void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); + void PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin, + const EditModel &model, const ViewStyle &vs); +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/PerLine.cxx b/src/stc/scintilla/src/PerLine.cxx index 8b0dbc44b7..8fd96cbedf 100644 --- a/src/stc/scintilla/src/PerLine.cxx +++ b/src/stc/scintilla/src/PerLine.cxx @@ -7,6 +7,7 @@ #include +#include #include #include "Platform.h" @@ -484,3 +485,72 @@ int LineAnnotation::Lines(int line) const { else return 0; } + +LineTabstops::~LineTabstops() { + Init(); +} + +void LineTabstops::Init() { + for (int line = 0; line < tabstops.Length(); line++) { + delete tabstops[line]; + } + tabstops.DeleteAll(); +} + +void LineTabstops::InsertLine(int line) { + if (tabstops.Length()) { + tabstops.EnsureLength(line); + tabstops.Insert(line, 0); + } +} + +void LineTabstops::RemoveLine(int line) { + if (tabstops.Length() > line) { + delete tabstops[line]; + tabstops.Delete(line); + } +} + +bool LineTabstops::ClearTabstops(int line) { + if (line < tabstops.Length()) { + TabstopList *tl = tabstops[line]; + if (tl) { + tl->clear(); + return true; + } + } + return false; +} + +bool LineTabstops::AddTabstop(int line, int x) { + tabstops.EnsureLength(line + 1); + if (!tabstops[line]) { + tabstops[line] = new TabstopList(); + } + + TabstopList *tl = tabstops[line]; + if (tl) { + // tabstop positions are kept in order - insert in the right place + std::vector::iterator it = std::lower_bound(tl->begin(), tl->end(), x); + // don't insert duplicates + if (it == tl->end() || *it != x) { + tl->insert(it, x); + return true; + } + } + return false; +} + +int LineTabstops::GetNextTabstop(int line, int x) const { + if (line < tabstops.Length()) { + TabstopList *tl = tabstops[line]; + if (tl) { + for (size_t i = 0; i < tl->size(); i++) { + if ((*tl)[i] > x) { + return (*tl)[i]; + } + } + } + } + return 0; +} diff --git a/src/stc/scintilla/src/PerLine.h b/src/stc/scintilla/src/PerLine.h index 70d0023e40..4bf1c88fdd 100644 --- a/src/stc/scintilla/src/PerLine.h +++ b/src/stc/scintilla/src/PerLine.h @@ -112,6 +112,23 @@ public: int Lines(int line) const; }; +typedef std::vector TabstopList; + +class LineTabstops : public PerLine { + SplitVector tabstops; +public: + LineTabstops() { + } + virtual ~LineTabstops(); + virtual void Init(); + virtual void InsertLine(int line); + virtual void RemoveLine(int line); + + bool ClearTabstops(int line); + bool AddTabstop(int line, int x); + int GetNextTabstop(int line, int x) const; +}; + #ifdef SCI_NAMESPACE } #endif diff --git a/src/stc/scintilla/src/PositionCache.cxx b/src/stc/scintilla/src/PositionCache.cxx index f197a65595..860a780d9a 100644 --- a/src/stc/scintilla/src/PositionCache.cxx +++ b/src/stc/scintilla/src/PositionCache.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include "Platform.h" +#include "ILexer.h" #include "Scintilla.h" #include "SplitVector.h" @@ -32,7 +34,6 @@ #include "ViewStyle.h" #include "CharClassify.h" #include "Decoration.h" -#include "ILexer.h" #include "CaseFolder.h" #include "Document.h" #include "UniConversion.h" @@ -54,16 +55,12 @@ LineLayout::LineLayout(int maxLineLength_) : validity(llInvalid), xHighlightGuide(0), highlightColumn(0), - psel(NULL), containsCaret(false), edgeColumn(0), chars(0), styles(0), - styleBitsSet(0), - indicators(0), positions(0), - hsStart(0), - hsEnd(0), + hotspot(0,0), widthLine(wrapWidthInfinite), lines(1), wrapIndent(0) { @@ -81,7 +78,6 @@ void LineLayout::Resize(int maxLineLength_) { Free(); chars = new char[maxLineLength_ + 1]; styles = new unsigned char[maxLineLength_ + 1]; - indicators = new char[maxLineLength_ + 1]; // Extra position allocated as sometimes the Windows // GetTextExtentExPoint API writes an extra element. positions = new XYPOSITION[maxLineLength_ + 1 + 1]; @@ -94,8 +90,6 @@ void LineLayout::Free() { chars = 0; delete []styles; styles = 0; - delete []indicators; - indicators = 0; delete []positions; positions = 0; delete []lineStarts; @@ -153,7 +147,7 @@ void LineLayout::SetLineStart(int line, int start) { lineStarts[line] = start; } -void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[], +void LineLayout::SetBracesHighlight(Range rangeLine, const Position braces[], char bracesMatchStyle, int xHighlight, bool ignoreStyle) { if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) { int braceOffset = braces[0] - rangeLine.start; @@ -175,7 +169,7 @@ void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[], } } -void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle) { +void LineLayout::RestoreBracesHighlight(Range rangeLine, const Position braces[], bool ignoreStyle) { if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) { int braceOffset = braces[0] - rangeLine.start; if (braceOffset < numCharsInLine) { @@ -232,7 +226,7 @@ Point LineLayout::PointFromPosition(int posInLine, int lineHeight) const { for (int subLine = 0; subLine < lines; subLine++) { const Range rangeSubLine = SubLineRange(subLine); if (posInLine >= rangeSubLine.start) { - pt.y = subLine*lineHeight; + pt.y = static_cast(subLine*lineHeight); if (posInLine <= rangeSubLine.end) { pt.x = positions[posInLine] - positions[rangeSubLine.start]; if (rangeSubLine.start != 0) // Wrapped lines may be indented @@ -410,11 +404,11 @@ void SpecialRepresentations::ClearRepresentation(const char *charBytes) { } } -Representation *SpecialRepresentations::RepresentationFromCharacter(const char *charBytes, size_t len) { +const Representation *SpecialRepresentations::RepresentationFromCharacter(const char *charBytes, size_t len) const { PLATFORM_ASSERT(len <= 4); if (!startByteHasReprs[static_cast(charBytes[0])]) return 0; - MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, len)); + MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len)); if (it != mapReprs.end()) { return &(it->second); } @@ -445,13 +439,12 @@ void BreakFinder::Insert(int val) { } } -BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, - int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_) : +BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, int posLineStart_, + int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw) : ll(ll_), - lineStart(lineStart_), - lineEnd(lineEnd_), + lineRange(lineRange_), posLineStart(posLineStart_), - nextBreak(lineStart_), + nextBreak(lineRange_.start), saeCurrentPos(0), saeNext(0), subBreak(-1), @@ -462,18 +455,18 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL // Search for first visible break // First find the first visible character if (xStart > 0.0f) - nextBreak = ll->FindBefore(xStart, lineStart, lineEnd); + nextBreak = ll->FindBefore(static_cast(xStart), lineRange.start, lineRange.end); // Now back to a style break - while ((nextBreak > lineStart) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) { + while ((nextBreak > lineRange.start) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) { nextBreak--; } if (breakForSelection) { SelectionPosition posStart(posLineStart); - SelectionPosition posEnd(posLineStart + lineEnd); + SelectionPosition posEnd(posLineStart + lineRange.end); SelectionSegment segmentLine(posStart, posEnd); - for (size_t r=0; rpsel->Count(); r++) { - SelectionSegment portion = ll->psel->Range(r).Intersect(segmentLine); + for (size_t r=0; rCount(); r++) { + SelectionSegment portion = psel->Range(r).Intersect(segmentLine); if (!(portion.start == portion.end)) { if (portion.start.IsValid()) Insert(portion.start.Position() - posLineStart); @@ -482,9 +475,19 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL } } } - + if (pvsDraw && pvsDraw->indicatorsSetFore > 0) { + for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { + if (pvsDraw->indicators[deco->indicator].OverridesTextFore()) { + int startPos = deco->rs.EndRun(posLineStart); + while (startPos < (posLineStart + lineRange.end)) { + Insert(startPos - posLineStart); + startPos = deco->rs.EndRun(startPos); + } + } + } + } Insert(ll->edgeColumn); - Insert(lineEnd); + Insert(lineRange.end); saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1; } @@ -494,19 +497,19 @@ BreakFinder::~BreakFinder() { TextSegment BreakFinder::Next() { if (subBreak == -1) { int prev = nextBreak; - while (nextBreak < lineEnd) { + while (nextBreak < lineRange.end) { int charWidth = 1; if (encodingFamily == efUnicode) - charWidth = UTF8DrawBytes(reinterpret_cast(ll->chars) + nextBreak, lineEnd - nextBreak); + charWidth = UTF8DrawBytes(reinterpret_cast(ll->chars) + nextBreak, lineRange.end - nextBreak); else if (encodingFamily == efDBCS) charWidth = pdoc->IsDBCSLeadByte(ll->chars[nextBreak]) ? 2 : 1; - Representation *repr = preprs->RepresentationFromCharacter(ll->chars + nextBreak, charWidth); + const Representation *repr = preprs->RepresentationFromCharacter(ll->chars + nextBreak, charWidth); if (((nextBreak > 0) && (ll->styles[nextBreak] != ll->styles[nextBreak - 1])) || repr || (nextBreak == saeNext)) { - while ((nextBreak >= saeNext) && (saeNext < lineEnd)) { + while ((nextBreak >= saeNext) && (saeNext < lineRange.end)) { saeCurrentPos++; - saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : lineEnd; + saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : lineRange.end; } if ((nextBreak > prev) || repr) { // Have a segment to report @@ -547,7 +550,7 @@ TextSegment BreakFinder::Next() { } bool BreakFinder::More() const { - return (subBreak >= 0) || (nextBreak < lineEnd); + return (subBreak >= 0) || (nextBreak < lineRange.end); } PositionCacheEntry::PositionCacheEntry() : @@ -563,9 +566,9 @@ void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_, if (s_ && positions_) { positions = new XYPOSITION[len + (len / 4) + 1]; for (unsigned int i=0; i(positions_[i]); + positions[i] = positions_[i]; } - memcpy(reinterpret_cast(positions + len), s_, len); + memcpy(reinterpret_cast(reinterpret_cast(positions + len)), s_, len); } } @@ -584,7 +587,7 @@ void PositionCacheEntry::Clear() { bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const { if ((styleNumber == styleNumber_) && (len == len_) && - (memcmp(reinterpret_cast(positions + len), s_, len)== 0)) { + (memcmp(reinterpret_cast(reinterpret_cast(positions + len)), s_, len)== 0)) { for (unsigned int i=0; i(hashValue % pces.size()); + unsigned int hashValue = PositionCacheEntry::Hash(styleNumber, s, len); + probe = hashValue % pces.size(); if (pces[probe].Retrieve(styleNumber, s, len, positions)) { return; } - int probe2 = static_cast((hashValue * 37) % pces.size()); + unsigned int probe2 = (hashValue * 37) % pces.size(); if (pces[probe2].Retrieve(styleNumber, s, len, positions)) { return; } @@ -672,7 +675,8 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned XYPOSITION xStartSegment = 0; while (startSegment < len) { unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision); - surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment); + FontAlias fontStyle = vstyle.styles[styleNumber].font; + surface->MeasureWidths(fontStyle, s + startSegment, lenSegment, positions + startSegment); for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) { positions[startSegment + inSeg] += xStartSegment; } @@ -680,9 +684,11 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned startSegment += lenSegment; } } else { - surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions); + FontAlias fontStyle = vstyle.styles[styleNumber].font; + surface->MeasureWidths(fontStyle, s, len, positions); } - if (probe >= 0) { + if (probe < pces.size()) { + // Store into cache clock++; if (clock > 60000) { // Since there are only 16 bits for the clock, wrap it round and diff --git a/src/stc/scintilla/src/PositionCache.h b/src/stc/scintilla/src/PositionCache.h index 871bb6e460..edc0a5ddb3 100644 --- a/src/stc/scintilla/src/PositionCache.h +++ b/src/stc/scintilla/src/PositionCache.h @@ -34,19 +34,15 @@ public: enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity; int xHighlightGuide; bool highlightColumn; - Selection *psel; bool containsCaret; int edgeColumn; char *chars; unsigned char *styles; - int styleBitsSet; - char *indicators; XYPOSITION *positions; char bracePreviousStyles[2]; // Hotspot support - int hsStart; - int hsEnd; + Range hotspot; // Wrapped line support int widthLine; @@ -63,9 +59,9 @@ public: Range SubLineRange(int line) const; bool InLine(int offset, int line) const; void SetLineStart(int line, int start); - void SetBracesHighlight(Range rangeLine, Position braces[], + void SetBracesHighlight(Range rangeLine, const Position braces[], char bracesMatchStyle, int xHighlight, bool ignoreStyle); - void RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle); + void RestoreBracesHighlight(Range rangeLine, const Position braces[], bool ignoreStyle); int FindBefore(XYPOSITION x, int lower, int upper) const; int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const; Point PointFromPosition(int posInLine, int lineHeight) const; @@ -108,10 +104,10 @@ class PositionCacheEntry { public: PositionCacheEntry(); ~PositionCacheEntry(); - void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock); + void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock_); void Clear(); bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const; - static int Hash(unsigned int styleNumber_, const char *s, unsigned int len); + static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len); bool NewerThan(const PositionCacheEntry &other) const; void ResetClock(); }; @@ -132,7 +128,7 @@ public: SpecialRepresentations(); void SetRepresentation(const char *charBytes, const char *value); void ClearRepresentation(const char *charBytes); - Representation *RepresentationFromCharacter(const char *charBytes, size_t len); + const Representation *RepresentationFromCharacter(const char *charBytes, size_t len) const; bool Contains(const char *charBytes, size_t len) const; void Clear(); }; @@ -140,8 +136,8 @@ public: struct TextSegment { int start; int length; - Representation *representation; - TextSegment(int start_=0, int length_=0, Representation *representation_=0) : + const Representation *representation; + TextSegment(int start_=0, int length_=0, const Representation *representation_=0) : start(start_), length(length_), representation(representation_) { } int end() const { @@ -151,18 +147,17 @@ struct TextSegment { // Class to break a line of text into shorter runs at sensible places. class BreakFinder { - LineLayout *ll; - int lineStart; - int lineEnd; + const LineLayout *ll; + Range lineRange; int posLineStart; int nextBreak; std::vector selAndEdge; unsigned int saeCurrentPos; int saeNext; int subBreak; - Document *pdoc; + const Document *pdoc; EncodingFamily encodingFamily; - SpecialRepresentations *preprs; + const SpecialRepresentations *preprs; void Insert(int val); // Private so BreakFinder objects can not be copied BreakFinder(const BreakFinder &); @@ -172,8 +167,8 @@ public: enum { lengthStartSubdivision = 300 }; // Try to make each subdivided run lengthEachSubdivision or shorter. enum { lengthEachSubdivision = 100 }; - BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, - int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_); + BreakFinder(const LineLayout *ll_, const Selection *psel, Range rangeLine_, int posLineStart_, + int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw); ~BreakFinder(); TextSegment Next(); bool More() const; @@ -191,7 +186,7 @@ public: void Clear(); void SetSize(size_t size_); size_t GetSize() const { return pces.size(); } - void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, + void MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber, const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc); }; diff --git a/src/stc/scintilla/src/RESearch.cxx b/src/stc/scintilla/src/RESearch.cxx index 81eddf0131..2824a5b707 100644 --- a/src/stc/scintilla/src/RESearch.cxx +++ b/src/stc/scintilla/src/RESearch.cxx @@ -203,15 +203,11 @@ #include #include +#include #include "CharClassify.h" #include "RESearch.h" -// Shut up annoying Visual C++ warnings: -#ifdef _MSC_VER -#pragma warning(disable: 4514) -#endif - #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -256,22 +252,18 @@ const char bitarr[] = { 1, 2, 4, 8, 16, 32, 64, '\200' }; RESearch::RESearch(CharClassify *charClassTable) { failure = 0; charClass = charClassTable; - Init(); + sta = NOP; /* status of lastpat */ + bol = 0; + std::fill(bittab, bittab + BITBLK, 0); + std::fill(tagstk, tagstk + MAXTAG, 0); + std::fill(nfa, nfa + MAXNFA, 0); + Clear(); } RESearch::~RESearch() { Clear(); } -void RESearch::Init() { - sta = NOP; /* status of lastpat */ - bol = 0; - for (int i = 0; i < MAXTAG; i++) - pat[i].clear(); - for (int j = 0; j < BITBLK; j++) - bittab[j] = 0; -} - void RESearch::Clear() { for (int i = 0; i < MAXTAG; i++) { pat[i].clear(); @@ -284,10 +276,9 @@ void RESearch::GrabMatches(CharacterIndexer &ci) { for (unsigned int i = 0; i < MAXTAG; i++) { if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) { unsigned int len = eopat[i] - bopat[i]; - pat[i] = std::string(len+1, '\0'); + pat[i].resize(len); for (unsigned int j = 0; j < len; j++) pat[i][j] = ci.CharAt(bopat[i] + j); - pat[i][len] = '\0'; } } } @@ -351,8 +342,8 @@ static int GetHexaChar(unsigned char hd1, unsigned char hd2) { /** * Called when the parser finds a backslash not followed * by a valid expression (like \( in non-Posix mode). - * @param pattern: pointer on the char after the backslash. - * @param incr: (out) number of chars to skip after expression evaluation. + * @param pattern : pointer on the char after the backslash. + * @param incr : (out) number of chars to skip after expression evaluation. * @return the char if it resolves to a simple char, * or -1 for a char class. In this case, bittab is changed. */ @@ -789,7 +780,7 @@ int RESearch::Execute(CharacterIndexer &ci, int lp, int endp) { c = *(ap+1); while ((lp < endp) && (static_cast(ci.CharAt(lp)) != c)) lp++; - if (lp >= endp) /* if EOS, fail, else fall thru. */ + if (lp >= endp) /* if EOS, fail, else fall through. */ return 0; default: /* regular matching all the way. */ while (lp < endp) { @@ -819,7 +810,7 @@ int RESearch::Execute(CharacterIndexer &ci, int lp, int endp) { * * special case optimizations: (nfa[n], nfa[n+1]) * CLO ANY - * We KNOW .* will match everything upto the + * We KNOW .* will match everything up to the * end of line. Thus, directly go to the end of * line, without recursive PMatch calls. As in * the other closure cases, the remaining pattern diff --git a/src/stc/scintilla/src/RESearch.h b/src/stc/scintilla/src/RESearch.h index 48533a41c1..3a7f0e4d61 100644 --- a/src/stc/scintilla/src/RESearch.h +++ b/src/stc/scintilla/src/RESearch.h @@ -33,6 +33,7 @@ class RESearch { public: explicit RESearch(CharClassify *charClassTable); ~RESearch(); + void Clear(); void GrabMatches(CharacterIndexer &ci); const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix); int Execute(CharacterIndexer &ci, int lp, int endp); @@ -46,8 +47,6 @@ public: std::string pat[MAXTAG]; private: - void Init(); - void Clear(); void ChSet(unsigned char c); void ChSetWithCase(unsigned char c, bool caseSensitive); int GetBackslashExpression(const char *pattern, int &incr); diff --git a/src/stc/scintilla/src/ScintillaBase.cxx b/src/stc/scintilla/src/ScintillaBase.cxx index dc154ec6d5..b52fb9a043 100644 --- a/src/stc/scintilla/src/ScintillaBase.cxx +++ b/src/stc/scintilla/src/ScintillaBase.cxx @@ -8,9 +8,10 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -21,12 +22,17 @@ #include "ILexer.h" #include "Scintilla.h" -#include "PropSetSimple.h" #ifdef SCI_LEXER #include "SciLexer.h" +#endif + +#include "PropSetSimple.h" + +#ifdef SCI_LEXER #include "LexerModule.h" #include "Catalogue.h" #endif + #include "SplitVector.h" #include "Partitioning.h" #include "RunStyles.h" @@ -39,14 +45,17 @@ #include "LineMarker.h" #include "Style.h" #include "ViewStyle.h" -#include "AutoComplete.h" #include "CharClassify.h" #include "Decoration.h" #include "CaseFolder.h" #include "Document.h" #include "Selection.h" #include "PositionCache.h" +#include "EditModel.h" +#include "MarginView.h" +#include "EditView.h" #include "Editor.h" +#include "AutoComplete.h" #include "ScintillaBase.h" #ifdef SCI_NAMESPACE @@ -57,6 +66,7 @@ ScintillaBase::ScintillaBase() { displayPopupMenu = true; listType = 0; maxListWidth = 0; + multiAutoCMode = SC_MULTIAUTOC_ONCE; } ScintillaBase::~ScintillaBase() { @@ -67,7 +77,7 @@ void ScintillaBase::Finalise() { popup.Destroy(); } -void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { +void ScintillaBase::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { bool isFillUp = ac.Active() && ac.IsFillUpChar(*s); if (!isFillUp) { Editor::AddCharUTF(s, len, treatAsDBCS); @@ -197,9 +207,30 @@ void ScintillaBase::AutoCompleteDoubleClick(void *p) { void ScintillaBase::AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen) { UndoGroup ug(pdoc); - pdoc->DeleteChars(startPos, removeLen); - pdoc->InsertString(startPos, text, textLen); - SetEmptySelection(startPos + textLen); + if (multiAutoCMode == SC_MULTIAUTOC_ONCE) { + pdoc->DeleteChars(startPos, removeLen); + const int lengthInserted = pdoc->InsertString(startPos, text, textLen); + SetEmptySelection(startPos + lengthInserted); + } else { + // SC_MULTIAUTOC_EACH + for (size_t r=0; r= 0) { + positionInsert -= removeLen; + pdoc->DeleteChars(positionInsert, removeLen); + } + const int lengthInserted = pdoc->InsertString(positionInsert, text, textLen); + if (lengthInserted > 0) { + sel.Range(r).caret.SetPosition(positionInsert + lengthInserted); + sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted); + } + sel.Range(r).ClearVirtualSpace(); + } + } + } } void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { @@ -233,7 +264,7 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { int heightLB = ac.heightLBDefault; int widthLB = ac.widthLBDefault; if (pt.x >= rcClient.right - widthLB) { - HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB); + HorizontalScrollTo(static_cast(xOffset + pt.x - rcClient.right + widthLB)); Redraw(); pt = PointMainCaret(); } @@ -248,17 +279,17 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above. rcac.top = pt.y - heightLB; if (rcac.top < rcPopupBounds.top) { - heightLB -= (rcPopupBounds.top - rcac.top); + heightLB -= static_cast(rcPopupBounds.top - rcac.top); rcac.top = rcPopupBounds.top; } } else { rcac.top = pt.y + vs.lineHeight; } rcac.right = rcac.left + widthLB; - rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcPopupBounds.bottom); + rcac.bottom = static_cast(Platform::Minimum(static_cast(rcac.top) + heightLB, static_cast(rcPopupBounds.bottom))); ac.lb->SetPositionRelative(rcac, wMain); ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font); - unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth; + unsigned int aveCharWidth = static_cast(vs.styles[STYLE_DEFAULT].aveCharWidth); ac.lb->SetAverageCharWidth(aveCharWidth); ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this); @@ -266,8 +297,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *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->GetDesiredRect(); - int heightAlloced = rcList.bottom - rcList.top; - widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left); + int heightAlloced = static_cast(rcList.bottom - rcList.top); + widthLB = Platform::Maximum(widthLB, static_cast(rcList.right - rcList.left)); if (maxListWidth != 0) widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth); // Make an allowance for large strings in list @@ -416,14 +447,14 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) { // If the call-tip window would be out of the client // space PRectangle rcClient = GetClientRectangle(); - int offset = vs.lineHeight + rc.Height(); + int offset = vs.lineHeight + static_cast(rc.Height()); // adjust so it displays above the text. - if (rc.bottom > rcClient.bottom) { + if (rc.bottom > rcClient.bottom && rc.Height() < rcClient.Height()) { rc.top -= offset; rc.bottom -= offset; } // adjust so it displays below the text. - if (rc.top < rcClient.top) { + if (rc.top < rcClient.top && rc.Height() < rcClient.Height()) { rc.top += offset; rc.bottom += offset; } @@ -492,7 +523,6 @@ public: void SetLexerLanguage(const char *languageName); const char *DescribeWordListSets(); void SetWordList(int n, const char *wl); - int GetStyleBitsNeeded() const; const char *GetName() const; void *PrivateCall(int operation, void *pointer); const char *PropertyNames(); @@ -557,7 +587,7 @@ void LexState::SetLexerModule(const LexerModule *lex) { } void LexState::SetLexer(uptr_t wParam) { - lexLanguage = wParam; + lexLanguage = static_cast(wParam); if (lexLanguage == SCLEX_CONTAINER) { SetLexerModule(0); } else { @@ -594,10 +624,6 @@ void LexState::SetWordList(int n, const char *wl) { } } -int LexState::GetStyleBitsNeeded() const { - return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; -} - const char *LexState::GetName() const { return lexCurrent ? lexCurrent->languageName : ""; } @@ -740,8 +766,7 @@ void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) { void ScintillaBase::NotifyLexerChanged(Document *, void *) { #ifdef SCI_LEXER - int bits = DocumentLexState()->GetStyleBitsNeeded(); - vs.EnsureStyle((1 << bits) - 1); + vs.EnsureStyle(0xff); #endif } @@ -749,7 +774,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara switch (iMessage) { case SCI_AUTOCSHOW: listType = 0; - AutoCompleteStart(wParam, reinterpret_cast(lParam)); + AutoCompleteStart(static_cast(wParam), reinterpret_cast(lParam)); break; case SCI_AUTOCCANCEL: @@ -813,21 +838,28 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return ac.ignoreCase; case SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR: - ac.ignoreCaseBehaviour = wParam; + ac.ignoreCaseBehaviour = static_cast(wParam); break; case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR: return ac.ignoreCaseBehaviour; + case SCI_AUTOCSETMULTI: + multiAutoCMode = static_cast(wParam); + break; + + case SCI_AUTOCGETMULTI: + return multiAutoCMode; + case SCI_AUTOCSETORDER: - ac.autoSort = wParam; + ac.autoSort = static_cast(wParam); break; case SCI_AUTOCGETORDER: return ac.autoSort; case SCI_USERLISTSHOW: - listType = wParam; + listType = static_cast(wParam); AutoCompleteStart(0, reinterpret_cast(lParam)); break; @@ -846,25 +878,26 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return ac.dropRestOfWord; case SCI_AUTOCSETMAXHEIGHT: - ac.lb->SetVisibleRows(wParam); + ac.lb->SetVisibleRows(static_cast(wParam)); break; case SCI_AUTOCGETMAXHEIGHT: return ac.lb->GetVisibleRows(); case SCI_AUTOCSETMAXWIDTH: - maxListWidth = wParam; + maxListWidth = static_cast(wParam); break; case SCI_AUTOCGETMAXWIDTH: return maxListWidth; case SCI_REGISTERIMAGE: - ac.lb->RegisterImage(wParam, reinterpret_cast(lParam)); + ac.lb->RegisterImage(static_cast(wParam), reinterpret_cast(lParam)); break; case SCI_REGISTERRGBAIMAGE: - ac.lb->RegisterRGBAImage(wParam, sizeRGBAImage.x, sizeRGBAImage.y, reinterpret_cast(lParam)); + ac.lb->RegisterRGBAImage(static_cast(wParam), static_cast(sizeRGBAImage.x), static_cast(sizeRGBAImage.y), + reinterpret_cast(lParam)); break; case SCI_CLEARREGISTEREDIMAGES: @@ -879,7 +912,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return ac.GetTypesep(); case SCI_CALLTIPSHOW: - CallTipShow(LocationFromPosition(wParam), + CallTipShow(LocationFromPosition(static_cast(wParam)), reinterpret_cast(lParam)); break; @@ -894,32 +927,32 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return ct.posStartCallTip; case SCI_CALLTIPSETPOSSTART: - ct.posStartCallTip = wParam; + ct.posStartCallTip = static_cast(wParam); break; case SCI_CALLTIPSETHLT: - ct.SetHighlight(wParam, lParam); + ct.SetHighlight(static_cast(wParam), static_cast(lParam)); break; case SCI_CALLTIPSETBACK: - ct.colourBG = ColourDesired(wParam); + ct.colourBG = ColourDesired(static_cast(wParam)); vs.styles[STYLE_CALLTIP].back = ct.colourBG; InvalidateStyleRedraw(); break; case SCI_CALLTIPSETFORE: - ct.colourUnSel = ColourDesired(wParam); + ct.colourUnSel = ColourDesired(static_cast(wParam)); vs.styles[STYLE_CALLTIP].fore = ct.colourUnSel; InvalidateStyleRedraw(); break; case SCI_CALLTIPSETFOREHLT: - ct.colourSel = ColourDesired(wParam); + ct.colourSel = ColourDesired(static_cast(wParam)); InvalidateStyleRedraw(); break; case SCI_CALLTIPUSESTYLE: - ct.SetTabSize((int)wParam); + ct.SetTabSize(static_cast(wParam)); InvalidateStyleRedraw(); break; @@ -934,7 +967,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara #ifdef SCI_LEXER case SCI_SETLEXER: - DocumentLexState()->SetLexer(wParam); + DocumentLexState()->SetLexer(static_cast(wParam)); break; case SCI_GETLEXER: @@ -942,10 +975,10 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara case SCI_COLOURISE: if (DocumentLexState()->lexLanguage == SCLEX_CONTAINER) { - pdoc->ModifiedAt(wParam); - NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam); + pdoc->ModifiedAt(static_cast(wParam)); + NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : static_cast(lParam)); } else { - DocumentLexState()->Colourise(wParam, lParam); + DocumentLexState()->Colourise(static_cast(wParam), static_cast(lParam)); } Redraw(); break; @@ -963,10 +996,10 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara reinterpret_cast(lParam)); case SCI_GETPROPERTYINT: - return DocumentLexState()->PropGetInt(reinterpret_cast(wParam), lParam); + return DocumentLexState()->PropGetInt(reinterpret_cast(wParam), static_cast(lParam)); case SCI_SETKEYWORDS: - DocumentLexState()->SetWordList(wParam, reinterpret_cast(lParam)); + DocumentLexState()->SetWordList(static_cast(wParam), reinterpret_cast(lParam)); break; case SCI_SETLEXERLANGUAGE: @@ -978,10 +1011,10 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara case SCI_PRIVATELEXERCALL: return reinterpret_cast( - DocumentLexState()->PrivateCall(wParam, reinterpret_cast(lParam))); + DocumentLexState()->PrivateCall(static_cast(wParam), reinterpret_cast(lParam))); case SCI_GETSTYLEBITSNEEDED: - return DocumentLexState()->GetStyleBitsNeeded(); + return 8; case SCI_PROPERTYNAMES: return StringResult(lParam, DocumentLexState()->PropertyNames()); @@ -990,7 +1023,8 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return DocumentLexState()->PropertyType(reinterpret_cast(wParam)); case SCI_DESCRIBEPROPERTY: - return StringResult(lParam, DocumentLexState()->DescribeProperty(reinterpret_cast(wParam))); + return StringResult(lParam, + DocumentLexState()->DescribeProperty(reinterpret_cast(wParam))); case SCI_DESCRIBEKEYWORDSETS: return StringResult(lParam, DocumentLexState()->DescribeWordListSets()); @@ -999,26 +1033,27 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return DocumentLexState()->LineEndTypesSupported(); case SCI_ALLOCATESUBSTYLES: - return DocumentLexState()->AllocateSubStyles(wParam, lParam); + return DocumentLexState()->AllocateSubStyles(static_cast(wParam), static_cast(lParam)); case SCI_GETSUBSTYLESSTART: - return DocumentLexState()->SubStylesStart(wParam); + return DocumentLexState()->SubStylesStart(static_cast(wParam)); case SCI_GETSUBSTYLESLENGTH: - return DocumentLexState()->SubStylesLength(wParam); + return DocumentLexState()->SubStylesLength(static_cast(wParam)); case SCI_GETSTYLEFROMSUBSTYLE: - return DocumentLexState()->StyleFromSubStyle(wParam); + return DocumentLexState()->StyleFromSubStyle(static_cast(wParam)); case SCI_GETPRIMARYSTYLEFROMSTYLE: - return DocumentLexState()->PrimaryStyleFromStyle(wParam); + return DocumentLexState()->PrimaryStyleFromStyle(static_cast(wParam)); case SCI_FREESUBSTYLES: DocumentLexState()->FreeSubStyles(); break; case SCI_SETIDENTIFIERS: - DocumentLexState()->SetIdentifiers(wParam, reinterpret_cast(lParam)); + DocumentLexState()->SetIdentifiers(static_cast(wParam), + reinterpret_cast(lParam)); break; case SCI_DISTANCETOSECONDARYSTYLES: diff --git a/src/stc/scintilla/src/ScintillaBase.h b/src/stc/scintilla/src/ScintillaBase.h index 59ffea41e6..668abed3cd 100644 --- a/src/stc/scintilla/src/ScintillaBase.h +++ b/src/stc/scintilla/src/ScintillaBase.h @@ -38,6 +38,8 @@ protected: idcmdSelectAll=16 }; + enum { maxLenInputIME = 200 }; + bool displayPopupMenu; Menu popup; AutoComplete ac; @@ -46,6 +48,7 @@ protected: int listType; ///< 0 is an autocomplete list int maxListWidth; /// Maximum width of list, in average character widths + int multiAutoCMode; /// Mode for autocompleting when multiple selections are present #ifdef SCI_LEXER LexState *DocumentLexState(); @@ -59,7 +62,7 @@ protected: virtual void Initialise() = 0; virtual void Finalise(); - virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); + virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false); void Command(int cmdId); virtual void CancelModes(); virtual int KeyCommand(unsigned int iMessage); diff --git a/src/stc/scintilla/src/Selection.cxx b/src/stc/scintilla/src/Selection.cxx index ae4d8bfc75..52ed5774eb 100644 --- a/src/stc/scintilla/src/Selection.cxx +++ b/src/stc/scintilla/src/Selection.cxx @@ -81,6 +81,11 @@ int SelectionRange::Length() const { } } +void SelectionRange::MoveForInsertDelete(bool insertion, int startChange, int length) { + caret.MoveForInsertDelete(insertion, startChange, length); + anchor.MoveForInsertDelete(insertion, startChange, length); +} + bool SelectionRange::Contains(int pos) const { if (anchor > caret) return (pos >= caret.Position()) && (pos <= anchor.Position()); @@ -226,10 +231,26 @@ SelectionRange &Selection::Range(size_t r) { return ranges[r]; } +const SelectionRange &Selection::Range(size_t r) const { + return ranges[r]; +} + SelectionRange &Selection::RangeMain() { return ranges[mainRange]; } +const SelectionRange &Selection::RangeMain() const { + return ranges[mainRange]; +} + +SelectionPosition Selection::Start() const { + if (IsRectangular()) { + return rangeRectangular.Start(); + } else { + return ranges[mainRange].Start(); + } +} + bool Selection::MoveExtends() const { return moveExtends; } @@ -267,9 +288,11 @@ int Selection::Length() const { void Selection::MovePositions(bool insertion, int startChange, int length) { for (size_t i=0; i(s[i]); if (ch < 0x80) { charLen = 1; @@ -102,10 +103,10 @@ unsigned int UTF16Length(const char *s, unsigned int len) { return ulen; } -unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) { - unsigned int ui=0; +size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen) { + size_t ui = 0; const unsigned char *us = reinterpret_cast(s); - unsigned int i=0; + size_t i = 0; while ((i(s); + unsigned int i=0; + while ((i= 1) && (ch < 0x80 + 0x40 + 0x20)) { + value = (ch & 0x1F) << 6; + ch = us[i++]; + value += ch & 0x7F; + } else if (((len-i) >= 2) && (ch < 0x80 + 0x40 + 0x20 + 0x10)) { + value = (ch & 0xF) << 12; + ch = us[i++]; + value += (ch & 0x7F) << 6; + ch = us[i++]; + value += ch & 0x7F; + } else if ((len-i) >= 3) { + value = (ch & 0x7) << 18; + ch = us[i++]; + value += (ch & 0x3F) << 12; + ch = us[i++]; + value += (ch & 0x3F) << 6; + ch = us[i++]; + value += ch & 0x3F; + } + tbuf[ui] = value; + ui++; + } + return ui; +} + +unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf) { + if (val < SUPPLEMENTAL_PLANE_FIRST) { + tbuf[0] = static_cast(val); + return 1; + } else { + tbuf[0] = static_cast(((val - SUPPLEMENTAL_PLANE_FIRST) >> 10) + SURROGATE_LEAD_FIRST); + tbuf[1] = static_cast((val & 0x3ff) + SURROGATE_TRAIL_FIRST); + return 2; + } +} + int UTF8BytesOfLead[256]; static bool initialisedBytesOfLead = false; diff --git a/src/stc/scintilla/src/UniConversion.h b/src/stc/scintilla/src/UniConversion.h index 753490bab5..08898cac38 100644 --- a/src/stc/scintilla/src/UniConversion.h +++ b/src/stc/scintilla/src/UniConversion.h @@ -14,11 +14,15 @@ namespace Scintilla { const int UTF8MaxBytes = 4; +const int unicodeReplacementChar = 0xFFFD; + unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen); void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len); unsigned int UTF8CharLength(unsigned char ch); -unsigned int UTF16Length(const char *s, unsigned int len); -unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen); +size_t UTF16Length(const char *s, size_t len); +size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen); +unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen); +unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf); extern int UTF8BytesOfLead[256]; void UTF8BytesOfLeadInitialise(); @@ -51,6 +55,12 @@ inline bool UTF8IsNEL(const unsigned char *us) { return (us[0] == 0xc2) && (us[1] == 0x85); } +enum { SURROGATE_LEAD_FIRST = 0xD800 }; +enum { SURROGATE_LEAD_LAST = 0xDBFF }; +inline unsigned int UTF16CharLength(wchar_t uch) { + return ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_LEAD_LAST)) ? 2 : 1; +} + #ifdef SCI_NAMESPACE } #endif diff --git a/src/stc/scintilla/src/ViewStyle.cxx b/src/stc/scintilla/src/ViewStyle.cxx index b1c9dc10bf..e56c8f3756 100644 --- a/src/stc/scintilla/src/ViewStyle.cxx +++ b/src/stc/scintilla/src/ViewStyle.cxx @@ -75,12 +75,12 @@ void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, cons if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; - float deviceHeight = surface.DeviceHeightFont(sizeZoomed); + float deviceHeight = static_cast(surface.DeviceHeightFont(sizeZoomed)); FontParameters fp(fs.fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, fs.weight, fs.italic, fs.extraFontFlag, technology, fs.characterSet); font.Create(fp); - ascent = surface.Ascent(font); - descent = surface.Descent(font); + ascent = static_cast(surface.Ascent(font)); + descent = static_cast(surface.Descent(font)); aveCharWidth = surface.AverageCharWidth(font); spaceWidth = surface.WidthChar(font, ' '); } @@ -101,8 +101,14 @@ ViewStyle::ViewStyle(const ViewStyle &source) { markers[mrk] = source.markers[mrk]; } CalcLargestMarkerHeight(); + indicatorsDynamic = 0; + indicatorsSetFore = 0; for (int ind=0; ind<=INDIC_MAX; ind++) { indicators[ind] = source.indicators[ind]; + if (indicators[ind].IsDynamic()) + indicatorsDynamic++; + if (indicators[ind].OverridesTextFore()) + indicatorsSetFore++; } selColours = source.selColours; @@ -192,18 +198,15 @@ void ViewStyle::Init(size_t stylesSize_) { // There are no image markers by default, so no need for calling CalcLargestMarkerHeight() largestMarkerHeight = 0; - indicators[0].style = INDIC_SQUIGGLE; - indicators[0].under = false; - indicators[0].fore = ColourDesired(0, 0x7f, 0); - indicators[1].style = INDIC_TT; - indicators[1].under = false; - indicators[1].fore = ColourDesired(0, 0, 0xff); - indicators[2].style = INDIC_PLAIN; - indicators[2].under = false; - indicators[2].fore = ColourDesired(0xff, 0, 0); + indicators[0] = Indicator(INDIC_SQUIGGLE, ColourDesired(0, 0x7f, 0)); + indicators[1] = Indicator(INDIC_TT, ColourDesired(0, 0, 0xff)); + indicators[2] = Indicator(INDIC_PLAIN, ColourDesired(0xff, 0, 0)); technology = SC_TECHNOLOGY_DEFAULT; + indicatorsDynamic = 0; + indicatorsSetFore = 0; lineHeight = 1; + lineOverlap = 0; maxAscent = 1; maxDescent = 1; aveCharWidth = 8; @@ -323,12 +326,25 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) { FontRealised *fr = Find(styles[k]); styles[k].Copy(fr->font, *fr); } + indicatorsDynamic = 0; + indicatorsSetFore = 0; + for (int ind = 0; ind <= INDIC_MAX; ind++) { + if (indicators[ind].IsDynamic()) + indicatorsDynamic++; + if (indicators[ind].OverridesTextFore()) + indicatorsSetFore++; + } maxAscent = 1; maxDescent = 1; FindMaxAscentDescent(); maxAscent += extraAscent; maxDescent += extraDescent; lineHeight = maxAscent + maxDescent; + lineOverlap = lineHeight / 10; + if (lineOverlap < 2) + lineOverlap = 2; + if (lineOverlap > lineHeight) + lineOverlap = lineHeight; someStylesProtected = false; someStylesForceCase = false; @@ -347,7 +363,7 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) { controlCharWidth = 0.0; if (controlCharSymbol >= 32) { - controlCharWidth = surface.WidthChar(styles[STYLE_CONTROLCHAR].font, controlCharSymbol); + controlCharWidth = surface.WidthChar(styles[STYLE_CONTROLCHAR].font, static_cast(controlCharSymbol)); } fixedColumnWidth = marginInside ? leftMarginWidth : 0; @@ -434,6 +450,51 @@ void ViewStyle::CalcLargestMarkerHeight() { } } +// See if something overrides the line background color: Either if caret is on the line +// and background color is set for that, or if a marker is defined that forces its background +// color onto the line, or if a marker is defined but has no selection margin in which to +// display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order +// with the earlier taking precedence. When multiple markers cause background override, +// the color for the highest numbered one is used. +ColourOptional ViewStyle::Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const { + ColourOptional background; + if ((caretActive || alwaysShowCaretLineBackground) && showCaretLineBackground && (caretLineAlpha == SC_ALPHA_NOALPHA) && lineContainsCaret) { + background = ColourOptional(caretLineBackground, true); + } + if (!background.isSet && marksOfLine) { + int marks = marksOfLine; + for (int markBit = 0; (markBit < 32) && marks; markBit++) { + if ((marks & 1) && (markers[markBit].markType == SC_MARK_BACKGROUND) && + (markers[markBit].alpha == SC_ALPHA_NOALPHA)) { + background = ColourOptional(markers[markBit].back, true); + } + marks >>= 1; + } + } + if (!background.isSet && maskInLine) { + int marksMasked = marksOfLine & maskInLine; + if (marksMasked) { + for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) { + if ((marksMasked & 1) && (markers[markBit].markType != SC_MARK_EMPTY) && + (markers[markBit].alpha == SC_ALPHA_NOALPHA)) { + background = ColourOptional(markers[markBit].back, true); + } + marksMasked >>= 1; + } + } + } + return background; +} + +bool ViewStyle::SelectionBackgroundDrawn() const { + return selColours.back.isSet && + ((selAlpha == SC_ALPHA_NOALPHA) || (selAdditionalAlpha == SC_ALPHA_NOALPHA)); +} + +bool ViewStyle::WhitespaceBackgroundDrawn() const { + return (viewWhitespace != wsInvisible) && (whitespaceColours.back.isSet); +} + ColourDesired ViewStyle::WrapColour() const { if (whitespaceColours.fore.isSet) return whitespaceColours.fore; diff --git a/src/stc/scintilla/src/ViewStyle.h b/src/stc/scintilla/src/ViewStyle.h index 91b51b2ada..930ad104c4 100644 --- a/src/stc/scintilla/src/ViewStyle.h +++ b/src/stc/scintilla/src/ViewStyle.h @@ -63,7 +63,7 @@ public: bool isSet; ColourOptional(ColourDesired colour_=ColourDesired(0,0,0), bool isSet_=false) : ColourDesired(colour_), isSet(isSet_) { } - ColourOptional(uptr_t wParam, sptr_t lParam) : ColourDesired(lParam), isSet(wParam != 0) { + ColourOptional(uptr_t wParam, sptr_t lParam) : ColourDesired(static_cast(lParam)), isSet(wParam != 0) { } }; @@ -83,8 +83,11 @@ public: LineMarker markers[MARKER_MAX + 1]; int largestMarkerHeight; Indicator indicators[INDIC_MAX + 1]; + unsigned int indicatorsDynamic; + unsigned int indicatorsSetFore; int technology; int lineHeight; + int lineOverlap; unsigned int maxAscent; unsigned int maxDescent; XYPOSITION aveCharWidth; @@ -157,7 +160,7 @@ public: ViewStyle(); ViewStyle(const ViewStyle &source); ~ViewStyle(); - void Init(size_t stylesSize_=64); + void Init(size_t stylesSize_=256); void Refresh(Surface &surface, int tabInChars); void ReleaseAllExtendedStyles(); int AllocateExtendedStyles(int numberStyles); @@ -169,7 +172,11 @@ public: int ExternalMarginWidth() const; bool ValidStyle(size_t styleIndex) const; void CalcLargestMarkerHeight(); + ColourOptional Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const; + bool SelectionBackgroundDrawn() const; + bool WhitespaceBackgroundDrawn() const; ColourDesired WrapColour() const; + bool SetWrapState(int wrapState_); bool SetWrapVisualFlags(int wrapVisualFlags_); bool SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_); diff --git a/src/stc/scintilla/src/XPM.cxx b/src/stc/scintilla/src/XPM.cxx index e1d91846da..c2b308acb7 100644 --- a/src/stc/scintilla/src/XPM.cxx +++ b/src/stc/scintilla/src/XPM.cxx @@ -47,7 +47,7 @@ ColourDesired XPM::ColourFromCode(int ch) const { void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) { if ((code != codeTransparent) && (startX != x)) { - PRectangle rc(startX, y, x, y+1); + PRectangle rc = PRectangle::FromInts(startX, y, x, y + 1); surface->FillRectangle(rc, ColourFromCode(code)); } } @@ -109,7 +109,7 @@ void XPM::Init(const char *const *linesForm) { if (*colourDef == '#') { colour.Set(colourDef); } else { - codeTransparent = code; + codeTransparent = static_cast(code); } colourCodeTable[code] = colour; } @@ -127,8 +127,8 @@ void XPM::Draw(Surface *surface, PRectangle &rc) { return; } // Centre the pixmap - int startY = rc.top + (rc.Height() - height) / 2; - int startX = rc.left + (rc.Width() - width) / 2; + int startY = static_cast(rc.top + (rc.Height() - height) / 2); + int startX = static_cast(rc.left + (rc.Width() - width) / 2); for (int y=0; y