소스 검색

Renamed GLTypes to GLVectorRecTypes

GLScene 5 년 전
부모
커밋
878588c45d

+ 1 - 1
Demos/CleanDemos.bat

@@ -72,4 +72,4 @@ for /r %1 %%R in (Debug_Build) do if exist "%%R" (rd /s /q "%%R")
 for /r %1 %%R in (Release_Build) do if exist "%%R" (rd /s /q "%%R")
 for /r %1 %%R in (Release_Build) do if exist "%%R" (rd /s /q "%%R")
 for /r %1 %%R in (__history) do if exist "%%R" (rd /s /q "%%R")
 for /r %1 %%R in (__history) do if exist "%%R" (rd /s /q "%%R")
 for /r %1 %%R in (__recovery) do if exist "%%R" (rd /s /q "%%R")
 for /r %1 %%R in (__recovery) do if exist "%%R" (rd /s /q "%%R")
-for /r %1 %%R in (__astcache) do if exist "%%R" (rd /s /q "%%R")
+for /r %1 %%R in (__astcache) do if exist "%%R" (rd /s /q "%%R")

+ 8 - 8
Packages/Win32/GLScene_RT.dpk

@@ -104,11 +104,11 @@ contains
   GLFileB3D in '..\..\Source\GLFileB3D.pas',
   GLFileB3D in '..\..\Source\GLFileB3D.pas',
   GLFileBMP in '..\..\Source\GLFileBMP.pas',
   GLFileBMP in '..\..\Source\GLFileBMP.pas',
   GLFileDDS in '..\..\Source\GLFileDDS.pas',
   GLFileDDS in '..\..\Source\GLFileDDS.pas',
-  GLFileDXF in '..\..\Source\GLFileDXF.pas',
+  GLS.FileDXF in '..\..\Source\GLS.FileDXF.pas',
   GLFileGL2 in '..\..\Source\GLFileGL2.pas',
   GLFileGL2 in '..\..\Source\GLFileGL2.pas',
   GLFileGLB in '..\..\Source\GLFileGLB.pas',
   GLFileGLB in '..\..\Source\GLFileGLB.pas',
   GLFileGLTF in '..\..\Source\GLFileGLTF.pas',
   GLFileGLTF in '..\..\Source\GLFileGLTF.pas',
-  GLFileGRD in '..\..\Source\GLFileGRD.pas',
+  GLS.FileGRD in '..\..\Source\GLS.FileGRD.pas',
   GLFileGTS in '..\..\Source\GLFileGTS.pas',
   GLFileGTS in '..\..\Source\GLFileGTS.pas',
   GLFileHDR in '..\..\Source\GLFileHDR.pas',
   GLFileHDR in '..\..\Source\GLFileHDR.pas',
   GLFileJPEG in '..\..\Source\GLFileJPEG.pas',
   GLFileJPEG in '..\..\Source\GLFileJPEG.pas',
@@ -132,7 +132,7 @@ contains
   GLFileSMD in '..\..\Source\GLFileSMD.pas',
   GLFileSMD in '..\..\Source\GLFileSMD.pas',
   GLFileSTL in '..\..\Source\GLFileSTL.pas',
   GLFileSTL in '..\..\Source\GLFileSTL.pas',
   GLFileTGA in '..\..\Source\GLFileTGA.pas',
   GLFileTGA in '..\..\Source\GLFileTGA.pas',
-  GLFileTIN in '..\..\Source\GLFileTIN.pas',
+  GLS.FileTIN in '..\..\Source\GLS.FileTIN.pas',
   GLFileVRML in '..\..\Source\GLFileVRML.pas',
   GLFileVRML in '..\..\Source\GLFileVRML.pas',
   GLFileWAV in '..\..\Source\GLFileWAV.pas',
   GLFileWAV in '..\..\Source\GLFileWAV.pas',
   GLFileX in '..\..\Source\GLFileX.pas',
   GLFileX in '..\..\Source\GLFileX.pas',
@@ -196,7 +196,7 @@ contains
   GLPhongShader in '..\..\Source\GLPhongShader.pas',
   GLPhongShader in '..\..\Source\GLPhongShader.pas',
   GLPictureRegisteredFormats in '..\..\Source\GLPictureRegisteredFormats.pas',
   GLPictureRegisteredFormats in '..\..\Source\GLPictureRegisteredFormats.pas',
   GLPipelineTransformation in '..\..\Source\GLPipelineTransformation.pas',
   GLPipelineTransformation in '..\..\Source\GLPipelineTransformation.pas',
-  GLPlugInManager in '..\..\Source\GLPlugInManager.pas',
+  GLS.PlugInManager in '..\..\Source\GLS.PlugInManager.pas',
   GLPluginIntf in '..\..\Source\GLPluginIntf.pas',
   GLPluginIntf in '..\..\Source\GLPluginIntf.pas',
   GLPolyhedron in '..\..\Source\GLPolyhedron.pas',
   GLPolyhedron in '..\..\Source\GLPolyhedron.pas',
   GLPolynomials in '..\..\Source\GLPolynomials.pas',
   GLPolynomials in '..\..\Source\GLPolynomials.pas',
@@ -229,7 +229,7 @@ contains
   GLSLVertexDisplacementShader in '..\..\Source\GLSLVertexDisplacementShader.pas',
   GLSLVertexDisplacementShader in '..\..\Source\GLSLVertexDisplacementShader.pas',
   GLSLanguage in '..\..\Source\GLSLanguage.pas',
   GLSLanguage in '..\..\Source\GLSLanguage.pas',
   GLSLog in '..\..\Source\GLSLog.pas',
   GLSLog in '..\..\Source\GLSLog.pas',
-  GLSMemo in '..\..\Source\GLSMemo.pas',
+  GLS.Memo in '..\..\Source\GLS.Memo.pas',
   GLSRGBE in '..\..\Source\GLSRGBE.pas',
   GLSRGBE in '..\..\Source\GLSRGBE.pas',
   GLSRedBlackTree in '..\..\Source\GLSRedBlackTree.pas',
   GLSRedBlackTree in '..\..\Source\GLSRedBlackTree.pas',
   GLScene in '..\..\Source\GLScene.pas',
   GLScene in '..\..\Source\GLScene.pas',
@@ -272,7 +272,7 @@ contains
   GLTrail in '..\..\Source\GLTrail.pas',
   GLTrail in '..\..\Source\GLTrail.pas',
   GLTree in '..\..\Source\GLTree.pas',
   GLTree in '..\..\Source\GLTree.pas',
   GLTriangulation in '..\..\Source\GLTriangulation.pas',
   GLTriangulation in '..\..\Source\GLTriangulation.pas',
-  GLTypes in '..\..\Source\GLTypes.pas',
+  GLVectorRecTypes in '..\..\Source\GLVectorRecTypes.pas',
   GLUserShader in '..\..\Source\GLUserShader.pas',
   GLUserShader in '..\..\Source\GLUserShader.pas',
   GLUtils in '..\..\Source\GLUtils.pas',
   GLUtils in '..\..\Source\GLUtils.pas',
   GLVectorGeometry in '..\..\Source\GLVectorGeometry.pas',
   GLVectorGeometry in '..\..\Source\GLVectorGeometry.pas',
@@ -283,7 +283,6 @@ contains
   GLVerletHairClasses in '..\..\Source\GLVerletHairClasses.pas',
   GLVerletHairClasses in '..\..\Source\GLVerletHairClasses.pas',
   GLVerletSkeletonColliders in '..\..\Source\GLVerletSkeletonColliders.pas',
   GLVerletSkeletonColliders in '..\..\Source\GLVerletSkeletonColliders.pas',
   GLVerletTypes in '..\..\Source\GLVerletTypes.pas',
   GLVerletTypes in '..\..\Source\GLVerletTypes.pas',
-  GLVfsPAK in '..\..\Source\GLVfsPAK.pas',
   GLWaterPlane in '..\..\Source\GLWaterPlane.pas',
   GLWaterPlane in '..\..\Source\GLWaterPlane.pas',
   GLWin32Context in '..\..\Source\GLWin32Context.pas',
   GLWin32Context in '..\..\Source\GLWin32Context.pas',
   GLWin32Viewer in '..\..\Source\GLWin32Viewer.pas',
   GLWin32Viewer in '..\..\Source\GLWin32Viewer.pas',
@@ -293,7 +292,8 @@ contains
   GLzBuffer in '..\..\Source\GLzBuffer.pas',
   GLzBuffer in '..\..\Source\GLzBuffer.pas',
   OpenGLAdapter in '..\..\Source\OpenGLAdapter.pas',
   OpenGLAdapter in '..\..\Source\OpenGLAdapter.pas',
   OpenGLTokens in '..\..\Source\OpenGLTokens.pas',
   OpenGLTokens in '..\..\Source\OpenGLTokens.pas',
-  XOpenGL in '..\..\Source\XOpenGL.pas';
+  XOpenGL in '..\..\Source\XOpenGL.pas',
+  GLFileVfsPAK in '..\..\Source\GLFileVfsPAK.pas';
 
 
 end.
 end.
 
 

+ 7 - 7
Packages/Win32/GLScene_RT.dproj

@@ -198,11 +198,11 @@
         <DCCReference Include="..\..\Source\GLFileB3D.pas"/>
         <DCCReference Include="..\..\Source\GLFileB3D.pas"/>
         <DCCReference Include="..\..\Source\GLFileBMP.pas"/>
         <DCCReference Include="..\..\Source\GLFileBMP.pas"/>
         <DCCReference Include="..\..\Source\GLFileDDS.pas"/>
         <DCCReference Include="..\..\Source\GLFileDDS.pas"/>
-        <DCCReference Include="..\..\Source\GLFileDXF.pas"/>
+        <DCCReference Include="..\..\Source\GLS.FileDXF.pas"/>
         <DCCReference Include="..\..\Source\GLFileGL2.pas"/>
         <DCCReference Include="..\..\Source\GLFileGL2.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLB.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLB.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLTF.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLTF.pas"/>
-        <DCCReference Include="..\..\Source\GLFileGRD.pas"/>
+        <DCCReference Include="..\..\Source\GLS.FileGRD.pas"/>
         <DCCReference Include="..\..\Source\GLFileGTS.pas"/>
         <DCCReference Include="..\..\Source\GLFileGTS.pas"/>
         <DCCReference Include="..\..\Source\GLFileHDR.pas"/>
         <DCCReference Include="..\..\Source\GLFileHDR.pas"/>
         <DCCReference Include="..\..\Source\GLFileJPEG.pas"/>
         <DCCReference Include="..\..\Source\GLFileJPEG.pas"/>
@@ -226,7 +226,7 @@
         <DCCReference Include="..\..\Source\GLFileSMD.pas"/>
         <DCCReference Include="..\..\Source\GLFileSMD.pas"/>
         <DCCReference Include="..\..\Source\GLFileSTL.pas"/>
         <DCCReference Include="..\..\Source\GLFileSTL.pas"/>
         <DCCReference Include="..\..\Source\GLFileTGA.pas"/>
         <DCCReference Include="..\..\Source\GLFileTGA.pas"/>
-        <DCCReference Include="..\..\Source\GLFileTIN.pas"/>
+        <DCCReference Include="..\..\Source\GLS.FileTIN.pas"/>
         <DCCReference Include="..\..\Source\GLFileVRML.pas"/>
         <DCCReference Include="..\..\Source\GLFileVRML.pas"/>
         <DCCReference Include="..\..\Source\GLFileWAV.pas"/>
         <DCCReference Include="..\..\Source\GLFileWAV.pas"/>
         <DCCReference Include="..\..\Source\GLFileX.pas"/>
         <DCCReference Include="..\..\Source\GLFileX.pas"/>
@@ -290,7 +290,7 @@
         <DCCReference Include="..\..\Source\GLPhongShader.pas"/>
         <DCCReference Include="..\..\Source\GLPhongShader.pas"/>
         <DCCReference Include="..\..\Source\GLPictureRegisteredFormats.pas"/>
         <DCCReference Include="..\..\Source\GLPictureRegisteredFormats.pas"/>
         <DCCReference Include="..\..\Source\GLPipelineTransformation.pas"/>
         <DCCReference Include="..\..\Source\GLPipelineTransformation.pas"/>
-        <DCCReference Include="..\..\Source\GLPlugInManager.pas"/>
+        <DCCReference Include="..\..\Source\GLS.PlugInManager.pas"/>
         <DCCReference Include="..\..\Source\GLPluginIntf.pas"/>
         <DCCReference Include="..\..\Source\GLPluginIntf.pas"/>
         <DCCReference Include="..\..\Source\GLPolyhedron.pas"/>
         <DCCReference Include="..\..\Source\GLPolyhedron.pas"/>
         <DCCReference Include="..\..\Source\GLPolynomials.pas"/>
         <DCCReference Include="..\..\Source\GLPolynomials.pas"/>
@@ -323,7 +323,7 @@
         <DCCReference Include="..\..\Source\GLSLVertexDisplacementShader.pas"/>
         <DCCReference Include="..\..\Source\GLSLVertexDisplacementShader.pas"/>
         <DCCReference Include="..\..\Source\GLSLanguage.pas"/>
         <DCCReference Include="..\..\Source\GLSLanguage.pas"/>
         <DCCReference Include="..\..\Source\GLSLog.pas"/>
         <DCCReference Include="..\..\Source\GLSLog.pas"/>
-        <DCCReference Include="..\..\Source\GLSMemo.pas"/>
+        <DCCReference Include="..\..\Source\GLS.Memo.pas"/>
         <DCCReference Include="..\..\Source\GLSRGBE.pas"/>
         <DCCReference Include="..\..\Source\GLSRGBE.pas"/>
         <DCCReference Include="..\..\Source\GLSRedBlackTree.pas"/>
         <DCCReference Include="..\..\Source\GLSRedBlackTree.pas"/>
         <DCCReference Include="..\..\Source\GLScene.pas"/>
         <DCCReference Include="..\..\Source\GLScene.pas"/>
@@ -366,7 +366,7 @@
         <DCCReference Include="..\..\Source\GLTrail.pas"/>
         <DCCReference Include="..\..\Source\GLTrail.pas"/>
         <DCCReference Include="..\..\Source\GLTree.pas"/>
         <DCCReference Include="..\..\Source\GLTree.pas"/>
         <DCCReference Include="..\..\Source\GLTriangulation.pas"/>
         <DCCReference Include="..\..\Source\GLTriangulation.pas"/>
-        <DCCReference Include="..\..\Source\GLTypes.pas"/>
+        <DCCReference Include="..\..\Source\GLVectorRecTypes.pas"/>
         <DCCReference Include="..\..\Source\GLUserShader.pas"/>
         <DCCReference Include="..\..\Source\GLUserShader.pas"/>
         <DCCReference Include="..\..\Source\GLUtils.pas"/>
         <DCCReference Include="..\..\Source\GLUtils.pas"/>
         <DCCReference Include="..\..\Source\GLVectorGeometry.pas"/>
         <DCCReference Include="..\..\Source\GLVectorGeometry.pas"/>
@@ -377,7 +377,6 @@
         <DCCReference Include="..\..\Source\GLVerletHairClasses.pas"/>
         <DCCReference Include="..\..\Source\GLVerletHairClasses.pas"/>
         <DCCReference Include="..\..\Source\GLVerletSkeletonColliders.pas"/>
         <DCCReference Include="..\..\Source\GLVerletSkeletonColliders.pas"/>
         <DCCReference Include="..\..\Source\GLVerletTypes.pas"/>
         <DCCReference Include="..\..\Source\GLVerletTypes.pas"/>
-        <DCCReference Include="..\..\Source\GLVfsPAK.pas"/>
         <DCCReference Include="..\..\Source\GLWaterPlane.pas"/>
         <DCCReference Include="..\..\Source\GLWaterPlane.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Context.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Context.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Viewer.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Viewer.pas"/>
@@ -388,6 +387,7 @@
         <DCCReference Include="..\..\Source\OpenGLAdapter.pas"/>
         <DCCReference Include="..\..\Source\OpenGLAdapter.pas"/>
         <DCCReference Include="..\..\Source\OpenGLTokens.pas"/>
         <DCCReference Include="..\..\Source\OpenGLTokens.pas"/>
         <DCCReference Include="..\..\Source\XOpenGL.pas"/>
         <DCCReference Include="..\..\Source\XOpenGL.pas"/>
+        <DCCReference Include="..\..\Source\GLFileVfsPAK.pas"/>
         <BuildConfiguration Include="Debug">
         <BuildConfiguration Include="Debug">
             <Key>Cfg_2</Key>
             <Key>Cfg_2</Key>
             <CfgParent>Base</CfgParent>
             <CfgParent>Base</CfgParent>

+ 8 - 9
Packages/Win64/GLScene_RT.dpk

@@ -104,11 +104,11 @@ contains
   GLFileB3D in '..\..\Source\GLFileB3D.pas',
   GLFileB3D in '..\..\Source\GLFileB3D.pas',
   GLFileBMP in '..\..\Source\GLFileBMP.pas',
   GLFileBMP in '..\..\Source\GLFileBMP.pas',
   GLFileDDS in '..\..\Source\GLFileDDS.pas',
   GLFileDDS in '..\..\Source\GLFileDDS.pas',
-  GLFileDXF in '..\..\Source\GLFileDXF.pas',
+  GLS.FileDXF in '..\..\Source\GLS.FileDXF.pas',
   GLFileGL2 in '..\..\Source\GLFileGL2.pas',
   GLFileGL2 in '..\..\Source\GLFileGL2.pas',
   GLFileGLB in '..\..\Source\GLFileGLB.pas',
   GLFileGLB in '..\..\Source\GLFileGLB.pas',
   GLFileGLTF in '..\..\Source\GLFileGLTF.pas',
   GLFileGLTF in '..\..\Source\GLFileGLTF.pas',
-  GLFileGRD in '..\..\Source\GLFileGRD.pas',
+  GLS.FileGRD in '..\..\Source\GLS.FileGRD.pas',
   GLFileGTS in '..\..\Source\GLFileGTS.pas',
   GLFileGTS in '..\..\Source\GLFileGTS.pas',
   GLFileHDR in '..\..\Source\GLFileHDR.pas',
   GLFileHDR in '..\..\Source\GLFileHDR.pas',
   GLFileJPEG in '..\..\Source\GLFileJPEG.pas',
   GLFileJPEG in '..\..\Source\GLFileJPEG.pas',
@@ -132,7 +132,7 @@ contains
   GLFileSMD in '..\..\Source\GLFileSMD.pas',
   GLFileSMD in '..\..\Source\GLFileSMD.pas',
   GLFileSTL in '..\..\Source\GLFileSTL.pas',
   GLFileSTL in '..\..\Source\GLFileSTL.pas',
   GLFileTGA in '..\..\Source\GLFileTGA.pas',
   GLFileTGA in '..\..\Source\GLFileTGA.pas',
-  GLFileTIN in '..\..\Source\GLFileTIN.pas',
+  GLS.FileTIN in '..\..\Source\GLS.FileTIN.pas',
   GLFileVRML in '..\..\Source\GLFileVRML.pas',
   GLFileVRML in '..\..\Source\GLFileVRML.pas',
   GLFileWAV in '..\..\Source\GLFileWAV.pas',
   GLFileWAV in '..\..\Source\GLFileWAV.pas',
   GLFileX in '..\..\Source\GLFileX.pas',
   GLFileX in '..\..\Source\GLFileX.pas',
@@ -196,8 +196,7 @@ contains
   GLPhongShader in '..\..\Source\GLPhongShader.pas',
   GLPhongShader in '..\..\Source\GLPhongShader.pas',
   GLPictureRegisteredFormats in '..\..\Source\GLPictureRegisteredFormats.pas',
   GLPictureRegisteredFormats in '..\..\Source\GLPictureRegisteredFormats.pas',
   GLPipelineTransformation in '..\..\Source\GLPipelineTransformation.pas',
   GLPipelineTransformation in '..\..\Source\GLPipelineTransformation.pas',
-  GLPlugInManager in '..\..\Source\GLPlugInManager.pas',
-  GLPluginIntf in '..\..\Source\GLPluginIntf.pas',
+  GLS.PlugInManager in '..\..\Source\GLS.PlugInManager.pas',
   GLPolyhedron in '..\..\Source\GLPolyhedron.pas',
   GLPolyhedron in '..\..\Source\GLPolyhedron.pas',
   GLPolynomials in '..\..\Source\GLPolynomials.pas',
   GLPolynomials in '..\..\Source\GLPolynomials.pas',
   GLPortal in '..\..\Source\GLPortal.pas',
   GLPortal in '..\..\Source\GLPortal.pas',
@@ -228,7 +227,7 @@ contains
   GLSLToonShader in '..\..\Source\GLSLToonShader.pas',
   GLSLToonShader in '..\..\Source\GLSLToonShader.pas',
   GLSLanguage in '..\..\Source\GLSLanguage.pas',
   GLSLanguage in '..\..\Source\GLSLanguage.pas',
   GLSLog in '..\..\Source\GLSLog.pas',
   GLSLog in '..\..\Source\GLSLog.pas',
-  GLSMemo in '..\..\Source\GLSMemo.pas',
+  GLS.Memo in '..\..\Source\GLS.Memo.pas',
   GLSRGBE in '..\..\Source\GLSRGBE.pas',
   GLSRGBE in '..\..\Source\GLSRGBE.pas',
   GLSRedBlackTree in '..\..\Source\GLSRedBlackTree.pas',
   GLSRedBlackTree in '..\..\Source\GLSRedBlackTree.pas',
   GLScene in '..\..\Source\GLScene.pas',
   GLScene in '..\..\Source\GLScene.pas',
@@ -269,18 +268,17 @@ contains
   GLTrail in '..\..\Source\GLTrail.pas',
   GLTrail in '..\..\Source\GLTrail.pas',
   GLTree in '..\..\Source\GLTree.pas',
   GLTree in '..\..\Source\GLTree.pas',
   GLTriangulation in '..\..\Source\GLTriangulation.pas',
   GLTriangulation in '..\..\Source\GLTriangulation.pas',
-  GLTypes in '..\..\Source\GLTypes.pas',
   GLUserShader in '..\..\Source\GLUserShader.pas',
   GLUserShader in '..\..\Source\GLUserShader.pas',
   GLUtils in '..\..\Source\GLUtils.pas',
   GLUtils in '..\..\Source\GLUtils.pas',
   GLVectorFileObjects in '..\..\Source\GLVectorFileObjects.pas',
   GLVectorFileObjects in '..\..\Source\GLVectorFileObjects.pas',
   GLVectorGeometry in '..\..\Source\GLVectorGeometry.pas',
   GLVectorGeometry in '..\..\Source\GLVectorGeometry.pas',
   GLVectorLists in '..\..\Source\GLVectorLists.pas',
   GLVectorLists in '..\..\Source\GLVectorLists.pas',
+  GLVectorRecTypes in '..\..\Source\GLVectorRecTypes.pas',
   GLVectorTypes in '..\..\Source\GLVectorTypes.pas',
   GLVectorTypes in '..\..\Source\GLVectorTypes.pas',
   GLVerletClothify in '..\..\Source\GLVerletClothify.pas',
   GLVerletClothify in '..\..\Source\GLVerletClothify.pas',
   GLVerletHairClasses in '..\..\Source\GLVerletHairClasses.pas',
   GLVerletHairClasses in '..\..\Source\GLVerletHairClasses.pas',
   GLVerletSkeletonColliders in '..\..\Source\GLVerletSkeletonColliders.pas',
   GLVerletSkeletonColliders in '..\..\Source\GLVerletSkeletonColliders.pas',
   GLVerletTypes in '..\..\Source\GLVerletTypes.pas',
   GLVerletTypes in '..\..\Source\GLVerletTypes.pas',
-  GLVfsPAK in '..\..\Source\GLVfsPAK.pas',
   GLWaterPlane in '..\..\Source\GLWaterPlane.pas',
   GLWaterPlane in '..\..\Source\GLWaterPlane.pas',
   GLWin32Context in '..\..\Source\GLWin32Context.pas',
   GLWin32Context in '..\..\Source\GLWin32Context.pas',
   GLWin32Viewer in '..\..\Source\GLWin32Viewer.pas',
   GLWin32Viewer in '..\..\Source\GLWin32Viewer.pas',
@@ -291,7 +289,8 @@ contains
   OpenGLTokens in '..\..\Source\OpenGLTokens.pas',
   OpenGLTokens in '..\..\Source\OpenGLTokens.pas',
   GLS.OpenGLx in '..\..\Source\GLS.OpenGLx.pas',
   GLS.OpenGLx in '..\..\Source\GLS.OpenGLx.pas',
   XCollection in '..\..\Source\XCollection.pas',
   XCollection in '..\..\Source\XCollection.pas',
-  XOpenGL in '..\..\Source\XOpenGL.pas';
+  XOpenGL in '..\..\Source\XOpenGL.pas',
+  GLFileVfsPAK in '..\..\Source\GLFileVfsPAK.pas';
 
 
 end.
 end.
 
 

+ 8 - 9
Packages/Win64/GLScene_RT.dproj

@@ -206,11 +206,11 @@
         <DCCReference Include="..\..\Source\GLFileB3D.pas"/>
         <DCCReference Include="..\..\Source\GLFileB3D.pas"/>
         <DCCReference Include="..\..\Source\GLFileBMP.pas"/>
         <DCCReference Include="..\..\Source\GLFileBMP.pas"/>
         <DCCReference Include="..\..\Source\GLFileDDS.pas"/>
         <DCCReference Include="..\..\Source\GLFileDDS.pas"/>
-        <DCCReference Include="..\..\Source\GLFileDXF.pas"/>
+        <DCCReference Include="..\..\Source\GLS.FileDXF.pas"/>
         <DCCReference Include="..\..\Source\GLFileGL2.pas"/>
         <DCCReference Include="..\..\Source\GLFileGL2.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLB.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLB.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLTF.pas"/>
         <DCCReference Include="..\..\Source\GLFileGLTF.pas"/>
-        <DCCReference Include="..\..\Source\GLFileGRD.pas"/>
+        <DCCReference Include="..\..\Source\GLS.FileGRD.pas"/>
         <DCCReference Include="..\..\Source\GLFileGTS.pas"/>
         <DCCReference Include="..\..\Source\GLFileGTS.pas"/>
         <DCCReference Include="..\..\Source\GLFileHDR.pas"/>
         <DCCReference Include="..\..\Source\GLFileHDR.pas"/>
         <DCCReference Include="..\..\Source\GLFileJPEG.pas"/>
         <DCCReference Include="..\..\Source\GLFileJPEG.pas"/>
@@ -234,7 +234,7 @@
         <DCCReference Include="..\..\Source\GLFileSMD.pas"/>
         <DCCReference Include="..\..\Source\GLFileSMD.pas"/>
         <DCCReference Include="..\..\Source\GLFileSTL.pas"/>
         <DCCReference Include="..\..\Source\GLFileSTL.pas"/>
         <DCCReference Include="..\..\Source\GLFileTGA.pas"/>
         <DCCReference Include="..\..\Source\GLFileTGA.pas"/>
-        <DCCReference Include="..\..\Source\GLFileTIN.pas"/>
+        <DCCReference Include="..\..\Source\GLS.FileTIN.pas"/>
         <DCCReference Include="..\..\Source\GLFileVRML.pas"/>
         <DCCReference Include="..\..\Source\GLFileVRML.pas"/>
         <DCCReference Include="..\..\Source\GLFileWAV.pas"/>
         <DCCReference Include="..\..\Source\GLFileWAV.pas"/>
         <DCCReference Include="..\..\Source\GLFileX.pas"/>
         <DCCReference Include="..\..\Source\GLFileX.pas"/>
@@ -298,8 +298,7 @@
         <DCCReference Include="..\..\Source\GLPhongShader.pas"/>
         <DCCReference Include="..\..\Source\GLPhongShader.pas"/>
         <DCCReference Include="..\..\Source\GLPictureRegisteredFormats.pas"/>
         <DCCReference Include="..\..\Source\GLPictureRegisteredFormats.pas"/>
         <DCCReference Include="..\..\Source\GLPipelineTransformation.pas"/>
         <DCCReference Include="..\..\Source\GLPipelineTransformation.pas"/>
-        <DCCReference Include="..\..\Source\GLPlugInManager.pas"/>
-        <DCCReference Include="..\..\Source\GLPluginIntf.pas"/>
+        <DCCReference Include="..\..\Source\GLS.PlugInManager.pas"/>
         <DCCReference Include="..\..\Source\GLPolyhedron.pas"/>
         <DCCReference Include="..\..\Source\GLPolyhedron.pas"/>
         <DCCReference Include="..\..\Source\GLPolynomials.pas"/>
         <DCCReference Include="..\..\Source\GLPolynomials.pas"/>
         <DCCReference Include="..\..\Source\GLPortal.pas"/>
         <DCCReference Include="..\..\Source\GLPortal.pas"/>
@@ -330,7 +329,7 @@
         <DCCReference Include="..\..\Source\GLSLToonShader.pas"/>
         <DCCReference Include="..\..\Source\GLSLToonShader.pas"/>
         <DCCReference Include="..\..\Source\GLSLanguage.pas"/>
         <DCCReference Include="..\..\Source\GLSLanguage.pas"/>
         <DCCReference Include="..\..\Source\GLSLog.pas"/>
         <DCCReference Include="..\..\Source\GLSLog.pas"/>
-        <DCCReference Include="..\..\Source\GLSMemo.pas"/>
+        <DCCReference Include="..\..\Source\GLS.Memo.pas"/>
         <DCCReference Include="..\..\Source\GLSRGBE.pas"/>
         <DCCReference Include="..\..\Source\GLSRGBE.pas"/>
         <DCCReference Include="..\..\Source\GLSRedBlackTree.pas"/>
         <DCCReference Include="..\..\Source\GLSRedBlackTree.pas"/>
         <DCCReference Include="..\..\Source\GLScene.pas"/>
         <DCCReference Include="..\..\Source\GLScene.pas"/>
@@ -371,18 +370,17 @@
         <DCCReference Include="..\..\Source\GLTrail.pas"/>
         <DCCReference Include="..\..\Source\GLTrail.pas"/>
         <DCCReference Include="..\..\Source\GLTree.pas"/>
         <DCCReference Include="..\..\Source\GLTree.pas"/>
         <DCCReference Include="..\..\Source\GLTriangulation.pas"/>
         <DCCReference Include="..\..\Source\GLTriangulation.pas"/>
-        <DCCReference Include="..\..\Source\GLTypes.pas"/>
         <DCCReference Include="..\..\Source\GLUserShader.pas"/>
         <DCCReference Include="..\..\Source\GLUserShader.pas"/>
         <DCCReference Include="..\..\Source\GLUtils.pas"/>
         <DCCReference Include="..\..\Source\GLUtils.pas"/>
         <DCCReference Include="..\..\Source\GLVectorFileObjects.pas"/>
         <DCCReference Include="..\..\Source\GLVectorFileObjects.pas"/>
         <DCCReference Include="..\..\Source\GLVectorGeometry.pas"/>
         <DCCReference Include="..\..\Source\GLVectorGeometry.pas"/>
         <DCCReference Include="..\..\Source\GLVectorLists.pas"/>
         <DCCReference Include="..\..\Source\GLVectorLists.pas"/>
+        <DCCReference Include="..\..\Source\GLVectorRecTypes.pas"/>
         <DCCReference Include="..\..\Source\GLVectorTypes.pas"/>
         <DCCReference Include="..\..\Source\GLVectorTypes.pas"/>
         <DCCReference Include="..\..\Source\GLVerletClothify.pas"/>
         <DCCReference Include="..\..\Source\GLVerletClothify.pas"/>
         <DCCReference Include="..\..\Source\GLVerletHairClasses.pas"/>
         <DCCReference Include="..\..\Source\GLVerletHairClasses.pas"/>
         <DCCReference Include="..\..\Source\GLVerletSkeletonColliders.pas"/>
         <DCCReference Include="..\..\Source\GLVerletSkeletonColliders.pas"/>
         <DCCReference Include="..\..\Source\GLVerletTypes.pas"/>
         <DCCReference Include="..\..\Source\GLVerletTypes.pas"/>
-        <DCCReference Include="..\..\Source\GLVfsPAK.pas"/>
         <DCCReference Include="..\..\Source\GLWaterPlane.pas"/>
         <DCCReference Include="..\..\Source\GLWaterPlane.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Context.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Context.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Viewer.pas"/>
         <DCCReference Include="..\..\Source\GLWin32Viewer.pas"/>
@@ -394,6 +392,7 @@
         <DCCReference Include="..\..\Source\GLS.OpenGLx.pas"/>
         <DCCReference Include="..\..\Source\GLS.OpenGLx.pas"/>
         <DCCReference Include="..\..\Source\XCollection.pas"/>
         <DCCReference Include="..\..\Source\XCollection.pas"/>
         <DCCReference Include="..\..\Source\XOpenGL.pas"/>
         <DCCReference Include="..\..\Source\XOpenGL.pas"/>
+        <DCCReference Include="..\..\Source\GLFileVfsPAK.pas"/>
         <BuildConfiguration Include="Debug">
         <BuildConfiguration Include="Debug">
             <Key>Cfg_2</Key>
             <Key>Cfg_2</Key>
             <CfgParent>Base</CfgParent>
             <CfgParent>Base</CfgParent>
@@ -426,7 +425,7 @@
                 <Platform value="Win64">True</Platform>
                 <Platform value="Win64">True</Platform>
             </Platforms>
             </Platforms>
             <Deployment Version="3">
             <Deployment Version="3">
-                <DeployFile LocalName="..\..\bpl\Win64\GLScene_RT.bpl" Configuration="Release" Class="ProjectOutput">
+                <DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\21.0\Bpl\Win64\GLScene_RT.bpl" Configuration="Release" Class="ProjectOutput">
                     <Platform Name="Win64">
                     <Platform Name="Win64">
                         <RemoteName>GLScene_RT.bpl</RemoteName>
                         <RemoteName>GLScene_RT.bpl</RemoteName>
                         <Overwrite>true</Overwrite>
                         <Overwrite>true</Overwrite>

+ 4 - 5
Source/FPlugInManagerEditor.pas

@@ -1,11 +1,11 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-  Need a short description of what it does here. 
-}
+
 unit FPlugInManagerEditor;
 unit FPlugInManagerEditor;
 
 
+(* Need a short description of what it does here *)
+
 interface
 interface
 
 
 {$I GLScene.inc}
 {$I GLScene.inc}
@@ -24,8 +24,7 @@ uses
   Vcl.ComCtrls, 
   Vcl.ComCtrls, 
   Vcl.ToolWin,
   Vcl.ToolWin,
    
    
-  GLPlugInIntf, 
-  GLPlugInManager;
+  GLS.PlugInManager;
 
 
 type
 type
   TGLPlugInManagerEditorForm = class(TForm)
   TGLPlugInManagerEditorForm = class(TForm)

+ 7 - 6
Source/FShaderMemo.pas

@@ -1,14 +1,15 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-   Shader code editor. 
+
+unit FShaderMemo;
+
+(*
+  Shader code editor.
 // TODO: need to decide how to load templates from external file
 // TODO: need to decide how to load templates from external file
 //       and update it without package recompilation
 //       and update it without package recompilation
-}
 
 
-
-unit FShaderMemo;
+*)
 
 
 interface
 interface
 
 
@@ -33,7 +34,7 @@ uses
   VCL.StdCtrls,
   VCL.StdCtrls,
   VCL.Graphics,
   VCL.Graphics,
    
    
-  GLSMemo;
+  GLS.Memo;
 
 
 type
 type
 
 

+ 148 - 150
Source/FileOCT.pas

@@ -10,83 +10,84 @@ interface
 
 
 {$I GLScene.inc}
 {$I GLScene.inc}
 
 
-uses 
-  System.Classes, 
+uses
+  System.Classes,
   System.SysUtils,
   System.SysUtils,
-   
+
   GLVectorGeometry,
   GLVectorGeometry,
   GLVectorTypes,
   GLVectorTypes,
   GLVectorLists;
   GLVectorLists;
 
 
 type
 type
 
 
-   TOCTHeader = record
-		numVerts : Integer;
-		numFaces : Integer;
-		numTextures : Integer;
-		numLightmaps : Integer;
-		numLights : Integer;
-	end;
-
-	TOCTVertex = record
-		tv : TTexPoint;      // texture coordinates
-		lv : TTexpoint;      // lightmap coordinates
-		pos : TAffineVector; // vertex position
-   end;
-
-	TOCTFace = record
-		start : Integer;     // first face vert in vertex array
-		num : Integer;			// number of verts in the face
-		id : Integer;			// texture index into the texture array
-		lid : Integer;			// lightmap index into the lightmap array
-		p : THmgPlane;
-	end;
-   POCTFace = ^TOCTFace;
-
-	TOCTTexture = record
-		id : Integer;				      // texture id
-		Name : array [0..63] of AnsiChar;	// texture name
-   end;
-
-	TOCTLightmap = record
-		id : Integer;				         // lightmaps id
-		map : array [0..49151] of Byte;	// 128 x 128 raw RGB data
-   end;
-   POCTLightmap = ^TOCTLightmap;
-
-	TOCTLight = record
-		pos : TAffineVector;		      // Position
-		color : TAffineVector;			// Color (RGB)
-		intensity : Integer;			   // Intensity
-	end;
-
-   TOCTFile = class (TObject)
-      public
-         Header         : TOCTHeader;
-         Vertices       : array of TOCTVertex;
-         Faces          : array of TOCTFace;
-         Textures       : array of TOCTTexture;
-         Lightmaps      : array of TOCTLightmap;
-         Lights         : array of TOCTLight;
-         PlayerPos      : TAffineVector;
-         constructor Create; overload;
-         constructor Create(octStream : TStream); overload;
-         {Saves content to stream in OCT format. 
-            The Header is automatically prepared before streaming. }
-         procedure SaveToStream(aStream : TStream);
-         procedure AddTriangles(vertexCoords : TAffineVectorList;
-                                texMapCoords : TAffineVectorList;
-                                const textureName : String);
-         procedure AddLight(const lightPos : TAffineVector;
-                            const lightColor : TVector;
-                            lightIntensity : Integer);
-   end;
-
-// ------------------------------------------------------------------
+  TOCTHeader = record
+    numVerts: Integer;
+    numFaces: Integer;
+    numTextures: Integer;
+    numLightmaps: Integer;
+    numLights: Integer;
+  end;
+
+  TOCTVertex = record
+    tv: TTexPoint; // texture coordinates
+    lv: TTexPoint; // lightmap coordinates
+    pos: TAffineVector; // vertex position
+  end;
+
+  TOCTFace = record
+    start: Integer; // first face vert in vertex array
+    num: Integer; // number of verts in the face
+    id: Integer; // texture index into the texture array
+    lid: Integer; // lightmap index into the lightmap array
+    p: THmgPlane;
+  end;
+
+  POCTFace = ^TOCTFace;
+
+  TOCTTexture = record
+    id: Integer; // texture id
+    Name: array [0 .. 63] of AnsiChar; // texture name
+  end;
+
+  TOCTLightmap = record
+    id: Integer; // lightmaps id
+    map: array [0 .. 49151] of Byte; // 128 x 128 raw RGB data
+  end;
+
+  POCTLightmap = ^TOCTLightmap;
+
+  TOCTLight = record
+    pos: TAffineVector; // Position
+    color: TAffineVector; // Color (RGB)
+    intensity: Integer; // Intensity
+  end;
+
+  TOCTFile = class(TObject)
+  public
+    Header: TOCTHeader;
+    Vertices: array of TOCTVertex;
+    Faces: array of TOCTFace;
+    Textures: array of TOCTTexture;
+    Lightmaps: array of TOCTLightmap;
+    Lights: array of TOCTLight;
+    PlayerPos: TAffineVector;
+    constructor Create; overload;
+    constructor Create(octStream: TStream); overload;
+    (* Saves content to stream in OCT format.
+      The Header is automatically prepared before streaming. *)
+    procedure SaveToStream(aStream: TStream);
+    procedure AddTriangles(vertexCoords: TAffineVectorList;
+      texMapCoords: TAffineVectorList; const textureName: String);
+    procedure AddLight(const lightPos: TAffineVector; const lightColor: TVector;
+      lightIntensity: Integer);
+  end;
+
+  // ------------------------------------------------------------------
 implementation
 implementation
+
 // ------------------------------------------------------------------
 // ------------------------------------------------------------------
 
 
-uses 
+uses
   GLMeshUtils;
   GLMeshUtils;
 
 
 // ------------------
 // ------------------
@@ -95,104 +96,101 @@ uses
 
 
 constructor TOCTFile.Create;
 constructor TOCTFile.Create;
 begin
 begin
-   inherited Create;
+  inherited Create;
 end;
 end;
 
 
-constructor TOCTFile.Create(octStream : TStream);
+constructor TOCTFile.Create(octStream: TStream);
 begin
 begin
-   inherited Create;
-   
-   // Read in the header
-   octStream.Read(Header, SizeOf(Header));
-
-   // then the rest of the stuff
-
-   SetLength(Vertices, Header.numVerts);
-   octStream.Read(Vertices[0], Header.numVerts*SizeOf(TOCTVertex));
-
-   SetLength(Faces, Header.numFaces);
-   octStream.Read(Faces[0], Header.numFaces*SizeOf(TOCTFace));
-
-   SetLength(Textures, Header.numTextures);
-   octStream.Read(Textures[0], Header.numTextures*SizeOf(TOCTTexture));
-
-   SetLength(Lightmaps, Header.numLightmaps);
-   octStream.Read(Lightmaps[0], Header.numLightmaps*SizeOf(TOCTLightmap));
-
-   SetLength(Lights, Header.numLights);
-   octStream.Read(Lights[0], Header.numLights*SizeOf(TOCTLight));
-
-   octStream.Read(PlayerPos, SizeOf(PlayerPos))
+  inherited Create;
+  // Read in the header
+  octStream.Read(Header, SizeOf(Header));
+  // then the rest of the stuff
+  SetLength(Vertices, Header.numVerts);
+  octStream.Read(Vertices[0], Header.numVerts * SizeOf(TOCTVertex));
+  SetLength(Faces, Header.numFaces);
+  octStream.Read(Faces[0], Header.numFaces * SizeOf(TOCTFace));
+  SetLength(Textures, Header.numTextures);
+  octStream.Read(Textures[0], Header.numTextures * SizeOf(TOCTTexture));
+  SetLength(Lightmaps, Header.numLightmaps);
+  octStream.Read(Lightmaps[0], Header.numLightmaps * SizeOf(TOCTLightmap));
+  SetLength(Lights, Header.numLights);
+  octStream.Read(Lights[0], Header.numLights * SizeOf(TOCTLight));
+  octStream.Read(PlayerPos, SizeOf(PlayerPos))
 end;
 end;
 
 
-procedure TOCTFile.SaveToStream(aStream : TStream);
+procedure TOCTFile.SaveToStream(aStream: TStream);
 begin
 begin
-   with Header, aStream do begin
-      numVerts:=Length(Vertices);
-      numFaces:=Length(Faces);
-      numTextures:=Length(Textures);
-      numLightmaps:=Length(Lightmaps);
-      numLights:=Length(Lights);
-
-      Write(Header, SizeOf(Header));
-      Write(Vertices[0], numVerts*SizeOf(TOCTVertex));
-      Write(Faces[0], numFaces*SizeOf(TOCTFace));
-      Write(Textures[0], numTextures*SizeOf(TOCTTexture));
-      Write(Lightmaps[0], numLightmaps*SizeOf(TOCTLightmap));
-      Write(Lights[0], numLights*SizeOf(TOCTLight));
-      Write(PlayerPos, SizeOf(PlayerPos))
-   end;
+  with Header, aStream do
+  begin
+    numVerts := Length(Vertices);
+    numFaces := Length(Faces);
+    numTextures := Length(Textures);
+    numLightmaps := Length(Lightmaps);
+    numLights := Length(Lights);
+
+    Write(Header, SizeOf(Header));
+    Write(Vertices[0], numVerts * SizeOf(TOCTVertex));
+    Write(Faces[0], numFaces * SizeOf(TOCTFace));
+    Write(Textures[0], numTextures * SizeOf(TOCTTexture));
+    Write(Lightmaps[0], numLightmaps * SizeOf(TOCTLightmap));
+    Write(Lights[0], numLights * SizeOf(TOCTLight));
+    Write(PlayerPos, SizeOf(PlayerPos))
+  end;
 end;
 end;
 
 
-procedure TOCTFile.AddTriangles(vertexCoords : TAffineVectorList;
-                                texMapCoords : TAffineVectorList;
-                                const textureName : String);
+procedure TOCTFile.AddTriangles(vertexCoords: TAffineVectorList;
+  texMapCoords: TAffineVectorList; const textureName: String);
 var
 var
-   i : Integer;
-   baseIdx, texIdx : Integer;
+  i: Integer;
+  baseIdx, texIdx: Integer;
 begin
 begin
-   Assert((texMapCoords=nil) or (texMapCoords.Count=vertexCoords.Count));
-
-   texIdx:=Length(Textures);
-   SetLength(Textures, texIdx+1);
-   Move(textureName[1], Textures[texIdx].Name[0], Length(textureName));
-   SetLength(Lightmaps, 1);
-   FillChar(Lightmaps[0].map[0], 128*3, 255);
-
-   baseIdx:=Length(Vertices);
-   SetLength(Vertices, baseIdx+vertexCoords.Count);
-   for i:=0 to vertexCoords.Count-1 do with Vertices[baseIdx+i] do begin
-      pos:=vertexCoords.List[i];
+  Assert((texMapCoords = nil) or (texMapCoords.Count = vertexCoords.Count));
+
+  texIdx := Length(Textures);
+  SetLength(Textures, texIdx + 1);
+  Move(textureName[1], Textures[texIdx].Name[0], Length(textureName));
+  SetLength(Lightmaps, 1);
+  FillChar(Lightmaps[0].map[0], 128 * 3, 255);
+
+  baseIdx := Length(Vertices);
+  SetLength(Vertices, baseIdx + vertexCoords.Count);
+  for i := 0 to vertexCoords.Count - 1 do
+    with Vertices[baseIdx + i] do
+    begin
+      pos := vertexCoords.List[i];
       if Assigned(texMapCoords) then
       if Assigned(texMapCoords) then
-         tv:=PTexPoint(@texMapCoords.List[i])^;
-   end;
-
-   SetLength(Faces, vertexCoords.Count div 3);
-   i:=0; while i<vertexCoords.Count do begin
-      with Faces[i div 3] do begin
-         start:=baseIdx+i;
-         num:=3;
-         id:=texIdx;
-         p:=PlaneMake(vertexCoords[i],
-                      CalcPlaneNormal(vertexCoords[i+0], vertexCoords[i+1], vertexCoords[i+0]));
-      end;
-      Inc(i, 3);
-   end;
+        tv := PTexPoint(@texMapCoords.List[i])^;
+    end;
+
+  SetLength(Faces, vertexCoords.Count div 3);
+  i := 0;
+  while i < vertexCoords.Count do
+  begin
+    with Faces[i div 3] do
+    begin
+      start := baseIdx + i;
+      num := 3;
+      id := texIdx;
+      p := PlaneMake(vertexCoords[i], CalcPlaneNormal(vertexCoords[i + 0],
+        vertexCoords[i + 1], vertexCoords[i + 0]));
+    end;
+    Inc(i, 3);
+  end;
 end;
 end;
 
 
-procedure TOCTFile.AddLight(const lightPos : TAffineVector;
-                            const lightColor : TVector;
-                            lightIntensity : Integer);
+procedure TOCTFile.AddLight(const lightPos: TAffineVector;
+  const lightColor: TVector; lightIntensity: Integer);
 var
 var
-   n : Integer;
+  n: Integer;
 begin
 begin
-   n:=Length(Lights);
-   SetLength(Lights, n+1);
-   with Lights[n] do begin
-      pos:=lightPos;
-      color:=PAffineVector(@lightColor)^;
-      intensity:=lightIntensity;
-   end;
+  n := Length(Lights);
+  SetLength(Lights, n + 1);
+  with Lights[n] do
+  begin
+    pos := lightPos;
+    color := PAffineVector(@lightColor)^;
+    intensity := lightIntensity;
+  end;
 end;
 end;
 
 
 end.
 end.

+ 4 - 4
Source/GLCollision.pas

@@ -1,11 +1,11 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-(*
-  Collision-detection management
-*)
+
 unit GLCollision;
 unit GLCollision;
 
 
+(* Collision-detection management *)
+
 interface
 interface
 
 
 {$I GLScene.inc}
 {$I GLScene.inc}
@@ -958,7 +958,6 @@ end;
 initialization
 initialization
 // ------------------------------------------------------------------
 // ------------------------------------------------------------------
 
 
-// class registrations
 RegisterXCollectionItemClass(TGLBCollision);
 RegisterXCollectionItemClass(TGLBCollision);
 
 
 finalization
 finalization
@@ -966,3 +965,4 @@ finalization
 UnregisterXCollectionItemClass(TGLBCollision);
 UnregisterXCollectionItemClass(TGLBCollision);
 
 
 end.
 end.
+

+ 24 - 25
Source/GLCoordinates.pas

@@ -1,39 +1,38 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-  Coordinate related classes.
-}
 
 
 unit GLCoordinates;
 unit GLCoordinates;
 
 
+(* Coordinate related classes *)
+
 interface
 interface
 
 
 {$I GLScene.inc}
 {$I GLScene.inc}
 
 
 uses
 uses
-  System.Classes, 
+  System.Classes,
   System.SysUtils,
   System.SysUtils,
-   
-  GLVectorGeometry, 
-  GLVectorTypes, 
-  OpenGLTokens, 
+
+  GLVectorGeometry,
+  GLVectorTypes,
+  OpenGLTokens,
   GLBaseClasses;
   GLBaseClasses;
 
 
 type
 type
 
 
-  { Identifie le type de données stockées au sein d'un TGLCustomCoordinates.
+  (* Identifie le type de données stockées au sein d'un TGLCustomCoordinates.
      csPoint2D : a simple 2D point (Z=0, W=0)
      csPoint2D : a simple 2D point (Z=0, W=0)
      csPoint : un point (W=1)
      csPoint : un point (W=1)
      csVector : un vecteur (W=0)
      csVector : un vecteur (W=0)
-     csUnknown : aucune contrainte }
+     csUnknown : aucune contrainte *)
   TGLCoordinatesStyle = (csPoint2D, csPoint, csVector, csUnknown);
   TGLCoordinatesStyle = (csPoint2D, csPoint, csVector, csUnknown);
 
 
-  {  Stores and homogeneous vector. 
+  (* Stores and homogeneous vector.
     This class is basicly a container for a TVector, allowing proper use of
     This class is basicly a container for a TVector, allowing proper use of
     delphi property editors and editing in the IDE. Vector/Coordinates
     delphi property editors and editing in the IDE. Vector/Coordinates
     manipulation methods are only minimal.
     manipulation methods are only minimal.
-    Handles dynamic default values to save resource file space.  }
+    Handles dynamic default values to save resource file space.  *)
   TGLCustomCoordinates = class(TGLUpdateAbleObject)
   TGLCustomCoordinates = class(TGLUpdateAbleObject)
   private
   private
    FCoords: TVector;
    FCoords: TVector;
@@ -63,12 +62,12 @@ type
     procedure ReadFromFiler(Reader: TReader);
     procedure ReadFromFiler(Reader: TReader);
     procedure Initialize(const Value: TVector);
     procedure Initialize(const Value: TVector);
     procedure NotifyChange(Sender: TObject); override;
     procedure NotifyChange(Sender: TObject); override;
-    { Identifies the coordinates styles.
+    (* Identifies the coordinates styles.
       The property is NOT persistent, csUnknown by default, and should be
       The property is NOT persistent, csUnknown by default, and should be
-      managed by owner object only (internally). 
+      managed by owner object only (internally).
       It is used by the TGLCustomCoordinates for internal "assertion" checks
       It is used by the TGLCustomCoordinates for internal "assertion" checks
       to detect "misuses" or "misunderstandings" of what the homogeneous
       to detect "misuses" or "misunderstandings" of what the homogeneous
-      coordinates system implies. }
+      coordinates system implies. *)
     property Style: TGLCoordinatesStyle read FStyle write FStyle;
     property Style: TGLCoordinatesStyle read FStyle write FStyle;
     procedure Translate(const TranslationVector: TVector); overload;
     procedure Translate(const TranslationVector: TVector); overload;
     procedure Translate(const TranslationVector: TAffineVector); overload;
     procedure Translate(const TranslationVector: TAffineVector); overload;
@@ -96,25 +95,25 @@ type
     procedure SetPoint2D(const Vector: TVector2f); overload;
     procedure SetPoint2D(const Vector: TVector2f); overload;
     procedure SetToZero;
     procedure SetToZero;
     function AsAddress: PGLFloat; inline;
     function AsAddress: PGLFloat; inline;
-    {  The coordinates viewed as a vector.
+    (* The coordinates viewed as a vector.
       Assigning a value to this property will trigger notification events,
       Assigning a value to this property will trigger notification events,
-      if you don't want so, use DirectVector instead. }
+      if you don't want so, use DirectVector instead. *)
     property AsVector: TVector read FCoords write SetAsVector;
     property AsVector: TVector read FCoords write SetAsVector;
-    { The coordinates viewed as an affine vector.
+    (* The coordinates viewed as an affine vector.
       Assigning a value to this property will trigger notification events,
       Assigning a value to this property will trigger notification events,
       if you don't want so, use DirectVector instead.
       if you don't want so, use DirectVector instead.
-      The W component is automatically adjustes depending on style. }
+      The W component is automatically adjustes depending on style. *)
     property AsAffineVector: TAffineVector read GetAsAffineVector  write SetAsAffineVector;
     property AsAffineVector: TAffineVector read GetAsAffineVector  write SetAsAffineVector;
-    {  The coordinates viewed as a 2D point. 
+    (*  The coordinates viewed as a 2D point.
       Assigning a value to this property will trigger notification events,
       Assigning a value to this property will trigger notification events,
-      if you don't want so, use DirectVector instead. }
+      if you don't want so, use DirectVector instead. *)
     property AsPoint2D: TVector2f read GetAsPoint2D write SetAsPoint2D;
     property AsPoint2D: TVector2f read GetAsPoint2D write SetAsPoint2D;
     property X: TGLFloat index 0 read GetCoordinate write SetCoordinate;
     property X: TGLFloat index 0 read GetCoordinate write SetCoordinate;
     property Y: TGLFloat index 1 read GetCoordinate write SetCoordinate;
     property Y: TGLFloat index 1 read GetCoordinate write SetCoordinate;
     property Z: TGLFloat index 2 read GetCoordinate write SetCoordinate;
     property Z: TGLFloat index 2 read GetCoordinate write SetCoordinate;
     property W: TGLFloat index 3 read GetCoordinate write SetCoordinate;
     property W: TGLFloat index 3 read GetCoordinate write SetCoordinate;
     property Coordinate[const AIndex: Integer]: TGLFloat read GetCoordinate write SetCoordinate; default;
     property Coordinate[const AIndex: Integer]: TGLFloat read GetCoordinate write SetCoordinate; default;
-    {  The coordinates, in-between brackets, separated by semi-colons. }
+    // The coordinates, in-between brackets, separated by semi-colons.
     property AsString: String read GetAsString;
     property AsString: String read GetAsString;
     // Similar to AsVector but does not trigger notification events
     // Similar to AsVector but does not trigger notification events
     property DirectVector: TVector read FCoords write SetDirectVector;
     property DirectVector: TVector read FCoords write SetDirectVector;
@@ -124,14 +123,14 @@ type
     property DirectW: TGLFloat index 3 read GetDirectCoordinate write SetDirectCoordinate;
     property DirectW: TGLFloat index 3 read GetDirectCoordinate write SetDirectCoordinate;
   end;
   end;
 
 
-  {  A TGLCustomCoordinates that publishes X, Y properties. }
+  // A TGLCustomCoordinates that publishes X, Y properties.
   TGLCoordinates2 = class(TGLCustomCoordinates)
   TGLCoordinates2 = class(TGLCustomCoordinates)
   published
   published
     property X stored False;
     property X stored False;
     property Y stored False;
     property Y stored False;
   end;
   end;
 
 
-  {  A TGLCustomCoordinates that publishes X, Y, Z properties. }
+  // A TGLCustomCoordinates that publishes X, Y, Z properties.
   TGLCoordinates3 = class(TGLCustomCoordinates)
   TGLCoordinates3 = class(TGLCustomCoordinates)
   published
   published
     property X stored False;
     property X stored False;
@@ -139,7 +138,7 @@ type
     property Z stored False;
     property Z stored False;
   end;
   end;
 
 
-  {  A TGLCustomCoordinates that publishes X, Y, Z, W properties. }
+  // A TGLCustomCoordinates that publishes X, Y, Z, W properties.
   TGLCoordinates4 = class(TGLCustomCoordinates)
   TGLCoordinates4 = class(TGLCustomCoordinates)
   published
   published
     property X stored False;
     property X stored False;

+ 2 - 3
Source/GLCurvesAndSurfaces.pas

@@ -1,12 +1,11 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-  Bezier and B-Spline Curve and Surface Routines.
-}
 
 
 unit GLCurvesAndSurfaces;
 unit GLCurvesAndSurfaces;
 
 
+(* Bezier and B-Spline Curve and Surface Routines *)
+
 interface
 interface
 
 
 {$I GLScene.inc}
 {$I GLScene.inc}

+ 7 - 8
Source/GLFileDXF.pas

@@ -1,17 +1,16 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-  Support-Code to load DXF (Drawing eXchange Files) TGLFreeForm or
-  TGLActor Components in GLScene. 
 
 
-  Note that you must manually add this unit to one of your project's uses
-  to enable support for DXF at run-time. 
+unit GLFileDXF;
 
 
+(*
+  Support-Code to load DXF (Drawing eXchange Files) TGLFreeForm or
+  TGLActor Components in GLScene.
+  Note that you must manually add this unit to one of your project's uses
+  to enable support for DXF at run-time.
   Turn on TwoSideLighting in your Buffer! DXF-Faces have no defined winding order
   Turn on TwoSideLighting in your Buffer! DXF-Faces have no defined winding order
-}
-
-unit GLFileDXF;
+*)
 
 
 interface
 interface
 
 

+ 474 - 0
Source/GLFileVfsPAK.pas

@@ -0,0 +1,474 @@
+//
+// This unit is part of the GLScene Engine, http://glscene.org
+//
+
+unit GLFileVfsPAK;
+
+(*
+  Support-code for loading files from Quake II PAK Files.
+  When instance is created all LoadFromFile methods using
+  GLApplicationFileIO mechanism will be pointed into PAK file.
+  You can change current PAK file by ActivePak variable.
+
+*)
+
+interface
+
+{$I GLScene.inc}
+
+uses
+  System.Classes,
+  System.Contnrs,
+  System.SysUtils,
+
+  GLStrings,
+  GLApplicationFileIO;
+
+const
+  SIGN = 'PACK'; // Signature for uncompressed - raw pak.
+  SIGN_COMPRESSED = 'PACZ'; // Signature for compressed pak.
+
+type
+
+  TZCompressedMode = (Good, Fast, Auto, None);
+
+  TPakHeader = record
+    Signature: array [0 .. 3] of AnsiChar;
+    DirOffset: integer;
+    DirLength: integer;
+  end;
+
+  TFileSection = record
+    FileName: array [0 .. 119] of AnsiChar;
+    FilePos: integer;
+    FileLength: integer;
+  end;
+
+  TGLVfsPAK = class(TComponent)
+  private
+    FPakFiles: TStringList;
+    FHeader: TPakHeader;
+    FHeaderList: array of TPakHeader;
+    FStream: TFileStream;
+    FStreamList: TObjectList;
+    FFiles: TStrings;
+    FFilesLists: TObjectList;
+    FFileName: string;
+    FCompressionLevel: TZCompressedMode;
+    FCompressed: Boolean;
+    function GetFileCount: integer;
+    procedure MakeFileList;
+    function GetStreamNumber: integer;
+    procedure SetStreamNumber(i: integer);
+  public
+    property PakFiles: TStringList read FPakFiles;
+    property Files: TStrings read FFiles;
+    property ActivePakNum: integer read GetStreamNumber write SetStreamNumber;
+    property FileCount: integer Read GetFileCount;
+    property PakFileName: string Read FFileName;
+    property Compressed: Boolean read FCompressed;
+    property CompressionLevel: TZCompressedMode read FCompressionLevel;
+    constructor Create(AOwner: TComponent); overload; override;
+    constructor Create(AOwner: TComponent; const CbrMode: TZCompressedMode);
+      reintroduce; overload;
+    destructor Destroy; override;
+    // for Mode value search Delphi Help for "File open mode constants"
+    procedure LoadFromFile(const FileName: string; Mode: word);
+    procedure ClearPakFiles;
+    function FileExists(const FileName: string): Boolean;
+    function GetFile(index: integer): TStream; overload;
+    function GetFile(const FileName: string): TStream; overload;
+    function GetFileSize(index: integer): integer; overload;
+    function GetFileSize(const FileName: string): integer; overload;
+    procedure AddFromStream(const FileName, Path: string; F: TStream);
+    procedure AddFromFile(const FileName, Path: string);
+    procedure AddEmptyFile(const FileName, Path: string);
+    procedure RemoveFile(index: integer); overload;
+    procedure RemoveFile(const FileName: string); overload;
+    procedure Extract(index: integer; const NewName: string); overload;
+    procedure Extract(const FileName, NewName: string); overload;
+  end;
+
+function PAKCreateFileStream(const FileName: string; Mode: word): TStream;
+function PAKFileStreamExists(const FileName: string): Boolean;
+
+var
+  ActiveVfsPAK: TGLVfsPAK;
+
+// ---------------------------------------------------------------------
+implementation
+// ---------------------------------------------------------------------
+
+var
+  Dir: TFileSection;
+
+function BackToSlash(const s: string): string;
+var
+  i: integer;
+begin
+  SetLength(Result, Length(s));
+  for i := 1 to Length(s) do
+    if s[i] = '\' then
+      Result[i] := '/'
+    else
+      Result[i] := s[i];
+end;
+
+function PAKCreateFileStream(const FileName: string; Mode: word): TStream;
+var
+  i: integer;
+begin
+  with ActiveVfsPAK do
+    for i := FStreamList.Count - 1 downto 0 do
+    begin
+      FFiles := TStrings(FFilesLists[i]);
+      if FileExists(BackToSlash(FileName)) then
+      begin
+        FHeader := FHeaderList[i];
+        FStream := TFileStream(FStreamList[i]);
+        Result := GetFile(BackToSlash(FileName));
+        Exit;
+      end
+      else
+      begin
+        if FileExists(FileName) then
+        begin
+          Result := TFileStream.Create(FileName, fmOpenReadWrite or
+            fmShareDenyWrite);
+          Exit;
+        end
+        else
+        begin
+          Result := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
+          Exit;
+        end;
+      end;
+    end;
+  if FileExists(FileName) then
+  begin
+    Result := TFileStream.Create(FileName, fmOpenReadWrite or fmShareDenyWrite);
+    Exit;
+  end
+  else
+  begin
+    Result := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
+    Exit;
+  end;
+  Result.Free;
+end;
+
+function PAKFileStreamExists(const FileName: string): Boolean;
+var
+  i: integer;
+begin
+  with ActiveVfsPAK do
+    for i := 0 to FStreamList.Count - 1 do
+    begin
+      FFiles := TStrings(FFilesLists[i]);
+      if FileExists(BackToSlash(FileName)) then
+      begin
+        Result := True;
+        Exit;
+      end;
+    end;
+  Result := FileExists(FileName);
+end;
+
+// --------------------------
+// TGLVfsPAK
+// --------------------------
+
+function TGLVfsPAK.GetStreamNumber: integer;
+begin
+  Result := FStreamList.IndexOf(FStream);
+end;
+
+procedure TGLVfsPAK.SetStreamNumber(i: integer);
+begin
+  FStream := TFileStream(FStreamList[i]);
+end;
+
+constructor TGLVfsPAK.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FPakFiles := TStringList.Create;
+  FStreamList := TObjectList.Create(True);
+  FFilesLists := TObjectList.Create(True);
+  ActiveVfsPAK := Self;
+  vAFIOCreateFileStream := PAKCreateFileStream;
+  vAFIOFileStreamExists := PAKFileStreamExists;
+  FCompressionLevel := None;
+  FCompressed := False;
+end;
+
+constructor TGLVfsPAK.Create(AOwner: TComponent;
+  const CbrMode: TZCompressedMode);
+begin
+  Self.Create(AOwner);
+  FCompressionLevel := None;
+  FCompressed := FCompressionLevel <> None;
+end;
+
+destructor TGLVfsPAK.Destroy;
+begin
+  vAFIOCreateFileStream := nil;
+  vAFIOFileStreamExists := nil;
+  SetLength(FHeaderList, 0);
+  FPakFiles.Free;
+  // Objects are automatically freed by TObjectList
+  FStreamList.Free;
+  FFilesLists.Free;
+  ActiveVfsPAK := nil;
+  inherited Destroy;
+end;
+
+function TGLVfsPAK.GetFileCount: integer;
+begin
+  Result := FHeader.DirLength div SizeOf(TFileSection);
+end;
+
+procedure TGLVfsPAK.MakeFileList;
+var
+  i: integer;
+begin
+  FStream.Seek(FHeader.DirOffset, soFromBeginning);
+  FFiles.Clear;
+  for i := 0 to FileCount - 1 do
+  begin
+    FStream.ReadBuffer(Dir, SizeOf(TFileSection));
+    FFiles.Add(string(Dir.FileName));
+  end;
+end;
+
+procedure TGLVfsPAK.LoadFromFile(const FileName: string; Mode: word);
+var
+  l: integer;
+begin
+  FFileName := FileName;
+  FPakFiles.Clear;
+  FPakFiles.Add(FileName);
+  FFiles := TStringList.Create;
+  FStream := TFileStream.Create(FileName, Mode);
+  if FStream.Size = 0 then
+  begin
+    if FCompressed then
+      FHeader.Signature := SIGN_COMPRESSED
+    else
+      FHeader.Signature := SIGN;
+    FHeader.DirOffset := SizeOf(TPakHeader);
+    FHeader.DirLength := 0;
+    if FHeader.Signature = SIGN_COMPRESSED then
+    begin
+      FStream.Free;
+      raise Exception.Create
+        (FileName +
+        ' - This is a compressed PAK file. This version of software does not support Compressed Pak files.');
+      Exit;
+    end;
+    FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
+    FStream.Position := 0;
+  end;
+  FStream.ReadBuffer(FHeader, SizeOf(TPakHeader));
+  if (FHeader.Signature <> SIGN) and (FHeader.Signature <> SIGN_COMPRESSED) then
+  begin
+    FStream.Free;
+    raise Exception.Create(FileName + ' - This is not PAK file');
+    Exit;
+  end;
+
+  // Set the compression flag property.
+  FCompressed := FHeader.Signature = SIGN_COMPRESSED;
+  if FCompressed then
+  begin
+    FStream.Free;
+    raise Exception.Create
+      (FileName +
+      ' - This is a compressed PAK file. This version of software does not support Compressed Pak files.');
+    Exit;
+  end;
+  if FileCount <> 0 then
+    MakeFileList;
+  l := Length(FHeaderList);
+  SetLength(FHeaderList, l + 1);
+  FHeaderList[l] := FHeader;
+  FFilesLists.Add(FFiles);
+  FStreamList.Add(FStream);
+end;
+
+procedure TGLVfsPAK.ClearPakFiles;
+begin
+  SetLength(FHeaderList, 0);
+  FPakFiles.Clear;
+  // Objects are automatically freed by TObjectList
+  FStreamList.Clear;
+  FFilesLists.Clear;
+  ActiveVfsPAK := nil;
+end;
+
+function TGLVfsPAK.GetFile(index: integer): TStream;
+begin
+  FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * index,
+    soFromBeginning);
+  FStream.Read(Dir, SizeOf(TFileSection));
+  FStream.Seek(Dir.FilePos, soFromBeginning);
+  Result := TMemoryStream.Create;
+  Result.CopyFrom(FStream, Dir.FileLength);
+  Result.Position := 0;
+end;
+
+function TGLVfsPAK.FileExists(const FileName: string): Boolean;
+begin
+  Result := (FFiles.IndexOf(FileName) > -1);
+end;
+
+function TGLVfsPAK.GetFile(const FileName: string): TStream;
+begin
+  Result := nil;
+  if Self.FileExists(FileName) then
+    Result := GetFile(FFiles.IndexOf(FileName));
+end;
+
+function TGLVfsPAK.GetFileSize(index: integer): integer;
+begin
+  FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * index,
+    soFromBeginning);
+  FStream.Read(Dir, SizeOf(Dir));
+  Result := Dir.FileLength;
+end;
+
+function TGLVfsPAK.GetFileSize(const FileName: string): integer;
+begin
+  Result := -1;
+  if Self.FileExists(FileName) then
+    Result := GetFileSize(FFiles.IndexOf(FileName));
+end;
+
+{$WARNINGS OFF}
+
+procedure TGLVfsPAK.AddFromStream(const FileName, Path: string; F: TStream);
+var
+  Temp: TMemoryStream;
+begin
+  FStream.Position := FHeader.DirOffset;
+  if FHeader.DirLength > 0 then
+  begin
+    Temp := TMemoryStream.Create;
+    Temp.CopyFrom(FStream, FHeader.DirLength);
+    Temp.Position := 0;
+    FStream.Position := FHeader.DirOffset;
+  end;
+  Dir.FilePos := FHeader.DirOffset;
+
+  Dir.FileLength := F.Size;
+  FStream.CopyFrom(F, 0);
+  FHeader.DirOffset := FStream.Position;
+  if FHeader.DirLength > 0 then
+  begin
+    FStream.CopyFrom(Temp, 0);
+    Temp.Free;
+  end;
+  StrPCopy(Dir.FileName, Path + ExtractFileName(FileName));
+  FStream.WriteBuffer(Dir, SizeOf(TFileSection));
+  FHeader.DirLength := FHeader.DirLength + SizeOf(TFileSection);
+  FStream.Position := 0;
+  FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
+  FFiles.Add(Dir.FileName);
+end;
+
+{$WARNINGS ON}
+
+procedure TGLVfsPAK.AddFromFile(const FileName, Path: string);
+var
+  F: TFileStream;
+begin
+  if not FileExists(FileName) then
+    Exit;
+  F := TFileStream.Create(FileName, fmOpenRead);
+  try
+    AddFromStream(FileName, Path, F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TGLVfsPAK.AddEmptyFile(const FileName, Path: string);
+var
+  F: TMemoryStream;
+begin
+  F := TMemoryStream.Create;
+  try
+    AddFromStream(FileName, Path, F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TGLVfsPAK.RemoveFile(index: integer);
+var
+  Temp: TMemoryStream;
+  i: integer;
+  F: TFileSection;
+begin
+  Temp := TMemoryStream.Create;
+  FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * index,
+    soFromBeginning);
+  FStream.ReadBuffer(Dir, SizeOf(TFileSection));
+  FStream.Seek(Dir.FilePos + Dir.FileLength, soFromBeginning);
+  Temp.CopyFrom(FStream, FStream.Size - FStream.Position);
+  FStream.Position := Dir.FilePos;
+  FStream.CopyFrom(Temp, 0);
+  FHeader.DirOffset := FHeader.DirOffset - Dir.FileLength;
+  Temp.Clear;
+  for i := 0 to FileCount - 1 do
+    if i > index then
+    begin
+      FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * i,
+        soFromBeginning);
+      FStream.ReadBuffer(F, SizeOf(TFileSection));
+      FStream.Position := FStream.Position - SizeOf(TFileSection);
+      F.FilePos := F.FilePos - Dir.FileLength;
+      FStream.WriteBuffer(F, SizeOf(TFileSection));
+    end;
+
+  i := FHeader.DirOffset + SizeOf(TFileSection) * index;
+  FStream.Position := i + SizeOf(TFileSection);
+  if FStream.Position < FStream.Size then
+  begin
+    Temp.CopyFrom(FStream, FStream.Size - FStream.Position);
+    FStream.Position := i;
+    FStream.CopyFrom(Temp, 0);
+  end;
+  Temp.Free;
+  FHeader.DirLength := FHeader.DirLength - SizeOf(TFileSection);
+  FStream.Position := 0;
+  FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
+  FStream.Size := FStream.Size - Dir.FileLength - SizeOf(TFileSection);
+  MakeFileList;
+end;
+
+procedure TGLVfsPAK.RemoveFile(const FileName: string);
+begin
+  if Self.FileExists(FileName) then
+    RemoveFile(FFiles.IndexOf(FileName));
+end;
+
+procedure TGLVfsPAK.Extract(index: integer; const NewName: string);
+var
+  s: TFileStream;
+begin
+  if NewName = '' then
+    Exit;
+  if (index < 0) or (index >= FileCount) then
+    Exit;
+  s := TFileStream.Create(NewName, fmCreate);
+  s.CopyFrom(GetFile(index), 0);
+  s.Free;
+end;
+
+procedure TGLVfsPAK.Extract(const FileName, NewName: string);
+begin
+  if Self.FileExists(FileName) then
+    Extract(FFiles.IndexOf(FileName), NewName);
+end;
+
+end.

+ 1 - 1
Source/GLIsolines.pas

@@ -21,7 +21,7 @@ uses
   GLObjects, 
   GLObjects, 
   GLMultiPolygon,  
   GLMultiPolygon,  
   GLCoordinates,
   GLCoordinates,
-  GLTypes, 
+  GLVectorRecTypes,
   GLColor, 
   GLColor, 
   GLSpline, 
   GLSpline, 
   GLspaceText, 
   GLspaceText, 

+ 1 - 1
Source/GLIsosurface.pas

@@ -42,7 +42,7 @@ uses
   GLMesh,
   GLMesh,
   GLVectorFileObjects,
   GLVectorFileObjects,
   GLVectorTypes,
   GLVectorTypes,
-  GLTypes;
+  GLVectorRecTypes;
 
 
 const
 const
   ALLOC_SIZE = 65536;
   ALLOC_SIZE = 65536;

+ 0 - 32
Source/GLPlugInIntf.pas

@@ -1,32 +0,0 @@
-//
-// This unit is part of the GLScene Engine, http://glscene.org
-//
-{
-  An interface unit to plug-ins. 
-  For more information see help file for writing plug-ins. 
-}
-
-unit GLPlugInIntf;
-
-interface
-
-{$I GLScene.inc}
-
-type
-  TPIServiceType = (stRaw, stObject, stBitmap, stTexture, stImport, stExport);
-  TPIServices = set of TPIServiceType;
-
-  TEnumCallBack = procedure(Name: PAnsiChar); stdcall;
-
-  TEnumResourceNames = procedure(Service: TPIServiceType;
-    Callback: TEnumCallBack); stdcall;
-  TGetServices = function: TPIServices; stdcall;
-  TGetVendor = function: PAnsiChar; stdcall;
-  TGetDescription = function: PAnsiChar; stdcall;
-  TGetVersion = function: PAnsiChar; stdcall;
-
-//------------------------------------------------------------
-implementation
-//------------------------------------------------------------
-
-end.

+ 904 - 0
Source/GLS.FileDXF.pas

@@ -0,0 +1,904 @@
+//
+// This unit is part of the GLScene Engine, http://glscene.org
+//
+
+unit GLS.FileDXF;
+
+(*
+  Support-Code to load DXF (Drawing eXchange Files) TGLFreeForm or
+  TGLActor Components in GLScene.
+  Note that you must manually add this unit to one of your project's uses
+  to enable support for DXF at run-time.
+  Turn on TwoSideLighting in your Buffer! DXF-Faces have no defined winding order
+*)
+
+interface
+
+uses
+  System.Classes,
+  System.SysUtils,
+
+  GLVectorTypes,
+  GLPersistentClasses,
+  GLApplicationFileIO,
+  GLVectorGeometry,
+  GLVectorLists,
+  GLScene,
+  GLTexture,
+  GLVectorFileObjects,
+  GLMaterial;
+
+type
+  TGLDXFVectorFile = class(TGLVectorFile)
+  private
+    // Load from this stream
+    FSourceStream: TStream;
+    // Buffer and current line
+    FBuffer: String;
+    // Line number - for error messages
+    FLineNo: Integer;
+    // Stream done?
+    FEof: Boolean;
+    // Position in the buffer
+    FBufPos: Integer;
+    HasPushedCode: Boolean;
+    PushedCode: Integer;
+    FLayers: TStringList;
+    FBlocks: TStringList;
+    FLastpercentdone: BYTE;
+  protected
+    procedure PushCode(code: Integer);
+    function GetCode: Integer;
+    procedure SkipTable;
+    procedure SkipSection;
+    // procedure DoProgress (Stage: TGLProgressStage; PercentDone: single; RedrawNow: Boolean; const Msg: string);
+    function NeedMesh(basemesh: TGLBaseMesh; layer: STRING): TMeshObject;
+    function NeedFaceGroup(m: TMeshObject; fgmode: TGLFaceGroupMeshMode;
+      fgmat: STRING): TFGVertexIndexList;
+    procedure NeedMeshAndFaceGroup(basemesh: TGLBaseMesh; layer: STRING;
+      fgmode: TGLFaceGroupMeshMode; fgmat: STRING; var m: TMeshObject;
+      var fg: TFGVertexIndexList);
+
+    function ReadLine: STRING;
+    // Read a single line of text from the source stream, set FEof to true when done.
+    function ReadInt: Integer;
+    function ReadDouble: double;
+    procedure ReadTables;
+    procedure ReadLayer;
+    procedure ReadLayerTable;
+    procedure ReadBlocks;
+    procedure ReadInsert(basemesh: TGLBaseMesh);
+    procedure ReadEntity3Dface(basemesh: TGLBaseMesh);
+    procedure ReadEntityPolyLine(basemesh: TGLBaseMesh);
+    procedure ReadEntities(basemesh: TGLBaseMesh);
+
+  public
+    class function Capabilities: TGLDataFileCapabilities; override;
+    procedure LoadFromStream(aStream: TStream); override;
+  end;
+
+implementation
+
+procedure BuildNormals(m: TMeshObject); FORWARD;
+
+const
+  DXFcolorsRGB: ARRAY [1 .. 255] OF LONGINT = ($FF0000, $FFFF00, $00FF00,
+    $00FFFF, $0000FF, $FF00FF, $000000, $000000, $000000, $FF0000, $FF8080,
+    $A60000, $A65353, $800000, $804040, $4D0000, $4D2626, $260000, $261313,
+    $FF4000, $FF9F80, $A62900, $A66853, $802000, $805040, $4D1300, $4D3026,
+    $260A00, $261813, $FF8000, $FFBF80, $A65300, $A67C53, $804000, $806040,
+    $4D2600, $4D3926, $261300, $261D13, $FFBF00, $FFDF80, $A67C00, $A69153,
+    $806000, $807040, $4D3900, $4D4326, $261D00, $262113, $FFFF00, $FFFF80,
+    $A6A600, $A6A653, $808000, $808040, $4D4D00, $4D4D26, $262600, $262613,
+    $BFFF00, $DFFF80, $7CA600, $91A653, $608000, $708040, $394D00, $434D26,
+    $1D2600, $212613, $80FF00, $BFFF80, $53A600, $7CA653, $408000, $608040,
+    $264D00, $394D26, $132600, $1D2613, $40FF00, $9FFF80, $29A600, $68A653,
+    $208000, $508040, $134D00, $304D26, $0A2600, $182613, $00FF00, $80FF80,
+    $00A600, $53A653, $008000, $408040, $004D00, $264D26, $002600, $132613,
+    $00FF40, $80FF9F, $00A629, $53A668, $008020, $408050, $004D13, $264D30,
+    $00260A, $132618, $00FF80, $80FFBF, $00A653, $53A67C, $008040, $408060,
+    $004D26, $264D39, $002613, $13261D, $00FFBF, $80FFDF, $00A67C, $53A691,
+    $008060, $408070, $004D39, $264D43, $00261D, $132621, $00FFFF, $80FFFF,
+    $00A6A6, $53A6A6, $008080, $408080, $004D4D, $264D4D, $002626, $132626,
+    $00BFFF, $80DFFF, $007CA6, $5391A6, $006080, $407080, $00394D, $26434D,
+    $001D26, $132126, $0080FF, $80BFFF, $0053A6, $537CA6, $004080, $406080,
+    $00264D, $26394D, $001326, $131D26, $0040FF, $809FFF, $0029A6, $5368A6,
+    $002080, $405080, $00134D, $26304D, $000A26, $131826, $0000FF, $8080FF,
+    $0000A6, $5353A6, $000080, $404080, $00004D, $26264D, $000026, $131326,
+    $4000FF, $9F80FF, $2900A6, $6853A6, $200080, $504080, $13004D, $30264D,
+    $0A0026, $181326, $8000FF, $BF80FF, $5300A6, $7C53A6, $400080, $604080,
+    $26004D, $39264D, $130026, $1D1326, $BF00FF, $DF80FF, $7C00A6, $9153A6,
+    $600080, $704080, $39004D, $43264D, $1D0026, $211326, $FF00FF, $FF80FF,
+    $A600A6, $A653A6, $800080, $804080, $4D004D, $4D264D, $260026, $261326,
+    $FF00BF, $FF80DF, $A6007C, $A65391, $800060, $804070, $4D0039, $4D2643,
+    $26001D, $261321, $FF0080, $FF80BF, $A60053, $A6537C, $800040, $804060,
+    $4D0026, $4D2639, $260013, $26131D, $FF0040, $FF809F, $A60029, $A65368,
+    $800020, $804050, $4D0013, $4D2630, $26000A, $261318, $545454, $767676,
+    $989898, $BBBBBB, $DDDDDD, $FFFFFF);
+
+const
+  BufSize = 65536; // Load input data in chunks of BufSize Bytes.
+  LineLen = 100; // Allocate memory for the current line in chunks
+
+  function RGB2BGR(bgr: LONGINT): LONGINT;
+  begin
+    result := ((bgr SHR 16) and $FF) or (bgr AND $FF00) or
+      ((bgr SHL 16) and $FF0000)
+  end;
+
+  function StreamEOF(S: TStream): Boolean;
+  begin // Is the stream at its end?
+    result := (S.Position >= S.Size);
+  end;
+
+  class function TGLDXFVectorFile.Capabilities: TGLDataFileCapabilities;
+  begin
+    result := [dfcRead];
+  end;
+
+  function TGLDXFVectorFile.ReadLine: STRING;
+  var
+    j: Integer;
+    FLine: STRING;
+    NewlineChar: CHAR;
+    procedure FillBuffer;
+    var
+      l: Integer;
+    begin
+      l := FSourceStream.Size - FSourceStream.Position;
+      if l > BufSize then
+        l := BufSize;
+      SetLength(FBuffer, l);
+      FSourceStream.Read(FBuffer[1], l);
+      FBufPos := 1;
+    end;
+
+  begin
+    Inc(FLineNo);
+    if FBufPos < 1 then
+      FillBuffer;
+    j := 1;
+    while True do
+    begin
+      if FBufPos > Length(FBuffer) then
+      begin
+        if StreamEOF(FSourceStream) then
+        begin
+          FEof := True;
+          break;
+        end
+        else
+          FillBuffer
+      end
+      else
+      begin
+        case FBuffer[FBufPos] of
+          #10, #13:
+            begin
+              NewlineChar := FBuffer[FBufPos];
+              Inc(FBufPos);
+              if FBufPos > Length(FBuffer) then
+                if StreamEOF(FSourceStream) then
+                  break
+                else
+                  FillBuffer;
+              if ((FBuffer[FBufPos] = #10) or (FBuffer[FBufPos] = #13)) and
+                (FBuffer[FBufPos] <> NewlineChar) then
+                Inc(FBufPos);
+              break;
+            end;
+        else
+          if j > Length(FLine) then
+            SetLength(FLine, Length(FLine) + LineLen);
+          if FBuffer[FBufPos] = #9 then
+            FLine[j] := #32
+          else
+            FLine[j] := FBuffer[FBufPos];
+          Inc(FBufPos);
+          Inc(j);
+        end;
+      end;
+    end;
+    SetLength(FLine, j - 1);
+    ReadLine := Trim(FLine);
+  end;
+
+(*
+  procedure TGLDXFVectorFile.DoProgress (Stage: TGLProgressStage; PercentDone: single; RedrawNow: Boolean; const Msg: string);
+  var perc:BYTE;
+  begin
+  // If the following line stops your compiler, just comment this function
+  if @owner.OnProgress<>NIL then
+  begin
+  perc:=round(percentdone);
+  if (perc<>Flastpercentdone) or (msg<>'') or redrawnow then
+  owner.OnProgress (owner,stage,perc,redrawnow,msg);
+  Flastpercentdone:=perc;
+  end;
+  end;
+*)
+  procedure TGLDXFVectorFile.PushCode(code: Integer);
+  begin
+    PushedCode := code;
+    HasPushedCode := True;
+  end;
+
+  function TGLDXFVectorFile.GetCode: Integer;
+  var
+    S: STRING;
+  begin
+    if HasPushedCode then
+    begin
+      GetCode := PushedCode;
+      HasPushedCode := FALSE;
+    end
+    else
+    begin
+      S := ReadLine;
+      result := StrToIntDef(S, -1);
+      if result = -1 then
+        raise Exception.create('Invalid DXF Code ' + S + ' on Line #' +
+          IntToStr(FLineNo));
+    end;
+  end;
+
+  function TGLDXFVectorFile.ReadDouble: double;
+  var
+    S: String;
+    c: CHAR;
+  begin
+    c := FormatSettings.DecimalSeparator;
+    FormatSettings.DecimalSeparator := '.';
+    S := Trim(ReadLine);
+    result := StrToFloat(S);
+    FormatSettings.DecimalSeparator := c;
+  end;
+
+  function TGLDXFVectorFile.ReadInt: Integer;
+  var
+    S: String;
+  begin
+    S := Trim(ReadLine);
+    result := StrToInt(S);
+  end;
+
+  procedure TGLDXFVectorFile.SkipSection;
+  var
+    S: String;
+    code: Integer;
+  begin
+    repeat
+      code := GetCode;
+      S := ReadLine;
+    until (code = 0) and (S = 'ENDSEC');
+  end;
+
+  procedure TGLDXFVectorFile.SkipTable;
+  var
+    S: String;
+    code: Integer;
+  begin
+    repeat
+      code := GetCode;
+      S := ReadLine;
+    until (code = 0) and (S = 'ENDTAB');
+  end;
+
+  procedure TGLDXFVectorFile.ReadLayer;
+  var
+    layername, color: String;
+    code: Integer;
+  begin
+    color := '1';
+    repeat
+      code := GetCode;
+      case code of
+        0:
+          ;
+        2:
+          layername := ReadLine;
+        70:
+          ReadLine; // freeze and lock flags
+        62:
+          color := ReadLine;
+      else
+        ReadLine;
+      end;
+    until code = 0;
+    PushCode(0);
+    FLayers.AddObject(layername, POINTER(StrToIntDef(color, 1)));
+  end;
+
+  procedure TGLDXFVectorFile.ReadLayerTable;
+  var
+    S: STRING;
+    code: Integer;
+  begin
+    repeat
+      code := GetCode;
+      S := ReadLine;
+      if (code = 0) and (S = 'LAYER') then
+        ReadLayer;
+    until (code = 0) and (S = 'ENDTAB');
+  end;
+
+  procedure TGLDXFVectorFile.ReadTables;
+  var
+    S: String;
+    code: Integer;
+  begin
+    repeat
+      code := GetCode;
+      S := ReadLine;
+      if (code = 0) and (S = 'TABLE') then
+      begin
+        code := GetCode;
+        S := ReadLine;
+        if (code = 2) then
+          if S = 'LAYER' then
+            ReadLayerTable
+          else
+            SkipTable; // LTYPE, STYLE, UCS, and more currently skipped
+      end
+      until (code = 0) and (S = 'ENDSEC');
+    end;
+
+    procedure TGLDXFVectorFile.ReadBlocks;
+    var
+      S: String;
+      code: Integer;
+      blockname: String;
+      blockmesh: TGLFreeForm;
+
+    begin
+      // This code reads blocks into orphaned TGLFreeForms.
+      // ReadInsert then either copies or parents this object to its parent
+      // unused blocks are freed upon completion
+      repeat
+        code := GetCode;
+        S := ReadLine;
+        if (code = 0) and (S = 'BLOCK') then
+        begin
+          blockmesh := TGLFreeForm.create(owner);
+          blockmesh.IgnoreMissingTextures := True;
+          blockmesh.MaterialLibrary := owner.MaterialLibrary;
+          blockmesh.OnProgress := NIL;
+          blockname := 'DXFBLOCK' + IntToStr(FBlocks.count);
+          repeat
+            code := GetCode;
+            case code of
+              0:
+                ;
+              2:
+                blockname := ReadLine;
+            else
+              S := ReadLine;
+            end;
+          until code = 0;
+          PushCode(0);
+          FBlocks.AddObject(blockname, blockmesh);
+          ReadEntities(blockmesh);
+          // basemesh.Direction.SetVector(0,1,0);
+          // code:=GetCode;
+          // s:=ReadLine;
+          // asm nop end;
+        end;
+      until (code = 0) and (S = 'ENDSEC');
+    end;
+
+    procedure TGLDXFVectorFile.ReadInsert(basemesh: TGLBaseMesh);
+    var
+      code, idx, indexoffset: Integer;
+      i, j, k: Integer;
+      blockname, S: STRING;
+      pt, insertpoint, scale: TAffineVector;
+      blockmesh: TGLBaseMesh;
+      // blockproxy  :TGLProxyObject;
+      mo_block: TMeshObject;
+      mo_base: TMeshObject;
+      fg_block, fg_base: TFGVertexIndexList;
+    begin
+      blockname := '';
+      insertpoint := NullVector;
+      scale := XYZvector;
+      repeat // see ReadBlocks for details
+        code := GetCode;
+        case code of
+          0:
+            ;
+          2:
+            blockname := ReadLine;
+          10:
+            insertpoint.X := ReadDouble;
+          20:
+            insertpoint.Y := ReadDouble;
+          30:
+            insertpoint.Z := ReadDouble;
+          41:
+            scale.X := ReadDouble;
+          42:
+            scale.Y := ReadDouble;
+          43:
+            scale.Z := ReadDouble;
+        else
+          S := ReadLine;
+        end;
+      until code = 0;
+      idx := FBlocks.IndexOf(blockname);
+      if idx >= 0 then
+      begin
+        blockmesh := FBlocks.Objects[idx] as TGLBaseMesh;
+
+        // FLAT STRUCTURES
+        // Insert a block into its parent by copying the contents.
+        // the blockmesh will be freed upon completion, leaving only the copies.
+        for i := 0 to blockmesh.MeshObjects.count - 1 do
+        begin
+          mo_block := blockmesh.MeshObjects[i];
+          mo_base := NeedMesh(basemesh, mo_block.name);
+          indexoffset := mo_base.vertices.count;
+          for j := 0 to mo_block.vertices.count - 1 do
+          begin
+            pt := mo_block.vertices[j];
+            ScaleVector(pt, scale);
+            AddVector(pt, insertpoint);
+            mo_base.vertices.Add(pt);
+          end;
+          for j := 0 to mo_block.FaceGroups.count - 1 do
+          begin
+            fg_block := mo_block.FaceGroups[j] as TFGVertexIndexList;
+            fg_base := NeedFaceGroup(mo_base, fg_block.mode,
+              fg_block.MaterialName);
+            for k := 0 to fg_block.VertexIndices.count - 1 do
+            begin
+              fg_base.VertexIndices.Add(fg_block.VertexIndices[k] +
+                indexoffset);
+            end;
+          end;
+        end;
+
+        // TREE STRUCTURES
+        // Instead of copying the contents of the block, they are parented to the
+        // base mesh. If the block already has a parent, a proxy object is created.
+        // WARNING: THE CODE BELOW DOES NOT WORK.
+        (*
+          if blockmesh.Parent =NIL then
+          begin
+          blockmesh.Position.AsAffineVector:=insertpoint;
+          blockmesh.ShowAxes:=TRUE;
+          basemesh.AddChild(blockmesh);
+          for i:=0 to blockmesh.MeshObjects.Count-1 do
+          BuildNormals(blockmesh.MeshObjects[i]);
+          end
+          else
+          begin
+          blockproxy:=TGLproxyObject.CreateAsChild(basemesh);
+          blockproxy.MasterObject:=blockmesh;
+          blockproxy.Position.AsAffineVector:=insertpoint;
+          blockproxy.ShowAxes:=TRUE;
+          end;
+        *)
+      end;
+      PushCode(0);
+    end;
+
+    function TGLDXFVectorFile.NeedMesh(basemesh: TGLBaseMesh; layer: STRING)
+      : TMeshObject;
+    var
+      i: Integer;
+    begin
+      i := 0;
+      while (i < basemesh.MeshObjects.count) and
+        not(basemesh.MeshObjects[i].name = layer) do
+        Inc(i);
+      if i < basemesh.MeshObjects.count then
+        result := basemesh.MeshObjects[i]
+      else
+      begin
+        result := TMeshObject.CreateOwned(basemesh.MeshObjects);
+        result.mode := momFaceGroups;
+        result.name := layer;
+      end;
+    end;
+
+    function TGLDXFVectorFile.NeedFaceGroup(m: TMeshObject;
+      fgmode: TGLFaceGroupMeshMode; fgmat: STRING): TFGVertexIndexList;
+    var
+      i: Integer;
+      acadcolor: LONGINT;
+      libmat: TGLLibMaterial;
+      fg: TFGVertexIndexList;
+    begin
+      i := 0;
+      while (i < m.FaceGroups.count) and
+        not((m.FaceGroups[i] is TFGVertexIndexList) and
+        ((m.FaceGroups[i] as TFGVertexIndexList).mode = fgmode) and
+        (m.FaceGroups[i].MaterialName = fgmat)) do
+        Inc(i);
+      if i < m.FaceGroups.count then
+        fg := m.FaceGroups[i] as TFGVertexIndexList
+      else
+      begin
+        fg := TFGVertexIndexList.CreateOwned(m.FaceGroups);
+        fg.mode := fgmode;
+        fg.MaterialName := fgmat;
+        if owner.MaterialLibrary <> NIL then
+        begin
+          libmat := owner.MaterialLibrary.Materials.GetLibMaterialByName(fgmat);
+          if libmat = NIL then // creates a colored material
+          begin
+            acadcolor := StrToIntDef(fgmat, 0);
+            if acadcolor in [1 .. 255] then
+            begin
+              libmat := owner.MaterialLibrary.Materials.Add;
+              libmat.name := fgmat;
+              libmat.Material.FrontProperties.Diffuse.AsWinColor :=
+                RGB2BGR(DXFcolorsRGB[acadcolor]);
+              libmat.Material.BackProperties.Diffuse.AsWinColor :=
+                RGB2BGR(DXFcolorsRGB[acadcolor]);
+              libmat.Material.FaceCulling := fcNoCull;
+            end;
+          end;
+        end;
+      end;
+      result := fg;
+    end;
+
+    procedure TGLDXFVectorFile.NeedMeshAndFaceGroup(basemesh: TGLBaseMesh;
+      layer: STRING; fgmode: TGLFaceGroupMeshMode; fgmat: STRING;
+      var m: TMeshObject; var fg: TFGVertexIndexList);
+    begin
+      m := NeedMesh(basemesh, layer);
+      fg := NeedFaceGroup(m, fgmode, fgmat);
+    end;
+
+    procedure TGLDXFVectorFile.ReadEntity3Dface(basemesh: TGLBaseMesh);
+    var
+      code, i: Integer;
+      pts: ARRAY [0 .. 3] of TAffineVector;
+      isquad: Boolean;
+      fg: TFGVertexIndexList;
+      color, layer: STRING;
+      m: TMeshObject;
+    begin
+      color := '';
+      layer := '';
+      isquad := FALSE;
+      for i := 0 to 3 do
+        pts[i] := NullVector;
+      repeat
+        code := GetCode;
+        case code of
+          0:
+            ;
+          8:
+            layer := ReadLine; // Layer
+          10:
+            pts[0].X := ReadDouble;
+          11:
+            pts[1].X := ReadDouble;
+          12:
+            pts[2].X := ReadDouble;
+          13:
+            begin
+              pts[3].X := ReadDouble;
+              isquad := True
+            end;
+          20:
+            pts[0].Y := ReadDouble;
+          21:
+            pts[1].Y := ReadDouble;
+          22:
+            pts[2].Y := ReadDouble;
+          23:
+            begin
+              pts[3].Y := ReadDouble;
+              isquad := True
+            end;
+          30:
+            pts[0].Z := ReadDouble;
+          31:
+            pts[1].Z := ReadDouble;
+          32:
+            pts[2].Z := ReadDouble;
+          33:
+            begin
+              pts[3].Z := ReadDouble;
+              isquad := True
+            end;
+          62:
+            color := ReadLine; // Color
+        else
+          ReadLine;
+        end;
+      until code = 0;
+      PushCode(0);
+      isquad := isquad and ((pts[2].X <> pts[3].X) or (pts[2].Y <> pts[3].Y) or
+        (pts[2].Z <> pts[3].Z));
+      if isquad then
+        NeedMeshAndFaceGroup(basemesh, layer, fgmmQuads, color, m, fg)
+      else
+        NeedMeshAndFaceGroup(basemesh, layer, fgmmTriangles, color, m, fg);
+      fg.Add(m.vertices.FindOrAdd(pts[0]));
+      fg.Add(m.vertices.FindOrAdd(pts[1]));
+      fg.Add(m.vertices.FindOrAdd(pts[2]));
+      if isquad then
+        fg.Add(m.vertices.FindOrAdd(pts[3]));
+    end;
+
+    procedure TGLDXFVectorFile.ReadEntityPolyLine(basemesh: TGLBaseMesh);
+
+      procedure ReadPolylineVertex(m: TMeshObject; vertexindexbase: Integer);
+      var
+        color: STRING;
+        pt: TAffineVector;
+        fg: TFGVertexIndexList;
+        code, idx, i70, i71, i72, i73, i74: Integer;
+      begin
+        color := '';
+        pt := NullVector;
+        i70 := 0;
+        i71 := 0;
+        i72 := 0;
+        i73 := 0;
+        i74 := 0;
+        repeat
+          code := GetCode;
+          case code of
+            0:
+              ;
+            5:
+              ReadLine; // ID   :=ReadHex16;
+            8:
+              ReadLine; // ignore per vertex layer. Polyline vertices cannot cross layers!
+            10:
+              pt.X := ReadDouble;
+            20:
+              pt.Y := ReadDouble;
+            30:
+              pt.Z := ReadDouble;
+            62:
+              color := ReadLine;
+            70:
+              i70 := ReadInt;
+            71:
+              i71 := abs(ReadInt);
+              // negative values should hide points... we cannot
+            72:
+              i72 := abs(ReadInt);
+            73:
+              i73 := abs(ReadInt);
+            74:
+              i74 := abs(ReadInt);
+            100:
+              ReadLine; // Subclass Marker
+            330:
+              ReadLine; // Soft Pointer?
+          else
+            ReadLine;
+          end;
+        until code = 0;
+        PushCode(0);
+        if (color = '') or (color = '256') or (color = 'BYLAYER') then
+        begin
+          idx := FLayers.IndexOf(m.name);
+          if idx >= 0 then
+            color := IntToStr(LONGINT(FLayers.Objects[idx]));
+        end;
+        if i70 and 192 = 192 then
+        begin
+          m.vertices.Add(pt);
+        end
+        else if i70 and 192 = 128 then
+        begin
+          i71 := i71 - 1 + vertexindexbase;
+          i72 := i72 - 1 + vertexindexbase;
+          i73 := i73 - 1 + vertexindexbase;
+          if i74 = 0 then
+          begin
+            fg := NeedFaceGroup(m, fgmmTriangles, color);
+            fg.Add(i71);
+            fg.Add(i72);
+            fg.Add(i73);
+          end
+          else
+          begin
+            i74 := i74 - 1 + vertexindexbase;
+            fg := NeedFaceGroup(m, fgmmQuads, color);
+            fg.Add(i71);
+            fg.Add(i72);
+            fg.Add(i73);
+            fg.Add(i74);
+          end
+        end
+        else
+          // hmm?
+      end;
+
+    var
+      m: TMeshObject;
+      code, vertexindexbase: Integer;
+      S, layer: STRING;
+    begin
+      m := NIL;
+      vertexindexbase := 0;
+      repeat
+        code := GetCode;
+        S := ReadLine;
+        if (code = 8) then
+        begin
+          layer := S;
+          m := NeedMesh(basemesh, layer);
+          vertexindexbase := m.vertices.count;
+        end;
+        if (code = 0) and (S = 'VERTEX') and (m <> NIL) then
+          ReadPolylineVertex(m, vertexindexbase);
+      until (code = 0) and (S = 'SEQEND');
+      repeat
+        code := GetCode;
+        if code <> 0 then
+          ReadLine;
+      until (code = 0);
+      PushCode(0);
+    end;
+
+    procedure TGLDXFVectorFile.ReadEntities(basemesh: TGLBaseMesh);
+    var
+      code: Integer;
+      S: STRING;
+    begin
+      repeat
+        code := GetCode;
+        // DoProgress (psRunning,FSourceStream.Position/FSourceStream.Size*100,false,'');
+        case code of
+          0:
+            begin
+              S := ReadLine;
+              if S = 'POLYLINE' then
+                ReadEntityPolyLine(basemesh)
+              else if S = '3DFACE' then
+                ReadEntity3Dface(basemesh)
+              else if S = 'INSERT' then
+                ReadInsert(basemesh)
+              else if S = 'ENDSEC' then
+              begin
+              end
+              else if S = 'ENDBLK' then
+              begin
+              end
+              else
+                (*
+                asm
+                  nop
+                end    // put breakpoint here to catch other entities
+                *)
+            end;
+        else
+          S := ReadLine;
+        end;
+      until (code = 0) and ((S = 'ENDSEC') or (S = 'ENDBLK'));
+    end;
+
+    // build normals
+    procedure BuildNormals(m: TMeshObject);
+    var
+      i, j: Integer;
+      v1, v2, v3, v4, n: TAffineVector;
+    begin
+      for i := 0 to m.vertices.count - 1 do
+        m.Normals.Add(0, 0, 0);
+      for i := 0 to m.FaceGroups.count - 1 do
+        if m.FaceGroups[i] is TFGVertexIndexList then
+          with m.FaceGroups[i] as TFGVertexIndexList do
+            case mode of
+              fgmmTriangles:
+                begin
+                  for j := 0 to (VertexIndices.count div 3) - 1 do
+                  begin
+                    v1 := m.vertices[VertexIndices[j * 3]];
+                    v2 := m.vertices[VertexIndices[j * 3 + 1]];
+                    v3 := m.vertices[VertexIndices[j * 3 + 2]];
+                    n := CalcPlaneNormal(v1, v2, v3);
+                    m.Normals.items[VertexIndices[j * 3]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 3]], n);
+                    m.Normals.items[VertexIndices[j * 3 + 1]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 3 + 1]], n);
+                    m.Normals.items[VertexIndices[j * 3 + 2]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 3 + 2]], n);
+                  end;
+                end;
+              fgmmQuads:
+                begin
+                  for j := 0 to (VertexIndices.count div 4) - 1 do
+                  begin
+                    v1 := m.vertices[VertexIndices[j * 4]];
+                    v2 := m.vertices[VertexIndices[j * 4 + 1]];
+                    v3 := m.vertices[VertexIndices[j * 4 + 2]];
+                    v4 := m.vertices[VertexIndices[j * 4 + 3]];
+                    n := CalcPlaneNormal(v1, v2, v3);
+                    m.Normals.items[VertexIndices[j * 4]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 4]], n);
+                    m.Normals.items[VertexIndices[j * 4 + 1]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 4 + 1]], n);
+                    m.Normals.items[VertexIndices[j * 4 + 2]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 4 + 2]], n);
+                    m.Normals.items[VertexIndices[j * 4 + 3]] :=
+                      VectorAdd(m.Normals.items[VertexIndices[j * 4 + 3]], n);
+                  end;
+                end;
+            end;
+      for i := 0 to m.Normals.count - 1 do
+        m.Normals.items[i] := VectorNormalize(m.Normals.items[i]);
+    end;
+
+    procedure TGLDXFVectorFile.LoadFromStream(aStream: TStream);
+    var
+      S: STRING;
+      code, i: Integer;
+    begin
+      FLastpercentdone := 1;
+      /// DoProgress (psStarting,0,false,'Starting');
+      FEof := FALSE;
+      FSourceStream := aStream;
+      FLineNo := 0;
+      HasPushedCode := FALSE;
+      FLayers := TStringList.create;
+      FBlocks := TStringList.create;
+      while not FEof do
+      begin
+        /// DoProgress (psStarting,FSourceStream.Position/FSourceStream.Size*90,false,'');
+        code := GetCode;
+        if (code = 0) then
+        begin
+          S := ReadLine;
+          if S = 'EOF' then
+            break
+          else if S = 'SECTION' then
+          begin
+            code := GetCode;
+            if code <> 2 then
+              raise Exception.create('Name must follow Section' + ' on Line #' +
+                IntToStr(FLineNo))
+            else
+            begin
+              S := ReadLine;
+              if S = 'HEADER' then
+                SkipSection
+              else if S = 'BLOCKS' then
+                ReadBlocks
+              else if S = 'ENTITIES' then
+                ReadEntities(owner)
+              else if S = 'CLASSES' then
+                SkipSection
+              else if S = 'TABLES' then
+                ReadTables
+              else if S = 'OBJECTS' then
+                SkipSection
+              else
+                SkipSection;
+            end
+          end
+          else if S = 'ENDSEC' then
+            raise Exception.create('SECTION/ENDSEC Mismatch' + ' on Line #' +
+              IntToStr(FLineNo))
+        end
+        else
+          S := ReadLine; // raise Exception.create ('Invalid Group Code');
+      end;
+      // calc normals
+      FLayers.free;
+      for i := FBlocks.count - 1 downto 0 do
+        (FBlocks.Objects[i] as TGLFreeForm).free;
+      FBlocks.free;
+      for i := 0 to owner.MeshObjects.count - 1 do
+        BuildNormals(owner.MeshObjects[i]);
+      /// DoProgress (psEnding,100,false,'');
+    end;
+
+//----------------------------------------------
+initialization
+//----------------------------------------------
+
+RegisterVectorFileFormat('dxf', 'AutoCAD Exchange Format', TGLDXFVectorFile);
+
+end.

+ 247 - 247
Source/GLFileGRD.pas → Source/GLS.FileGRD.pas

@@ -1,247 +1,247 @@
-//
-// This unit is part of the GLScene Engine, http://glscene.org
-//
-
-unit GLFileGRD;
-
-(* GRD (Grid Text Format) vector file format implementation *)
-
-interface
-
-{$I GLScene.inc}
-
-uses
-  System.Classes,
-  System.SysUtils,
-
-  GLVectorGeometry,
-  GLVectorTypes,
-  GLVectorFileObjects,
-  GLApplicationFileIO,
-  GLGraph;
-
-type
-  (* The GRD file represents ascii grid formats in 2D/3D.
-    This is a format for storing regular grid values as a
-    matrices of cell centers. The format supports variations and
-    subformats. This importer works for Sutfer, ArcInfo and GMS formats *)
-  TGLGRDVectorFile = class(TGLVectorFile)
-  public
-    GLHeightField: TGLHeightField;
-    Nodes: array of TSingleArray;
-    class function Capabilities: TGLDataFileCapabilities; override;
-    procedure LoadFromStream(aStream: TStream); override;
-  private
-    StrVal: String;
-    StrLine: String;
-    MaxZ: Single;
-    function ExtractWord(N: Integer; const S: string;
-      const WordDelims: TSysCharSet): string;
-    function WordPosition(const N: Integer; const S: string;
-      const WordDelims: TSysCharSet): Integer;
-  end;
-
-// ------------------------------------------------------------------
-implementation
-// ------------------------------------------------------------------
-
-// ------------------
-// ------------------ TGLGRDVectorFile ------------------
-// ------------------
-
-const
-  dSURFBLANKVAL = 1.70141E38; // default value in Surfer for blanking
-  NODATA_value = -9999; // default value in GIS ArcInfo for blanking
-
-class function TGLGRDVectorFile.Capabilities: TGLDataFileCapabilities;
-begin
-  Result := [dfcRead];
-end;
-
-function TGLGRDVectorFile.WordPosition(const N: Integer; const S: string;
-  const WordDelims: TSysCharSet): Integer;
-var
-  Count, I: Integer;
-begin
-  Count := 0;
-  I := 1;
-  Result := 0;
-  while ((I <= Length(S)) and (Count <> N)) do
-  begin
-    // skip over delimiters
-    while (I <= Length(S)) and CharInSet(S[I], WordDelims) do
-      Inc(I);
-    // if we're not beyond end of S, we're at the start of a word
-    if I <= Length(S) then
-      Inc(Count);
-    // if not finished, find the end of the current word
-    if Count <> N then
-      while (I <= Length(S)) and not CharInSet(S[I], WordDelims) do
-        Inc(I)
-    else
-      Result := I;
-  end;
-end;
-
-function TGLGRDVectorFile.ExtractWord(N: Integer; const S: string;
-  const WordDelims: TSysCharSet): string;
-
-var
-  I, Len: Integer;
-
-begin
-  Len := 0;
-  I := WordPosition(N, S, WordDelims);
-  if (I <> 0) then
-    // find the end of the current word
-    while (I <= Length(S)) and not CharInSet(S[I], WordDelims) do
-    begin
-      // add the I'th character to result
-      Inc(Len);
-      SetLength(Result, Len);
-      Result[Len] := S[I];
-      Inc(I);
-    end;
-  SetLength(Result, Len);
-end;
-
-procedure TGLGRDVectorFile.LoadFromStream(aStream: TStream);
-var
-  I, J, K: Integer;
-  N: Integer; // N => counter to increment through file
-  Sl, Tl: TStringList;
-
-  Nx, Ny: Integer;
-  Dx, Dy: Single;
-  Xo, Xe, Yo, Ye, Zo, Ze: Single;
-  NBlanks: Integer; // Number of blank nodes
-  BlankVal, NoData: Double;
-
-  { sub } function ReadLine: string;
-begin
-  Result := Sl[N];
-  Inc(N);
-end;
-
-begin
-  Sl := TStringList.Create;
-  Tl := TStringList.Create;
-  try
-    Sl.LoadFromStream(aStream);
-    if (Copy(Sl[0], 1, 4) <> 'DSAA') and (Copy(Sl[0], 1, 5) <> 'ncols') then
-    begin
-      raise Exception.Create('Not a valid grd file !');
-      Exit;
-    end;
-
-    GLHeightField := TGLHeightField.Create(Owner);
-
-    Zo := 3 * 10E38; // Low
-    Ze := -3 * 10E38; // High
-    Tl.DelimitedText := Copy(ReadLine, 1, 4);
-
-    if (Tl[0] = 'DSAA') then // Surfer ASCII grid
-    begin
-      Tl.DelimitedText := ReadLine;
-      Nx := StrToInt(Tl[0]);
-      Ny := StrToInt(Tl[1]);
-
-      Tl.DelimitedText := ReadLine;
-      Xo := StrToFloat(Tl[0]);
-      Xe := StrToFloat(Tl[1]);
-
-      Tl.DelimitedText := ReadLine;
-      Yo := StrToFloat(Tl[0]);
-      Ye := StrToFloat(Tl[1]);
-
-      Tl.DelimitedText := ReadLine;
-      Zo := StrToFloat(Tl[0]);
-      Ze := StrToFloat(Tl[1]);
-
-      Dx := (Xe - Xo) / Nx;
-      Dy := (Ye - Yo) / Ny;
-
-      SetLength(Nodes, Ny, Nx);
-
-      NBlanks := 0;
-      BlankVal := dSURFBLANKVAL;
-      NoData := BlankVal; // NoData value
-
-      // loop over the Ny-1 Rows
-      for I := 0 to Ny - 1 do
-      begin
-        J := 0;
-        // reading lines until Nx-1 Cols entries have been obtained
-        while J <= Nx - 1 do
-        begin
-          StrLine := ReadLine;
-          K := 1;
-          StrVal := ExtractWord(K, StrLine, [' ']);
-          while (StrVal <> '') do
-          begin
-            if (J <= Nx - 1) then
-              Nodes[I, J] := StrToFloat(StrVal);
-            if Nodes[I, J] > MaxZ then
-              MaxZ := Nodes[I, J];
-            if (Nodes[I, J] >= BlankVal) then
-              NBlanks := NBlanks + 1;
-
-            Inc(J);
-            Inc(K);
-            StrVal := ExtractWord(K, StrLine, [' ']);
-          end;
-          if (J > Nx - 1) then
-            Break;
-        end;
-      end
-    end
-    else // ArcInfo ASCII grid
-    begin
-      Tl.DelimitedText := Sl[0];
-      Ny := StrToInt(Tl[1]); // ncols
-      Tl.DelimitedText := Sl[1];
-      Nx := StrToInt(Tl[1]); // nrows
-      Tl.DelimitedText := Sl[2];
-      Xo := StrToFloat(Tl[1]); // xllcorner
-      Tl.DelimitedText := Sl[3];
-      Yo := StrToFloat(Tl[1]); // yllcorner
-      Tl.DelimitedText := Sl[4];
-      Dx := StrToFloat(Tl[1]);
-      Dy := Dx; // cellsize
-      Tl.DelimitedText := Sl[5];
-      NoData := StrToFloat(Tl[1]); // NoData value
-
-      MaxZ := -3 * 10E38;
-      SetLength(Nodes, Nx, Ny);
-
-      for I := 0 to Nx - 1 do
-      begin
-        Tl.DelimitedText := Sl[I + 6];
-        for J := 0 to Ny - 1 do
-        begin
-          StrVal := Tl[J];
-          Nodes[I, J] := StrToFloat(StrVal);
-          if Nodes[I, J] > MaxZ then
-            MaxZ := Nodes[I, J];
-        end;
-      end;
-    end;
-
-    GLHeightField.XSamplingScale.Min := -(Nx div 2);
-    GLHeightField.XSamplingScale.Max := (Nx div 2);
-    GLHeightField.YSamplingScale.Min := -(Ny div 2);
-    GLHeightField.YSamplingScale.Max := (Ny div 2);
-
-  finally
-    Tl.Free;
-    Sl.Free;
-  end;
-end;
-
-// ------------------------------------------------------------------
-initialization
-// ------------------------------------------------------------------
-
-RegisterVectorFileFormat('grd', 'ArcInfo/Surfer grids', TGLGRDVectorFile);
-
-end.
+//
+// This unit is part of the GLScene Engine, http://glscene.org
+//
+
+unit GLS.FileGRD;
+
+(* GRD (Grid Text Format) vector file format implementation *)
+
+interface
+
+{$I GLScene.inc}
+
+uses
+  System.Classes,
+  System.SysUtils,
+
+  GLVectorGeometry,
+  GLVectorTypes,
+  GLVectorFileObjects,
+  GLApplicationFileIO,
+  GLGraph;
+
+type
+  (* The GRD file represents ascii grid formats in 2D/3D.
+    This is a format for storing regular grid values as a
+    matrices of cell centers. The format supports variations and
+    subformats. This importer works for Sutfer, ArcInfo and GMS formats *)
+  TGLGRDVectorFile = class(TGLVectorFile)
+  public
+    GLHeightField: TGLHeightField;
+    Nodes: array of TSingleArray;
+    class function Capabilities: TGLDataFileCapabilities; override;
+    procedure LoadFromStream(aStream: TStream); override;
+  private
+    StrVal: String;
+    StrLine: String;
+    MaxZ: Single;
+    function ExtractWord(N: Integer; const S: string;
+      const WordDelims: TSysCharSet): string;
+    function WordPosition(const N: Integer; const S: string;
+      const WordDelims: TSysCharSet): Integer;
+  end;
+
+// ------------------------------------------------------------------
+implementation
+// ------------------------------------------------------------------
+
+// ------------------
+// ------------------ TGLGRDVectorFile ------------------
+// ------------------
+
+const
+  dSURFBLANKVAL = 1.70141E38; // default value in Surfer for blanking
+  NODATA_value = -9999; // default value in GIS ArcInfo for blanking
+
+class function TGLGRDVectorFile.Capabilities: TGLDataFileCapabilities;
+begin
+  Result := [dfcRead];
+end;
+
+function TGLGRDVectorFile.WordPosition(const N: Integer; const S: string;
+  const WordDelims: TSysCharSet): Integer;
+var
+  Count, I: Integer;
+begin
+  Count := 0;
+  I := 1;
+  Result := 0;
+  while ((I <= Length(S)) and (Count <> N)) do
+  begin
+    // skip over delimiters
+    while (I <= Length(S)) and CharInSet(S[I], WordDelims) do
+      Inc(I);
+    // if we're not beyond end of S, we're at the start of a word
+    if I <= Length(S) then
+      Inc(Count);
+    // if not finished, find the end of the current word
+    if Count <> N then
+      while (I <= Length(S)) and not CharInSet(S[I], WordDelims) do
+        Inc(I)
+    else
+      Result := I;
+  end;
+end;
+
+function TGLGRDVectorFile.ExtractWord(N: Integer; const S: string;
+  const WordDelims: TSysCharSet): string;
+
+var
+  I, Len: Integer;
+
+begin
+  Len := 0;
+  I := WordPosition(N, S, WordDelims);
+  if (I <> 0) then
+    // find the end of the current word
+    while (I <= Length(S)) and not CharInSet(S[I], WordDelims) do
+    begin
+      // add the I'th character to result
+      Inc(Len);
+      SetLength(Result, Len);
+      Result[Len] := S[I];
+      Inc(I);
+    end;
+  SetLength(Result, Len);
+end;
+
+procedure TGLGRDVectorFile.LoadFromStream(aStream: TStream);
+var
+  I, J, K: Integer;
+  N: Integer; // N => counter to increment through file
+  Sl, Tl: TStringList;
+
+  Nx, Ny: Integer;
+  Dx, Dy: Single;
+  Xo, Xe, Yo, Ye, Zo, Ze: Single;
+  NBlanks: Integer; // Number of blank nodes
+  BlankVal, NoData: Double;
+
+  { sub } function ReadLine: string;
+begin
+  Result := Sl[N];
+  Inc(N);
+end;
+
+begin
+  Sl := TStringList.Create;
+  Tl := TStringList.Create;
+  try
+    Sl.LoadFromStream(aStream);
+    if (Copy(Sl[0], 1, 4) <> 'DSAA') and (Copy(Sl[0], 1, 5) <> 'ncols') then
+    begin
+      raise Exception.Create('Not a valid grd file !');
+      Exit;
+    end;
+
+    GLHeightField := TGLHeightField.Create(Owner);
+
+    Zo := 3 * 10E38; // Low
+    Ze := -3 * 10E38; // High
+    Tl.DelimitedText := Copy(ReadLine, 1, 4);
+
+    if (Tl[0] = 'DSAA') then // Surfer ASCII grid
+    begin
+      Tl.DelimitedText := ReadLine;
+      Nx := StrToInt(Tl[0]);
+      Ny := StrToInt(Tl[1]);
+
+      Tl.DelimitedText := ReadLine;
+      Xo := StrToFloat(Tl[0]);
+      Xe := StrToFloat(Tl[1]);
+
+      Tl.DelimitedText := ReadLine;
+      Yo := StrToFloat(Tl[0]);
+      Ye := StrToFloat(Tl[1]);
+
+      Tl.DelimitedText := ReadLine;
+      Zo := StrToFloat(Tl[0]);
+      Ze := StrToFloat(Tl[1]);
+
+      Dx := (Xe - Xo) / Nx;
+      Dy := (Ye - Yo) / Ny;
+
+      SetLength(Nodes, Ny, Nx);
+
+      NBlanks := 0;
+      BlankVal := dSURFBLANKVAL;
+      NoData := BlankVal; // NoData value
+
+      // loop over the Ny-1 Rows
+      for I := 0 to Ny - 1 do
+      begin
+        J := 0;
+        // reading lines until Nx-1 Cols entries have been obtained
+        while J <= Nx - 1 do
+        begin
+          StrLine := ReadLine;
+          K := 1;
+          StrVal := ExtractWord(K, StrLine, [' ']);
+          while (StrVal <> '') do
+          begin
+            if (J <= Nx - 1) then
+              Nodes[I, J] := StrToFloat(StrVal);
+            if Nodes[I, J] > MaxZ then
+              MaxZ := Nodes[I, J];
+            if (Nodes[I, J] >= BlankVal) then
+              NBlanks := NBlanks + 1;
+
+            Inc(J);
+            Inc(K);
+            StrVal := ExtractWord(K, StrLine, [' ']);
+          end;
+          if (J > Nx - 1) then
+            Break;
+        end;
+      end
+    end
+    else // ArcInfo ASCII grid
+    begin
+      Tl.DelimitedText := Sl[0];
+      Ny := StrToInt(Tl[1]); // ncols
+      Tl.DelimitedText := Sl[1];
+      Nx := StrToInt(Tl[1]); // nrows
+      Tl.DelimitedText := Sl[2];
+      Xo := StrToFloat(Tl[1]); // xllcorner
+      Tl.DelimitedText := Sl[3];
+      Yo := StrToFloat(Tl[1]); // yllcorner
+      Tl.DelimitedText := Sl[4];
+      Dx := StrToFloat(Tl[1]);
+      Dy := Dx; // cellsize
+      Tl.DelimitedText := Sl[5];
+      NoData := StrToFloat(Tl[1]); // NoData value
+
+      MaxZ := -3 * 10E38;
+      SetLength(Nodes, Nx, Ny);
+
+      for I := 0 to Nx - 1 do
+      begin
+        Tl.DelimitedText := Sl[I + 6];
+        for J := 0 to Ny - 1 do
+        begin
+          StrVal := Tl[J];
+          Nodes[I, J] := StrToFloat(StrVal);
+          if Nodes[I, J] > MaxZ then
+            MaxZ := Nodes[I, J];
+        end;
+      end;
+    end;
+
+    GLHeightField.XSamplingScale.Min := -(Nx div 2);
+    GLHeightField.XSamplingScale.Max := (Nx div 2);
+    GLHeightField.YSamplingScale.Min := -(Ny div 2);
+    GLHeightField.YSamplingScale.Max := (Ny div 2);
+
+  finally
+    Tl.Free;
+    Sl.Free;
+  end;
+end;
+
+// ------------------------------------------------------------------
+initialization
+// ------------------------------------------------------------------
+
+RegisterVectorFileFormat('grd', 'ArcInfo/Surfer grids', TGLGRDVectorFile);
+
+end.

+ 5 - 5
Source/GLFileTIN.pas → Source/GLS.FileTIN.pas

@@ -1,10 +1,10 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-   TIN (Triangular Irregular Network) vector file format implementation. 
-}
-unit GLFileTIN;
+
+unit GLS.FileTIN;
+
+(* TIN (Triangular Irregular Network) vector file format implementation *)
 
 
 interface
 interface
 
 
@@ -19,7 +19,7 @@ uses
   GLApplicationFileIO,
   GLApplicationFileIO,
   GLVectorGeometry,
   GLVectorGeometry,
   GLUtils,
   GLUtils,
-  GLTypes;
+  GLVectorRecTypes;
 
 
 
 
 type
 type

+ 5461 - 5462
Source/GLSMemo.pas → Source/GLS.Memo.pas

@@ -1,5462 +1,5461 @@
-//
-// This unit is part of the GLScene Engine, http://glscene.org
-//
-{
-  Memo for GLScene
-}
-
-unit GLSMemo;
-
-interface
-
-{$I GLScene.inc}
-
-uses
-  WinApi.Windows,
-  WinApi.Messages,
-  System.SysUtils,
-  System.Classes,
-  System.UITypes,
-  VCL.Graphics,
-  VCL.Controls, 
-  VCL.Forms, 
-  VCL.Dialogs, 
-  VCL.ClipBrd,
-  VCL.StdCtrls, 
-  VCL.ExtCtrls;
-
-
-
-type
-  TBorderType = (btRaised, btLowered, btFlatRaised, btFlatLowered);
-  TCommand = Integer;
-
-  TCellSize = record
-    W, H: integer;
-  end;
-
-  TCellPos = record
-    X, Y: integer;
-  end;
-
-  TFullPos = record
-    LineNo, Pos: integer;
-  end;
-
-  TLineProp = class
-    FObject: TObject;
-    FStyleNo: integer;
-    FInComment: Boolean;
-    FInBrackets: integer;
-    FValidAttrs: Boolean;
-    FCharAttrs: string;
-  end;
-
-  TCharStyle = class(TPersistent)
-  private
-    FTextColor, FBkColor: TColor;
-    FStyle: TFontStyles;
-  published
-
-    property TextColor: TColor read FTextColor write FTextColor;
-    property BkColor: TColor read FBkColor write FBkColor;
-    property Style: TFontStyles read FStyle write FStyle;
-  end;
-
-  TStyleList = class(TList)
-  private
-    procedure CheckRange(Index: integer);
-    function GetTextColor(Index: Integer): TColor;
-    procedure SetTextColor(Index: Integer; Value: TColor);
-    function GetBkColor(Index: Integer): TColor;
-    procedure SetBkColor(Index: Integer; Value: TColor);
-    function GetStyle(Index: Integer): TFontStyles;
-    procedure SetStyle(Index: Integer; Value: TFontStyles);
-  protected
-    
-    property TextColor[Index: Integer]: TColor read GetTextColor write
-    SetTextColor;
-    property BkColor[Index: Integer]: TColor read GetBkColor write SetBkColor;
-    property Style[Index: Integer]: TFontStyles read GetStyle write SetStyle;
-  public
-    
-    destructor Destroy; override;
-    procedure Clear; override;
-    procedure Delete(Index: Integer);
-    function Add(ATextColor, ABkCOlor: TColor; AStyle: TFontStyles): Integer;
-    procedure Change(Index: integer; ATextColor, ABkColor: TColor; AStyle:
-      TFontStyles);
-  end;
-
-  TGLAbstractMemoObject = class(TObject)
-  public
-    function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
-      Boolean; virtual; abstract;
-    function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
-      Boolean; virtual; abstract;
-    function MouseMove(Shift: TShiftState; X, Y: Integer):
-      Boolean; virtual; abstract;
-  end;
-
-  TGLSMemoScrollBar = class;
-
-  TGLSMemoAbstractScrollableObject = class(TCustomControl)
-  protected
-    procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
-      virtual; abstract;
-    procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer);
-      virtual; abstract;
-  end;
-
-  TGLSCustomMemo = class;
-
-  TsbState =
-    (
-    sbsWait,
-    sbsBack,
-    sbsForward,
-    sbsPageBack,
-    sbsPageForward,
-    sbsDragging
-    );
-
-  TGLSMemoScrollBar = class(TGLAbstractMemoObject)
-  private
-    FKind: TScrollBarKind;
-    FParent: TGLSMemoAbstractScrollableObject;
-    FLeft, FTop, FWidth, FHeight: integer;
-    FTotal, FMaxPosition, FPosition: integer;
-    FButtonLength: integer;
-    FState: TsbState;
-    FXOffset, FYOffset: integer;
-    procedure SetParams(Index: integer; Value: integer);
-    procedure SetState(Value: TsbState);
-    function GetRect: TRect;
-    function GetThumbRect: TRect;
-    function GetBackRect: TRect;
-    function GetMiddleRect: TRect;
-    function GetForwardRect: TRect;
-    function GetPgBackRect: TRect;
-    function GetPgForwardRect: TRect;
-  public
-    constructor Create(AParent: TGLSMemoAbstractScrollableObject;
-      AKind: TScrollBarKind);
-    procedure PaintTo(ACanvas: TCanvas);
-    function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
-      Boolean; override;
-    function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
-      Boolean; override;
-    function MouseMove(Shift: TShiftState; X, Y: Integer):
-      Boolean; override;
-    function MoveThumbTo(X, Y: Integer): integer;
-    property Parent: TGLSMemoAbstractScrollableObject read FParent;
-    property Kind: TScrollBarKind read FKind write FKind;
-    property State: TsbState read FState write SetState;
-    property Left: integer index 0 read FLeft write SetParams;
-    property Top: integer index 1 read FTop write SetParams;
-    property Width: integer index 2 read FWidth write SetParams;
-    property Height: integer index 3 read FHeight write SetParams;
-    property Total: integer index 4 read FTotal write SetParams;
-    property MaxPosition: integer index 5 read FMaxPosition write SetParams;
-    property Position: integer index 6 read FPosition write SetParams;
-    property FullRect: TRect read GetRect;
-    property ThumbRect: TRect read GetThumbRect;
-    property BackRect: TRect read GetBackRect;
-    property MiddleRect: TRect read GetMiddleRect;
-    property ForwardRect: TRect read GetForwardRect;
-    property PageForwardRect: TRect read GetPgForwardRect;
-    property PageBackRect: TRect read GetPgBackRect;
-  end;
-
-  TGLSMemoStrings = class(TStringList)
-  private
-    FMemo: TGLSCustomMemo;
-    FLockCount: integer;
-    FDeleting: Boolean;
-    procedure CheckRange(Index: integer);
-    function GetLineProp(Index: integer): TLineProp;
-    procedure SetLineStyle(Index: integer; Value: integer);
-    function GetLineStyle(Index: integer): integer;
-    function GetInComment(Index: Integer): Boolean;
-    procedure SetInComment(Index: Integer; Value: Boolean);
-    function GetInBrackets(Index: Integer): integer;
-    procedure SetInBrackets(Index: Integer; Value: integer);
-    function GetValidAttrs(Index: Integer): Boolean;
-    procedure SetValidAttrs(Index: Integer; Value: Boolean);
-    function GetCharAttrs(Index: Integer): string;
-    procedure SetCharAttrs(Index: Integer; const Value: string);
-  protected
-    function GetObject(Index: Integer): TObject; override;
-    procedure PutObject(Index: Integer; AObject: TObject); override;
-    procedure SetUpdateState(Updating: Boolean); override;
-    function CreateProp(Index: integer): TLineProp;
-    property LineProp[Index: integer]: TLineProp read GetLineProp; //PALOFF
-    property Style[Index: integer]: integer read GetLineStyle write
-    SetLineStyle;
-    property InComment[Index: integer]: Boolean read GetInComment write
-    SetInComment;
-    property InBrackets[Index: integer]: integer read GetInBrackets write
-    SetInBrackets;
-    property ValidAttrs[Index: integer]: Boolean read GetValidAttrs write
-    SetValidAttrs;
-    property CharAttrs[Index: integer]: string read GetCharAttrs write
-    SetCharAttrs;
-  public
-    destructor Destroy; override;
-    procedure Clear; override;
-    function DoAdd(const S: string): Integer;
-    function Add(const S: string): Integer; override;
-    function AddObject(const S: string; AObject: TObject): Integer; override;
-    procedure Assign(Source: TPersistent); override;
-    procedure Insert(Index: Integer; const S: string); override;
-    procedure DoInsert(Index: Integer; const S: string);
-    procedure InsertObject(Index: Integer; const S: string; AObject: TObject);
-      override;
-    procedure Delete(Index: Integer); override;
-    procedure LoadFromFile(const FileName: string); override;
-  end;
-
-  TGLSMemoGutter = class(TObject)
-  private
-    FMemo: TGLSCustomMemo;
-    FLeft, FTop, FWidth, FHeight: integer;
-    FColor: TColor;
-    procedure SetParams(Index: integer; Value: integer);
-    function GetRect: TRect;
-  protected
-    procedure PaintTo(ACanvas: TCanvas);
-    procedure Invalidate;
-  public
-    property Left: integer index 0 read FLeft write SetParams;
-    property Top: integer index 1 read FTop write SetParams;
-    property Width: integer index 2 read FWidth write SetParams;
-    property Height: integer index 3 read FHeight write SetParams;
-    property FullRect: TRect read GetRect;
-  end;
-
-  TGLSMemoUndo = class
-  private
-    FMemo: TGLSCustomMemo;
-    FUndoCurX0, FUndoCurY0: integer;
-    FUndoCurX, FUndoCurY: integer;
-    FUndoText: string;
-  public
-    constructor Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText: string);
-    function Append(NewUndo: TGLSMemoUndo): Boolean; virtual;
-    procedure Undo;
-    procedure Redo;
-    procedure PerformUndo; virtual; abstract;
-    procedure PerformRedo; virtual; abstract;
-    property UndoCurX0: integer read FUndoCurX0 write FUndoCurX0;
-    property UndoCurY0: integer read FUndoCurY0 write FUndoCurY0;
-    property UndoCurX: integer read FUndoCurX write FUndoCurX;
-    property UndoCurY: integer read FUndoCurY write FUndoCurY;
-  end;
-
-  TGLSMemoInsCharUndo = class(TGLSMemoUndo)
-  public
-    function Append(NewUndo: TGLSMemoUndo): Boolean; override;
-    procedure PerformUndo; override;
-    procedure PerformRedo; override;
-  end;
-
-  TGLSMemoDelCharUndo = class(TGLSMemoUndo)
-  private
-    FIsBackspace: Boolean;
-  public
-    function Append(NewUndo: TGLSMemoUndo): Boolean; override;
-    procedure PerformUndo; override;
-    procedure PerformRedo; override;
-    property IsBackspace: Boolean read FIsBackspace write FIsBackspace;
-  end;
-
-  TGLSMEmoDelLineUndo = class(TGLSMemoUndo)
-  private
-    FIndex: integer;
-  public
-    constructor Create(AIndex, ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
-      string);
-    procedure PerformUndo; override;
-    procedure PerformRedo; override;
-  end;
-
-  TGLSMemoSelUndo = class(TGLSMemoUndo)
-  private
-    FUndoSelStartX, FUndoSelStartY,
-      FUndoSelEndX, FUndoSelEndY: integer;
-  public
-    property UndoSelStartX: integer read FUndoSelStartX write FUndoSelStartX;
-    property UndoSelStartY: integer read FUndoSelStartY write FUndoSelStartY;
-    property UndoSelEndX: integer read FUndoSelEndX write FUndoSelEndX;
-    property UndoSelEndY: integer read FUndoSelEndY write FUndoSelEndY;
-  end;
-
-  TGLSMemoDeleteBufUndo = class(TGLSMemoSelUndo)
-  public
-    procedure PerformUndo; override;
-    procedure PerformRedo; override;
-  end;
-
-  TGLSMemoPasteUndo = class(TGLSMemoUndo)
-  public
-    procedure PerformUndo; override;
-    procedure PerformRedo; override;
-  end;
-
-  TGLSMemoUndoList = class(TList)
-  private
-    FPos: integer;
-    FMemo: TGLSCustomMemo;
-    FIsPerforming: Boolean;
-    FLimit: integer;
-  protected
-    function Get(Index: Integer): TGLSMemoUndo;
-    procedure SetLimit(Value: integer);
-  public
-    constructor Create;
-    destructor Destroy; override;
-    function Add(Item: Pointer): Integer;
-    procedure Clear; override;
-    procedure Delete(Index: Integer);
-    procedure Undo;
-    procedure Redo;
-    property Items[Index: Integer]: TGLSMemoUndo read Get; default;
-    property IsPerforming: Boolean read FIsPerforming write FIsPerforming;
-    property Memo: TGLSCustomMemo read FMemo write FMemo;
-    property Pos: integer read FPos write FPos;
-    property Limit: integer read FLimit write SetLimit;
-  end;
-
-  //--------------------------------------------------------------
-
-  TGutterClickEvent = procedure(Sender: TObject; LineNo: integer) of object;
-  TGutterDrawEvent = procedure(Sender: TObject; ACanvas: TCanvas;
-    LineNo: integer; rct: TRect) of object;
-  TGetLineAttrsEvent = procedure(Sender: TObject; LineNo: integer;
-    var Attrs: string) of object;
-  TUndoChangeEvent = procedure(Sender: TObject;
-    CanUndo, CanRedo: Boolean) of object;
-  TScrollMode = (smAuto, smStrict);
-
-  TGLSCustomMemo = class(TGLSMemoAbstractScrollableObject)
-  private
-    FAutoIndent: Boolean;
-    FMargin: integer;
-    FHiddenCaret, FCaretVisible: Boolean;
-    FCellSize: TCellSize;
-    FCurX, FCurY: integer;
-    FLeftCol, FTopLine: integer;
-    FTabSize: integer;
-    FFont: TFont;
-    FBkColor: TColor;
-    FSelColor: TColor;
-    FSelBkColor: TColor;
-    FReadOnly: Boolean;
-    FDelErase: Boolean;
-    FLines: TStrings;
-    FSelStartX, FSelStartY,
-      FSelEndX, FSelEndY,
-      FPrevSelX, FPrevSelY: integer;
-    FScrollBars: System.UITypes.TScrollStyle;
-    FScrollBarWidth: integer;
-    FGutter: TGLSMemoGutter;
-    FGutterWidth: integer;
-    sbVert, sbHorz: TGLSMemoScrollBar;
-    FStyles: TStyleList;
-    FLineBitmap: TBitmap;
-    FSelCharPos: TFullPos;
-    FSelCharStyle: integer;
-    FLeftButtonDown: Boolean;
-    FScrollMode: TScrollMode;
-    FUndoList: TGLSMemoUndoList;
-    FFirstUndoList: TGLSMemoUndoList;
-    FUndoLimit: integer;
-    FLastMouseUpX,
-      FLastMouseUpY: integer;
-    FAfterDoubleClick: Boolean;
-    {events}
-    FOnMoveCursor: TNotifyEvent;
-    FOnChange: TNotifyEvent;
-    FOnAttrChange: TNotifyEvent;
-    FOnStatusChange: TNotifyEvent;
-    FOnSelectionChange: TNotifyEvent;
-    FOnGutterDraw: TGutterDrawEvent;
-    FOnGutterClick: TGutterClickEvent;
-    FOnGetLineAttrs: TGetLineAttrsEvent;
-    FOnUndoChange: TUndoChangeEvent;
-    FHideCursor: Boolean;
-    procedure SetHiddenCaret(Value: Boolean);
-    procedure SetScrollBars(Value: System.UITypes.TScrollStyle);
-    procedure SetGutterWidth(Value: integer);
-    procedure SetGutterColor(Value: TColor);
-    function GetGutterColor: TColor;
-    procedure SetCurX(Value: integer);
-    procedure SetCurY(Value: integer);
-    procedure SetFont(Value: TFont);
-    procedure SetColor(Index: integer; Value: TColor);
-    function GetSelStart: TPoint;
-    function GetSelEnd: TPoint;
-    procedure SetLines(ALines: TStrings);
-    procedure SetLineStyle(Index: integer; Value: integer);
-    function GetLineStyle(Index: integer): integer;
-    function GetInComment(Index: integer): Boolean;
-    procedure SetInComment(Index: integer; Value: Boolean);
-    function GetInBrackets(Index: Integer): integer;
-    procedure SetInBrackets(Index: Integer; Value: integer);
-    function GetValidAttrs(Index: integer): Boolean;
-    procedure SetValidAttrs(Index: integer; Value: Boolean);
-    function GetCharAttrs(Index: integer): string;
-    procedure SetCharAttrs(Index: integer; const Value: string);
-    procedure ExpandSelection;
-    function GetSelText: string;
-    procedure SetSelText(const AValue: string);
-    function GetSelLength: integer;
-    procedure MovePage(dP: integer; Shift: TShiftState);
-    procedure ShowCaret(State: Boolean);
-    procedure MakeVisible;
-    function GetVisible(Index: integer): integer;
-    function MaxLength: integer;
-    procedure WMSize(var Msg: TWMSize); message WM_SIZE;
-    procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
-    procedure WMEraseBkgnd(var Msg: TWmEraseBkgnd); message WM_ERASEBKGND;
-    procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
-    procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS;
-    procedure WMKillFocus(var Msg: TWMSetFocus); message WM_KILLFOCUS;
-    procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL;
-    procedure MoveCursor(dX, dY: integer; Shift: TShiftState);
-    procedure ResizeEditor;
-    procedure ResizeScrollBars;
-    procedure ResizeGutter;
-    procedure DoCommand(cmd: TCommand; const AShift: TShiftState);
-    procedure DrawLine(LineNo: integer);
-    function IsLineVisible(LineNo: integer): Boolean;
-    procedure FreshLineBitmap;
-    procedure SetUndoLimit(Value: integer);
-  protected
-    procedure WndProc(var Message: TMessage); override;
-    function EditorRect: TRect;
-    function LineRangeRect(FromLine, ToLine: integer): TRect;
-    function ColRangeRect(FromCol, ToCol: integer): TRect;
-    procedure InvalidateLineRange(FromLine, ToLine: integer);
-    function AddString(const S: string): integer;
-    procedure InsertString(Index: integer; S: string);
-    procedure GoHome(Shift: TShiftState);
-    procedure GoEnd(Shift: TShiftState);
-    procedure InsertChar(C: Char);
-    procedure DeleteChar(OldX, OldY: integer);
-    procedure DeleteLine(Index, OldX, OldY, NewX, NewY: integer; FixUndo: Boolean);
-    procedure BackSpace;
-    procedure BackSpaceWord;
-    function IndentCurrLine: string;
-    procedure NewLine;
-    procedure CreateParams(var Params: TCreateParams); override;
-    procedure Paint; override;
-    procedure DrawMargin;
-    procedure DrawGutter;
-    procedure DrawScrollBars;
-    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
-    procedure KeyPress(var Key: Char); override;
-    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
-    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
-    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
-    procedure DblClick; override;
-    procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer); override;
-    procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer); override;
-    property VisiblePosCount: integer index 0 read GetVisible;
-    property VisibleLineCount: integer index 1 read GetVisible;
-    property LastVisiblePos: integer index 2 read GetVisible;
-    property LastVisibleLine: integer index 3 read GetVisible;
-    procedure DeleteSelection(bRepaint: Boolean);
-    procedure Changed(FromLine, ToLine: integer); virtual;
-    procedure AttrChanged(LineNo: integer); virtual;
-    procedure SelectionChanged; virtual;
-    procedure StatusChanged; virtual;
-    procedure ClearUndoList;
-    procedure UndoChange;
-    property AutoIndent: Boolean read FAutoIndent write FAutoIndent;
-    property GutterWidth: integer read FGutterWidth write SetGutterWidth;
-    property GutterColor: TColor read GetGutterColor write SetGutterColor;
-    property ScrollBars: System.UITypes.TScrollStyle read FScrollBars write SetScrollBars default ssBoth;
-    property Font: TFont read FFont write SetFont;
-    property ReadOnly: Boolean read FReadOnly write FReadOnly;
-    property Lines: TStrings read FLines write SetLines;
-    property BkColor: TColor index 0 read FBkColor write SetColor;
-    property SelColor: TColor index 1 read FSelColor write SetColor;
-    property SelBkColor: TColor index 2 read FSelBkColor write SetColor;
-    property HiddenCaret: Boolean read FHiddenCaret write SetHiddenCaret;
-    property TabSize: integer read FTabSize write FTabSize;
-    property ScrollMode: TScrollMode read FScrollMode write FScrollMode default smAuto;
-    property UndoLimit: integer read FUndoLimit write SetUndoLimit;
-    property HideCursor: Boolean read FHideCursor write FHideCursor;
-    property InComment[Index: integer]: Boolean read GetInComment write SetInComment;
-    property InBrackets[Index: integer]: integer read GetInBrackets write SetInBrackets;
-    property ValidAttrs[Index: integer]: Boolean read GetValidAttrs write SetValidAttrs;
-    property CharAttrs[Index: integer]: string read GetCharAttrs write SetCharAttrs;
-    {events}
-    property OnGutterClick: TGutterClickEvent read FOnGutterClick write FOnGutterClick;
-    property OnGutterDraw: TGutterDrawEvent read FOnGutterDraw write FOnGutterDraw;
-    property OnChange: TNotifyEvent read FOnChange write FOnChange;
-    property OnMoveCursor: TNotifyEvent read FOnMoveCursor write FOnMoveCursor;
-    property OnAttrChange: TNotifyEvent read FOnAttrChange write FOnAttrChange;
-    property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
-    property OnStatusChange: TNotifyEvent read FOnStatusChange write FOnStatusChange;
-    property OnGetLineAttrs: TGetLineAttrsEvent read FOnGetLineAttrs write FOnGetLineAttrs;
-    property OnUndoChange: TUndoChangeEvent read FOnUndoChange write FOnUndoChange;
-  public
-    constructor Create(AOwner: TComponent); override;
-    destructor Destroy; override;
-    procedure CopyToClipBoard;
-    procedure PasteFromClipBoard;
-    procedure CutToClipBoard;
-    procedure SelectLines(StartLine, EndLine: Integer);
-    procedure SelectAll;
-    property SelStart: TPoint read GetSelStart;
-    property SelEnd: TPoint read GetSelEnd;
-    property Selection: string read GetSelText write SetSelText;
-    property SelLength: integer read GetSelLength;
-    procedure ClearSelection;
-    procedure Clear;
-    procedure SetCursor(ACurX, ACurY: Integer);
-    function SelectLine(LineNo, StyleNo: Integer): integer;
-    procedure SelectChar(LineNo, Pos, StyleNo: Integer);
-    function CellFromPos(X, Y: integer): TCellPos;
-    function CharFromPos(X, Y: integer): TFullPos;
-    function CellRect(ACol, ARow: integer): TRect;
-    function LineRect(ARow: integer): TRect;
-    function ColRect(ACol: integer): TRect;
-    function CharStyleNo(LineNo, Pos: integer): integer;
-    procedure InsertTemplate(AText: string);
-    procedure UnSelectChar;
-    procedure Undo;
-    procedure Redo;
-    function CanUndo: Boolean;
-    function CanRedo: Boolean;
-    function FindText(Text: string; Options: TFindOptions; Select: Boolean): Boolean;
-    property CurX: integer read FCurX write SetCurX;
-    property CurY: integer read FCurY write SetCurY;
-    property DelErase: Boolean read FDelErase write FDelErase;
-    property LineStyle[Index: integer]: integer read GetLineStyle write
-    SetLineStyle;
-    property Styles: TStyleList read FStyles;
-    property UndoList: TGLSMemoUndoList read FUndoList write FUndoList;
-  end;
-
-  TGLSMemo = class(TGLSCustomMemo)
-  published
-    {TControl }
-    property PopupMenu;
-    {TCustomControl }
-    property Align;
-    property Enabled;
-    property ShowHint;
-    property TabOrder;
-    property TabStop;
-    property Visible;
-    property ReadOnly;
-    {TGLSCustomMemo }
-    property AutoIndent;
-    property GutterColor;
-    property GutterWidth;
-    property ScrollBars;
-    property Font;
-    property BkColor;
-    property Selection;
-    property SelColor;
-    property SelBkColor;
-    property Lines;
-    property HiddenCaret;
-    property TabSize;
-    property ScrollMode;
-    property UndoLimit;
-    property DelErase;
-    {Inherited events }
-    property OnClick;
-    property OnDblClick;
-    property OnDragDrop;
-    property OnDragOver;
-    property OnEndDrag;
-    property OnMouseDown;
-    property OnMouseMove;
-    property OnMouseUp;
-    property OnStartDrag;
-    property OnEnter;
-    property OnExit;
-    property OnKeyDown;
-    property OnKeyPress;
-    property OnKeyUp;
-    {Events }
-    property OnGutterDraw;
-    property OnGutterClick;
-    property OnChange;
-    property OnMoveCursor;
-    property OnAttrChange;
-    property OnSelectionChange;
-    property OnStatusChange;
-    property OnGetLineAttrs;
-    property OnUndoChange;
-  end;
-
-  TGLSMemoStringList = class(TStringList)
-  private
-    procedure ReadStrings(Reader: TReader);
-    procedure WriteStrings(Writer: TWriter);
-  protected
-    procedure DefineProperties(Filer: TFiler); override;
-  end;
-
-  TDelimiters = TSysCharSet;
-  TTokenType =
-    (
-    ttWord,
-    ttBracket,
-    ttSpecial,
-    ttDelimiter,
-    ttSpace,
-    ttEOL,
-    ttInteger,
-    ttFloat,
-    ttComment,
-    ttOther,
-    ttWrongNumber);
-
-  //--------------------------------------------------------------
-  //        SYNTAX MEMO - declaration
-  //--------------------------------------------------------------
-  TGLSSynHiMemo = class(TGLSCustomMemo)
-  private
-
-    FIsPainting: Boolean;
-    FInComment: Boolean;
-
-    FWordList: TGLSMemoStringList;
-    FSpecialList: TGLSMemoStringList;
-    FBracketList: TGLSMemoStringList;
-    FDelimiters: TDelimiters;
-    FInBrackets: integer;
-    FLineComment: string;
-    FMultiCommentLeft: string;
-    FMultiCommentRight: string;
-    FDelimiterStyle: TCharStyle;
-    FCommentStyle: TCharStyle;
-    FNumberStyle: TCharStyle;
-    FDelimiterStyleNo,
-      FCommentStyleNo,
-      FNumberStyleNo: integer;
-    FCaseSensitive: Boolean;
-    function GetToken(const S: string; var From: integer;
-      out TokenType: TTokenType; out StyleNo: integer): string;
-    procedure SetWordList(Value: TGLSMemoStringList);
-    procedure SetSpecialList(Value: TGLSMemoStringList);
-    procedure SetBracketList(Value: TGLSMemoStringList);
-    procedure FindLineAttrs(Sender: TObject; LineNo: integer; var Attrs:
-      string);
-    procedure SetStyle(Index: integer; Value: TCharStyle);
-    procedure SetCaseSensitive(Value: Boolean);
-  protected
-    procedure Paint; override;
-  public
-    constructor Create(AOwner: TComponent); override;
-    destructor Destroy; override;
-    procedure AddWord(StyleNo: integer; const ArrS: array of string);
-    procedure AddSpecial(StyleNo: integer; const ArrS: array of string);
-    procedure AddBrackets(StyleNo: integer; const ArrS: array of string);
-    property Delimiters: TDelimiters read FDelimiters write FDelimiters;
-  published
-    {TControl}
-    property PopupMenu;
-    {TCustomControl}
-    property Align;
-    property Enabled;
-    property ShowHint;
-    property TabOrder;
-    property TabStop;
-    property Visible;
-    property ReadOnly;
-    {TGLSCustomMemo}
-    property AutoIndent;
-    property GutterColor;
-    property GutterWidth;
-    property ScrollBars;
-    property Font;
-    property BkColor;
-    property SelColor;
-    property SelBkColor;
-    property Lines;
-    property HiddenCaret;
-    property TabSize;
-    property ScrollMode;
-    property UndoLimit;
-    property DelErase;
-    {Inherited events }
-    property OnClick;
-    property OnDblClick;
-    property OnDragDrop;
-    property OnDragOver;
-    property OnEndDrag;
-    property OnMouseDown;
-    property OnMouseMove;
-    property OnMouseUp;
-    property OnStartDrag;
-    property OnEnter;
-    property OnExit;
-    property OnKeyDown;
-    property OnKeyPress;
-    property OnKeyUp;
-    {Events }
-    property OnGutterClick;
-    property OnGutterDraw;
-    property OnChange;
-    property OnMoveCursor;
-    property OnSelectionChange;
-    property OnStatusChange;
-    property OnUndoChange;
-    {TGLSSyntaxMemo }
-    property LineComment: string read FLineComment write FLineComment;
-    property MultiCommentLeft: string read FMultiCommentLeft write FMultiCommentLeft;
-    property MultiCommentRight: string read FMultiCommentRight write FMultiCommentRight;
-    property WordList: TGLSMemoStringList read FWordList write SetWordList;
-    property SpecialList: TGLSMemoStringList read FSpecialList write SetSpecialList;
-    property BracketList: TGLSMemoStringList read FBracketList write SetBracketList;
-    property DelimiterStyle: TCharStyle index 0 read FDelimiterStyle write SetStyle;
-    property CommentStyle: TCharStyle index 1 read FCommentStyle write SetStyle;
-    property NumberStyle: TCharStyle index 2 read FNumberStyle write SetStyle;
-    property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
-  end;
-
-procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
-
-//==========================================================
-implementation
-//==========================================================
-
-const
-  cmDelete = VK_DELETE;
-  cmBackSpace = VK_BACK;
-  cmWordBackSpace = 127; // Ctrl-BackSpace
-  cmNewLine = VK_RETURN;
-  cmHome = VK_HOME;
-  cmEnd = VK_END;
-  cmPageUp = VK_PRIOR;
-  cmPageDown = VK_NEXT;
-  cmInsert = VK_INSERT;
-  cmDelLine = 25; // Ctrl-Y
-  cmCopy = 3; // Ctrl-C
-  cmCut = 24; // Ctrl-X
-  cmPaste = 22; // Ctrl-V
-
-resourcestring
-  SObjectsNotSupported = 'Linked object not supported';
-
-var
-  bmScrollBarFill: TBitmap;
-  bmScrollBarUp: TBitmap;
-  bmScrollBarDown: TBitmap;
-  bmScrollBarLeft: TBitmap;
-  bmScrollBarRight: TBitmap;
-
-  fIntelliWheelSupport: Boolean; // True if IntelliMouse + wheel enabled
-  fIntelliMessage: UINT; // message sent from mouse on wheel roll
-  fIntelliScrollLines: Integer; // number of lines to scroll per wheel roll
-
-// ---------------------Helper functions 
-
-function PointInRect(const P: TPoint; const rct: TRect): Boolean; inline;
-begin
-  with rct do
-    Result := (Left <= P.X) and (Top <= P.Y) and
-      (Right >= P.X) and (Bottom >= P.Y);
-end;
-
-procedure Swap(var I1, I2: integer); inline;
-var
-  temp: integer;
-begin
-  temp := I1;
-  I1 := I2;
-  I2 := temp;
-end;
-
-procedure OrderPos(var StartX, StartY, EndX, EndY: integer); inline;
-begin
-  if (EndY < StartY) or
-    ((EndY = StartY) and (EndX < StartX)) then
-  begin
-    Swap(StartX, EndX);
-    Swap(StartY, EndY);
-  end;
-end;
-
-function TotalRect(const rct1, rct2: TRect): TRect; inline;
-begin
-  Result := rct1;
-  with Result do
-  begin
-    if rct2.Left < Left then
-      Left := rct2.Left;
-    if rct2.Top < Top then
-      Top := rct2.Top;
-    if rct2.Right > Right then
-      Right := rct2.Right;
-    if rct2.Bottom > Bottom then
-      Bottom := rct2.Bottom;
-  end;
-end;
-
-
-
-// ---------------------TGLSCustomMemo functions
-
-procedure TGLSCustomMemo.WndProc(var Message: TMessage);
-  function GetShiftState: Integer;
-  begin
-    Result := 0;
-    if GetAsyncKeyState(vk_Shift) < 0 then
-      Result := Result or mk_Shift;
-    if GetAsyncKeyState(vk_Control) < 0 then
-      Result := Result or mk_Control;
-    if GetAsyncKeyState(vk_LButton) < 0 then
-      Result := Result or mk_LButton;
-    if GetAsyncKeyState(vk_RButton) < 0 then
-      Result := Result or mk_RButton;
-    if GetAsyncKeyState(vk_MButton) < 0 then
-      Result := Result or mk_MButton;
-  end;
-  //---------------------------------------------------
-begin
-  if (Message.Msg = fIntelliMessage) and (fIntelliMessage <> wm_MouseWheel) then
-  begin
-    PostMessage(Handle, wm_MouseWheel, MakeLong(GetShiftState, Message.wParam),
-      Message.lParam);
-  end
-  else
-    inherited;
-end;
-
-//------------------------------------------------
-//    INTELLIMOUSE INIT
-//------------------------------------------------
-
-procedure IntelliMouseInit;
-var
-  hWndMouse: hWnd;
-  mQueryScrollLines: UINT;
-  //--------------------------------------------
-  function NativeMouseWheelSupport: Boolean;
-  var
-    ver: TOSVersionInfo;
-  begin
-    Result := False;
-    ver.dwOSVersionInfoSize := sizeof(ver);
-    // For Windows 98, assume dwMajorVersion = 5 (It's 4 for W95)
-    // For NT, we need 4.0 or better.
-    if GetVersionEx(ver) then
-      case ver.dwPlatformID of
-        ver_Platform_Win32_Windows: Result := ver.dwMajorVersion >= 5;
-        ver_Platform_Win32_NT: Result := ver.dwMajorVersion >= 4;
-      end;
-    { Quick and dirty temporary hack for Windows 98 beta 3 }
-    if (not Result) and (ver.szCSDVersion = ' Beta 3') then
-      Result := True;
-  end;
-  //--------------------------------------------
-begin
-  if NativeMouseWheelSupport then
-  begin
-    fIntelliWheelSupport := Boolean(GetSystemMetrics(sm_MouseWheelPresent));
-    SystemParametersInfo(spi_GetWheelScrollLines, 0, @fIntelliScrollLines, 0);
-    fIntelliMessage := wm_MouseWheel;
-  end
-  else
-  begin
-    { Look for hidden mouse window }
-    hWndMouse := FindWindow('MouseZ', 'Magellan MSWHEEL');
-    if hWndMouse <> 0 then
-    begin
-      { We're in business - get the scroll line info }
-      fIntelliWheelSupport := True;
-      mQueryScrollLines := RegisterWindowMessage('MSH_SCROLL_LINES_MSG');
-      fIntelliScrollLines := SendMessage(hWndMouse, mQueryScrollLines, 0, 0);
-      { Finally, get the custom mouse message as well }
-      fIntelliMessage := RegisterWindowMessage('MSWHEEL_ROLLMSG');
-    end;
-  end;
-  if (fIntelliScrollLines < 0) or (fIntelliScrollLines > 100) then
-    fIntelliScrollLines := 3;
-end;
-
-//------------------------------------------------
-//    WM MOUSE WHEEL
-//------------------------------------------------
-
-procedure TGLSCustomMemo.WMMouseWheel(var Message: TMessage);
-{$J+}
-{$IFOPT R+} {$DEFINE StoreRangeCheck} {$ENDIF} {$R-}
-const
-  Delta: SmallInt = 0;
-begin
-  Delta := Delta + SmallInt(HiWord(Message.wParam));
-  while Abs(Delta) >= 120 do
-  begin
-    if Delta < 0 then
-    begin
-      DoScroll(sbVert, fIntelliScrollLines);
-      Delta := Delta + 120;
-    end
-    else
-    begin
-      DoScroll(sbVert, -fIntelliScrollLines);
-      Delta := Delta - 120;
-    end;
-  end;
-end;
-{$J-}
-{$IFDEF StoreRangeCheck} {$R+} {$UNDEF StoreRangeCheck} {$ENDIF}
-
-//--------------------------------------------------------------
-//        SET CURSOR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetCursor(ACurX, ACurY: Integer);
-begin
-  ClearSelection;
-  CurX := 0;
-  CurY := ACurY;
-  CurX := ACurX;
-end;
-
-//--------------------------------------------------------------
-//        SELECT LINE, CHAR
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.SelectLine(LineNo, StyleNo: Integer): integer;
-var
-  rct: TRect;
-begin
-  Result := LineStyle[LineNo];
-  LineStyle[LineNo] := StyleNo;
-  rct := LineRect(LineNo);
-  InvalidateRect(Handle, @rct, True);
-end;
-
-procedure TGLSCustomMemo.SelectLines(StartLine, EndLine: Integer);
-var
-  rct: TRect;
-begin
-  FSelStartX := 0;
-  FSelStartY := StartLine;
-  FSelEndX := Length(Lines[EndLine]);
-  FSelEndY := EndLine;
-  rct := LineRangeRect(FSelStartY, FSelEndY);
-  SelectionChanged;
-  InvalidateRect(Handle, @rct, true);
-end;
-
-procedure TGLSCustomMemo.SelectChar(LineNo, Pos, StyleNo: Integer);
-var
-  rct: TRect;
-begin
-  UnselectChar;
-  FSelCharPos.LineNo := LineNo;
-  FSelCharPos.Pos := Pos;
-  FSelCharStyle := StyleNo;
-  rct := LineRect(LineNo);
-  InvalidateRect(Handle, @rct, True);
-end;
-
-procedure TGLSCustomMemo.UnSelectChar;
-var
-  rct: TRect;
-begin
-  with FSelCharPos do
-  begin
-    if LineNo < 0 then
-      Exit;
-    rct := LineRect(LineNo);
-    LineNo := -1;
-    Pos := -1;
-  end;
-  FSelCharStyle := -1;
-  InvalidateRect(Handle, @rct, True);
-end;
-
-//--------------------------------------------------------------
-//        CLEAR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.Clear;
-begin
-  CurY := 0;
-  CurX := 0;
-  FLeftCol := 0;
-  FTopLine := 0;
-  Lines.Clear;
-  TGLSMemoStrings(Lines).DoAdd('');
-  ClearUndoList;
-  Invalidate;
-end;
-
-//--------------------------------------------------------------
-//        SELECT ALL
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SelectAll;
-begin
-  FSelStartY := 0;
-  FSelStartX := 0;
-  FSelEndY := Lines.Count - 1;
-  FSelEndX := Length(Lines[Lines.Count - 1]);
-  Invalidate;
-end;
-
-//-----------------------------------------------------------
-//   SET CLIPBOARD CODE PAGE
-//-----------------------------------------------------------
-
-procedure SetClipboardCodePage(const CodePage: longint);
-var
-  Data: THandle;
-  DataPtr: Pointer;
-begin
-  // Define new code page for clipboard
-  Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 4);
-  try
-    DataPtr := GlobalLock(Data);
-    try
-      Move(CodePage, DataPtr^, 4);
-      SetClipboardData(CF_LOCALE, Data);
-    finally
-      GlobalUnlock(Data);
-    end;
-  except
-    GlobalFree(Data);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        COPY TO CLIPBOARD
-//--------------------------------------------------------------
-
-procedure CopyStringToClipboard(const Value: string);
-const
-  RusLocale = (SUBLANG_DEFAULT shl $A) or LANG_RUSSIAN;
-begin
-  Clipboard.Open;
-  SetClipboardCodePage(RusLocale);
-  try
-    Clipboard.AsText := Value;
-  finally
-    SetClipboardCodePage(RusLocale);
-    Clipboard.Close;
-  end;
-end;
-
-procedure TGLSCustomMemo.CopyToClipBoard;
-begin
-  CopyStringToClipboard(GetSelText);
-end;
-//--------------------------------------------------------------
-//        PASTE FROM CLIPBOARD
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.PasteFromClipBoard;
-var
-  H, len: integer;
-  Buff: string;
-begin
-  H := ClipBoard.GetAsHandle(CF_TEXT);
-  len := GlobalSize(H);
-  if len = 0 then
-    Exit;
-
-  SetLength(Buff, len);
-  SetLength(Buff, ClipBoard.GetTextBuf(PChar(Buff), len));
-  AdjustLineBreaks(Buff);
-
-  SetSelText(Buff);
-end;
-
-//--------------------------------------------------------------
-//        DELETE SELECTION
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DeleteSelection(bRepaint: Boolean);
-var
-  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
-  i, len: integer;
-  OldX, OldY: integer;
-  S1, S2, S, AddSpaces: string;
-  Undo: TGLSMemoDeleteBufUndo;
-begin
-  if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
-    Exit;
-
-  OldX := CurX;
-  OldY := CurY;
-  xSelStartX := FSelStartX;
-  xSelStartY := FSelStartY;
-  xSelEndX := FSelEndX;
-  xSelEndY := FSelEndY;
-  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
-
-  if xSelStartY = xSelEndY then
-  begin
-    S1 := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX);
-    S2 := '';
-    AddSpaces := '';
-  end
-  else
-  begin
-    len := Length(Lines[xSelStartY]);
-    S1 := Copy(Lines[xSelStartY], xSelStartX + 1, len);
-    AddSpaces := StringOfChar(' ', xSelStartX - len);
-    S2 := Copy(Lines[xSelEndY], 1, xSelEndX);
-  end;
-  Lines[xSelStartY] := Copy(Lines[xSelStartY], 1, xSelStartX) + AddSpaces +
-    Copy(Lines[xSelEndY], xSelEndX + 1, Length(Lines[xSelEndY]));
-  S := S1;
-  for i := xSelStartY + 1 to xSelEndY do
-  begin
-    S := S + #13#10;
-    if i <> xSelEndY then
-      S := S + Lines[xSelStartY + 1];
-    DeleteLine(xSelStartY + 1, -1, -1, -1, -1, False);
-  end;
-  S := S + S2;
-
-  CurY := xSelStartY;
-  CurX := xSelStartX;
-  ClearSelection;
-
-  Changed(xSelStartY, -1);
-  SelectionChanged;
-  if bRepaint then
-    Invalidate;
-
-  Undo := TGLSMemoDeleteBufUndo.Create(OldX, OldY, CurX, CurY, S);
-  Undo.UndoSelStartX := xSelStartX;
-  Undo.UndoSelStartY := xSelStartY;
-  Undo.UndoSelEndX := xSelEndX;
-  Undo.UndoSelEndY := xSelEndY;
-  if Assigned(FUndoList) then
-    FUndoList.Add(Undo);
-end;
-
-//--------------------------------------------------------------
-//        CUT TO CLIPBOARD
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.CutToClipBoard;
-begin
-  ClipBoard.SetTextBuf(PChar(GetSelText));
-  DeleteSelection(True);
-end;
-
-//--------------------------------------------------------------
-//        GET SEL TEXT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetSelText: string;
-var
-  i: integer;
-  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
-begin
-  Result := '';
-  if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
-    Exit;
-
-  xSelStartX := FSelStartX;
-  xSelStartY := FSelStartY;
-  xSelEndX := FSelEndX;
-  xSelEndY := FSelEndY;
-  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
-
-  if xSelStartY = xSelEndY then
-    Result := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX)
-  else
-  begin
-    Result := Copy(Lines[xSelStartY], xSelStartX + 1,
-      Length(Lines[xSelStartY]));
-    for i := xSelStartY + 1 to xSelEndY - 1 do
-      Result := Result + #13#10 + Lines[i];
-    Result := Result + #13#10 + Copy(Lines[xSelEndY], 1, xSelEndX);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        GET SEL START
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetSelStart: TPoint;
-var
-  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
-begin
-  xSelStartX := FSelStartX;
-  xSelStartY := FSelStartY;
-  xSelEndX := FSelEndX;
-  xSelEndY := FSelEndY;
-  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
-  Result := Point(xSelStartX, xSelStartY);
-end;
-
-//--------------------------------------------------------------
-//        GET SEL END
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetSelEnd: TPoint;
-var
-  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
-begin
-  xSelStartX := FSelStartX;
-  xSelStartY := FSelStartY;
-  xSelEndX := FSelEndX;
-  xSelEndY := FSelEndY;
-  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
-  Result := Point(xSelEndX, xSelEndY);
-end;
-
-//--------------------------------------------------------------
-//        SET SEL TEXT
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetSelText(const AValue: string);
-var
-  i, k: integer;
-  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
-  Buff, S: string;
-  OldX, OldY: integer;
-begin
-  Buff := AValue;
-  xSelStartX := FSelStartX;
-  xSelStartY := FSelStartY;
-  xSelEndX := FSelEndX;
-  xSelEndY := FSelEndY;
-  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
-
-  DeleteSelection(False);
-
-  OldX := CurX;
-  OldY := CurY;
-  i := Pos(#13#10, Buff);
-  S := Lines[xSelStartY];
-  if i = 0 then
-  begin
-    Lines[xSelStartY] := Copy(S, 1, xSelStartX) + Buff
-      + Copy(S, xSelStartX + 1, Length(S));
-    CurX := xSelStartX;
-    if Buff <> '' then
-      CurX := CurX + Length(Buff);
-  end
-  else
-  begin
-    k := xSelStartY;
-    Lines[k] := Copy(S, 1, xSelStartX) + Copy(Buff, 1, i - 1);
-    TGLSMemoStrings(Lines).DoInsert(k + 1, Copy(S, xSelStartX + 1, Length(S)));
-    while True do
-    begin
-      Buff := Copy(Buff, i + 2, Length(Buff));
-      i := Pos(#13#10, Buff);
-      k := k + 1;
-      if i = 0 then
-        break;
-      TGLSMemoStrings(Lines).DoInsert(k, Copy(Buff, 1, i - 1));
-    end;
-    Lines[k] := Buff + Lines[k];
-    CurY := k;
-    CurX := Length(Buff);
-  end;
-
-  ClearSelection;
-  Changed(xSelStartY, -1);
-  if Assigned(FUndoList) then
-    FUndoList.Add(TGLSMemoPasteUndo.Create(OldX, OldY, CurX, CurY, AValue));
-  Invalidate;
-end;
-
-//--------------------------------------------------------------
-//        GET SEL LENGTH
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetSelLength: integer;
-begin
-  Result := Length(GetSelText);
-end;
-
-//--------------------------------------------------------------
-//        CHANGED
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.Changed(FromLine, ToLine: integer);
-var
-  i: integer;
-begin
-  if ToLine < FromLine then
-    ToLine := Lines.Count - 1;
-  for i := FromLine to ToLine do
-    ValidAttrs[i] := False;
-  InvalidateLineRange(FromLine, ToLine);
-  if Assigned(FOnChange) then
-    FOnChange(Self);
-end;
-
-//--------------------------------------------------------------
-//        ATTR CHANGED
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.AttrChanged(LineNo: integer);
-begin
-  ValidAttrs[LineNo] := False;
-  InvalidateLineRange(LineNo, LineNo);
-  if Assigned(FOnAttrChange) then
-    FOnAttrChange(Self);
-end;
-
-//--------------------------------------------------------------
-//        SELECTION CHANGED
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SelectionChanged;
-begin
-  if Assigned(FOnSelectionChange) then
-    FOnSelectionChange(Self);
-end;
-
-//--------------------------------------------------------------
-//        STATUS CHANGED
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.StatusChanged;
-begin
-  if Assigned(FOnStatusChange) then
-    FOnStatusChange(Self);
-end;
-
-//--------------------------------------------------------------
-//        CLEAR SELECTION
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ClearSelection;
-var
-  rct: TRect;
-  Changed: Boolean;
-begin
-  Changed := not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY));
-  rct := LineRangeRect(FSelStartY, FSelEndY);
-  FSelStartX := CurX;
-  FSelStartY := CurY;
-  FSelEndX := CurX;
-  FSelEndY := CurY;
-  FPrevSelX := CurX;
-  FPrevSelY := CurY;
-  if Changed then
-  begin
-    SelectionChanged;
-    InvalidateRect(Handle, @rct, true);
-  end;
-  if Assigned(FOnMoveCursor) then
-    FOnMoveCursor(Self);
-end;
-
-//--------------------------------------------------------------
-//        EXPAND SELECTION
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ExpandSelection;
-var
-  rct: TRect;
-begin
-  rct := LineRangeRect(FPrevSelY, CurY);
-  FSelEndX := CurX;
-  FSelEndY := CurY;
-  FPrevSelX := CurX;
-  FPrevSelY := CurY;
-  SelectionChanged;
-  InvalidateRect(Handle, @rct, true);
-  if Assigned(FOnMoveCursor) then
-    FOnMoveCursor(Self);
-end;
-
-//--------------------------------------------------------------
-//        MAX LENGTH
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.MaxLength: integer;
-var
-  i, len: integer;
-begin
-  Result := 0;
-  for i := 0 to Lines.Count - 1 do
-  begin
-    len := Length(Lines[i]);
-    if len > Result then
-      Result := len;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        DO SCROLL
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
-var
-  eRect, scrRect, sbRect: TRect;
-  Old: integer;
-begin
-  eRect := EditorRect;
-  case Sender.Kind of
-    sbVertical:
-      begin
-        Old := FTopLine;
-        FTopLine := FTopLine + ByValue;
-        if FTopLine > Sender.MaxPosition then
-          FTopLine := Sender.MaxPosition;
-        if FTopLine < 0 then
-          FTopLine := 0;
-        if Old <> FTopLine then
-        begin
-          ShowCaret(False);
-          if CurY < FTopLine then
-            CurY := FTopLine;
-          if CurY > LastVisibleLine then
-            CurY := LastVisibleLine;
-
-          ScrollDC(Canvas.Handle, 0, (Old - FTopLine) * FCellSize.H,
-            eRect, eRect, 0, @scrRect);
-          InvalidateRect(Handle, @scrRect, True);
-          sbRect := Sender.FullRect;
-          InvalidateRect(Handle, @sbRect, True);
-          FGutter.Invalidate;
-          ShowCaret(True);
-        end;
-      end;
-    sbHorizontal:
-      begin
-        Old := FLeftCol;
-        FLeftCol := FLeftCol + ByValue;
-        if FLeftCol > Sender.MaxPosition then
-          FLeftCol := Sender.MaxPosition;
-        if FLeftCol < 0 then
-          FLeftCol := 0;
-        if Old <> FLeftCol then
-        begin
-          ShowCaret(False);
-          if CurX < FLeftCol then
-            CurX := FLeftCol;
-          if CurX > LastVisiblePos then
-            CurX := LastVisiblePos;
-          ScrollDC(Canvas.Handle, (Old - FLeftCol) * FCellSize.W, 0,
-            eRect, eRect, 0, @scrRect);
-          InvalidateRect(Handle, @scrRect, True);
-          sbRect := Sender.FullRect;
-          InvalidateRect(Handle, @sbRect, True);
-          ShowCaret(True);
-        end;
-      end;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        DO SCROLL PAGE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DoScrollPage(Sender: TGLSMemoScrollBar; ByValue:
-  integer);
-begin
-  case Sender.Kind of
-    sbVertical: DoScroll(Sender, ByValue * VisibleLineCount);
-    sbHorizontal: DoScroll(Sender, ByValue * VisiblePosCount);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SET LINES
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetLines(ALines: TStrings);
-begin
-  if ALines <> nil then
-  begin
-    FLines.Assign(ALines);
-    Changed(0, -1);
-    SelectionChanged;
-    Invalidate;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SET/GET LINE STYLE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetLineStyle(Index: integer; Value: integer);
-begin
-  TGLSMemoStrings(FLines).Style[Index] := Value;
-  if IsLineVisible(Index) then
-    AttrChanged(Index);
-end;
-
-function TGLSCustomMemo.GetLineStyle(Index: integer): integer;
-begin
-  Result := TGLSMemoStrings(FLines).Style[Index];
-end;
-
-//--------------------------------------------------------------
-//        GET/SET IN COMMENT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetInComment(Index: integer): Boolean;
-begin
-  Result := TGLSMemoStrings(FLines).InComment[Index];
-end;
-
-procedure TGLSCustomMemo.SetInComment(Index: integer; Value: Boolean);
-begin
-  TGLSMemoStrings(FLines).InComment[Index] := Value;
-end;
-
-//--------------------------------------------------------------
-//        GET/SET IN BRACKETS
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetInBrackets(Index: integer): integer;
-begin
-  Result := TGLSMemoStrings(FLines).InBrackets[Index];
-end;
-
-procedure TGLSCustomMemo.SetInBrackets(Index: integer; Value: integer);
-begin
-  TGLSMemoStrings(FLines).InBrackets[Index] := Value;
-end;
-
-//--------------------------------------------------------------
-//        GET/SET VALID ATTRS
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetValidAttrs(Index: integer): Boolean;
-begin
-  Result := TGLSMemoStrings(FLines).ValidAttrs[Index];
-end;
-
-procedure TGLSCustomMemo.SetValidAttrs(Index: integer; Value: Boolean);
-begin
-  TGLSMemoStrings(FLines).ValidAttrs[Index] := Value;
-end;
-
-//--------------------------------------------------------------
-//        GET/SET CHAR ATTRS
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetCharAttrs(Index: integer): string;
-begin
-  Result := TGLSMemoStrings(FLines).CharAttrs[Index];
-end;
-
-procedure TGLSCustomMemo.SetCharAttrs(Index: integer; const Value: string);
-begin
-  TGLSMemoStrings(FLines).CharAttrs[Index] := Value;
-  if IsLineVisible(Index) then
-    AttrChanged(Index);
-end;
-
-//--------------------------------------------------------------
-//        SET CUR X
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetCurX(Value: integer);
-var
-  len: integer;
-  WasVisible: Boolean;
-begin
-  if Value < 0 then
-    if CurY = 0 then
-      Value := 0
-    else
-    begin
-      CurY := CurY - 1;
-      Value := Length(Lines[CurY]);
-    end;
-
-  if (CurY >= 0) and (CurY < Lines.Count) then
-  begin
-    len := Length(Lines[CurY]);
-    if Value > len then
-    begin
-      Lines[CurY] := Lines[CurY] + StringOfChar(' ', Value - len);
-      // Value := len;
-      ValidAttrs[CurY] := False;
-      InvalidateLineRange(CurY, CurY);
-    end;
-  end;
-
-  FCurX := Value;
-
-  WasVisible := FCaretVisible;
-  if WasVisible then
-    ShowCaret(False);
-  MakeVisible;
-  ResizeScrollBars;
-  StatusChanged;
-  if WasVisible then
-    ShowCaret(True);
-end;
-
-//--------------------------------------------------------------
-//        SET CUR Y
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetCurY(Value: integer);
-var
-  Old: integer;
-  WasVisible: Boolean;
-begin
-  WasVisible := FCaretVisible;
-  if WasVisible then
-    ShowCaret(False);
-  Old := CurY;
-
-  if Value < 0 then
-    Value := 0;
-  if Value >= Lines.Count then
-    Value := Lines.Count - 1;
-
-  FCurY := Value;
-  if (CurY <> Old) and (Old >= 0) and (Old < Lines.Count) then
-    Lines[Old] := TrimRight(Lines[Old]);
-  CurX := CurX;
-
-  MakeVisible;
-  ResizeScrollBars;
-  StatusChanged;
-  if WasVisible then
-    ShowCaret(True);
-end;
-
-//--------------------------------------------------------------
-//        MOVE CURSOR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.MoveCursor(dX, dY: integer; Shift: TShiftState);
-var
-  Selecting: Boolean;
-  //------------------------------------------------------------
-  function IsDelimiter(c: char): Boolean;
-  begin
-    Result := Pos(c, ' .,;:/?!@#$%^&*(){}[]<>-+=|\') > 0;
-  end;
-  //------------------------------------------------------------
-  function IsStopChar(c, cThis: char): Boolean;
-  begin
-    Result := IsDelimiter(c) <> IsDelimiter(cThis);
-  end;
-  //------------------------------------------------------------
-  procedure MoveWordLeft;
-  var
-    S: string;
-  begin
-    CurX := CurX - 1;
-    S := TrimRight(Lines[CurY]);
-    while CurX > 0 do
-    begin
-      if IsStopChar(S[CurX], S[CurX + 1]) then
-        break;
-      CurX := CurX - 1;
-    end;
-    if (CurX < 0) then
-      if CurY > 0 then
-      begin
-        CurY := CurY - 1;
-        CurX := Length(Lines[CurY]);
-      end;
-  end;
-  //------------------------------------------------------------
-  procedure MoveWordRight;
-  var
-    Len: integer;
-    S: string;
-  begin
-    S := TrimRight(Lines[CurY]);
-    Len := Length(S);
-    CurX := CurX + 1;
-    while CurX < Len do
-    begin
-      if IsStopChar(S[CurX + 1], S[CurX]) then
-        break;
-      CurX := CurX + 1;
-    end;
-    if CurX > Len then
-      if CurY < Lines.Count - 1 then
-      begin
-        CurY := CurY + 1;
-        CurX := 0;
-      end;
-  end;
-  //------------------------------------------------------------
-begin
-  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
-    and (CurY = FPrevSelY);
-  if ssCtrl in Shift then
-  begin
-    if dX > 0 then
-      MoveWordRight;
-    if dX < 0 then
-      MoveWordLeft;
-  end
-  else
-  begin
-    CurY := CurY + dY;
-    CurX := CurX + dX;
-  end;
-  if Selecting then
-    ExpandSelection
-  else
-    ClearSelection;
-end;
-
-//--------------------------------------------------------------
-//        MOVE PAGE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.MovePage(dP: integer; Shift: TShiftState);
-var
-  eRect: TRect;
-  LinesPerPage: integer;
-  Selecting: Boolean;
-begin
-  if FCellSize.H = 0 then
-    Exit;
-  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
-    and (CurY = FPrevSelY);
-  eRect := EditorRect;
-  LinesPerPage := (eRect.Bottom - eRect.Top) div FCellSize.H - 1;
-  CurY := CurY + dP * LinesPerPage;
-  if ssCtrl in Shift then
-    if dP > 0 then
-    begin
-      CurY := Lines.Count - 1;
-      CurX := Length(Lines[Lines.Count - 1]);
-    end
-    else
-    begin
-      CurY := 0;
-      CurX := 0;
-    end;
-  if Selecting then
-    ExpandSelection
-  else
-    ClearSelection;
-end;
-
-//--------------------------------------------------------------
-//        GO HOME
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.GoHome(Shift: TShiftState);
-var
-  Selecting: Boolean;
-begin
-  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
-    and (CurY = FPrevSelY);
-  CurX := 0;
-  FLeftCol := 0;
-  if Selecting then
-    ExpandSelection
-  else
-    ClearSelection;
-end;
-
-//--------------------------------------------------------------
-//        GO END
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.GoEnd(Shift: TShiftState);
-var
-  Selecting: Boolean;
-  S, S1: string;
-begin
-  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
-    and (CurY = FPrevSelY);
-
-  S := Lines[CurY];
-  if not Selecting then
-    S := TrimRight(S);
-  S1 := TrimRight(Copy(S, CurX + 1, Length(S)));
-  S := Copy(S, 1, CurX);
-  Lines[CurY] := S + S1;
-
-  CurX := Length(Lines[CurY]);
-  if Selecting then
-    ExpandSelection
-  else
-    ClearSelection;
-end;
-
-//--------------------------------------------------------------
-//        INSERT CHAR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.InsertChar(C: Char);
-var
-  S, S1: string;
-  NewPlace: integer;
-  rct: TRect;
-  CurX0, CurY0: integer;
-begin
-  CurX0 := CurX;
-  CurY0 := CurY;
-  S := Lines[CurY];
-  NewPlace := CurX + 1;
-  if C = #9 then
-  begin
-    while (NewPlace mod TabSize) <> 0 do
-      Inc(NewPlace);
-    S1 := StringOfChar(' ', NewPlace - CurX);
-  end
-  else
-    S1 := C;
-  Insert(S1, S, CurX + 1);
-  Lines[CurY] := S;
-  CurX := NewPlace;
-  ClearSelection;
-  rct := LineRect(CurY);
-  Changed(CurY, CurY);
-
-  if Assigned(FUndoList) then
-    FUndoList.Add(TGLSMemoInsCharUndo.Create(CurX0, CurY0, CurX, CurY, S1));
-
-  InvalidateRect(Handle, @rct, True);
-end;
-
-//--------------------------------------------------------------
-//        INSERT TEMPLATE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.InsertTemplate(AText: string);
-var
-  i, NewCurX, NewCurY: integer;
-  Indent: string;
-  FoundCursor: Boolean;
-begin
-  Indent := IndentCurrLine;
-
-  DeleteSelection(False);
-  ClearSelection;
-
-  NewCurX := CurX;
-  NewCurY := CurY;
-  FoundCursor := False;
-  i := 1;
-  while i <= Length(AText) do
-  begin
-    if AText[i] = #13 then
-    begin
-      if (i = Length(AText)) or (AText[i + 1] <> #10) then
-        Insert(#10 + Indent, AText, i + 1);
-      if not FoundCursor then
-      begin
-        Inc(NewCurY);
-        NewCurX := Length(Indent);
-      end;
-      Inc(i, 1 + Length(Indent));
-    end
-    else if AText[i] = #7 then
-    begin
-      FoundCursor := True;
-      Delete(AText, i, 1);
-      Dec(i);
-    end
-    else if Ord(AText[i]) < Ord(' ') then
-    begin
-      Delete(AText, i, 1);
-      Dec(i);
-    end
-    else if not FoundCursor then
-      Inc(NewCurX);
-    Inc(i);
-  end;
-
-  SetSelText(AText);
-  SetCursor(NewCurX, NewCurY);
-  ClearSelection;
-  try
-    SetFocus;
-  except
-  end;
-
-end;
-
-//--------------------------------------------------------------
-//        DELETE CHAR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DeleteChar(OldX, OldY: integer);
-var
-  S, S1: string;
-  rct: TRect;
-  C: char;
-  Undo: TGLSMemoDelCharUndo;
-  IsBackspace: Boolean;
-begin
-  if FReadOnly then
-    Exit;
-  if OldX < 0 then
-  begin
-    OldX := CurX;
-    OldY := CurY;
-    IsBackspace := False;
-  end
-  else
-    IsBackspace := True;
-
-  ClearSelection;
-
-  S := Lines[CurY];
-  S1 := Copy(S, CurX + 1, Length(S));
-  if not IsBackspace then
-    S1 := TrimRight(S1);
-  S := Copy(S, 1, CurX);
-  Lines[CurY] := S + S1;
-
-  if CurX < Length(Lines[CurY]) then
-  begin
-    S := Lines[CurY];
-    C := S[CurX + 1];
-    Delete(S, CurX + 1, 1);
-    Lines[CurY] := S;
-    Changed(CurY, CurY);
-    rct := LineRect(CurY);
-    Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, C);
-    Undo.IsBackSpace := IsBackSpace;
-    if Assigned(FUndoList) then
-      FUndoList.Add(Undo);
-  end
-  else if CurY < Lines.Count - 1 then
-  begin
-    S := Lines[CurY] + Lines[CurY + 1];
-    Lines[CurY] := S;
-    DeleteLine(CurY + 1, OldX, OldY, CurX, CurY, False);
-    Changed(CurY, -1);
-    rct := EditorRect;
-    Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, #13);
-    Undo.IsBackSpace := IsBackSpace;
-    if Assigned(FUndoList) then
-      FUndoList.Add(Undo);
-  end;
-  ClearSelection;
-  InvalidateRect(Handle, @rct, True);
-end;
-
-//--------------------------------------------------------------
-//        DELETE LINE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DeleteLine(Index, OldX, OldY, NewX, NewY: integer;
-  FixUndo: Boolean);
-var
-  rct: TRect;
-  s: string;
-begin
-  if Index < 0 then
-    Index := CurY;
-  if OldX < 0 then
-  begin
-    OldX := CurX;
-    OldY := CurY;
-  end;
-
-  s := Lines[Index];
-
-  TGLSMemoStrings(Lines).FDeleting := True;
-  if Lines.Count = 1 then
-    TGLSMemoStrings(Lines)[0] := ''
-  else
-    Lines.Delete(Index);
-  TGLSMemoStrings(Lines).FDeleting := False;
-
-  ClearSelection;
-  if Index >= Lines.Count then
-    Changed(Index - 1, -1)
-  else
-    Changed(Index, -1);
-  rct := EditorRect;
-  InvalidateRect(Handle, @rct, True);
-
-  if NewX < 0 then
-  begin
-    if Length(Lines[0]) < CurX then
-      CurX := Length(Lines[0]);
-    if Index >= Lines.Count then
-      CurY := Index - 1
-    else
-      CurY := Index;
-    NewX := CurX;
-    NewY := CurY;
-  end
-  else
-  begin
-    CurX := NewX;
-    CurY := NewY;
-  end;
-  if Assigned(FUndoList) and FixUndo then
-    FUndoList.Add(TGLSMEmoDelLineUndo.Create(Index, OldX, OldY, NewX, NewY, s));
-end;
-
-//--------------------------------------------------------------
-//        BACK SPACE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.BackSpace;
-var
-  OldX, OldY: integer;
-begin
-  OldX := CurX;
-  OldY := CurY;
-  MoveCursor(-1, 0, []);
-  if (OldX = CurX) and (OldY = CurY) then
-    Exit;
-  DeleteChar(OldX, OldY);
-end;
-
-//--------------------------------------------------------------
-//        BACK SPACE WORD
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.BackSpaceWord;
-begin
-  ClearSelection;
-  MoveCursor(-1, 0, [ssShift, ssCtrl]);
-  DeleteSelection(True);
-end;
-
-//--------------------------------------------------------------
-//        INDENT CURR LINE
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.IndentCurrLine: string;
-var
-  Len, Count: integer;
-  CurS: string;
-begin
-  Result := '';
-  if not AutoIndent then
-    Exit;
-  CurS := Lines[CurY];
-  Len := Length(CurS);
-  Count := 0;
-  while (Count < CurX) and (Count < Len) do
-  begin
-    if CurS[Count + 1] <> ' ' then
-      break;
-    Inc(Count);
-  end;
-  Result := StringOfChar(' ', Count);
-end;
-
-//--------------------------------------------------------------
-//        NEW LINE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.NewLine;
-var
-  S, sIndent: string;
-  OldX, OldY: integer;
-begin
-  OldX := CurX;
-  OldY := CurY;
-  S := Lines[CurY];
-  sIndent := IndentCurrLine;
-  Lines[CurY] := Copy(S, 1, CurX);
-
-  S := TrimRight(Copy(S, CurX + 1, Length(S)));
-  if AutoIndent then
-    while (Length(S) > 0) and (S[1] = ' ') do
-      Delete(S, 1, 1);
-
-  TGLSMemoStrings(Lines).DoInsert(CurY + 1, sIndent + S);
-  GoHome([]);
-  MoveCursor(0, 1, []);
-  CurX := Length(sIndent);
-  ClearSelection;
-  if Assigned(FUndoList) then
-    FUndoList.Add(TGLSMemoInsCharUndo.Create(OldX, OldY, CurX, CurY, #13 +
-      sIndent));
-  Invalidate;
-  Changed(CurY - 1, -1);
-end;
-
-//--------------------------------------------------------------
-//        ADD STRING
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.AddString(const S: string): integer;
-begin
-  if Lines.Count = 0 then
-    TGLSMemoStrings(Lines).DoAdd('');
-  MovePage(1, [ssCtrl]); // end of text
-  if not ((Lines.Count = 1) and (Lines[0] = '')) then
-  begin
-    TGLSMemoStrings(Lines).DoAdd('');
-    CurX := 0;
-    CurY := Lines.Count;
-    ClearSelection;
-    // S := #13#10 + S;
-  end;
-  SetSelText(S);
-  Result := Lines.Count - 1;
-end;
-
-//--------------------------------------------------------------
-//        INSERT STRING
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.InsertString(Index: integer; S: string);
-begin
-  CurY := Index;
-  CurX := 0;
-  ClearSelection;
-  if not ((Lines.Count = 1) and (Lines[0] = '')) then
-    S := S + #13#10;
-  SetSelText(S);
-end;
-
-//--------------------------------------------------------------
-//        DO COMMAND
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DoCommand(cmd: TCommand; const AShift: TShiftState);
-begin
-  case cmd of
-    cmDelete: if not FReadOnly then
-      begin
-        if ssShift in AShift then
-          CutToClipboard
-        else if FDelErase and
-          (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY))) then
-          DeleteSelection(True)
-        else
-          DeleteChar(-1, -1);
-      end;
-    cmBackSpace: BackSpace;
-    cmWordBackSpace: BackSpaceWord;
-    cmNewLine: NewLine;
-    cmDelLine: DeleteLine(-1, -1, -1, -1, -1, True);
-    cmCopy: CopyToClipboard;
-    cmCut: CutToClipboard;
-    cmPaste: PasteFromClipboard;
-    cmHome: GoHome(AShift);
-    cmEnd: GoEnd(AShift);
-    cmPageDown: MovePage(1, AShift);
-    cmPageUp: MovePage(-1, AShift);
-    cmInsert:
-      begin
-        if ssShift in AShift then
-          PasteFromClipboard;
-        if ssCtrl in AShift then
-          CopyToClipboard;
-      end;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        KEY DOWN
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.KeyDown(var Key: Word; Shift: TShiftState);
-begin
-  ShowCaret(False);
-  inherited;
-  case Key of
-    VK_LEFT: MoveCursor(-1, 0, Shift);
-    VK_RIGHT: MoveCursor(1, 0, Shift);
-    VK_UP: MoveCursor(0, -1, Shift);
-    VK_DOWN: MoveCursor(0, 1, Shift);
-    VK_HOME, VK_END,
-      VK_DELETE: DoCommand(Key, Shift);
-    VK_PRIOR, VK_NEXT:
-      DoCommand(Key, Shift);
-    VK_INSERT: DoCommand(Key, Shift);
-  end;
-  ShowCaret(True);
-end;
-
-//--------------------------------------------------------------
-//        KEY PRESS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.KeyPress(var Key: Char);
-begin
-  if FReadOnly then
-    Exit;
-  ShowCaret(False);
-  inherited;
-  if (ord(Key) in [9, 32..255]) and (ord(Key) <> 127) then
-  begin
-    if FDelErase and (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY)))
-      then
-      DeleteSelection(True);
-    InsertChar(Key);
-  end
-  else
-    DoCommand(Ord(Key), []);
-  ShowCaret(True);
-end;
-
-//--------------------------------------------------------------
-//        MOUSE DOWN
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.MouseDown(Button: TMouseButton; Shift: TShiftState;
-  X, Y: Integer);
-var
-  newPos: TCellPos;
-  charPos: TFullPos;
-  Selecting: Boolean;
-begin
-  inherited;
-  if not Focused then
-  begin
-    SetFocus;
-    //     Exit;
-  end;
-
-  if FAfterDoubleClick then
-  begin
-    FAfterDoubleClick := False;
-    Exit;
-  end;
-
-  if Button <>mbLeft then
-    Exit;
-
-
-  if sbVert.MouseDown(Button, Shift, X, Y) then
-    Exit;
-  if sbHorz.MouseDown(Button, Shift, X, Y) then
-    Exit;
-
-  if PointInRect(Point(X, Y), EditorRect) then
-  begin
-    ShowCaret(False);
-    newPos := CellFromPos(X, Y);
-    CurY := newPos.Y + FTopLine;
-    CurX := newPos.X + FLeftCol;
-    if Assigned(FOnMoveCursor) then
-      FOnMoveCursor(Self);
-
-    Selecting := ssShift in Shift;
-    if Button = mbLeft then
-    begin
-      if Selecting then
-        ExpandSelection
-      else
-        ClearSelection;
-      FLeftButtonDown := True;
-    end
-    else
-      ShowCaret(True);
-  end;
-
-  if Assigned(FOnGutterClick) then
-    if PointInRect(Point(X, Y), FGutter.FullRect) then
-    begin
-      charPos := CharFromPos(X, Y);
-      if charPos.LineNo < Lines.Count then
-        FOnGutterClick(Self, charPos.LineNo);
-    end;
-end;
-
-//--------------------------------------------------------------
-//        MOUSE MOVE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
-var
-  newPos: TCellPos;
-begin
-  inherited;
-  if sbVert.MouseMove(Shift, X, Y) then
-    Exit;
-  if sbHorz.MouseMove(Shift, X, Y) then
-    Exit;
-  if PointInRect(Point(X, Y), EditorRect) then
-  begin
-    if (ssLeft in Shift) and FLeftButtonDown then
-    begin
-      newPos := CellFromPos(X, Y);
-      CurY := newPos.Y + FTopLine;
-      CurX := newPos.X + FLeftCol;
-      ExpandSelection;
-    end;
-  end
-end;
-
-//--------------------------------------------------------------
-//        MOUSE UP
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:
-  Integer);
-begin
-  inherited;
-  if sbVert.MouseUp(Button, Shift, X, Y) then
-    Exit;
-  if sbHorz.MouseUp(Button, Shift, X, Y) then
-    Exit;
-  if Button = mbLeft then
-    ShowCaret(True);
-  FLeftButtonDown := False;
-  FLastMouseUpX := X;
-  FLastMouseUpY := Y;
-end;
-
-//--------------------------------------------------------------
-//        DBL CLICK
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DblClick;
-var
-  clickPos: TCellPos;
-  clickX, clickY: integer;
-  //------------------------------------------------------------
-  //   SELECT WORD
-  //------------------------------------------------------------
-  procedure SelectWord;
-  const
-    stopChars: TSysCharSet = [' ', ';', '.', ',', ':', '?', '!', '''', '"',
-      '<', '>', '/', '*', '+', '-', '=', '(', ')',
-      '[', ']', '{', '}', '@', '#', '$', '%', '^',
-      '&', '|', '\'];
-  var
-    s: string;
-    i: integer;
-    rct: TRect;
-  begin
-    CurX := clickX;
-    CurY := clickY;
-    if (CurX = clickX) and (CurY = clickY) then
-    begin
-      s := Lines[clickY];
-      if s[clickX + 1] = ' ' then
-        Exit;
-
-      i := clickX;
-      while (i >= 0) and not CharInSet(s[i + 1], stopChars) do
-        Dec(i);
-      FSelStartY := clickY;
-      FSelStartX := i + 1;
-
-      i := clickX;
-      while (i < Length(s)) and not CharInSet(s[i + 1], stopChars) do
-        Inc(i);
-      FSelEndY := clickY;
-      FSelEndX := i;
-
-      if FSelEndX <> FSelStartX then
-      begin
-        FAfterDoubleClick := True;
-        rct := LineRangeRect(CurY, CurY);
-        SelectionChanged;
-        InvalidateRect(Handle, @rct, true);
-      end;
-    end;
-  end;
-  //------------------------------------------------------------
-begin
-
-  if PointInRect(Point(FLastMouseUpX, FLastMouseUpY), EditorRect) then
-  begin
-    clickPos := CellFromPos(FLastMouseUpX, FLastMouseUpY);
-    clickX := clickPos.X + FLeftCol;
-    clickY := clickPos.Y + FTopLine;
-    SelectWord;
-  end;
-  inherited;
-end;
-
-//--------------------------------------------------------------
-//        WM_GETDLGCODE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.WMGetDlgCode(var Msg: TWMGetDlgCode);
-begin
-  Msg.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
-end;
-
-//--------------------------------------------------------------
-//        WM_ERASEBKGND
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.WMEraseBkgnd(var Msg: TWmEraseBkgnd);
-begin
-  Msg.Result := 1;
-end;
-
-//--------------------------------------------------------------
-//        WM_SIZE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.WMSize(var Msg: TWMSize);
-begin
-  if not (csLoading in ComponentState) then
-    try
-      ResizeEditor;
-    except
-    end;
-end;
-
-//--------------------------------------------------------------
-//        WM_SETCURSOR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.WMSetCursor(var Msg: TWMSetCursor);
-var
-  P: TPoint;
-begin
-  Msg.Result := 1;
-  GetCursorPos(P);
-  P := ScreenToClient(P);
-  if PointInRect(P, EditorRect) then
-    Winapi.Windows.SetCursor(Screen.Cursors[crIBeam])
-  else
-    Winapi.Windows.SetCursor(Screen.Cursors[crArrow]);
-end;
-
-//--------------------------------------------------------------
-//        WM_SETFOCUS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.WMSetFocus(var Msg: TWMSetFocus);
-begin
-  if FCellSize.H = 0 then
-    SetFont(FFont);
-  CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
-  ShowCaret(true);
-end;
-
-//--------------------------------------------------------------
-//        WM_KILLFOCUS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.WMKillFocus(var Msg: TWMSetFocus);
-begin
-  DestroyCaret;
-  FCaretVisible := False;
-  inherited;
-end;
-
-//--------------------------------------------------------------
-//        SHOW CARET
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ShowCaret(State: Boolean);
-var
-  rct: TRect;
-begin
-  FCaretVisible := False;
-  if not State then
-    HideCaret(Handle)
-  else if Focused and not HiddenCaret then
-  begin
-    rct := CellRect(CurX - FLeftCol, CurY - FTopLine);
-    SetCaretPos(rct.Left, rct.Top + 1);
-    Winapi.Windows.ShowCaret(Handle);
-    FCaretVisible := True;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        CELL RECT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.CellRect(ACol, ARow: integer): TRect;
-var
-  rct: TRect;
-begin
-  rct := EditorRect;
-  with FCellSize do
-    Result := Rect(rct.Left + W * ACol, rct.Top + H * ARow,
-      rct.Left + W * (ACol + 1), rct.Top + H * (ARow + 1));
-end;
-
-//--------------------------------------------------------------
-//        LINE RECT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.LineRect(ARow: integer): TRect;
-var
-  rct: TRect;
-begin
-  rct := EditorRect;
-  ARow := ARow - FTopLine;
-  with FCellSize do
-    Result := Rect(rct.Left, rct.Top + H * ARow, rct.Right, rct.Top + H * (ARow
-      + 1));
-end;
-
-//--------------------------------------------------------------
-//        COL RECT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.ColRect(ACol: integer): TRect;
-var
-  rct: TRect;
-begin
-  rct := EditorRect;
-  ACol := ACol - FLeftCol;
-  with FCellSize do
-    Result := Rect(rct.Left + W * ACol, rct.Top, rct.Left + W * (ACol + 1),
-      rct.Bottom);
-end;
-
-//--------------------------------------------------------------
-//        LINE RANGE RECT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.LineRangeRect(FromLine, ToLine: integer): TRect;
-var
-  rct1, rct2: TRect;
-begin
-  rct1 := LineRect(FromLine);
-  rct2 := LineRect(ToLine);
-  Result := TotalRect(rct1, rct2);
-end;
-
-//--------------------------------------------------------------
-//        INVALIDATE LINE RANGE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.InvalidateLineRange(FromLine, ToLine: integer);
-var
-  rct: TRect;
-begin
-  if ToLine < FromLine then
-    ToLine := Lines.Count - 1;
-  rct := LineRangeRect(FromLine, ToLine);
-  if GutterWidth > 2 then
-    rct.Left := FGutter.Left;
-  InvalidateRect(Handle, @rct, True);
-end;
-
-//--------------------------------------------------------------
-//        COL RANGE RECT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.ColRangeRect(FromCol, ToCol: integer): TRect;
-var
-  rct1, rct2: TRect;
-begin
-  rct1 := ColRect(FromCol);
-  rct2 := ColRect(ToCol);
-  Result := TotalRect(rct1, rct2);
-end;
-
-//--------------------------------------------------------------
-//        CELL and CHAR FROM POS
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.CellFromPos(X, Y: integer): TCellPos;
-var
-  rct: TRect;
-begin
-  rct := EditorRect;
-  if (FCellSize.H = 0) and Assigned(FFont) then
-    SetFont(FFont);
-  if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
-  begin
-    Result.X := (X - rct.Left) div FCellSize.W;
-    Result.Y := (Y - rct.Top) div FCellSize.H;
-  end
-  else
-  begin
-    Result.X := 0;
-    Result.Y := 0;
-  end;
-end;
-
-function TGLSCustomMemo.CharFromPos(X, Y: integer): TFullPos;
-var
-  rct: TRect;
-begin
-  rct := EditorRect;
-  if (FCellSize.H = 0) and Assigned(FFont) then
-    SetFont(FFont);
-  if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
-  begin
-    Result.Pos := (X - rct.Left) div FCellSize.W + FLeftCol;
-    Result.LineNo := (Y - rct.Top) div FCellSize.H + FTopLine;
-  end
-  else
-  begin
-    Result.Pos := 1;
-    Result.LineNo := 1;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SET COLOR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetColor(Index: integer; Value: TColor);
-var
-  eRect: TRect;
-  Changed: Boolean;
-begin
-  Changed := False;
-  case Index of
-    0: if FBkColor <> Value then
-      begin
-        FBkColor := Value;
-        FStyles.BkColor[0] := Value;
-        Changed := True;
-      end;
-    1: if FSelColor <> Value then
-      begin
-        FSelColor := Value;
-        Changed := True;
-      end;
-    2: if FSelBkColor <> Value then
-      begin
-        FSelBkColor := Value;
-        Changed := True;
-      end;
-  end;
-  if Changed then
-  begin
-    eRect := EditorRect;
-    InvalidateRect(Handle, @eRect, True);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SET FONT
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetFont(Value: TFont);
-var
-  wW, wi: integer;
-  OldFontName: string;
-  eRect: TRect;
-begin
-  OldFontName := Canvas.Font.Name;
-  Canvas.Font.Name := Value.Name;
-  wW := Canvas.TextWidth('W');
-  wi := Canvas.TextWidth('i');
-  Canvas.Font.Name := OldFontName;
-
-  if wW <> wi then
-    raise EAbort.Create('Monospace font required');
-
-  FFont.Assign(Value);
-  Canvas.Font.Assign(Value);
-  FCellSize.W := Canvas.TextWidth('W');
-  FCellSize.H := Canvas.TextHeight('W') + 1;
-
-  if FCaretVisible then
-  begin
-    ShowCaret(False);
-    DestroyCaret;
-    CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
-    ShowCaret(true);
-  end;
-
-  FStyles.TextColor[0] := FFont.Color;
-  FStyles.Style[0] := FFont.Style;
-
-  eRect := EditorRect;
-  InvalidateRect(Handle, @eRect, True);
-end;
-
-//--------------------------------------------------------------
-//        SET GUTTER WIDTH
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetGutterWidth(Value: integer);
-begin
-  FGutterWidth := Value;
-  FGutter.FWidth := Value;
-  if not (csLoading in ComponentState) then
-    ResizeEditor;
-end;
-
-//--------------------------------------------------------------
-//        SET GUTTER COLOR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetGutterColor(Value: TColor);
-begin
-  if FGutter.FColor <> Value then
-  begin
-    FGutter.FColor := Value;
-    FGutter.Invalidate;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        GET GUTTER COLOR
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetGutterColor: TColor;
-begin
-  Result := FGutter.FColor;
-end;
-
-//--------------------------------------------------------------
-//        CHAR STYLE NO
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.CharStyleNo(LineNo, Pos: integer): integer;
-var
-  ChStyle: string;
-begin
-  Result := 0;
-  if (LineNo < 0) or (LineNo >= Lines.Count) then
-    Exit;
-
-  ChStyle := CharAttrs[LineNo];
-  if (Pos <= 0) or (Pos > Length(ChStyle)) then
-    Exit;
-
-  Result := integer(ChStyle[Pos]);
-end;
-
-//--------------------------------------------------------------
-//        DRAW LINE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DrawLine(LineNo: integer);
-var
-  eRect, rct0, rct1, rct, lineRct: TRect;
-  LineSelStart, LineSelEnd, LineStyleNo, pos: integer;
-  S, S1, S2, S3, ChStyle: string;
-  //--------- FIND LINE SELECTION -------------
-  procedure FindLineSelection;
-  var
-    len: integer;
-    xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
-  begin
-    xSelStartX := FSelStartX;
-    xSelStartY := FSelStartY;
-    xSelEndX := FSelEndX;
-    xSelEndY := FSelEndY;
-    OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
-    len := Length(Lines[LineNo]);
-    LineSelStart := 0;
-    LineSelEnd := 0;
-    if xSelStartY = Lineno then
-    begin
-      LineSelStart := xSelStartX - FLeftCol;
-      LineSelEnd := len - FLeftCol;
-    end
-    else if (xSelStartY < LineNo) and (LineNo < xSelEndY) then
-    begin
-      LineSelStart := 0;
-      LineSelEnd := len - FLeftCol;
-    end;
-
-    if xSelEndY = LineNo then
-      LineSelEnd := xSelEndX - FLeftCol;
-
-    if LineSelEnd < LineSelStart then
-      Swap(LineSelEnd, LineSelStart);
-
-    if LineSelStart < 0 then
-      LineSelStart := 0;
-    S := Copy(Lines[LineNo], FLeftCol + 1, len);
-    S1 := Copy(S, 1, LineSelStart);
-    S2 := Copy(S, LineSelStart + 1, LineSelEnd - LineSelStart);
-    S3 := Copy(S, LineSelEnd + 1, len);
-  end;
-  //------------- DRAW PART ---------------------
-  procedure DrawPart(const Part: string; PartStyle, StartPos: integer;
-    var rct: TRect; IsSelection: Boolean);
-  var
-    len, w: integer;
-    rctInternal: TRect;
-  begin
-    len := Length(Part);
-    if len > 0 then
-      with FLineBitmap.Canvas do
-      begin
-        w := FCellSize.W * len;
-        Font.Style := FStyles.Style[PartStyle];
-        if IsSelection then
-        begin
-          Font.Color := SelColor;
-          Brush.Color := SelBkColor;
-        end
-        else
-        begin
-          if LineStyleNo = 0 then
-          begin
-            Font.Color := FStyles.TextColor[PartStyle];
-            Brush.Color := FStyles.BkColor[PartStyle];
-          end
-          else
-          begin
-            if (LineNo = FSelCharPos.LineNo) and
-              (StartPos = FSelCharPos.Pos + 1) and (Length(Part) = 1) then
-            begin
-              Font.Color := FStyles.TextColor[PartStyle];
-              Brush.Color := FStyles.BkColor[PartStyle];
-            end
-            else
-            begin
-              Font.Color := FStyles.TextColor[LineStyleNo];
-              Brush.Color := FStyles.BkColor[LineStyleNo];
-              Font.Style := FStyles.Style[LineStyleNo];
-            end;
-          end;
-        end;
-        rct.Right := rct.Left + w;
-        rctInternal := rct;
-        rctInternal.Left := rctInternal.Left - eRect.Left;
-        rctInternal.Right := rctInternal.Right - eRect.Left;
-        rctInternal.Top := rctInternal.Top - rct.Top;
-        rctInternal.Bottom := rctInternal.Bottom - rct.Top;
-        FillRect(rctInternal);
-        DrawText(Handle, PChar(Part), len, rctInternal, DT_LEFT
-          or DT_SINGLELINE or DT_NOPREFIX);
-        rct0.Left := rct.Left + w;
-        rct := rct0;
-      end;
-  end;
-  //------------- DRAW SEGMENTS ---------------------
-  procedure DrawSegments(S: string; WorkPos: integer;
-    var rct: TRect; IsSelection: Boolean);
-  var
-    i, len, ThisStyle: integer;
-  begin
-    while True do
-    begin
-      Len := Length(S);
-      if Len = 0 then
-        Exit;
-      ThisStyle := Ord(ChStyle[WorkPos]);
-      i := 1;
-      while (i <= Len) and
-        (ThisStyle = Ord(ChStyle[WorkPos + i - 1])) do
-        Inc(i);
-      DrawPart(Copy(S, 1, i - 1), ThisStyle, WorkPos, rct, IsSelection);
-      Inc(WorkPos, i - 1);
-      s := Copy(s, i, Len);
-    end;
-  end;
-  //---------------------------------------------
-begin
-  eRect := EditorRect;
-  rct := CellRect(0, LineNo - FTopLine);
-  rct0 := Rect(eRect.Left, rct.Top, eRect.Right, rct.Bottom);
-  lineRct := rct0;
-
-  if LineNo < Lines.Count then
-  begin
-
-    rct := rct0;
-    S := Lines[LineNo];
-    LineStyleNo := LineStyle[LineNo];
-    ChStyle := CharAttrs[LineNo];
-    FindLineSelection;
-
-    if not Assigned(FOnGetLineAttrs) then
-      ChStyle := StringOfChar(#0, Length(Lines[LineNo]));
-
-    if Length(S) > 0 then
-      if (FSelCharStyle >= 0) and (LineNo = FSelCharPos.LineNo) then
-        ChStyle[FSelCharPos.Pos + 1] := Char(FSelCharStyle);
-
-    pos := FLeftCol + 1; // 1
-    DrawSegments(S1, pos, rct, False);
-    Inc(pos, Length(S1));
-    DrawSegments(S2, pos, rct, True);
-    Inc(pos, Length(S2));
-    DrawSegments(S3, pos, rct, False);
-
-    //       else begin
-    //            DrawPart(S1,StyleNo,rct,False);
-    //            DrawPart(S2,StyleNo,rct,True);
-    //            DrawPart(S3,StyleNo,rct,False);
-    //       end;
-
-    rct1 := rct;
-    rct1.Left := rct1.Left - eRect.Left;
-    rct1.Right := rct1.Right - eRect.Left;
-    rct1.Top := rct1.Top - rct.Top;
-    rct1.Bottom := rct1.Bottom - rct.Top;
-    with FLineBitmap.Canvas do
-    begin
-      Brush.Color := FStyles.BkColor[LineStyleNo];
-      FillRect(rct1);
-    end;
-
-    with LineRct do
-      BitBlt(Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
-        FLineBitmap.Canvas.Handle, 0, 0, SRCCOPY);
-  end
-  else
-    with Canvas do
-    begin
-      Brush.Color := BkColor;
-      FillRect(rct0);
-    end;
-end;
-
-//--------------------------------------------------------------
-//        SET HIDDEN CARET
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetHiddenCaret(Value: Boolean);
-begin
-  if Value <> FHiddenCaret then
-  begin
-    FHiddenCaret := Value;
-    if Focused then
-      if FHiddenCaret = FCaretVisible then
-        ShowCaret(not FHiddenCaret);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        BORDER
-//--------------------------------------------------------------
-
-procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
-const
-  Colors: array[TBorderType] of array[1..4] of TColor
-    = (($D0D0D0, clWhite, clGray, clBlack),
-    (clGray, clBlack, $D0D0D0, clWhite),
-    (clWhite, clWhite, clWhite, clGray),
-    (clGray, clWhite, clWhite, clGray));
-begin
-  with Canvas do
-  begin
-    Pen.Color := Colors[BorderType][1];
-    MoveTo(rct.Left, rct.Bottom - 1);
-    LineTo(rct.Left, rct.Top);
-    LineTo(rct.Right, rct.Top);
-    if BorderType in [btRaised, btLowered] then
-    begin
-      Pen.Color := Colors[BorderType][2];
-      MoveTo(rct.Left + 1, rct.Bottom);
-      LineTo(rct.Left + 1, rct.Top + 1);
-      LineTo(rct.Right, rct.Top + 1);
-      Pen.Color := Colors[BorderType][3];
-      MoveTo(rct.Left + 1, rct.Bottom - 2);
-      LineTo(rct.Right - 2, rct.Bottom - 2);
-      LineTo(rct.Right - 2, rct.Top + 1);
-    end;
-    Pen.Color := Colors[BorderType][4];
-    MoveTo(rct.Left, rct.Bottom - 1);
-    LineTo(rct.Right - 1, rct.Bottom - 1);
-    LineTo(rct.Right - 1, rct.Top);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        EDITOR RECT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.EditorRect: TRect;
-var
-  l, t, r, b: integer;
-begin
-  l := 2;
-  r := Width - 2;
-  t := 2;
-  b := Height - 2;
-  if GutterWidth > 2 then
-    l := l + GutterWidth;
-  if FScrollBars in [ssBoth, ssVertical] then
-    r := r - FScrollBarWidth;
-  if FScrollBars in [ssBoth, ssHorizontal] then
-    b := b - FScrollBarWidth;
-  Result := Rect(l + FMargin, t, r, b);
-end;
-
-//--------------------------------------------------------------
-//        DRAW MARGIN
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DrawMargin;
-var
-  eRect: TRect;
-  i: integer;
-begin
-  eRect := EditorRect;
-  with Canvas do
-  begin
-    Pen.Color := clWhite;
-    for i := 1 to FMargin do
-    begin
-      MoveTo(eRect.Left - i, eRect.Top);
-      LineTo(eRect.Left - i, eRect.Bottom + 1);
-    end;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        DRAW GUTTER
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DrawGutter;
-begin
-  if GutterWidth < 2 then
-    Exit;
-  ResizeGutter;
-  FGutter.PaintTo(Canvas);
-end;
-
-//--------------------------------------------------------------
-//        DRAW SCROLLBARS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.DrawScrollBars;
-begin
-  ResizeScrollBars;
-  if FScrollBars in [ssBoth, ssVertical] then
-    sbVert.PaintTo(Canvas);
-  if FScrollBars in [ssBoth, ssHorizontal] then
-    sbHorz.PaintTo(Canvas);
-  if FScrollBars = ssBoth then
-    with Canvas do
-    begin
-      Brush.Color := clSilver;
-      FillRect(Rect(sbVert.Left, sbHorz.Top + 1,
-        sbVert.Left + sbVert.Width, sbHorz.Top + sbHorz.Height));
-    end;
-end;
-
-//--------------------------------------------------------------
-//        FRESH LINE BITMAP
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.FreshLineBitmap;
-var
-  eRect: TRect;
-begin
-  eRect := EditorRect;
-  with FLineBitmap do
-  begin
-    Width := eRect.Right - eRect.Left;
-    Height := FCellSize.H;
-    FLineBitmap.Canvas.Font.Assign(Self.Canvas.Font);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        PAINT
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.Paint;
-var
-  pTop, pBottom: TFullPos;
-  rct, eRect: TRect;
-  i: integer;
-  clipRgn: HRGN;
-  Attrs: string;
-begin
-  if TGLSMemoStrings(Lines).FLockCount > 0 then
-    Exit;
-  with Canvas do
-  begin
-    if FCellSize.H = 0 then
-      SetFont(FFont);
-    FreshLineBitmap;
-
-    Border(Canvas, Rect(0, 0, Width, Height), btLowered);
-    DrawMargin;
-    DrawGutter;
-    DrawScrollBars;
-
-    eRect := EditorRect;
-    clipRgn := CreateRectRgn(eRect.Left, eRect.Top, eRect.Right, eRect.Bottom);
-    ExtSelectClipRgn(Canvas.Handle, clipRgn, RGN_AND);
-    DeleteObject(clipRgn);
-
-    rct := Canvas.ClipRect;
-    pTop := CharFromPos(rct.Left, rct.Top);
-    pBottom := CharFromPos(rct.Left, rct.Bottom);
-
-    if Assigned(FOnGetLineAttrs) then
-      for i := 0 to Lines.Count - 1 do
-        if not ValidAttrs[i] then
-        begin
-          FOnGetLineAttrs(Self, i, Attrs);
-          CharAttrs[i] := Attrs;
-          ValidAttrs[i] := True;
-        end;
-
-    for i := pTop.LineNo to pBottom.LineNo do
-      DrawLine(i);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        GET VISIBLE
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.GetVisible(Index: integer): integer;
-var
-  Coord: TFullPos;
-  Cell: TCellPos;
-  eRect: TRect;
-begin
-  eRect := EditorRect;
-  Coord := CharFromPos(eRect.Right - 1, eRect.Bottom - 1);
-  Cell := CellFromPos(eRect.Right - 1, eRect.Bottom - 1);
-  case Index of
-    0: Result := Cell.X;
-    1: Result := Cell.Y;
-    2: Result := Coord.Pos - 1;
-    3: Result := Coord.LineNo - 1;
-  else
-    Result := 0;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        IS LINE VISIBLE
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.IsLineVisible(LineNo: integer): Boolean;
-begin
-  if FCellSize.H = 0 then
-    SetFont(FFont);
-  Result := (FTopLine <= LineNo) and (LineNo <= LastVisibleLine + 1);
-end;
-
-//--------------------------------------------------------------
-//        MAKE VISIBLE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.MakeVisible;
-var
-  Modified: Boolean;
-begin
-  Modified := False;
-  if CurX < FLeftCol then
-  begin
-    FLeftCol := CurX - 2;
-    if FLeftCol < 0 then
-      FLeftCol := 0;
-    Modified := True;
-  end;
-  if CurX > LastVisiblePos then
-  begin
-    if (FScrollBars in [ssBoth, ssHorizontal]) or
-      (ScrollMode = smAuto) then
-    begin
-      FLeftCol := FLeftCol + CurX - LastVisiblePos + 2;
-    end
-    else
-      CurX := LastVisiblePos;
-    Modified := True;
-  end;
-  if CurY < FTopLine then
-  begin
-    FTopLine := CurY;
-    if FTopLine < 0 then
-      FTopLine := 0;
-    Modified := True;
-  end;
-  if CurY > LastVisibleLine then
-  begin
-    if (FScrollBars in [ssBoth, ssVertical]) or
-      (ScrollMode = smAuto) then
-    begin
-      FTopLine := FTopLine + CurY - LastVisibleLine;
-    end
-    else
-      CurY := LastVisibleLine;
-    Modified := True;
-  end;
-  if Modified then
-    Invalidate;
-end;
-
-//--------------------------------------------------------------
-//        RESIZE EDITOR
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ResizeEditor;
-begin
-  ResizeScrollBars;
-  ResizeGutter;
-  MakeVisible;
-  Invalidate;
-end;
-
-//--------------------------------------------------------------
-//        FIND TEXT
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.FindText(Text: string; Options: TFindOptions; Select:
-  Boolean): Boolean;
-var
-  i, p: integer;
-  s1, s0, s: string;
-  //-----------------------------------------------------------
-  function LastPos(const Substr, s: string): integer;
-  var
-    i, j, lenSub: integer;
-  begin
-    Result := 0;
-    lenSub := Length(Substr);
-    i := Length(s) - lenSub + 1;
-    while i > 0 do
-    begin
-      if s[i] = Substr[1] then
-      begin
-        Result := i;
-        for j := i + 1 to i + lenSub - 1 do
-          if s[j] <> Substr[j - i + 1] then
-          begin
-            Result := 0;
-            break;
-          end;
-      end;
-      if Result <> 0 then
-        break;
-      Dec(i);
-    end;
-  end;
-  //-----------------------------------------------------------
-begin
-  Result := False;
-  if not (frMatchCase in Options) then
-    Text := AnsiLowerCase(Text);
-
-  if SelLength > 0 then
-    ClearSelection;
-  s := Lines[CurY];
-  s0 := Copy(s, 1, CurX);
-  s1 := Copy(s, CurX + 1, Length(s));
-  i := CurY;
-
-  while True do
-  begin
-
-    if not (frMatchCase in Options) then
-    begin
-      s0 := AnsiLowerCase(s0);
-      s1 := AnsiLowerCase(s1);
-    end;
-
-    if frDown in Options then
-      p := Pos(Text, s1)
-    else
-      p := LastPos(Text, s0);
-
-    if p > 0 then
-    begin
-      Result := True;
-      CurY := i;
-      if frDown in Options then
-        CurX := Length(s0) + p - 1
-      else
-        CurX := p - 1;
-      if Select then
-      begin
-        if not (frDown in Options) then
-          CurX := CurX + Length(Text);
-        ClearSelection;
-        if frDown in Options then
-          CurX := CurX + Length(Text)
-        else
-          CurX := CurX - Length(Text);
-        ExpandSelection;
-      end;
-      break;
-    end;
-
-    if frDown in Options then
-      Inc(i)
-    else
-      Dec(i);
-    if (i < 0) or (i > Lines.Count - 1) then
-      break;
-    if frDown in Options then
-    begin
-      s0 := '';
-      s1 := Lines[i];
-    end
-    else
-    begin
-      s0 := Lines[i];
-      s1 := '';
-    end;
-
-  end;
-
-end;
-
-//--------------------------------------------------------------
-//        RESIZE SCROLLBARS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ResizeScrollBars;
-var
-  eRect, sbRect: TRect;
-  MaxLen, OldMax, NewTop, Margin: integer;
-begin
-  eRect := EditorRect;
-  if FScrollBars in [ssBoth, ssVertical] then
-  begin
-    with sbVert do
-    begin
-      Width := 16;
-      Height := eRect.Bottom - eRect.Top + 1;
-      Left := eRect.Right;
-      Top := eRect.Top;
-      OldMax := MaxPosition;
-      MaxPosition := (Lines.Count - 1) - (LastVisibleLine - FTopLine);
-      NewTop := FTopLine;
-      if (FTopLine > 0) and (LastVisibleLine > Lines.Count - 1) then
-      begin
-        Dec(NewTop, LastVisibleLine - (Lines.Count - 1));
-        if NewTop < 0 then
-          NewTop := 0;
-        MaxPosition := NewTop;
-      end;
-      if MaxPosition < 0 then
-        MaxPosition := 0;
-      Position := NewTop;
-      Total := Lines.Count;
-      if OldMax <> MaxPosition then
-      begin
-        if NewTop <> FTopLine then
-        begin
-          DoScroll(sbVert, NewTop - FTopLine);
-          FGutter.Invalidate;
-        end;
-        sbRect := sbVert.FullRect;
-        InvalidateRect(Handle, @sbRect, True);
-      end;
-    end;
-  end;
-  if FScrollBars in [ssBoth, ssHorizontal] then
-  begin
-    MaxLen := MaxLength;
-    with sbHorz do
-    begin
-      Width := Self.Width - 4;
-      if FScrollBars = ssBoth then
-        Width := Width - sbVert.Width;
-      Height := 16;
-      Left := 2;
-      Top := eRect.Bottom;
-      OldMax := MaxPosition;
-
-      Margin := LastVisiblePos - MaxLen;
-      if Margin < 2 then
-        Margin := 2;
-      MaxPosition := MaxLen - (LastVisiblePos - FLeftCol) + Margin;
-
-      if MaxPosition < 0 then
-        MaxPosition := 0;
-      Position := FLeftCol;
-      Total := MaxLen;
-      if OldMax <> MaxPosition then
-      begin
-        if MaxPosition = 0 then
-        begin
-          FLeftCol := 0;
-          InvalidateRect(Handle, @eRect, True);
-          ;
-          FGutter.Invalidate;
-        end;
-        sbRect := sbHorz.FullRect;
-        InvalidateRect(Handle, @sbRect, True);
-      end;
-    end;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        RESIZE GUTTER
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ResizeGutter;
-var
-  eRect: TRect;
-begin
-  eRect := EditorRect;
-  with FGutter do
-  begin
-    Height := eRect.Bottom - eRect.Top;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        CREATE PARAMS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.CreateParams(var Params: TCreateParams);
-begin
-  inherited;
-end;
-
-//--------------------------------------------------------------
-//        UNDO, REDO
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.Undo;
-begin
-  FUndoList.Undo;
-end;
-
-procedure TGLSCustomMemo.Redo;
-begin
-  FUndoList.Redo;
-end;
-
-//--------------------------------------------------------------
-//        SET UNDO LIMIT
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetUndoLimit(Value: integer);
-begin
-  if (FUndoLimit <> Value) then
-  begin
-    if Value <= 0 then
-      Value := 1;
-    if Value > 100 then
-      Value := 100;
-    FUndoLimit := Value;
-    FUndoList.Limit := Value;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        UNDO (REDO) CHANGE
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.UndoChange;
-begin
-  if Assigned(FOnUndoChange) then
-    FOnUndoChange(Self, FUndoList.Pos < FUndoList.Count,
-      FUndoList.Pos > 0);
-end;
-
-//--------------------------------------------------------------
-//        CAN UNDO
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.CanUndo: boolean;
-begin
-  Result := FUndoList.FPos < FUndoList.Count;
-end;
-
-//--------------------------------------------------------------
-//        CAN REDO
-//--------------------------------------------------------------
-
-function TGLSCustomMemo.CanRedo: Boolean;
-begin
-  Result := FUndoList.FPos > 0;
-end;
-
-//--------------------------------------------------------------
-//        CLEAR UNDO LIST
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.ClearUndoList;
-begin
-  if Assigned(FUndoList) then
-    FUndoList.Clear;
-end;
-
-//--------------------------------------------------------------
-//        SET SCROLL BARS
-//--------------------------------------------------------------
-
-procedure TGLSCustomMemo.SetScrollBars(Value: System.UITypes.TScrollStyle);
-begin
-  if FScrollBars <> Value then
-  begin
-    FScrollBars := Value;
-    if not (csLoading in ComponentState) then
-      ResizeEditor;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        CREATE
-//--------------------------------------------------------------
-
-constructor TGLSCustomMemo.Create(AOwner: TComponent);
-begin
-  inherited;
-
-  ControlStyle := [csCaptureMouse, csClickEvents,
-    csDoubleClicks, csReplicatable];
-  Width := 100;
-  Height := 40;
-  TabStop := True;
-  Cursor := crIBeam;
-
-  FFont := TFont.Create;
-  FFont.Name := 'Courier New';
-  FFont.Size := 10;
-  Canvas.Font.Assign(FFont);
-
-  FHiddenCaret := False;
-  FCaretVisible := False;
-
-  FCurX := 0;
-  FCurY := 0;
-  FLeftCol := 0;
-  FTopLine := 0;
-  FTabSize := 4;
-  FMargin := 2;
-  FAutoIndent := True;
-  FLines := TGLSMemoStrings.Create;
-  TGLSMemoStrings(FLines).FMemo := Self;
-
-  FScrollBars := ssBoth;
-  FScrollBarWidth := 16;
-  sbVert := TGLSMemoScrollBar.Create(Self, sbVertical);
-  sbVert.Width := FScrollBarWidth;
-  sbHorz := TGLSMemoScrollBar.Create(Self, sbHorizontal);
-  sbHorz.Height := FScrollBarWidth;
-
-  FGutter := TGLSMemoGutter.Create;
-  with FGutter do
-  begin
-    FLeft := 2;
-    FTop := 2;
-    FWidth := 0;
-    FHeight := 0;
-    FColor := clBtnFace;
-    FMemo := Self;
-  end;
-
-  FSelStartX := 0;
-  FSelStartY := 0;
-  FSelEndX := 0;
-  FSelEndY := 0;
-
-  FBkColor := clWhite;
-  FSelColor := clWhite;
-  FSelBkColor := clNavy;
-
-  FStyles := TStyleList.Create;
-  FStyles.Add(clBlack, clWhite, []);
-
-  FSelCharPos.LineNo := -1;
-  FSelCharPos.Pos := -1;
-  FSelCharStyle := -1;
-
-  FLineBitmap := TBitmap.Create;
-
-  FLeftButtonDown := False;
-  FScrollMode := smAuto;
-
-  FUndoList := TGLSMemoUndoList.Create;
-  FFirstUndoList := FUndoList;
-  FUndoList.Memo := Self;
-
-  FUndoLimit := 100;
-
-  TGLSMemoStrings(FLines).DoAdd('');
-
-  FAfterDoubleClick := False;
-
-end;
-
-//--------------------------------------------------------------
-//        DESTROY
-//--------------------------------------------------------------
-
-destructor TGLSCustomMemo.Destroy;
-begin
-  FFont.Free;
-  FLines.Free;
-  FGutter.Free;
-  sbVert.Free;
-  sbHorz.Free;
-  FStyles.Free;
-  FLineBitmap.Free;
-  FFirstUndoList.Free;
-  inherited;
-end;
-
- 
-
-// ---------------------TGLSMemoScrollBar functions 
-
-procedure TGLSMemoScrollBar.SetParams(Index: integer; Value: integer);
-begin
-  case Index of
-    0: if Left <> Value then
-        FLeft := Value;
-    1: if Top <> Value then
-        FTop := Value;
-    2: if Width <> Value then
-        FWidth := Value;
-    3: if Height <> Value then
-        FHeight := Value;
-    4: if Total <> Value then
-        FTotal := Value;
-    5: if MaxPosition <> Value then
-        FMaxPosition := Value;
-    6: if Position <> Value then
-        FPosition := Value;
-  end;
-end;
-//-------------------- CREATE ------------------------------
-
-constructor TGLSMemoScrollBar.Create(AParent: TGLSMemoAbstractScrollableObject;
-  AKind: TScrollBarKind);
-begin
-  FParent := AParent;
-  FButtonLength := 16;
-  FKind := AKind;
-  FState := sbsWait;
-end;
-//-------------------- RECT -----------------------
-
-function TGLSMemoScrollBar.GetRect: TRect;
-begin
-  Result := Rect(Left, Top, Left + Width, Top + Height);
-end;
-//-------------------- GET THUMB RECT -----------------------
-
-function TGLSMemoScrollBar.GetThumbRect: TRect;
-var
-  TotalLen, FreeLen, ThumbLen, ThumbOffset, ThumbCoord: integer;
-  K: double;
-begin
-  if MaxPosition <= 0 then
-  begin
-    Result := Rect(0, 0, 0, 0);
-    Exit;
-  end;
-  if Kind = sbVertical then
-    TotalLen := Height
-  else
-    TotalLen := Width;
-  FreeLen := TotalLen - 2 * FButtonLength;
-
-  K := (Total - MaxPosition) / MaxPosition;
-  if K > 0 then
-  begin
-    ThumbLen := round(FreeLen * K / (1 + K));
-    if ThumbLen < 8 then
-      ThumbLen := 8;
-  end
-  else
-    ThumbLen := 8;
-
-  if ThumbLen >= FreeLen then
-    Result := Rect(0, 0, 0, 0)
-  else
-  begin
-    ThumbOffset := round((FreeLen - ThumbLen) * Position / MaxPosition);
-    ThumbCoord := FButtonLength + ThumbOffset;
-    if Kind = sbVertical then
-      Result := Rect(Left + 1, Top + ThumbCoord, Left + Width, Top + ThumbCoord
-        + ThumbLen)
-    else
-      Result := Rect(Left + ThumbCoord, Top + 1, Left + ThumbCoord + ThumbLen,
-        Top + Height);
-  end;
-end;
-//-------------------- GET Back RECT -----------------------
-
-function TGLSMemoScrollBar.GetBackRect: TRect;
-begin
-  if Kind = sbVertical then
-    Result := Rect(Left + 1, Top, Left + Width, Top + FButtonLength)
-  else
-    Result := Rect(Left, Top + 1, Left + FButtonLength, Top + Height);
-end;
-//-------------------- GET MIDDLE RECT -----------------------
-
-function TGLSMemoScrollBar.GetMiddleRect: TRect;
-var
-  bRect, fRect: TRect;
-begin
-  bRect := BackRect;
-  fRect := ForwardRect;
-  if Kind = sbVertical then
-    Result := Rect(Left + 1, bRect.Bottom, Left + Width, fRect.Top)
-  else
-    Result := Rect(bRect.Right, Top + 1, fRect.Left, Top + Height);
-end;
-//-------------------- GET Forward RECT -----------------------
-
-function TGLSMemoScrollBar.GetForwardRect: TRect;
-begin
-  if Kind = sbVertical then
-    Result := Rect(Left + 1, Top + Height - FButtonLength, Left + Width, Top +
-      Height)
-  else
-    Result := Rect(Left + Width - FButtonLength, Top + 1, Left + Width, Top +
-      Height);
-end;
-//-------------------- GET PAGE BACK RECT -----------------------
-
-function TGLSMemoScrollBar.GetPgBackRect: TRect;
-var
-  thRect: TRect;
-begin
-  thRect := GetThumbRect;
-  if thRect.Bottom = 0 then
-  begin
-    Result := Rect(0, 0, 0, 0);
-    Exit;
-  end;
-  if Kind = sbVertical then
-    Result := Rect(Left + 1, Top + FButtonLength, Left + Width, thRect.Top - 1)
-  else
-    Result := Rect(Left + FButtonLength, Top + 1, thRect.Left - 1, Top +
-      Height);
-end;
-//-------------------- GET PG FORWARD RECT -----------------------
-
-function TGLSMemoScrollBar.GetPgForwardRect: TRect;
-var
-  thRect: TRect;
-begin
-  thRect := GetThumbRect;
-  if thRect.Bottom = 0 then
-  begin
-    Result := Rect(0, 0, 0, 0);
-    Exit;
-  end;
-  if Kind = sbVertical then
-    Result := Rect(Left + 1, thRect.Bottom, Left + Width, Top + Height -
-      FButtonLength)
-  else
-    Result := Rect(thRect.Right, Top + 1, Left + Width - FButtonLength, Top +
-      Height);
-end;
-//-------------------- PAINT TO -----------------------
-
-procedure TGLSMemoScrollBar.PaintTo(ACanvas: TCanvas);
-var
-  sRect, mRect, gRect, thRect: TRect;
-  iconX, iconY, shift: integer;
-begin
-  with ACanvas do
-  begin
-    if Kind = sbVertical then
-    begin
-      Pen.Color := clSilver;
-      MoveTo(Left, Top);
-      LineTo(Left, Top + Height);
-
-      sRect := BackRect;
-      Brush.Color := clSilver;
-      FillRect(sRect);
-      if State = sbsBack then
-      begin
-        shift := 1;
-        Pen.Color := clGray;
-        with sRect do
-          Rectangle(Left, Top, Right, Bottom);
-      end
-      else
-      begin
-        shift := 0;
-        Border(ACanvas, sRect, btFlatRaised);
-      end;
-      iconX := sRect.Left + (Width - 1 - 7) div 2;
-      iconY := sRect.Top + (FButtonLength - 8) div 2;
-      Draw(iconX + shift, iconY + shift, bmScrollBarUp);
-
-      gRect := ForwardRect;
-      Brush.Color := clSilver;
-      FillRect(gRect);
-      if State = sbsForward then
-      begin
-        shift := 1;
-        Pen.Color := clGray;
-        with gRect do
-          Rectangle(Left, Top, Right, Bottom);
-      end
-      else
-      begin
-        shift := 0;
-        Border(ACanvas, gRect, btFlatRaised);
-      end;
-      iconX := gRect.Left + (Width - 1 - 7) div 2;
-      iconY := gRect.Top + (FButtonLength - 8) div 2;
-      Draw(iconX + shift, iconY + shift, bmScrollBarDown);
-
-      mRect := Rect(sRect.Left, sRect.Bottom, gRect.Right, gRect.Top);
-    end
-    else
-    begin
-      Pen.Color := clSilver;
-      MoveTo(Left, Top);
-      LineTo(Left + Width, Top);
-
-      sRect := BackRect;
-      Brush.Color := clSilver;
-      FillRect(sRect);
-      if State = sbsBack then
-      begin
-        shift := 1;
-        Pen.Color := clGray;
-        with sRect do
-          Rectangle(Left, Top, Right, Bottom);
-      end
-      else
-      begin
-        shift := 0;
-        Border(ACanvas, sRect, btFlatRaised);
-      end;
-      iconX := sRect.Left + shift + (FButtonLength - 8) div 2;
-      iconY := sRect.Top + shift + (Height - 1 - 7) div 2;
-      Draw(iconX + shift, iconY + shift, bmScrollBarLeft);
-
-      gRect := ForwardRect;
-      Brush.Color := clSilver;
-      FillRect(gRect);
-      if State = sbsForward then
-      begin
-        shift := 1;
-        Pen.Color := clGray;
-        with gRect do
-          Rectangle(Left, Top, Right, Bottom);
-      end
-      else
-      begin
-        shift := 0;
-        Border(ACanvas, gRect, btFlatRaised);
-      end;
-      iconX := gRect.Left + (FButtonLength - 8) div 2;
-      iconY := gRect.Top + (Height - 1 - 7) div 2;
-      Draw(iconX + shift, iconY + shift, bmScrollBarRight);
-
-      mRect := Rect(sRect.Right, sRect.Top, gRect.Left, gRect.Bottom);
-    end;
-
-    Brush.Bitmap := bmScrollBarFill;
-    FillRect(mRect);
-    Brush.Bitmap := nil;
-    if State = sbsPageBack then
-    begin
-      Brush.Color := clGray;
-      FillRect(PageBackRect);
-    end;
-    if State = sbsPageForward then
-    begin
-      Brush.Color := clGray;
-      FillRect(PageForwardRect);
-    end;
-
-    thRect := ThumbRect;
-    Brush.Color := clSilver;
-    FillRect(thRect);
-    Border(ACanvas, thRect, btFlatRaised);
-  end;
-end;
-//-------------------- SET STATE ----------
-
-procedure TGLSMemoScrollBar.SetState(Value: TsbState);
-begin
-  if FState <> Value then
-  begin
-    FState := Value;
-  end;
-end;
-//-------------------- MOUSE DOWN ------------
-
-function TGLSMemoScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
-  X,
-  Y: Integer):
-  Boolean;
-var
-  sRect, gRect, thRect, pbRect, pfRect: TRect;
-begin
-  Result := False;
-  if (Width = 0) or (Height = 0) then
-    Exit;
-  sRect := BackRect;
-  gRect := ForwardRect;
-  pbRect := PageBackRect;
-  pfRect := PageForwardRect;
-  thRect := ThumbRect;
-  if PointInRect(Point(X, Y), sRect) then
-  begin
-    State := sbsBack;
-    InvalidateRect(Parent.Handle, @sRect, True);
-    Result := True;
-    Exit;
-  end;
-  if PointInRect(Point(X, Y), gRect) then
-  begin
-    State := sbsForward;
-    InvalidateRect(Parent.Handle, @gRect, True);
-    Result := True;
-    Exit;
-  end;
-  if PointInRect(Point(X, Y), pbRect) then
-  begin
-    State := sbsPageBack;
-    InvalidateRect(Parent.Handle, @pbRect, True);
-    Result := True;
-    Exit;
-  end;
-  if PointInRect(Point(X, Y), pfRect) then
-  begin
-    State := sbsPageForward;
-    InvalidateRect(Parent.Handle, @pfRect, True);
-    Result := True;
-    Exit;
-  end;
-  if PointInRect(Point(X, Y), thRect) then
-  begin
-    State := sbsDragging;
-    FXOffset := X - thRect.Left;
-    FYOffset := Y - thRect.Top;
-    Result := True;
-    Exit;
-  end;
-
-end;
-//-------------------- MOUSE UP ----------
-
-function TGLSMemoScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
-  Y:
-  Integer):
-  Boolean;
-var
-  sRect, gRect, thRect, pbRect, pfRect: TRect;
-begin
-  Result := False;
-  if (Width = 0) or (Height = 0) then
-    Exit;
-  sRect := BackRect;
-  gRect := ForwardRect;
-  pbRect := PageBackRect;
-  pfRect := PageForwardRect;
-  thRect := ThumbRect;
-  case State of
-    sbsBack:
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @sRect, True);
-        FParent.DoScroll(Self, -1);
-        Result := True;
-        Exit;
-      end;
-    sbsForward:
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @gRect, True);
-        FParent.DoScroll(Self, 1);
-        Result := True;
-        Exit;
-      end;
-    sbsPageBack:
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @pbRect, True);
-        FParent.DoScrollPage(Self, -1);
-        Result := True;
-        Exit;
-      end;
-    sbsPageForward:
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @pfRect, True);
-        FParent.DoScrollPage(Self, 1);
-        Result := True;
-        Exit;
-      end;
-    sbsDragging:
-      begin
-        State := sbsWait;
-        Result := True;
-        Exit;
-      end;
-  end;
-end;
-//-------------------- MOUSE MOVE -----------
-
-function TGLSMemoScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer):
-  Boolean;
-var
-  sRect, gRect, thRect, pbRect, pfRect: TRect;
-begin
-  Result := False;
-  if (Width = 0) or (Height = 0) then
-    Exit;
-  sRect := BackRect;
-  gRect := ForwardRect;
-  pbRect := PageBackRect;
-  pfRect := PageForwardRect;
-  thRect := ThumbRect;
-  case State of
-    sbsBack:
-      if not PointInRect(Point(X, Y), sRect) then
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @sRect, True);
-        Result := True;
-        Exit;
-      end;
-    sbsForward:
-      if not PointInRect(Point(X, Y), gRect) then
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @gRect, True);
-        Result := True;
-        Exit;
-      end;
-    sbsPageBack:
-      if not PointInRect(Point(X, Y), pbRect) then
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @pbRect, True);
-        Result := True;
-        Exit;
-      end;
-    sbsPageForward:
-      if not PointInRect(Point(X, Y), pfRect) then
-      begin
-        State := sbsWait;
-        InvalidateRect(Parent.Handle, @pfRect, True);
-        Result := True;
-        Exit;
-      end;
-    sbsDragging:
-      begin
-        MoveThumbTo(X, Y);
-        Result := True;
-        Exit;
-      end;
-  end;
-end;
-//-------------------- MOVE THUMB TO ------------
-
-function TGLSMemoScrollBar.MoveThumbTo(X, Y: Integer): integer;
-var
-  thRect, mRect: TRect;
-  FreeLen, ThumbLen, NewPosition, NewOffset: integer;
-begin
-  thRect := ThumbRect;
-  mRect := MiddleRect;
-  NewOffset := 0;
-  FreeLen := 0;
-  ThumbLen := 0;
-  case Kind of
-    sbVertical:
-      begin
-        FreeLen := mRect.Bottom - mRect.Top;
-        ThumbLen := thRect.Bottom - thRect.Top;
-        NewOffset := Y - FYOffset - (Top + FButtonLength);
-      end;
-    sbHorizontal:
-      begin
-        FreeLen := mRect.Right - mRect.Left;
-        ThumbLen := thRect.Right - thRect.Left;
-        NewOffset := X - FXOffset - (Left + FButtonLength);
-      end
-  end;
-  NewPosition := round(NewOffset * MaxPosition / (FreeLen - ThumbLen));
-  Result := NewPosition - Position;
-  if NewPosition <> Position then
-  begin
-    Parent.DoScroll(Self, NewPosition - Position);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        GUTTER
-//--------------------------------------------------------------
-//-------------------- SET PARAMS -----------------------
-
-procedure TGLSMemoGutter.SetParams(Index: integer; Value: integer);
-begin
-  case Index of
-    0: FLeft := Value;
-    1: FTop := Value;
-    2: FWidth := Value;
-    3: FHeight := Value;
-  end;
-end;
-//-------------------- PAINT TO -----------------------
-
-procedure TGLSMemoGutter.PaintTo(ACanvas: TCanvas);
-var
-  LineNo, T, H: integer;
-begin
-  with ACanvas do
-  begin
-    Pen.Color := clGray;
-    MoveTo(Left + Width - 1, Top);
-    LineTo(Left + Width - 1, Top + Height);
-    Pen.Color := clWhite;
-    MoveTo(Left + Width - 2, Top);
-    LineTo(Left + Width - 2, Top + Height);
-    Brush.Color := Self.FColor;
-    FillRect(Rect(Left, Top, Left + Width - 2, Top + Height));
-    if Assigned(FMemo.OnGutterDraw) then
-    begin
-      T := Top;
-      H := FMemo.FCellSize.H;
-      LineNo := FMemo.FTopLine;
-      while T < Top + Height do
-      begin
-        FMemo.OnGutterDraw(FMemo, ACanvas, LineNo,
-          Rect(Left, T, Left + Width - 2, T + H));
-        T := T + H;
-        Inc(LineNo);
-        if LineNo >= FMemo.Lines.Count then
-          break;
-      end;
-    end;
-  end;
-end;
-
-//-------------------- INVALIDATE -----------------------
-
-procedure TGLSMemoGutter.Invalidate;
-var
-  gRect: TRect;
-begin
-  gRect := Rect(Left, Top, Left + Width, Top + Height);
-  InvalidateRect(FMemo.Handle, @gRect, True);
-end;
-
-//-------------------- GET RECT -----------------------
-
-function TGLSMemoGutter.GetRect: TRect;
-begin
-  Result := Rect(Left, Top, Left + Width, Top + Height);
-end;
-
- 
-
-// ---------------------TStyleList 
-
-procedure TStyleList.CheckRange(Index: integer);
-begin
-  if (Index < 0) or (Index >= Count) then
-    raise EListError.Create('Incorrect list item index ' + IntToStr(Index));
-end;
-//-------------------- DESTROY ---------------------------
-
-destructor TStyleList.Destroy;
-begin
-  Clear;
-  inherited;
-end;
-//-------------------- CHANGE ---------------------------
-
-procedure TStyleList.Change(Index: integer; ATextColor, ABkCOlor: TColor;
-  AStyle: TFontStyles);
-var
-  P: TCharStyle;
-begin
-  CheckRange(Index);
-  P := TCharStyle(Items[Index]);
-  P.TextColor := ATextColor;
-  P.BkColor := ABkColor;
-  P.Style := AStyle;
-end;
-//-------------------- ADD ---------------------------
-
-function TStyleList.Add(ATextColor, ABkColor: TColor; AStyle: TFontStyles):
-  Integer;
-var
-  P: TCharStyle;
-begin
-  P := TCharStyle.Create;
-  with P do
-  begin
-    TextColor := ATextColor;
-    BkColor := ABkColor;
-    Style := AStyle;
-  end;
-  Result := inherited Add(P);
-end;
-//-------------------- CLEAR ---------------------------
-
-procedure TStyleList.Clear;
-begin
-  while Count > 0 do
-    Delete(0);
-end;
-//-------------------- DELETE ---------------------------
-
-procedure TStyleList.Delete(Index: Integer);
-var
-  P: TCharStyle;
-begin
-  CheckRange(Index);
-  P := TCharStyle(Items[Index]);
-  P.Free;
-  inherited;
-end;
-//-------------------- GET/SET TEXT COLOR ---------------------------
-
-function TStyleList.GetTextColor(Index: Integer): TColor;
-begin
-  CheckRange(Index);
-  Result := TCharStyle(Items[Index]).TextColor;
-end;
-
-procedure TStyleList.SetTextColor(Index: Integer; Value: TColor);
-begin
-  CheckRange(Index);
-  TCharStyle(Items[Index]).TextColor := Value;
-end;
-//-------------------- GET/SET BK COLOR ---------------------------
-
-function TStyleList.GetBkColor(Index: Integer): TColor;
-begin
-  CheckRange(Index);
-  Result := TCharStyle(Items[Index]).BkColor;
-end;
-
-procedure TStyleList.SetBkColor(Index: Integer; Value: TColor);
-begin
-  CheckRange(Index);
-  TCharStyle(Items[Index]).BkColor := Value;
-end;
-//-------------------- GET/SET STYLE ---------------------------
-
-function TStyleList.GetStyle(Index: Integer): TFontStyles;
-begin
-  CheckRange(Index);
-  Result := TCharStyle(Items[Index]).Style;
-end;
-
-procedure TStyleList.SetStyle(Index: Integer; Value: TFontStyles);
-begin
-  CheckRange(Index);
-  TCharStyle(Items[Index]).Style := Value;
-end;
-
- 
-
-// ---------------------TGLSMemoStrings 
-
-destructor TGLSMemoStrings.Destroy;
-var
-  P: TObject;
-begin
-  while Count > 0 do
-  begin
-    P := inherited GetObject(0);
-    P.Free;
-    inherited Delete(0);
-  end;
-  inherited;
-end;
-//-------------------- CLEAR ----------------------
-
-procedure TGLSMemoStrings.Clear;
-begin
-  while Count > 0 do
-  begin
-    Delete(0);
-    if (Count = 1) and (Strings[0] = '') then
-      break;
-  end;
-end;
-
-//-------------------- ASSIGN ----------------------
-
-procedure TGLSMemoStrings.Assign(Source: TPersistent);
-var
-  P: TObject;
-begin
-  if Source is TStrings then
-  begin
-    BeginUpdate;
-    try
-      while Count > 0 do
-      begin
-        P := inherited GetObject(0);
-        P.Free;
-        inherited Delete(0);
-      end;
-      //      inherited Clear;
-      AddStrings(TStrings(Source));
-    finally
-      EndUpdate;
-    end;
-    Exit;
-  end;
-  inherited Assign(Source);
-end;
-
-//-------------------- ADD ----------------------
-
-function TGLSMemoStrings.DoAdd(const S: string): Integer;
-begin
-  Result := inherited AddObject(S, nil);
-end;
-//-------------------- ADD ----------------------
-
-function TGLSMemoStrings.Add(const S: string): Integer;
-begin
-  if Assigned(FMemo.Parent) then
-    Result := FMemo.AddString(S)
-  else
-    Result := DoAdd(S);
-end;
-//-------------------- OBJECT ----------------------
-
-function TGLSMemoStrings.AddObject(const S: string; AObject: TObject): Integer;
-begin
-  if AObject <> nil then
-    raise EInvalidOp.Create(SObjectsNotSupported);
-  Result := DoAdd(S);
-end;
-//-------------------- INSERT ----------------------
-
-procedure TGLSMemoStrings.InsertObject(Index: Integer;
-  const S: string; AObject: TObject);
-begin
-  if AObject <> nil then
-    raise EInvalidOp.Create(SObjectsNotSupported);
-  DoInsert(Index, S);
-end;
-//-------------------- DO INSERT ----------------------
-
-procedure TGLSMemoStrings.DoInsert(Index: Integer; const S: string);
-begin
-  InsertItem(Index, S, nil);
-end;
-//-------------------- INSERT ----------------------
-
-procedure TGLSMemoStrings.Insert(Index: Integer; const S: string);
-begin
-  if Assigned(FMemo) then
-    FMemo.InsertString(Index, S)
-  else
-    DoInsert(Index, S);
-end;
-//-------------------- DELETE ----------------------
-
-procedure TGLSMemoStrings.Delete(Index: Integer);
-var
-  P: TObject;
-begin
-  if (Index < 0) or (Index > Count - 1) then
-    Exit;
-  if FDeleting or (not Assigned(FMemo)) then
-  begin
-    P := inherited GetObject(Index);
-    P.Free;
-    inherited;
-  end
-  else
-  begin
-    FMemo.DeleteLine(Index, -1, -1, -1, -1, True);
-  end;
-end;
-//-------------------- LOAD FROM FILE ----------------------
-
-procedure TGLSMemoStrings.LoadFromFile(const FileName: string);
-begin
-  with FMemo do
-  begin
-    ClearSelection;
-    ClearUndoList;
-    CurX := 0;
-    CurY := 0;
-  end;
-  Clear;
-  inherited;
-  FMemo.Invalidate;
-end;
-//-------------------- SET UPDATE STATE ----------------------
-
-procedure TGLSMemoStrings.SetUpdateState(Updating: Boolean);
-begin
-  if Updating then
-    Inc(FLockCount)
-  else if FLockCount > 0 then
-    Dec(FLockCount);
-end;
-//-------------------- CHECK RANGE ---------------------------
-
-procedure TGLSMemoStrings.CheckRange(Index: integer);
-begin
-  if (Index < 0) or (Index >= Count) then
-    raise EListError('Incorrect index of list item ' + IntToStr(Index));
-end;
-//-------------------- GET OBJECT ---------------------------
-
-function TGLSMemoStrings.GetObject(Index: Integer): TObject;
-begin
-  CheckRange(Index);
-  Result := inherited GetObject(Index);
-  if Assigned(Result) and (Result is TLineProp) then
-    Result := TLineProp(Result).FObject;
-end;
-//-------------------- PUT OBJECT ---------------------------
-
-procedure TGLSMemoStrings.PutObject(Index: Integer; AObject: TObject);
-var
-  P: TObject;
-begin
-  CheckRange(Index);
-  P := Objects[Index];
-  if Assigned(P) and (P is TLineProp) then
-    TLineProp(P).FObject := AObject
-  else
-    inherited PutObject(Index, AObject);
-end;
-//-------------------- GET LINE PROP ---------------------------
-
-function TGLSMemoStrings.GetLineProp(Index: integer): TLineProp;
-var
-  P: TObject;
-begin
-  CheckRange(Index);
-  Result := nil;
-  P := inherited GetObject(Index);
-  if Assigned(P) and (P is TLineProp) then
-    Result := TLineProp(P);
-end;
-
-//-------------------- CREATE PROP --------------------------
-
-function TGLSMemoStrings.CreateProp(Index: integer): TLineProp;
-begin
-  Result := TLineProp.Create;
-  with Result do
-  begin
-    FStyleNo := 0;
-    FInComment := False;
-    FInBrackets := -1;
-    FValidAttrs := False;
-    FCharAttrs := '';
-    FObject := Objects[Index];
-  end;
-  inherited PutObject(Index, Result);
-end;
-
-//-------------------- GET LINE STYLE --------------------------
-
-function TGLSMemoStrings.GetLineStyle(Index: integer): integer;
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    Result := 0
-  else
-    Result := P.FStyleNo;
-end;
-
-//-------------------- SET LINE STYLE --------------------------
-
-procedure TGLSMemoStrings.SetLineStyle(Index: integer; Value: integer);
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    P := CreateProp(Index);
-  P.FStyleNo := Value;
-end;
-
-//-------------------- GET/SET IN COMMENT ---------------------------
-
-function TGLSMemoStrings.GetInComment(Index: Integer): Boolean;
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    Result := False
-  else
-    Result := P.FInComment;
-end;
-
-procedure TGLSMemoStrings.SetInComment(Index: Integer; Value: Boolean);
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    P := CreateProp(Index);
-  P.FInComment := Value;
-end;
-
-//-------------------- GET/SET IN BRACKETS ---------------------------
-
-function TGLSMemoStrings.GetInBrackets(Index: Integer): integer;
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    Result := -1
-  else
-    Result := P.FInBrackets;
-end;
-
-procedure TGLSMemoStrings.SetInBrackets(Index: Integer; Value: integer);
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    P := CreateProp(Index);
-  P.FInBrackets := Value;
-end;
-
-//-------------------- GET/SET VALID ATTRS ---------------------------
-
-function TGLSMemoStrings.GetValidAttrs(Index: Integer): Boolean;
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    Result := False
-  else
-    Result := P.FValidAttrs;
-end;
-
-procedure TGLSMemoStrings.SetValidAttrs(Index: Integer; Value: Boolean);
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    P := CreateProp(Index);
-  P.FValidAttrs := Value;
-end;
-//-------------------- GET/SET CHAR ATTRS ---------------------------
-
-function TGLSMemoStrings.GetCharAttrs(Index: Integer): string;
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    Result := ''
-  else
-    Result := P.FCharAttrs;
-end;
-
-procedure TGLSMemoStrings.SetCharAttrs(Index: Integer; const Value: string);
-var
-  P: TLineProp;
-begin
-  P := LineProp[Index];
-  if P = nil then
-    P := CreateProp(Index);
-  P.FCharAttrs := Value;
-end;
-
- 
-
-// ---------------------TGLSMemoUndo 
-
-constructor TGLSMemoUndo.Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
-  string);
-begin
-  inherited Create;
-  FUndoCurX0 := ACurX0;
-  FUndoCurY0 := ACurY0;
-  FUndoCurX := ACurX;
-  FUndoCurY := ACurY;
-  FUndoText := AText;
-end;
-
-procedure TGLSMemoUndo.Undo;
-begin
-  if Assigned(FMemo) then
-    with FMemo do
-    begin
-      CurY := FUndoCurY;
-      CurX := FUndoCurX;
-      PerformUndo;
-      CurY := FUndoCurY0;
-      CurX := FUndoCurX0;
-    end;
-end;
-
-procedure TGLSMemoUndo.Redo;
-begin
-  if Assigned(FMemo) then
-    with FMemo do
-    begin
-      CurY := FUndoCurY0;
-      CurX := FUndoCurX0;
-      PerformRedo;
-      CurY := FUndoCurY;
-      CurX := FUndoCurX;
-    end;
-end;
-
-function TGLSMemoUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
-begin
-  Result := False;
-end;
-
-//----------------  TINSERT CHAR UNDO --------------------------
-
-procedure TGLSMemoInsCharUndo.PerformUndo;
-var
-  i: integer;
-  CurrLine: string;
-begin
-  for i := Length(FUndoText) downto 1 do
-  begin
-    CurrLine := FMemo.Lines[FMemo.CurY];
-    if ((FUndoText[i] = #13) and (FMemo.CurX = 0)) or
-      (FUndoText[i] = CurrLine[FMemo.CurX]) then
-      FMemo.BackSpace;
-  end;
-end;
-
-procedure TGLSMemoInsCharUndo.PerformRedo;
-var
-  i: integer;
-begin
-  with FMemo do
-    for i := 1 to Length(FUndoText) do
-      if FUndoText[i] = #13 then
-        NewLine
-      else
-        InsertChar(FUndoText[i]);
-end;
-
-function TGLSMemoInsCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
-begin
-  Result := False;
-  if not ((NewUndo is TGLSMemoInsCharUndo) and
-    (NewUndo.UndoCurX0 = FUndoCurX) and
-    (NewUndo.UndoCurY0 = FUndoCurY)) then
-    Exit;
-  FUndoText := FUndoText + NewUndo.FUndoText;
-  FUndoCurX := NewUndo.UndoCurX;
-  FUndoCurY := NewUndo.UndoCurY;
-  Result := True;
-end;
-
-//----------------  TDELETE CHAR UNDO --------------------------
-
-procedure TGLSMemoDelCharUndo.PerformUndo;
-var
-  i: integer;
-begin
-  with FMemo do
-    for i := 1 to Length(FUndoText) do
-    begin
-      if not FIsBackspace then
-      begin
-        CurY := FUndoCurY0;
-        CurX := FUndoCurX0;
-      end;
-      if FUndoText[i] = #13 then
-        NewLine
-      else
-        InsertChar(FUndoText[i]);
-    end;
-end;
-
-procedure TGLSMemoDelCharUndo.PerformRedo;
-var
-  i: integer;
-begin
-  with FMemo do
-    for i := 1 to Length(FUndoText) do
-      if FIsBackspace then
-        BackSpace
-      else
-        DeleteChar(-1, -1);
-end;
-
-function TGLSMemoDelCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
-begin
-  Result := False;
-  if not ((NewUndo is TGLSMemoDelCharUndo) and
-    (NewUndo.UndoCurX0 = FUndoCurX) and
-    (NewUndo.UndoCurY0 = FUndoCurY)) then
-    Exit;
-  if TGLSMemoDelCharUndo(NewUndo).FIsBackspace <> FIsBackspace then
-    Exit;
-  FUndoText := NewUndo.FUndoText + FUndoText;
-  FUndoCurX := NewUndo.UndoCurX;
-  FUndoCurY := NewUndo.UndoCurY;
-  Result := True;
-end;
-
-//----------------  TDELETE BUF, LINE UNDO --------------------------
-
-constructor TGLSMemoDelLineUndo.Create(AIndex, ACurX0, ACurY0, ACurX, ACurY:
-  integer; const AText: string);
-begin
-  inherited Create(ACurX0, ACurY0, ACurX, ACurY, AText);
-  FIndex := AIndex;
-end;
-
-procedure TGLSMemoDelLineUndo.PerformUndo;
-var
-  SaveCurX: integer;
-begin
-  with FMemo do
-  begin
-    SaveCurX := CurX;
-    CurX := 0;
-    ClearSelection;
-    SetSelText(PChar(FUndoText + #13#10));
-    CurX := SaveCurX;
-  end;
-end;
-
-procedure TGLSMemoDelLineUndo.PerformRedo;
-begin
-  FMemo.DeleteLine(FIndex, FUndoCurX0, FUndoCurY0, FUndoCurX, FUndoCurY, True);
-end;
-
-procedure TGLSMemoDeleteBufUndo.PerformUndo;
-begin
-  with FMemo do
-  begin
-    ClearSelection;
-    SetSelText(PChar(FUndoText));
-  end;
-end;
-
-procedure TGLSMemoDeleteBufUndo.PerformRedo;
-begin
-  with FMemo do
-  begin
-    FSelStartX := FUndoSelStartX;
-    FSelStartY := FUndoSelStartY;
-    FSelEndX := FUndoSelEndX;
-    FSelEndY := FUndoSelEndY;
-    DeleteSelection(True);
-  end;
-end;
-
-//----------------  TPASTE UNDO --------------------------
-
-procedure TGLSMemoPasteUndo.PerformUndo;
-begin
-  with FMemo do
-  begin
-    FSelStartX := FUndoCurX0;
-    FSelStartY := FUndoCurY0;
-    FSelEndX := FUndoCurX;
-    FSelEndY := FUndoCurY;
-    DeleteSelection(True);
-  end;
-end;
-
-procedure TGLSMemoPasteUndo.PerformRedo;
-begin
-  with FMemo do
-  begin
-    ClearSelection;
-    SetSelText(PChar(FUndoText));
-  end;
-end;
-
-//----------------  TUNDO LIST --------------------------
-
-constructor TGLSMemoUndoList.Create;
-begin
-  inherited;
-  FPos := 0;
-  FIsPerforming := False;
-  FLimit := 100;
-end;
-
-destructor TGLSMemoUndoList.Destroy;
-begin
-  Clear;
-  inherited;
-end;
-
-function TGLSMemoUndoList.Get(Index: Integer): TGLSMemoUndo;
-begin
-  Result := TGLSMemoUndo(inherited Get(Index));
-end;
-
-function TGLSMemoUndoList.Add(Item: Pointer): Integer;
-begin
-  Result := -1;
-  if FIsPerforming then
-  begin
-    TGLSMemoUndo(Item).Free;
-    Exit;
-  end;
-
-  if (Count > 0) and
-    Items[0].Append(TGLSMemoUndo(Item)) then
-  begin
-    TGLSMemoUndo(Item).Free;
-    Exit;
-  end;
-
-  TGLSMemoUndo(Item).FMemo := Self.FMemo;
-  if FPos > 0 then
-    while FPos > 0 do
-    begin
-      Delete(0);
-      Dec(FPos);
-    end;
-  Insert(0, Item);
-  if Count > FLimit then
-    Delete(Count - 1);
-  Memo.UndoChange;
-  Result := 0;
-end;
-
-procedure TGLSMemoUndoList.Clear;
-begin
-  while Count > 0 do
-    Delete(0);
-  FPos := 0;
-  with Memo do
-    if not (csDestroying in ComponentState) then
-      UndoChange;
-end;
-
-procedure TGLSMemoUndoList.Delete(Index: Integer);
-begin
-  TGLSMemoUndo(Items[Index]).Free;
-  inherited;
-end;
-
-procedure TGLSMemoUndoList.Undo;
-var
-  OldAutoIndent: Boolean;
-begin
-  if FPos < Count then
-  begin
-    OldAutoIndent := Memo.AutoIndent;
-    Memo.AutoIndent := False;
-    FIsPerforming := True;
-    Items[FPos].Undo;
-    Inc(FPos);
-    FIsPerforming := False;
-    Memo.AutoIndent := OldAutoIndent;
-    Memo.UndoChange;
-  end;
-end;
-
-procedure TGLSMemoUndoList.Redo;
-var
-  OldAutoIndent: Boolean;
-begin
-  if FPos > 0 then
-  begin
-    OldAutoIndent := Memo.AutoIndent;
-    Memo.AutoIndent := False;
-    FIsPerforming := True;
-    Dec(FPos);
-    Items[FPos].Redo;
-    FIsPerforming := False;
-    Memo.AutoIndent := OldAutoIndent;
-    Memo.UndoChange;
-  end;
-end;
-
-procedure TGLSMemoUndoList.SetLimit(Value: integer);
-begin
-  if FLimit <> Value then
-  begin
-    if Value <= 0 then
-      Value := 10;
-    if Value > 0 then
-      Value := 100;
-    FLimit := Value;
-    Clear;
-  end;
-end;
-
-procedure TGLSSynHiMemo.Paint;
-begin
-  FIsPainting := True;
-  try
-    DelimiterStyle := FDelimiterStyle;
-    CommentStyle := FCommentStyle;
-    NumberStyle := FNumberStyle;
-    inherited;
-  finally
-    FIsPainting := False;
-  end;
-end;
-
- 
-
-// ---------------------TGLSSynHiMemo 
-
-procedure TGLSSynHiMemo.SetStyle(Index: integer; Value: TCharStyle);
-var
-  No: integer;
-  eRect: TRect;
-begin
-  No := -1;
-  case Index of
-    0: No := FDelimiterStyleNo;
-    1: No := FCommentStyleNo;
-    2: No := FNumberStyleNo;
-  end;
-  with Value do
-    Styles.Change(No, TextColor, BkColor, Style);
-  if not FIsPainting then
-  begin
-    eRect := EditorRect;
-    InvalidateRect(Handle, @eRect, True);
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - SET WORD LIST
-//--------------------------------------------------------------
-
-procedure TGLSSynHiMemo.SetWordList(Value: TGLSMemoStringList);
-begin
-  FWordList.Assign(Value);
-end;
-
-procedure TGLSSynHiMemo.SetSpecialList(Value: TGLSMemoStringList);
-begin
-  FSpecialList.Assign(Value);
-end;
-
-procedure TGLSSynHiMemo.SetBracketList(Value: TGLSMemoStringList);
-begin
-  FBracketList.Assign(Value);
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - SET CASE SENSITIVE
-//--------------------------------------------------------------
-
-procedure TGLSSynHiMemo.SetCaseSensitive(Value: Boolean);
-var
-  LineNo: integer;
-begin
-  if Value <> FCaseSensitive then
-  begin
-    FCaseSensitive := Value;
-    for LineNo := 0 to Lines.Count - 1 do
-      ValidAttrs[LineNo] := False;
-    Invalidate;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - GET TOKEN
-//--------------------------------------------------------------
-
-function TGLSSynHiMemo.GetToken(const S: string; var From: integer;
-  out TokenType: TTokenType; out StyleNo: integer): string;
-var
-  i, toStart, toEnd, Len, LenSpec: integer;
-  Done: Boolean;
-  Brackets: string;
-  IntPart: integer;
-  WasPoint: Boolean;
-  //-------------------------------------------------------------
-  function StartsFrom(const S: string; Pos: integer; const S0: string): Boolean;
-  begin
-    Result := (StrLComp(PChar(S) + Pos - 1, PChar(S0), Length(S0)) = 0);
-  end;
-  //-------------------------------------------------------------
-  function Equal(const s1, s2: string): Boolean;
-  begin
-    if FCaseSensitive then
-      Result := s1 = s2
-    else
-      Result := AnsiLowerCase(s1) = AnsiLowerCase(s2);
-  end;
-begin
-  toStart := From;
-  toEnd := From;
-  TokenType := ttOther;
-  StyleNo := 0;
-  Len := Length(S);
-  // End of line
-  if From > Len then
-  begin
-    From := -1;
-    Result := '';
-    TokenType := ttEOL;
-    StyleNo := 0;
-    Exit;
-  end;
-  // Begin of multiline comment
-  if (MultiCommentLeft <> '') and (MultiCommentRight <> '') and
-    StartsFrom(S, From, MultiCommentLeft) then
-  begin
-    Result := MultiCommentLeft;
-    FInComment := True;
-    TokenType := ttComment;
-    StyleNo := FCommentStyleNo;
-    Inc(From, Length(MultiCommentLeft));
-    Exit;
-  end;
-  // Inside multiline comment
-  if FInComment then
-  begin
-    toEnd := toStart;
-    while (toEnd <= Len) and (not StartsFrom(S, toEnd, MultiCommentRight)) do
-      Inc(toEnd);
-    if toEnd > Len then
-    begin
-      Result := Copy(S, From, toEnd - From);
-      From := toEnd;
-    end
-    else
-    begin
-      FInComment := False;
-      toEnd := toEnd + Length(MultiCommentRight);
-      Result := Copy(S, From, toEnd - From);
-      From := toEnd;
-    end;
-    TokenType := ttComment;
-    StyleNo := FCommentStyleNo;
-    Exit;
-  end;
-
-  // Inside brikets
-  if FInBrackets >= 0 then
-  begin
-    Brackets := FBracketList[FInBrackets];
-    toEnd := toStart + 1;
-    while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
-      Inc(toEnd);
-    StyleNo := integer(FBracketList.Objects[FInBrackets]);
-    if toEnd <= Len then
-    begin
-      FInBrackets := -1;
-      From := toEnd + 1;
-    end
-    else
-      From := toEnd;
-    Result := Copy(S, toStart, toEnd - toStart + 1);
-    TokenType := ttBracket;
-    Exit;
-  end;
-  // Spaces
-  while (toStart <= Len) and (S[toStart] = ' ') do
-    Inc(toStart);
-  if toStart > From then
-  begin
-    Result := Copy(S, From, toStart - From);
-    From := toStart;
-    TokenType := ttSpace;
-    StyleNo := 0;
-    Exit;
-  end;
-  // Comment
-  if (FLineComment <> '') and StartsFrom(S, From, FLineComment) then
-  begin
-    Result := Copy(S, From, Len);
-    From := Len + 1;
-    TokenType := ttComment;
-    StyleNo := FCommentStyleNo;
-    Exit;
-  end;
-
-  // Special keyword
-  Done := False;
-  for i := 0 to FSpecialList.Count - 1 do
-  begin
-    LenSpec := Length(FSpecialList[i]);
-    if StrLComp(PChar(S) + toStart - 1,
-      PChar(FSpecialList[i]), LenSpec) = 0 then
-    begin
-      toEnd := toStart + LenSpec - 1;
-      StyleNo := integer(FSpecialList.Objects[i]);
-      TokenType := ttSpecial;
-      From := toEnd + 1;
-      Done := True;
-      break;
-    end;
-  end;
-  // Brickets
-  if not Done then
-  begin
-    for i := 0 to FBracketList.Count - 1 do
-    begin
-      Brackets := FBracketList[i];
-      if S[toStart] = Brackets[1] then
-      begin
-        FInBrackets := i;
-        toEnd := toStart + 1;
-        while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
-          Inc(toEnd);
-        if toEnd <= Len then
-          FInBrackets := -1
-        else
-          Dec(toEnd);
-        StyleNo := integer(FBracketList.Objects[i]);
-        TokenType := ttBracket;
-        Done := True;
-        break;
-      end;
-    end;
-  end;
-  // Delimeters
-  if not Done and CharInSet(S[toStart], Delimiters) then
-  begin
-    toEnd := toStart;
-    StyleNo := FDelimiterStyleNo;
-    TokenType := ttDelimiter;
-    Done := True;
-  end;
-  // --- Integer or float type
-  if not Done and CharInSet(S[toStart], ['0'..'9', '.']) then
-  begin
-    IntPart := 0;
-    WasPoint := False;
-    toEnd := toStart;
-    Done := True;
-    TokenType := ttInteger;
-    StyleNo := FNumberStyleNo;
-    while (toEnd <= Len) and CharInSet(S[toEnd], ['0'..'9', '.']) do
-    begin
-      if S[toEnd] = '.' then
-      begin
-        if not WasPoint then
-        begin
-          WasPoint := True;
-          TokenType := ttFloat;
-        end
-        else
-        begin
-          TokenType := ttWrongNumber;
-          Color := clRed;
-        end;
-      end
-      else if not WasPoint then
-        try
-          IntPart := IntPart * 10 + Ord(S[toEnd]) - Ord('0');
-        except
-          IntPart := MaxInt;
-        end;
-      Inc(toEnd);
-    end;
-    Dec(toEnd);
-  end;
-  // Select word
-  if not Done then
-  begin
-    toEnd := toStart;
-    while (toEnd <= Len) and not CharInSet(S[toEnd], Delimiters) do
-      Inc(toEnd);
-    Dec(toEnd);
-  end;
-  // Find in dictionary
-  Result := Copy(S, toStart, toEnd - toStart + 1);
-  for i := 0 to FWordList.Count - 1 do
-    if Equal(Result, FWordList[i]) then
-    begin
-      StyleNo := integer(FWordList.Objects[i]);
-      TokenType := ttWord;
-      break;
-    end;
-  From := toEnd + 1;
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - FIND LINE ATTRS
-//--------------------------------------------------------------
-
-procedure TGLSSynHiMemo.FindLineAttrs(Sender: TObject; LineNo: integer;
-  var Attrs: string);
-var
-  i, From, TokenLen: integer;
-  S, Token: string;
-  TokenType: TTokenType;
-  StyleNo, OldInBrackets: integer;
-  OldInComment: Boolean;
-begin
-  S := Lines[LineNo];
-  SetLength(Attrs, Length(S));
-  FInComment := InComment[LineNo];
-  FInBrackets := InBrackets[LineNo];
-  From := 1;
-  while True do
-  begin
-    Token := GetToken(S, From, TokenType, StyleNo);
-    if TokenType = ttEOL then
-      break;
-    TokenLen := Length(Token);
-    for i := From - TokenLen to From - 1 do
-      Attrs[i] := Char(StyleNo);
-  end;
-  if LineNo < Lines.Count - 1 then
-  begin
-    OldInComment := InComment[LineNo + 1];
-    OldInBrackets := InBrackets[LineNo + 1];
-    if OldInComment <> FInComment then
-    begin
-      InComment[LineNo + 1] := FInComment;
-      ValidAttrs[LineNo + 1] := False;
-    end;
-    if OldInBrackets <> FInBrackets then
-    begin
-      InBrackets[LineNo + 1] := FInBrackets;
-      ValidAttrs[LineNo + 1] := False;
-    end;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - ADD WORD
-//--------------------------------------------------------------
-
-procedure TGLSSynHiMemo.AddWord(StyleNo: integer; const ArrS: array of string);
-var
-  i: integer;
-begin
-  for i := Low(ArrS) to high(ArrS) do
-    FWordList.AddObject(ArrS[i], TObject(StyleNo));
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - ADD SPECIAL
-//--------------------------------------------------------------
-
-procedure TGLSSynHiMemo.AddSpecial(StyleNo: integer; const ArrS: array of string);
-var
-  i: integer;
-begin
-  for i := Low(ArrS) to high(ArrS) do
-    FSpecialList.AddObject(ArrS[i], TObject(StyleNo));
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - ADD BRACKETS
-//--------------------------------------------------------------
-
-procedure TGLSSynHiMemo.AddBrackets(StyleNo: integer; const ArrS: array of string);
-var
-  i: integer;
-begin
-  for i := Low(ArrS) to high(ArrS) do
-    FBracketList.AddObject(ArrS[i], TObject(StyleNo));
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - CREATE
-//--------------------------------------------------------------
-
-constructor TGLSSynHiMemo.Create(AOwner: TComponent);
-begin
-  inherited;
-  FInBrackets := -1;
-  FIsPainting := False;
-  FInComment := False;
-  FWordList := TGLSMemoStringList.Create;
-  FSpecialList := TGLSMemoStringList.Create;
-  FBracketList := TGLSMemoStringList.Create;
-
-  FDelimiterStyle := TCharStyle.Create;
-  with FDelimiterStyle do
-  begin
-    TextColor := clBlue;
-    BkColor := clWhite;
-    Style := [];
-  end;
-
-  FCommentStyle := TCharStyle.Create;
-  with FCommentStyle do
-  begin
-    TextColor := clYellow;
-    BkColor := clSkyBlue;
-    Style := [fsItalic];
-  end;
-
-  FNumberStyle := TCharStyle.Create;
-  with FNumberStyle do
-  begin
-    TextColor := clNavy;
-    BkColor := clWhite;
-    Style := [fsBold];
-  end;
-
-  FDelimiterStyleNo := Styles.Add(clBlue, clWhite, []);
-  FCommentStyleNo := Styles.Add(clSilver, clWhite, [fsItalic]);
-  FNumberStyleNo := Styles.Add(clNavy, clWhite, [fsBold]);
-
-  OnGetLineAttrs := FindLineAttrs;
-  Delimiters := [' ', ',', ';', ':', '.', '(', ')', '{', '}', '[', ']',
-    '=', '+', '-', '*', '/', '^', '%', '<', '>',
-    '"', '''', #13, #10];
-end;
-
-//--------------------------------------------------------------
-//        SYNTAX MEMO - DESTROY
-//--------------------------------------------------------------
-
-destructor TGLSSynHiMemo.Destroy;
-begin
-  FWordList.Free;
-  FSpecialList.Free;
-  FBracketList.Free;
-  FDelimiterStyle.Free;
-  FCommentStyle.Free;
-  FNumberStyle.Free;
-  inherited;
-end;
-
- 
-
-// ---------------------TGLSMemoStringList 
-
-procedure TGLSMemoStringList.ReadStrings(Reader: TReader);
-var
-  i: Integer;
-begin
-  try
-    Reader.ReadListBegin;
-    Clear;
-    while not Reader.EndOfList do
-    begin
-      i := Add(Reader.ReadString);
-      Objects[i] := TObject(Reader.ReadInteger);
-    end;
-    Reader.ReadListEnd;
-  finally
-  end;
-end;
-
-//--------------------------------------------------------------
-//        STRING LIST - WRITE STRINGS
-//--------------------------------------------------------------
-
-procedure TGLSMemoStringList.WriteStrings(Writer: TWriter);
-var
-  i: Integer;
-begin
-  with Writer do
-  begin
-    WriteListBegin;
-    for i := 0 to Count - 1 do
-    begin
-      WriteString(Strings[i]);
-      WriteInteger(Integer(Objects[i]));
-    end;
-    WriteListEnd;
-  end;
-end;
-
-//--------------------------------------------------------------
-//        STRING LIST - DEFINE PROPERTIES
-//--------------------------------------------------------------
-
-procedure TGLSMemoStringList.DefineProperties(Filer: TFiler);
-begin
-  Filer.DefineProperty('Strings', ReadStrings, WriteStrings, Count > 0);
-end;
-
- 
-
-// ---------------------ScrollBar bitmaps 
-
-procedure CreateScrollBarBitmaps;
-var
-  i, j: integer;
-begin
-  bmScrollBarFill := TBitmap.Create;
-  with bmScrollBarFill, Canvas do
-  begin
-    Width := 8;
-    Height := 8;
-    Transparent := False;
-    for i := 0 to 7 do
-      for j := 0 to 7 do
-        if Odd(i + j) then
-          Pixels[i, j] := clSilver;
-  end;
-
-  bmScrollBarUp := TBitmap.Create;
-  with bmScrollBarUp, Canvas do
-  begin
-    Width := 7;
-    Height := 8;
-    Brush.Color := clSilver;
-    FillRect(Rect(0, 0, Width, Height));
-    Pixels[3, 2] := clBlack;
-    MoveTo(2, 3);
-    LineTo(5, 3);
-    MoveTo(1, 4);
-    LineTo(6, 4);
-    MoveTo(0, 5);
-    LineTo(7, 5);
-  end;
-
-  bmScrollBarDown := TBitmap.Create;
-  with bmScrollBarDown, Canvas do
-  begin
-    Width := 7;
-    Height := 8;
-    Brush.Color := clSilver;
-    FillRect(Rect(0, 0, Width, Height));
-    MoveTo(0, 2);
-    LineTo(7, 2);
-    MoveTo(1, 3);
-    LineTo(6, 3);
-    MoveTo(2, 4);
-    LineTo(5, 4);
-    Pixels[3, 5] := clBlack;
-  end;
-
-  bmScrollBarLeft := TBitmap.Create;
-  with bmScrollBarLeft, Canvas do
-  begin
-    Width := 8;
-    Height := 7;
-    Brush.Color := clSilver;
-    FillRect(Rect(0, 0, Width, Height));
-    Pixels[2, 3] := clBlack;
-    MoveTo(3, 2);
-    LineTo(3, 5);
-    MoveTo(4, 1);
-    LineTo(4, 6);
-    MoveTo(5, 0);
-    LineTo(5, 7);
-  end;
-
-  bmScrollBarRight := TBitmap.Create;
-  with bmScrollBarRight, Canvas do
-  begin
-    Width := 8;
-    Height := 7;
-    Brush.Color := clSilver;
-    FillRect(Rect(0, 0, Width, Height));
-    MoveTo(2, 0);
-    LineTo(2, 7);
-    MoveTo(3, 1);
-    LineTo(3, 6);
-    MoveTo(4, 2);
-    LineTo(4, 5);
-    Pixels[5, 3] := clBlack;
-  end;
-
-end;
-//------------------ FREE SCROLL BAR BITMAPs -------------------
-
-procedure FreeScrollBarBitmaps;
-begin
-  bmScrollBarFill.Free;
-  bmScrollBarUp.Free;
-  bmScrollBarDown.Free;
-  bmScrollBarLeft.Free;
-  bmScrollBarRight.Free;
-end;
-
- 
-
-initialization
-
-  RegisterClasses([TGLSSynHiMemo]);
-  CreateScrollBarBitmaps;
-  IntelliMouseInit;
-
-finalization
-  FreeScrollBarBitmaps;
-
-end.
-
+//
+// This unit is part of the GLScene Engine, http://glscene.org
+//
+
+unit GLS.Memo;
+
+(* Memo for GLScene *)
+
+interface
+
+{$I GLScene.inc}
+
+uses
+  WinApi.Windows,
+  WinApi.Messages,
+  System.SysUtils,
+  System.Classes,
+  System.UITypes,
+  VCL.Graphics,
+  VCL.Controls, 
+  VCL.Forms, 
+  VCL.Dialogs, 
+  VCL.ClipBrd,
+  VCL.StdCtrls, 
+  VCL.ExtCtrls;
+
+
+
+type
+  TBorderType = (btRaised, btLowered, btFlatRaised, btFlatLowered);
+  TCommand = Integer;
+
+  TCellSize = record
+    W, H: integer;
+  end;
+
+  TCellPos = record
+    X, Y: integer;
+  end;
+
+  TFullPos = record
+    LineNo, Pos: integer;
+  end;
+
+  TLineProp = class
+    FObject: TObject;
+    FStyleNo: integer;
+    FInComment: Boolean;
+    FInBrackets: integer;
+    FValidAttrs: Boolean;
+    FCharAttrs: string;
+  end;
+
+  TCharStyle = class(TPersistent)
+  private
+    FTextColor, FBkColor: TColor;
+    FStyle: TFontStyles;
+  published
+
+    property TextColor: TColor read FTextColor write FTextColor;
+    property BkColor: TColor read FBkColor write FBkColor;
+    property Style: TFontStyles read FStyle write FStyle;
+  end;
+
+  TStyleList = class(TList)
+  private
+    procedure CheckRange(Index: integer);
+    function GetTextColor(Index: Integer): TColor;
+    procedure SetTextColor(Index: Integer; Value: TColor);
+    function GetBkColor(Index: Integer): TColor;
+    procedure SetBkColor(Index: Integer; Value: TColor);
+    function GetStyle(Index: Integer): TFontStyles;
+    procedure SetStyle(Index: Integer; Value: TFontStyles);
+  protected
+    
+    property TextColor[Index: Integer]: TColor read GetTextColor write
+    SetTextColor;
+    property BkColor[Index: Integer]: TColor read GetBkColor write SetBkColor;
+    property Style[Index: Integer]: TFontStyles read GetStyle write SetStyle;
+  public
+    
+    destructor Destroy; override;
+    procedure Clear; override;
+    procedure Delete(Index: Integer);
+    function Add(ATextColor, ABkCOlor: TColor; AStyle: TFontStyles): Integer;
+    procedure Change(Index: integer; ATextColor, ABkColor: TColor; AStyle:
+      TFontStyles);
+  end;
+
+  TGLAbstractMemoObject = class(TObject)
+  public
+    function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
+      Boolean; virtual; abstract;
+    function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
+      Boolean; virtual; abstract;
+    function MouseMove(Shift: TShiftState; X, Y: Integer):
+      Boolean; virtual; abstract;
+  end;
+
+  TGLSMemoScrollBar = class;
+
+  TGLSMemoAbstractScrollableObject = class(TCustomControl)
+  protected
+    procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
+      virtual; abstract;
+    procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer);
+      virtual; abstract;
+  end;
+
+  TGLSCustomMemo = class;
+
+  TsbState =
+    (
+    sbsWait,
+    sbsBack,
+    sbsForward,
+    sbsPageBack,
+    sbsPageForward,
+    sbsDragging
+    );
+
+  TGLSMemoScrollBar = class(TGLAbstractMemoObject)
+  private
+    FKind: TScrollBarKind;
+    FParent: TGLSMemoAbstractScrollableObject;
+    FLeft, FTop, FWidth, FHeight: integer;
+    FTotal, FMaxPosition, FPosition: integer;
+    FButtonLength: integer;
+    FState: TsbState;
+    FXOffset, FYOffset: integer;
+    procedure SetParams(Index: integer; Value: integer);
+    procedure SetState(Value: TsbState);
+    function GetRect: TRect;
+    function GetThumbRect: TRect;
+    function GetBackRect: TRect;
+    function GetMiddleRect: TRect;
+    function GetForwardRect: TRect;
+    function GetPgBackRect: TRect;
+    function GetPgForwardRect: TRect;
+  public
+    constructor Create(AParent: TGLSMemoAbstractScrollableObject;
+      AKind: TScrollBarKind);
+    procedure PaintTo(ACanvas: TCanvas);
+    function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
+      Boolean; override;
+    function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
+      Boolean; override;
+    function MouseMove(Shift: TShiftState; X, Y: Integer):
+      Boolean; override;
+    function MoveThumbTo(X, Y: Integer): integer;
+    property Parent: TGLSMemoAbstractScrollableObject read FParent;
+    property Kind: TScrollBarKind read FKind write FKind;
+    property State: TsbState read FState write SetState;
+    property Left: integer index 0 read FLeft write SetParams;
+    property Top: integer index 1 read FTop write SetParams;
+    property Width: integer index 2 read FWidth write SetParams;
+    property Height: integer index 3 read FHeight write SetParams;
+    property Total: integer index 4 read FTotal write SetParams;
+    property MaxPosition: integer index 5 read FMaxPosition write SetParams;
+    property Position: integer index 6 read FPosition write SetParams;
+    property FullRect: TRect read GetRect;
+    property ThumbRect: TRect read GetThumbRect;
+    property BackRect: TRect read GetBackRect;
+    property MiddleRect: TRect read GetMiddleRect;
+    property ForwardRect: TRect read GetForwardRect;
+    property PageForwardRect: TRect read GetPgForwardRect;
+    property PageBackRect: TRect read GetPgBackRect;
+  end;
+
+  TGLSMemoStrings = class(TStringList)
+  private
+    FMemo: TGLSCustomMemo;
+    FLockCount: integer;
+    FDeleting: Boolean;
+    procedure CheckRange(Index: integer);
+    function GetLineProp(Index: integer): TLineProp;
+    procedure SetLineStyle(Index: integer; Value: integer);
+    function GetLineStyle(Index: integer): integer;
+    function GetInComment(Index: Integer): Boolean;
+    procedure SetInComment(Index: Integer; Value: Boolean);
+    function GetInBrackets(Index: Integer): integer;
+    procedure SetInBrackets(Index: Integer; Value: integer);
+    function GetValidAttrs(Index: Integer): Boolean;
+    procedure SetValidAttrs(Index: Integer; Value: Boolean);
+    function GetCharAttrs(Index: Integer): string;
+    procedure SetCharAttrs(Index: Integer; const Value: string);
+  protected
+    function GetObject(Index: Integer): TObject; override;
+    procedure PutObject(Index: Integer; AObject: TObject); override;
+    procedure SetUpdateState(Updating: Boolean); override;
+    function CreateProp(Index: integer): TLineProp;
+    property LineProp[Index: integer]: TLineProp read GetLineProp; //PALOFF
+    property Style[Index: integer]: integer read GetLineStyle write
+    SetLineStyle;
+    property InComment[Index: integer]: Boolean read GetInComment write
+    SetInComment;
+    property InBrackets[Index: integer]: integer read GetInBrackets write
+    SetInBrackets;
+    property ValidAttrs[Index: integer]: Boolean read GetValidAttrs write
+    SetValidAttrs;
+    property CharAttrs[Index: integer]: string read GetCharAttrs write
+    SetCharAttrs;
+  public
+    destructor Destroy; override;
+    procedure Clear; override;
+    function DoAdd(const S: string): Integer;
+    function Add(const S: string): Integer; override;
+    function AddObject(const S: string; AObject: TObject): Integer; override;
+    procedure Assign(Source: TPersistent); override;
+    procedure Insert(Index: Integer; const S: string); override;
+    procedure DoInsert(Index: Integer; const S: string);
+    procedure InsertObject(Index: Integer; const S: string; AObject: TObject);
+      override;
+    procedure Delete(Index: Integer); override;
+    procedure LoadFromFile(const FileName: string); override;
+  end;
+
+  TGLSMemoGutter = class(TObject)
+  private
+    FMemo: TGLSCustomMemo;
+    FLeft, FTop, FWidth, FHeight: integer;
+    FColor: TColor;
+    procedure SetParams(Index: integer; Value: integer);
+    function GetRect: TRect;
+  protected
+    procedure PaintTo(ACanvas: TCanvas);
+    procedure Invalidate;
+  public
+    property Left: integer index 0 read FLeft write SetParams;
+    property Top: integer index 1 read FTop write SetParams;
+    property Width: integer index 2 read FWidth write SetParams;
+    property Height: integer index 3 read FHeight write SetParams;
+    property FullRect: TRect read GetRect;
+  end;
+
+  TGLSMemoUndo = class
+  private
+    FMemo: TGLSCustomMemo;
+    FUndoCurX0, FUndoCurY0: integer;
+    FUndoCurX, FUndoCurY: integer;
+    FUndoText: string;
+  public
+    constructor Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText: string);
+    function Append(NewUndo: TGLSMemoUndo): Boolean; virtual;
+    procedure Undo;
+    procedure Redo;
+    procedure PerformUndo; virtual; abstract;
+    procedure PerformRedo; virtual; abstract;
+    property UndoCurX0: integer read FUndoCurX0 write FUndoCurX0;
+    property UndoCurY0: integer read FUndoCurY0 write FUndoCurY0;
+    property UndoCurX: integer read FUndoCurX write FUndoCurX;
+    property UndoCurY: integer read FUndoCurY write FUndoCurY;
+  end;
+
+  TGLSMemoInsCharUndo = class(TGLSMemoUndo)
+  public
+    function Append(NewUndo: TGLSMemoUndo): Boolean; override;
+    procedure PerformUndo; override;
+    procedure PerformRedo; override;
+  end;
+
+  TGLSMemoDelCharUndo = class(TGLSMemoUndo)
+  private
+    FIsBackspace: Boolean;
+  public
+    function Append(NewUndo: TGLSMemoUndo): Boolean; override;
+    procedure PerformUndo; override;
+    procedure PerformRedo; override;
+    property IsBackspace: Boolean read FIsBackspace write FIsBackspace;
+  end;
+
+  TGLSMEmoDelLineUndo = class(TGLSMemoUndo)
+  private
+    FIndex: integer;
+  public
+    constructor Create(AIndex, ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
+      string);
+    procedure PerformUndo; override;
+    procedure PerformRedo; override;
+  end;
+
+  TGLSMemoSelUndo = class(TGLSMemoUndo)
+  private
+    FUndoSelStartX, FUndoSelStartY,
+      FUndoSelEndX, FUndoSelEndY: integer;
+  public
+    property UndoSelStartX: integer read FUndoSelStartX write FUndoSelStartX;
+    property UndoSelStartY: integer read FUndoSelStartY write FUndoSelStartY;
+    property UndoSelEndX: integer read FUndoSelEndX write FUndoSelEndX;
+    property UndoSelEndY: integer read FUndoSelEndY write FUndoSelEndY;
+  end;
+
+  TGLSMemoDeleteBufUndo = class(TGLSMemoSelUndo)
+  public
+    procedure PerformUndo; override;
+    procedure PerformRedo; override;
+  end;
+
+  TGLSMemoPasteUndo = class(TGLSMemoUndo)
+  public
+    procedure PerformUndo; override;
+    procedure PerformRedo; override;
+  end;
+
+  TGLSMemoUndoList = class(TList)
+  private
+    FPos: integer;
+    FMemo: TGLSCustomMemo;
+    FIsPerforming: Boolean;
+    FLimit: integer;
+  protected
+    function Get(Index: Integer): TGLSMemoUndo;
+    procedure SetLimit(Value: integer);
+  public
+    constructor Create;
+    destructor Destroy; override;
+    function Add(Item: Pointer): Integer;
+    procedure Clear; override;
+    procedure Delete(Index: Integer);
+    procedure Undo;
+    procedure Redo;
+    property Items[Index: Integer]: TGLSMemoUndo read Get; default;
+    property IsPerforming: Boolean read FIsPerforming write FIsPerforming;
+    property Memo: TGLSCustomMemo read FMemo write FMemo;
+    property Pos: integer read FPos write FPos;
+    property Limit: integer read FLimit write SetLimit;
+  end;
+
+  //--------------------------------------------------------------
+
+  TGutterClickEvent = procedure(Sender: TObject; LineNo: integer) of object;
+  TGutterDrawEvent = procedure(Sender: TObject; ACanvas: TCanvas;
+    LineNo: integer; rct: TRect) of object;
+  TGetLineAttrsEvent = procedure(Sender: TObject; LineNo: integer;
+    var Attrs: string) of object;
+  TUndoChangeEvent = procedure(Sender: TObject;
+    CanUndo, CanRedo: Boolean) of object;
+  TScrollMode = (smAuto, smStrict);
+
+  TGLSCustomMemo = class(TGLSMemoAbstractScrollableObject)
+  private
+    FAutoIndent: Boolean;
+    FMargin: integer;
+    FHiddenCaret, FCaretVisible: Boolean;
+    FCellSize: TCellSize;
+    FCurX, FCurY: integer;
+    FLeftCol, FTopLine: integer;
+    FTabSize: integer;
+    FFont: TFont;
+    FBkColor: TColor;
+    FSelColor: TColor;
+    FSelBkColor: TColor;
+    FReadOnly: Boolean;
+    FDelErase: Boolean;
+    FLines: TStrings;
+    FSelStartX, FSelStartY,
+      FSelEndX, FSelEndY,
+      FPrevSelX, FPrevSelY: integer;
+    FScrollBars: System.UITypes.TScrollStyle;
+    FScrollBarWidth: integer;
+    FGutter: TGLSMemoGutter;
+    FGutterWidth: integer;
+    sbVert, sbHorz: TGLSMemoScrollBar;
+    FStyles: TStyleList;
+    FLineBitmap: TBitmap;
+    FSelCharPos: TFullPos;
+    FSelCharStyle: integer;
+    FLeftButtonDown: Boolean;
+    FScrollMode: TScrollMode;
+    FUndoList: TGLSMemoUndoList;
+    FFirstUndoList: TGLSMemoUndoList;
+    FUndoLimit: integer;
+    FLastMouseUpX,
+      FLastMouseUpY: integer;
+    FAfterDoubleClick: Boolean;
+    // events
+    FOnMoveCursor: TNotifyEvent;
+    FOnChange: TNotifyEvent;
+    FOnAttrChange: TNotifyEvent;
+    FOnStatusChange: TNotifyEvent;
+    FOnSelectionChange: TNotifyEvent;
+    FOnGutterDraw: TGutterDrawEvent;
+    FOnGutterClick: TGutterClickEvent;
+    FOnGetLineAttrs: TGetLineAttrsEvent;
+    FOnUndoChange: TUndoChangeEvent;
+    FHideCursor: Boolean;
+    procedure SetHiddenCaret(Value: Boolean);
+    procedure SetScrollBars(Value: System.UITypes.TScrollStyle);
+    procedure SetGutterWidth(Value: integer);
+    procedure SetGutterColor(Value: TColor);
+    function GetGutterColor: TColor;
+    procedure SetCurX(Value: integer);
+    procedure SetCurY(Value: integer);
+    procedure SetFont(Value: TFont);
+    procedure SetColor(Index: integer; Value: TColor);
+    function GetSelStart: TPoint;
+    function GetSelEnd: TPoint;
+    procedure SetLines(ALines: TStrings);
+    procedure SetLineStyle(Index: integer; Value: integer);
+    function GetLineStyle(Index: integer): integer;
+    function GetInComment(Index: integer): Boolean;
+    procedure SetInComment(Index: integer; Value: Boolean);
+    function GetInBrackets(Index: Integer): integer;
+    procedure SetInBrackets(Index: Integer; Value: integer);
+    function GetValidAttrs(Index: integer): Boolean;
+    procedure SetValidAttrs(Index: integer; Value: Boolean);
+    function GetCharAttrs(Index: integer): string;
+    procedure SetCharAttrs(Index: integer; const Value: string);
+    procedure ExpandSelection;
+    function GetSelText: string;
+    procedure SetSelText(const AValue: string);
+    function GetSelLength: integer;
+    procedure MovePage(dP: integer; Shift: TShiftState);
+    procedure ShowCaret(State: Boolean);
+    procedure MakeVisible;
+    function GetVisible(Index: integer): integer;
+    function MaxLength: integer;
+    procedure WMSize(var Msg: TWMSize); message WM_SIZE;
+    procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
+    procedure WMEraseBkgnd(var Msg: TWmEraseBkgnd); message WM_ERASEBKGND;
+    procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
+    procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS;
+    procedure WMKillFocus(var Msg: TWMSetFocus); message WM_KILLFOCUS;
+    procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL;
+    procedure MoveCursor(dX, dY: integer; Shift: TShiftState);
+    procedure ResizeEditor;
+    procedure ResizeScrollBars;
+    procedure ResizeGutter;
+    procedure DoCommand(cmd: TCommand; const AShift: TShiftState);
+    procedure DrawLine(LineNo: integer);
+    function IsLineVisible(LineNo: integer): Boolean;
+    procedure FreshLineBitmap;
+    procedure SetUndoLimit(Value: integer);
+  protected
+    procedure WndProc(var Message: TMessage); override;
+    function EditorRect: TRect;
+    function LineRangeRect(FromLine, ToLine: integer): TRect;
+    function ColRangeRect(FromCol, ToCol: integer): TRect;
+    procedure InvalidateLineRange(FromLine, ToLine: integer);
+    function AddString(const S: string): integer;
+    procedure InsertString(Index: integer; S: string);
+    procedure GoHome(Shift: TShiftState);
+    procedure GoEnd(Shift: TShiftState);
+    procedure InsertChar(C: Char);
+    procedure DeleteChar(OldX, OldY: integer);
+    procedure DeleteLine(Index, OldX, OldY, NewX, NewY: integer; FixUndo: Boolean);
+    procedure BackSpace;
+    procedure BackSpaceWord;
+    function IndentCurrLine: string;
+    procedure NewLine;
+    procedure CreateParams(var Params: TCreateParams); override;
+    procedure Paint; override;
+    procedure DrawMargin;
+    procedure DrawGutter;
+    procedure DrawScrollBars;
+    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
+    procedure KeyPress(var Key: Char); override;
+    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
+    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
+    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
+    procedure DblClick; override;
+    procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer); override;
+    procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer); override;
+    property VisiblePosCount: integer index 0 read GetVisible;
+    property VisibleLineCount: integer index 1 read GetVisible;
+    property LastVisiblePos: integer index 2 read GetVisible;
+    property LastVisibleLine: integer index 3 read GetVisible;
+    procedure DeleteSelection(bRepaint: Boolean);
+    procedure Changed(FromLine, ToLine: integer); virtual;
+    procedure AttrChanged(LineNo: integer); virtual;
+    procedure SelectionChanged; virtual;
+    procedure StatusChanged; virtual;
+    procedure ClearUndoList;
+    procedure UndoChange;
+    property AutoIndent: Boolean read FAutoIndent write FAutoIndent;
+    property GutterWidth: integer read FGutterWidth write SetGutterWidth;
+    property GutterColor: TColor read GetGutterColor write SetGutterColor;
+    property ScrollBars: System.UITypes.TScrollStyle read FScrollBars write SetScrollBars default ssBoth;
+    property Font: TFont read FFont write SetFont;
+    property ReadOnly: Boolean read FReadOnly write FReadOnly;
+    property Lines: TStrings read FLines write SetLines;
+    property BkColor: TColor index 0 read FBkColor write SetColor;
+    property SelColor: TColor index 1 read FSelColor write SetColor;
+    property SelBkColor: TColor index 2 read FSelBkColor write SetColor;
+    property HiddenCaret: Boolean read FHiddenCaret write SetHiddenCaret;
+    property TabSize: integer read FTabSize write FTabSize;
+    property ScrollMode: TScrollMode read FScrollMode write FScrollMode default smAuto;
+    property UndoLimit: integer read FUndoLimit write SetUndoLimit;
+    property HideCursor: Boolean read FHideCursor write FHideCursor;
+    property InComment[Index: integer]: Boolean read GetInComment write SetInComment;
+    property InBrackets[Index: integer]: integer read GetInBrackets write SetInBrackets;
+    property ValidAttrs[Index: integer]: Boolean read GetValidAttrs write SetValidAttrs;
+    property CharAttrs[Index: integer]: string read GetCharAttrs write SetCharAttrs;
+    {events}
+    property OnGutterClick: TGutterClickEvent read FOnGutterClick write FOnGutterClick;
+    property OnGutterDraw: TGutterDrawEvent read FOnGutterDraw write FOnGutterDraw;
+    property OnChange: TNotifyEvent read FOnChange write FOnChange;
+    property OnMoveCursor: TNotifyEvent read FOnMoveCursor write FOnMoveCursor;
+    property OnAttrChange: TNotifyEvent read FOnAttrChange write FOnAttrChange;
+    property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
+    property OnStatusChange: TNotifyEvent read FOnStatusChange write FOnStatusChange;
+    property OnGetLineAttrs: TGetLineAttrsEvent read FOnGetLineAttrs write FOnGetLineAttrs;
+    property OnUndoChange: TUndoChangeEvent read FOnUndoChange write FOnUndoChange;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure CopyToClipBoard;
+    procedure PasteFromClipBoard;
+    procedure CutToClipBoard;
+    procedure SelectLines(StartLine, EndLine: Integer);
+    procedure SelectAll;
+    property SelStart: TPoint read GetSelStart;
+    property SelEnd: TPoint read GetSelEnd;
+    property Selection: string read GetSelText write SetSelText;
+    property SelLength: integer read GetSelLength;
+    procedure ClearSelection;
+    procedure Clear;
+    procedure SetCursor(ACurX, ACurY: Integer);
+    function SelectLine(LineNo, StyleNo: Integer): integer;
+    procedure SelectChar(LineNo, Pos, StyleNo: Integer);
+    function CellFromPos(X, Y: integer): TCellPos;
+    function CharFromPos(X, Y: integer): TFullPos;
+    function CellRect(ACol, ARow: integer): TRect;
+    function LineRect(ARow: integer): TRect;
+    function ColRect(ACol: integer): TRect;
+    function CharStyleNo(LineNo, Pos: integer): integer;
+    procedure InsertTemplate(AText: string);
+    procedure UnSelectChar;
+    procedure Undo;
+    procedure Redo;
+    function CanUndo: Boolean;
+    function CanRedo: Boolean;
+    function FindText(Text: string; Options: TFindOptions; Select: Boolean): Boolean;
+    property CurX: integer read FCurX write SetCurX;
+    property CurY: integer read FCurY write SetCurY;
+    property DelErase: Boolean read FDelErase write FDelErase;
+    property LineStyle[Index: integer]: integer read GetLineStyle write
+    SetLineStyle;
+    property Styles: TStyleList read FStyles;
+    property UndoList: TGLSMemoUndoList read FUndoList write FUndoList;
+  end;
+
+  TGLSMemo = class(TGLSCustomMemo)
+  published
+    {TControl }
+    property PopupMenu;
+    {TCustomControl }
+    property Align;
+    property Enabled;
+    property ShowHint;
+    property TabOrder;
+    property TabStop;
+    property Visible;
+    property ReadOnly;
+    {TGLSCustomMemo }
+    property AutoIndent;
+    property GutterColor;
+    property GutterWidth;
+    property ScrollBars;
+    property Font;
+    property BkColor;
+    property Selection;
+    property SelColor;
+    property SelBkColor;
+    property Lines;
+    property HiddenCaret;
+    property TabSize;
+    property ScrollMode;
+    property UndoLimit;
+    property DelErase;
+    {Inherited events }
+    property OnClick;
+    property OnDblClick;
+    property OnDragDrop;
+    property OnDragOver;
+    property OnEndDrag;
+    property OnMouseDown;
+    property OnMouseMove;
+    property OnMouseUp;
+    property OnStartDrag;
+    property OnEnter;
+    property OnExit;
+    property OnKeyDown;
+    property OnKeyPress;
+    property OnKeyUp;
+    {Events }
+    property OnGutterDraw;
+    property OnGutterClick;
+    property OnChange;
+    property OnMoveCursor;
+    property OnAttrChange;
+    property OnSelectionChange;
+    property OnStatusChange;
+    property OnGetLineAttrs;
+    property OnUndoChange;
+  end;
+
+  TGLSMemoStringList = class(TStringList)
+  private
+    procedure ReadStrings(Reader: TReader);
+    procedure WriteStrings(Writer: TWriter);
+  protected
+    procedure DefineProperties(Filer: TFiler); override;
+  end;
+
+  TDelimiters = TSysCharSet;
+  TTokenType =
+    (
+    ttWord,
+    ttBracket,
+    ttSpecial,
+    ttDelimiter,
+    ttSpace,
+    ttEOL,
+    ttInteger,
+    ttFloat,
+    ttComment,
+    ttOther,
+    ttWrongNumber);
+
+  //--------------------------------------------------------------
+  //        SYNTAX MEMO - declaration
+  //--------------------------------------------------------------
+  TGLSSynHiMemo = class(TGLSCustomMemo)
+  private
+
+    FIsPainting: Boolean;
+    FInComment: Boolean;
+
+    FWordList: TGLSMemoStringList;
+    FSpecialList: TGLSMemoStringList;
+    FBracketList: TGLSMemoStringList;
+    FDelimiters: TDelimiters;
+    FInBrackets: integer;
+    FLineComment: string;
+    FMultiCommentLeft: string;
+    FMultiCommentRight: string;
+    FDelimiterStyle: TCharStyle;
+    FCommentStyle: TCharStyle;
+    FNumberStyle: TCharStyle;
+    FDelimiterStyleNo,
+      FCommentStyleNo,
+      FNumberStyleNo: integer;
+    FCaseSensitive: Boolean;
+    function GetToken(const S: string; var From: integer;
+      out TokenType: TTokenType; out StyleNo: integer): string;
+    procedure SetWordList(Value: TGLSMemoStringList);
+    procedure SetSpecialList(Value: TGLSMemoStringList);
+    procedure SetBracketList(Value: TGLSMemoStringList);
+    procedure FindLineAttrs(Sender: TObject; LineNo: integer; var Attrs:
+      string);
+    procedure SetStyle(Index: integer; Value: TCharStyle);
+    procedure SetCaseSensitive(Value: Boolean);
+  protected
+    procedure Paint; override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure AddWord(StyleNo: integer; const ArrS: array of string);
+    procedure AddSpecial(StyleNo: integer; const ArrS: array of string);
+    procedure AddBrackets(StyleNo: integer; const ArrS: array of string);
+    property Delimiters: TDelimiters read FDelimiters write FDelimiters;
+  published
+    {TControl}
+    property PopupMenu;
+    {TCustomControl}
+    property Align;
+    property Enabled;
+    property ShowHint;
+    property TabOrder;
+    property TabStop;
+    property Visible;
+    property ReadOnly;
+    {TGLSCustomMemo}
+    property AutoIndent;
+    property GutterColor;
+    property GutterWidth;
+    property ScrollBars;
+    property Font;
+    property BkColor;
+    property SelColor;
+    property SelBkColor;
+    property Lines;
+    property HiddenCaret;
+    property TabSize;
+    property ScrollMode;
+    property UndoLimit;
+    property DelErase;
+    {Inherited events }
+    property OnClick;
+    property OnDblClick;
+    property OnDragDrop;
+    property OnDragOver;
+    property OnEndDrag;
+    property OnMouseDown;
+    property OnMouseMove;
+    property OnMouseUp;
+    property OnStartDrag;
+    property OnEnter;
+    property OnExit;
+    property OnKeyDown;
+    property OnKeyPress;
+    property OnKeyUp;
+    {Events }
+    property OnGutterClick;
+    property OnGutterDraw;
+    property OnChange;
+    property OnMoveCursor;
+    property OnSelectionChange;
+    property OnStatusChange;
+    property OnUndoChange;
+    {TGLSSyntaxMemo }
+    property LineComment: string read FLineComment write FLineComment;
+    property MultiCommentLeft: string read FMultiCommentLeft write FMultiCommentLeft;
+    property MultiCommentRight: string read FMultiCommentRight write FMultiCommentRight;
+    property WordList: TGLSMemoStringList read FWordList write SetWordList;
+    property SpecialList: TGLSMemoStringList read FSpecialList write SetSpecialList;
+    property BracketList: TGLSMemoStringList read FBracketList write SetBracketList;
+    property DelimiterStyle: TCharStyle index 0 read FDelimiterStyle write SetStyle;
+    property CommentStyle: TCharStyle index 1 read FCommentStyle write SetStyle;
+    property NumberStyle: TCharStyle index 2 read FNumberStyle write SetStyle;
+    property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
+  end;
+
+procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
+
+//==========================================================
+implementation
+//==========================================================
+
+const
+  cmDelete = VK_DELETE;
+  cmBackSpace = VK_BACK;
+  cmWordBackSpace = 127; // Ctrl-BackSpace
+  cmNewLine = VK_RETURN;
+  cmHome = VK_HOME;
+  cmEnd = VK_END;
+  cmPageUp = VK_PRIOR;
+  cmPageDown = VK_NEXT;
+  cmInsert = VK_INSERT;
+  cmDelLine = 25; // Ctrl-Y
+  cmCopy = 3; // Ctrl-C
+  cmCut = 24; // Ctrl-X
+  cmPaste = 22; // Ctrl-V
+
+resourcestring
+  SObjectsNotSupported = 'Linked object not supported';
+
+var
+  bmScrollBarFill: TBitmap;
+  bmScrollBarUp: TBitmap;
+  bmScrollBarDown: TBitmap;
+  bmScrollBarLeft: TBitmap;
+  bmScrollBarRight: TBitmap;
+
+  fIntelliWheelSupport: Boolean; // True if IntelliMouse + wheel enabled
+  fIntelliMessage: UINT; // message sent from mouse on wheel roll
+  fIntelliScrollLines: Integer; // number of lines to scroll per wheel roll
+
+// ---------------------Helper functions 
+
+function PointInRect(const P: TPoint; const rct: TRect): Boolean; inline;
+begin
+  with rct do
+    Result := (Left <= P.X) and (Top <= P.Y) and
+      (Right >= P.X) and (Bottom >= P.Y);
+end;
+
+procedure Swap(var I1, I2: integer); inline;
+var
+  temp: integer;
+begin
+  temp := I1;
+  I1 := I2;
+  I2 := temp;
+end;
+
+procedure OrderPos(var StartX, StartY, EndX, EndY: integer); inline;
+begin
+  if (EndY < StartY) or
+    ((EndY = StartY) and (EndX < StartX)) then
+  begin
+    Swap(StartX, EndX);
+    Swap(StartY, EndY);
+  end;
+end;
+
+function TotalRect(const rct1, rct2: TRect): TRect; inline;
+begin
+  Result := rct1;
+  with Result do
+  begin
+    if rct2.Left < Left then
+      Left := rct2.Left;
+    if rct2.Top < Top then
+      Top := rct2.Top;
+    if rct2.Right > Right then
+      Right := rct2.Right;
+    if rct2.Bottom > Bottom then
+      Bottom := rct2.Bottom;
+  end;
+end;
+
+
+
+// ---------------------TGLSCustomMemo functions
+
+procedure TGLSCustomMemo.WndProc(var Message: TMessage);
+  function GetShiftState: Integer;
+  begin
+    Result := 0;
+    if GetAsyncKeyState(vk_Shift) < 0 then
+      Result := Result or mk_Shift;
+    if GetAsyncKeyState(vk_Control) < 0 then
+      Result := Result or mk_Control;
+    if GetAsyncKeyState(vk_LButton) < 0 then
+      Result := Result or mk_LButton;
+    if GetAsyncKeyState(vk_RButton) < 0 then
+      Result := Result or mk_RButton;
+    if GetAsyncKeyState(vk_MButton) < 0 then
+      Result := Result or mk_MButton;
+  end;
+  //---------------------------------------------------
+begin
+  if (Message.Msg = fIntelliMessage) and (fIntelliMessage <> wm_MouseWheel) then
+  begin
+    PostMessage(Handle, wm_MouseWheel, MakeLong(GetShiftState, Message.wParam),
+      Message.lParam);
+  end
+  else
+    inherited;
+end;
+
+//------------------------------------------------
+//    INTELLIMOUSE INIT
+//------------------------------------------------
+
+procedure IntelliMouseInit;
+var
+  hWndMouse: hWnd;
+  mQueryScrollLines: UINT;
+  //--------------------------------------------
+  function NativeMouseWheelSupport: Boolean;
+  var
+    ver: TOSVersionInfo;
+  begin
+    Result := False;
+    ver.dwOSVersionInfoSize := sizeof(ver);
+    // For Windows 98, assume dwMajorVersion = 5 (It's 4 for W95)
+    // For NT, we need 4.0 or better.
+    if GetVersionEx(ver) then
+      case ver.dwPlatformID of
+        ver_Platform_Win32_Windows: Result := ver.dwMajorVersion >= 5;
+        ver_Platform_Win32_NT: Result := ver.dwMajorVersion >= 4;
+      end;
+    { Quick and dirty temporary hack for Windows 98 beta 3 }
+    if (not Result) and (ver.szCSDVersion = ' Beta 3') then
+      Result := True;
+  end;
+  //--------------------------------------------
+begin
+  if NativeMouseWheelSupport then
+  begin
+    fIntelliWheelSupport := Boolean(GetSystemMetrics(sm_MouseWheelPresent));
+    SystemParametersInfo(spi_GetWheelScrollLines, 0, @fIntelliScrollLines, 0);
+    fIntelliMessage := wm_MouseWheel;
+  end
+  else
+  begin
+    { Look for hidden mouse window }
+    hWndMouse := FindWindow('MouseZ', 'Magellan MSWHEEL');
+    if hWndMouse <> 0 then
+    begin
+      { We're in business - get the scroll line info }
+      fIntelliWheelSupport := True;
+      mQueryScrollLines := RegisterWindowMessage('MSH_SCROLL_LINES_MSG');
+      fIntelliScrollLines := SendMessage(hWndMouse, mQueryScrollLines, 0, 0);
+      { Finally, get the custom mouse message as well }
+      fIntelliMessage := RegisterWindowMessage('MSWHEEL_ROLLMSG');
+    end;
+  end;
+  if (fIntelliScrollLines < 0) or (fIntelliScrollLines > 100) then
+    fIntelliScrollLines := 3;
+end;
+
+//------------------------------------------------
+//    WM MOUSE WHEEL
+//------------------------------------------------
+
+procedure TGLSCustomMemo.WMMouseWheel(var Message: TMessage);
+{$J+}
+{$IFOPT R+} {$DEFINE StoreRangeCheck} {$ENDIF} {$R-}
+const
+  Delta: SmallInt = 0;
+begin
+  Delta := Delta + SmallInt(HiWord(Message.wParam));
+  while Abs(Delta) >= 120 do
+  begin
+    if Delta < 0 then
+    begin
+      DoScroll(sbVert, fIntelliScrollLines);
+      Delta := Delta + 120;
+    end
+    else
+    begin
+      DoScroll(sbVert, -fIntelliScrollLines);
+      Delta := Delta - 120;
+    end;
+  end;
+end;
+{$J-}
+{$IFDEF StoreRangeCheck} {$R+} {$UNDEF StoreRangeCheck} {$ENDIF}
+
+//--------------------------------------------------------------
+//        SET CURSOR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetCursor(ACurX, ACurY: Integer);
+begin
+  ClearSelection;
+  CurX := 0;
+  CurY := ACurY;
+  CurX := ACurX;
+end;
+
+//--------------------------------------------------------------
+//        SELECT LINE, CHAR
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.SelectLine(LineNo, StyleNo: Integer): integer;
+var
+  rct: TRect;
+begin
+  Result := LineStyle[LineNo];
+  LineStyle[LineNo] := StyleNo;
+  rct := LineRect(LineNo);
+  InvalidateRect(Handle, @rct, True);
+end;
+
+procedure TGLSCustomMemo.SelectLines(StartLine, EndLine: Integer);
+var
+  rct: TRect;
+begin
+  FSelStartX := 0;
+  FSelStartY := StartLine;
+  FSelEndX := Length(Lines[EndLine]);
+  FSelEndY := EndLine;
+  rct := LineRangeRect(FSelStartY, FSelEndY);
+  SelectionChanged;
+  InvalidateRect(Handle, @rct, true);
+end;
+
+procedure TGLSCustomMemo.SelectChar(LineNo, Pos, StyleNo: Integer);
+var
+  rct: TRect;
+begin
+  UnselectChar;
+  FSelCharPos.LineNo := LineNo;
+  FSelCharPos.Pos := Pos;
+  FSelCharStyle := StyleNo;
+  rct := LineRect(LineNo);
+  InvalidateRect(Handle, @rct, True);
+end;
+
+procedure TGLSCustomMemo.UnSelectChar;
+var
+  rct: TRect;
+begin
+  with FSelCharPos do
+  begin
+    if LineNo < 0 then
+      Exit;
+    rct := LineRect(LineNo);
+    LineNo := -1;
+    Pos := -1;
+  end;
+  FSelCharStyle := -1;
+  InvalidateRect(Handle, @rct, True);
+end;
+
+//--------------------------------------------------------------
+//        CLEAR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.Clear;
+begin
+  CurY := 0;
+  CurX := 0;
+  FLeftCol := 0;
+  FTopLine := 0;
+  Lines.Clear;
+  TGLSMemoStrings(Lines).DoAdd('');
+  ClearUndoList;
+  Invalidate;
+end;
+
+//--------------------------------------------------------------
+//        SELECT ALL
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SelectAll;
+begin
+  FSelStartY := 0;
+  FSelStartX := 0;
+  FSelEndY := Lines.Count - 1;
+  FSelEndX := Length(Lines[Lines.Count - 1]);
+  Invalidate;
+end;
+
+//-----------------------------------------------------------
+//   SET CLIPBOARD CODE PAGE
+//-----------------------------------------------------------
+
+procedure SetClipboardCodePage(const CodePage: longint);
+var
+  Data: THandle;
+  DataPtr: Pointer;
+begin
+  // Define new code page for clipboard
+  Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 4);
+  try
+    DataPtr := GlobalLock(Data);
+    try
+      Move(CodePage, DataPtr^, 4);
+      SetClipboardData(CF_LOCALE, Data);
+    finally
+      GlobalUnlock(Data);
+    end;
+  except
+    GlobalFree(Data);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        COPY TO CLIPBOARD
+//--------------------------------------------------------------
+
+procedure CopyStringToClipboard(const Value: string);
+const
+  RusLocale = (SUBLANG_DEFAULT shl $A) or LANG_RUSSIAN;
+begin
+  Clipboard.Open;
+  SetClipboardCodePage(RusLocale);
+  try
+    Clipboard.AsText := Value;
+  finally
+    SetClipboardCodePage(RusLocale);
+    Clipboard.Close;
+  end;
+end;
+
+procedure TGLSCustomMemo.CopyToClipBoard;
+begin
+  CopyStringToClipboard(GetSelText);
+end;
+//--------------------------------------------------------------
+//        PASTE FROM CLIPBOARD
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.PasteFromClipBoard;
+var
+  H, len: integer;
+  Buff: string;
+begin
+  H := ClipBoard.GetAsHandle(CF_TEXT);
+  len := GlobalSize(H);
+  if len = 0 then
+    Exit;
+
+  SetLength(Buff, len);
+  SetLength(Buff, ClipBoard.GetTextBuf(PChar(Buff), len));
+  AdjustLineBreaks(Buff);
+
+  SetSelText(Buff);
+end;
+
+//--------------------------------------------------------------
+//        DELETE SELECTION
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DeleteSelection(bRepaint: Boolean);
+var
+  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+  i, len: integer;
+  OldX, OldY: integer;
+  S1, S2, S, AddSpaces: string;
+  Undo: TGLSMemoDeleteBufUndo;
+begin
+  if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
+    Exit;
+
+  OldX := CurX;
+  OldY := CurY;
+  xSelStartX := FSelStartX;
+  xSelStartY := FSelStartY;
+  xSelEndX := FSelEndX;
+  xSelEndY := FSelEndY;
+  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+
+  if xSelStartY = xSelEndY then
+  begin
+    S1 := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX);
+    S2 := '';
+    AddSpaces := '';
+  end
+  else
+  begin
+    len := Length(Lines[xSelStartY]);
+    S1 := Copy(Lines[xSelStartY], xSelStartX + 1, len);
+    AddSpaces := StringOfChar(' ', xSelStartX - len);
+    S2 := Copy(Lines[xSelEndY], 1, xSelEndX);
+  end;
+  Lines[xSelStartY] := Copy(Lines[xSelStartY], 1, xSelStartX) + AddSpaces +
+    Copy(Lines[xSelEndY], xSelEndX + 1, Length(Lines[xSelEndY]));
+  S := S1;
+  for i := xSelStartY + 1 to xSelEndY do
+  begin
+    S := S + #13#10;
+    if i <> xSelEndY then
+      S := S + Lines[xSelStartY + 1];
+    DeleteLine(xSelStartY + 1, -1, -1, -1, -1, False);
+  end;
+  S := S + S2;
+
+  CurY := xSelStartY;
+  CurX := xSelStartX;
+  ClearSelection;
+
+  Changed(xSelStartY, -1);
+  SelectionChanged;
+  if bRepaint then
+    Invalidate;
+
+  Undo := TGLSMemoDeleteBufUndo.Create(OldX, OldY, CurX, CurY, S);
+  Undo.UndoSelStartX := xSelStartX;
+  Undo.UndoSelStartY := xSelStartY;
+  Undo.UndoSelEndX := xSelEndX;
+  Undo.UndoSelEndY := xSelEndY;
+  if Assigned(FUndoList) then
+    FUndoList.Add(Undo);
+end;
+
+//--------------------------------------------------------------
+//        CUT TO CLIPBOARD
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.CutToClipBoard;
+begin
+  ClipBoard.SetTextBuf(PChar(GetSelText));
+  DeleteSelection(True);
+end;
+
+//--------------------------------------------------------------
+//        GET SEL TEXT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetSelText: string;
+var
+  i: integer;
+  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+begin
+  Result := '';
+  if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
+    Exit;
+
+  xSelStartX := FSelStartX;
+  xSelStartY := FSelStartY;
+  xSelEndX := FSelEndX;
+  xSelEndY := FSelEndY;
+  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+
+  if xSelStartY = xSelEndY then
+    Result := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX)
+  else
+  begin
+    Result := Copy(Lines[xSelStartY], xSelStartX + 1,
+      Length(Lines[xSelStartY]));
+    for i := xSelStartY + 1 to xSelEndY - 1 do
+      Result := Result + #13#10 + Lines[i];
+    Result := Result + #13#10 + Copy(Lines[xSelEndY], 1, xSelEndX);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        GET SEL START
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetSelStart: TPoint;
+var
+  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+begin
+  xSelStartX := FSelStartX;
+  xSelStartY := FSelStartY;
+  xSelEndX := FSelEndX;
+  xSelEndY := FSelEndY;
+  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+  Result := Point(xSelStartX, xSelStartY);
+end;
+
+//--------------------------------------------------------------
+//        GET SEL END
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetSelEnd: TPoint;
+var
+  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+begin
+  xSelStartX := FSelStartX;
+  xSelStartY := FSelStartY;
+  xSelEndX := FSelEndX;
+  xSelEndY := FSelEndY;
+  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+  Result := Point(xSelEndX, xSelEndY);
+end;
+
+//--------------------------------------------------------------
+//        SET SEL TEXT
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetSelText(const AValue: string);
+var
+  i, k: integer;
+  xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+  Buff, S: string;
+  OldX, OldY: integer;
+begin
+  Buff := AValue;
+  xSelStartX := FSelStartX;
+  xSelStartY := FSelStartY;
+  xSelEndX := FSelEndX;
+  xSelEndY := FSelEndY;
+  OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+
+  DeleteSelection(False);
+
+  OldX := CurX;
+  OldY := CurY;
+  i := Pos(#13#10, Buff);
+  S := Lines[xSelStartY];
+  if i = 0 then
+  begin
+    Lines[xSelStartY] := Copy(S, 1, xSelStartX) + Buff
+      + Copy(S, xSelStartX + 1, Length(S));
+    CurX := xSelStartX;
+    if Buff <> '' then
+      CurX := CurX + Length(Buff);
+  end
+  else
+  begin
+    k := xSelStartY;
+    Lines[k] := Copy(S, 1, xSelStartX) + Copy(Buff, 1, i - 1);
+    TGLSMemoStrings(Lines).DoInsert(k + 1, Copy(S, xSelStartX + 1, Length(S)));
+    while True do
+    begin
+      Buff := Copy(Buff, i + 2, Length(Buff));
+      i := Pos(#13#10, Buff);
+      k := k + 1;
+      if i = 0 then
+        break;
+      TGLSMemoStrings(Lines).DoInsert(k, Copy(Buff, 1, i - 1));
+    end;
+    Lines[k] := Buff + Lines[k];
+    CurY := k;
+    CurX := Length(Buff);
+  end;
+
+  ClearSelection;
+  Changed(xSelStartY, -1);
+  if Assigned(FUndoList) then
+    FUndoList.Add(TGLSMemoPasteUndo.Create(OldX, OldY, CurX, CurY, AValue));
+  Invalidate;
+end;
+
+//--------------------------------------------------------------
+//        GET SEL LENGTH
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetSelLength: integer;
+begin
+  Result := Length(GetSelText);
+end;
+
+//--------------------------------------------------------------
+//        CHANGED
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.Changed(FromLine, ToLine: integer);
+var
+  i: integer;
+begin
+  if ToLine < FromLine then
+    ToLine := Lines.Count - 1;
+  for i := FromLine to ToLine do
+    ValidAttrs[i] := False;
+  InvalidateLineRange(FromLine, ToLine);
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+//--------------------------------------------------------------
+//        ATTR CHANGED
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.AttrChanged(LineNo: integer);
+begin
+  ValidAttrs[LineNo] := False;
+  InvalidateLineRange(LineNo, LineNo);
+  if Assigned(FOnAttrChange) then
+    FOnAttrChange(Self);
+end;
+
+//--------------------------------------------------------------
+//        SELECTION CHANGED
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SelectionChanged;
+begin
+  if Assigned(FOnSelectionChange) then
+    FOnSelectionChange(Self);
+end;
+
+//--------------------------------------------------------------
+//        STATUS CHANGED
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.StatusChanged;
+begin
+  if Assigned(FOnStatusChange) then
+    FOnStatusChange(Self);
+end;
+
+//--------------------------------------------------------------
+//        CLEAR SELECTION
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ClearSelection;
+var
+  rct: TRect;
+  Changed: Boolean;
+begin
+  Changed := not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY));
+  rct := LineRangeRect(FSelStartY, FSelEndY);
+  FSelStartX := CurX;
+  FSelStartY := CurY;
+  FSelEndX := CurX;
+  FSelEndY := CurY;
+  FPrevSelX := CurX;
+  FPrevSelY := CurY;
+  if Changed then
+  begin
+    SelectionChanged;
+    InvalidateRect(Handle, @rct, true);
+  end;
+  if Assigned(FOnMoveCursor) then
+    FOnMoveCursor(Self);
+end;
+
+//--------------------------------------------------------------
+//        EXPAND SELECTION
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ExpandSelection;
+var
+  rct: TRect;
+begin
+  rct := LineRangeRect(FPrevSelY, CurY);
+  FSelEndX := CurX;
+  FSelEndY := CurY;
+  FPrevSelX := CurX;
+  FPrevSelY := CurY;
+  SelectionChanged;
+  InvalidateRect(Handle, @rct, true);
+  if Assigned(FOnMoveCursor) then
+    FOnMoveCursor(Self);
+end;
+
+//--------------------------------------------------------------
+//        MAX LENGTH
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.MaxLength: integer;
+var
+  i, len: integer;
+begin
+  Result := 0;
+  for i := 0 to Lines.Count - 1 do
+  begin
+    len := Length(Lines[i]);
+    if len > Result then
+      Result := len;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        DO SCROLL
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
+var
+  eRect, scrRect, sbRect: TRect;
+  Old: integer;
+begin
+  eRect := EditorRect;
+  case Sender.Kind of
+    sbVertical:
+      begin
+        Old := FTopLine;
+        FTopLine := FTopLine + ByValue;
+        if FTopLine > Sender.MaxPosition then
+          FTopLine := Sender.MaxPosition;
+        if FTopLine < 0 then
+          FTopLine := 0;
+        if Old <> FTopLine then
+        begin
+          ShowCaret(False);
+          if CurY < FTopLine then
+            CurY := FTopLine;
+          if CurY > LastVisibleLine then
+            CurY := LastVisibleLine;
+
+          ScrollDC(Canvas.Handle, 0, (Old - FTopLine) * FCellSize.H,
+            eRect, eRect, 0, @scrRect);
+          InvalidateRect(Handle, @scrRect, True);
+          sbRect := Sender.FullRect;
+          InvalidateRect(Handle, @sbRect, True);
+          FGutter.Invalidate;
+          ShowCaret(True);
+        end;
+      end;
+    sbHorizontal:
+      begin
+        Old := FLeftCol;
+        FLeftCol := FLeftCol + ByValue;
+        if FLeftCol > Sender.MaxPosition then
+          FLeftCol := Sender.MaxPosition;
+        if FLeftCol < 0 then
+          FLeftCol := 0;
+        if Old <> FLeftCol then
+        begin
+          ShowCaret(False);
+          if CurX < FLeftCol then
+            CurX := FLeftCol;
+          if CurX > LastVisiblePos then
+            CurX := LastVisiblePos;
+          ScrollDC(Canvas.Handle, (Old - FLeftCol) * FCellSize.W, 0,
+            eRect, eRect, 0, @scrRect);
+          InvalidateRect(Handle, @scrRect, True);
+          sbRect := Sender.FullRect;
+          InvalidateRect(Handle, @sbRect, True);
+          ShowCaret(True);
+        end;
+      end;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        DO SCROLL PAGE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DoScrollPage(Sender: TGLSMemoScrollBar; ByValue:
+  integer);
+begin
+  case Sender.Kind of
+    sbVertical: DoScroll(Sender, ByValue * VisibleLineCount);
+    sbHorizontal: DoScroll(Sender, ByValue * VisiblePosCount);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SET LINES
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetLines(ALines: TStrings);
+begin
+  if ALines <> nil then
+  begin
+    FLines.Assign(ALines);
+    Changed(0, -1);
+    SelectionChanged;
+    Invalidate;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SET/GET LINE STYLE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetLineStyle(Index: integer; Value: integer);
+begin
+  TGLSMemoStrings(FLines).Style[Index] := Value;
+  if IsLineVisible(Index) then
+    AttrChanged(Index);
+end;
+
+function TGLSCustomMemo.GetLineStyle(Index: integer): integer;
+begin
+  Result := TGLSMemoStrings(FLines).Style[Index];
+end;
+
+//--------------------------------------------------------------
+//        GET/SET IN COMMENT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetInComment(Index: integer): Boolean;
+begin
+  Result := TGLSMemoStrings(FLines).InComment[Index];
+end;
+
+procedure TGLSCustomMemo.SetInComment(Index: integer; Value: Boolean);
+begin
+  TGLSMemoStrings(FLines).InComment[Index] := Value;
+end;
+
+//--------------------------------------------------------------
+//        GET/SET IN BRACKETS
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetInBrackets(Index: integer): integer;
+begin
+  Result := TGLSMemoStrings(FLines).InBrackets[Index];
+end;
+
+procedure TGLSCustomMemo.SetInBrackets(Index: integer; Value: integer);
+begin
+  TGLSMemoStrings(FLines).InBrackets[Index] := Value;
+end;
+
+//--------------------------------------------------------------
+//        GET/SET VALID ATTRS
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetValidAttrs(Index: integer): Boolean;
+begin
+  Result := TGLSMemoStrings(FLines).ValidAttrs[Index];
+end;
+
+procedure TGLSCustomMemo.SetValidAttrs(Index: integer; Value: Boolean);
+begin
+  TGLSMemoStrings(FLines).ValidAttrs[Index] := Value;
+end;
+
+//--------------------------------------------------------------
+//        GET/SET CHAR ATTRS
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetCharAttrs(Index: integer): string;
+begin
+  Result := TGLSMemoStrings(FLines).CharAttrs[Index];
+end;
+
+procedure TGLSCustomMemo.SetCharAttrs(Index: integer; const Value: string);
+begin
+  TGLSMemoStrings(FLines).CharAttrs[Index] := Value;
+  if IsLineVisible(Index) then
+    AttrChanged(Index);
+end;
+
+//--------------------------------------------------------------
+//        SET CUR X
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetCurX(Value: integer);
+var
+  len: integer;
+  WasVisible: Boolean;
+begin
+  if Value < 0 then
+    if CurY = 0 then
+      Value := 0
+    else
+    begin
+      CurY := CurY - 1;
+      Value := Length(Lines[CurY]);
+    end;
+
+  if (CurY >= 0) and (CurY < Lines.Count) then
+  begin
+    len := Length(Lines[CurY]);
+    if Value > len then
+    begin
+      Lines[CurY] := Lines[CurY] + StringOfChar(' ', Value - len);
+      // Value := len;
+      ValidAttrs[CurY] := False;
+      InvalidateLineRange(CurY, CurY);
+    end;
+  end;
+
+  FCurX := Value;
+
+  WasVisible := FCaretVisible;
+  if WasVisible then
+    ShowCaret(False);
+  MakeVisible;
+  ResizeScrollBars;
+  StatusChanged;
+  if WasVisible then
+    ShowCaret(True);
+end;
+
+//--------------------------------------------------------------
+//        SET CUR Y
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetCurY(Value: integer);
+var
+  Old: integer;
+  WasVisible: Boolean;
+begin
+  WasVisible := FCaretVisible;
+  if WasVisible then
+    ShowCaret(False);
+  Old := CurY;
+
+  if Value < 0 then
+    Value := 0;
+  if Value >= Lines.Count then
+    Value := Lines.Count - 1;
+
+  FCurY := Value;
+  if (CurY <> Old) and (Old >= 0) and (Old < Lines.Count) then
+    Lines[Old] := TrimRight(Lines[Old]);
+  CurX := CurX;
+
+  MakeVisible;
+  ResizeScrollBars;
+  StatusChanged;
+  if WasVisible then
+    ShowCaret(True);
+end;
+
+//--------------------------------------------------------------
+//        MOVE CURSOR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.MoveCursor(dX, dY: integer; Shift: TShiftState);
+var
+  Selecting: Boolean;
+  //------------------------------------------------------------
+  function IsDelimiter(c: char): Boolean;
+  begin
+    Result := Pos(c, ' .,;:/?!@#$%^&*(){}[]<>-+=|\') > 0;
+  end;
+  //------------------------------------------------------------
+  function IsStopChar(c, cThis: char): Boolean;
+  begin
+    Result := IsDelimiter(c) <> IsDelimiter(cThis);
+  end;
+  //------------------------------------------------------------
+  procedure MoveWordLeft;
+  var
+    S: string;
+  begin
+    CurX := CurX - 1;
+    S := TrimRight(Lines[CurY]);
+    while CurX > 0 do
+    begin
+      if IsStopChar(S[CurX], S[CurX + 1]) then
+        break;
+      CurX := CurX - 1;
+    end;
+    if (CurX < 0) then
+      if CurY > 0 then
+      begin
+        CurY := CurY - 1;
+        CurX := Length(Lines[CurY]);
+      end;
+  end;
+  //------------------------------------------------------------
+  procedure MoveWordRight;
+  var
+    Len: integer;
+    S: string;
+  begin
+    S := TrimRight(Lines[CurY]);
+    Len := Length(S);
+    CurX := CurX + 1;
+    while CurX < Len do
+    begin
+      if IsStopChar(S[CurX + 1], S[CurX]) then
+        break;
+      CurX := CurX + 1;
+    end;
+    if CurX > Len then
+      if CurY < Lines.Count - 1 then
+      begin
+        CurY := CurY + 1;
+        CurX := 0;
+      end;
+  end;
+  //------------------------------------------------------------
+begin
+  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
+    and (CurY = FPrevSelY);
+  if ssCtrl in Shift then
+  begin
+    if dX > 0 then
+      MoveWordRight;
+    if dX < 0 then
+      MoveWordLeft;
+  end
+  else
+  begin
+    CurY := CurY + dY;
+    CurX := CurX + dX;
+  end;
+  if Selecting then
+    ExpandSelection
+  else
+    ClearSelection;
+end;
+
+//--------------------------------------------------------------
+//        MOVE PAGE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.MovePage(dP: integer; Shift: TShiftState);
+var
+  eRect: TRect;
+  LinesPerPage: integer;
+  Selecting: Boolean;
+begin
+  if FCellSize.H = 0 then
+    Exit;
+  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
+    and (CurY = FPrevSelY);
+  eRect := EditorRect;
+  LinesPerPage := (eRect.Bottom - eRect.Top) div FCellSize.H - 1;
+  CurY := CurY + dP * LinesPerPage;
+  if ssCtrl in Shift then
+    if dP > 0 then
+    begin
+      CurY := Lines.Count - 1;
+      CurX := Length(Lines[Lines.Count - 1]);
+    end
+    else
+    begin
+      CurY := 0;
+      CurX := 0;
+    end;
+  if Selecting then
+    ExpandSelection
+  else
+    ClearSelection;
+end;
+
+//--------------------------------------------------------------
+//        GO HOME
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.GoHome(Shift: TShiftState);
+var
+  Selecting: Boolean;
+begin
+  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
+    and (CurY = FPrevSelY);
+  CurX := 0;
+  FLeftCol := 0;
+  if Selecting then
+    ExpandSelection
+  else
+    ClearSelection;
+end;
+
+//--------------------------------------------------------------
+//        GO END
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.GoEnd(Shift: TShiftState);
+var
+  Selecting: Boolean;
+  S, S1: string;
+begin
+  Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
+    and (CurY = FPrevSelY);
+
+  S := Lines[CurY];
+  if not Selecting then
+    S := TrimRight(S);
+  S1 := TrimRight(Copy(S, CurX + 1, Length(S)));
+  S := Copy(S, 1, CurX);
+  Lines[CurY] := S + S1;
+
+  CurX := Length(Lines[CurY]);
+  if Selecting then
+    ExpandSelection
+  else
+    ClearSelection;
+end;
+
+//--------------------------------------------------------------
+//        INSERT CHAR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.InsertChar(C: Char);
+var
+  S, S1: string;
+  NewPlace: integer;
+  rct: TRect;
+  CurX0, CurY0: integer;
+begin
+  CurX0 := CurX;
+  CurY0 := CurY;
+  S := Lines[CurY];
+  NewPlace := CurX + 1;
+  if C = #9 then
+  begin
+    while (NewPlace mod TabSize) <> 0 do
+      Inc(NewPlace);
+    S1 := StringOfChar(' ', NewPlace - CurX);
+  end
+  else
+    S1 := C;
+  Insert(S1, S, CurX + 1);
+  Lines[CurY] := S;
+  CurX := NewPlace;
+  ClearSelection;
+  rct := LineRect(CurY);
+  Changed(CurY, CurY);
+
+  if Assigned(FUndoList) then
+    FUndoList.Add(TGLSMemoInsCharUndo.Create(CurX0, CurY0, CurX, CurY, S1));
+
+  InvalidateRect(Handle, @rct, True);
+end;
+
+//--------------------------------------------------------------
+//        INSERT TEMPLATE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.InsertTemplate(AText: string);
+var
+  i, NewCurX, NewCurY: integer;
+  Indent: string;
+  FoundCursor: Boolean;
+begin
+  Indent := IndentCurrLine;
+
+  DeleteSelection(False);
+  ClearSelection;
+
+  NewCurX := CurX;
+  NewCurY := CurY;
+  FoundCursor := False;
+  i := 1;
+  while i <= Length(AText) do
+  begin
+    if AText[i] = #13 then
+    begin
+      if (i = Length(AText)) or (AText[i + 1] <> #10) then
+        Insert(#10 + Indent, AText, i + 1);
+      if not FoundCursor then
+      begin
+        Inc(NewCurY);
+        NewCurX := Length(Indent);
+      end;
+      Inc(i, 1 + Length(Indent));
+    end
+    else if AText[i] = #7 then
+    begin
+      FoundCursor := True;
+      Delete(AText, i, 1);
+      Dec(i);
+    end
+    else if Ord(AText[i]) < Ord(' ') then
+    begin
+      Delete(AText, i, 1);
+      Dec(i);
+    end
+    else if not FoundCursor then
+      Inc(NewCurX);
+    Inc(i);
+  end;
+
+  SetSelText(AText);
+  SetCursor(NewCurX, NewCurY);
+  ClearSelection;
+  try
+    SetFocus;
+  except
+  end;
+
+end;
+
+//--------------------------------------------------------------
+//        DELETE CHAR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DeleteChar(OldX, OldY: integer);
+var
+  S, S1: string;
+  rct: TRect;
+  C: char;
+  Undo: TGLSMemoDelCharUndo;
+  IsBackspace: Boolean;
+begin
+  if FReadOnly then
+    Exit;
+  if OldX < 0 then
+  begin
+    OldX := CurX;
+    OldY := CurY;
+    IsBackspace := False;
+  end
+  else
+    IsBackspace := True;
+
+  ClearSelection;
+
+  S := Lines[CurY];
+  S1 := Copy(S, CurX + 1, Length(S));
+  if not IsBackspace then
+    S1 := TrimRight(S1);
+  S := Copy(S, 1, CurX);
+  Lines[CurY] := S + S1;
+
+  if CurX < Length(Lines[CurY]) then
+  begin
+    S := Lines[CurY];
+    C := S[CurX + 1];
+    Delete(S, CurX + 1, 1);
+    Lines[CurY] := S;
+    Changed(CurY, CurY);
+    rct := LineRect(CurY);
+    Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, C);
+    Undo.IsBackSpace := IsBackSpace;
+    if Assigned(FUndoList) then
+      FUndoList.Add(Undo);
+  end
+  else if CurY < Lines.Count - 1 then
+  begin
+    S := Lines[CurY] + Lines[CurY + 1];
+    Lines[CurY] := S;
+    DeleteLine(CurY + 1, OldX, OldY, CurX, CurY, False);
+    Changed(CurY, -1);
+    rct := EditorRect;
+    Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, #13);
+    Undo.IsBackSpace := IsBackSpace;
+    if Assigned(FUndoList) then
+      FUndoList.Add(Undo);
+  end;
+  ClearSelection;
+  InvalidateRect(Handle, @rct, True);
+end;
+
+//--------------------------------------------------------------
+//        DELETE LINE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DeleteLine(Index, OldX, OldY, NewX, NewY: integer;
+  FixUndo: Boolean);
+var
+  rct: TRect;
+  s: string;
+begin
+  if Index < 0 then
+    Index := CurY;
+  if OldX < 0 then
+  begin
+    OldX := CurX;
+    OldY := CurY;
+  end;
+
+  s := Lines[Index];
+
+  TGLSMemoStrings(Lines).FDeleting := True;
+  if Lines.Count = 1 then
+    TGLSMemoStrings(Lines)[0] := ''
+  else
+    Lines.Delete(Index);
+  TGLSMemoStrings(Lines).FDeleting := False;
+
+  ClearSelection;
+  if Index >= Lines.Count then
+    Changed(Index - 1, -1)
+  else
+    Changed(Index, -1);
+  rct := EditorRect;
+  InvalidateRect(Handle, @rct, True);
+
+  if NewX < 0 then
+  begin
+    if Length(Lines[0]) < CurX then
+      CurX := Length(Lines[0]);
+    if Index >= Lines.Count then
+      CurY := Index - 1
+    else
+      CurY := Index;
+    NewX := CurX;
+    NewY := CurY;
+  end
+  else
+  begin
+    CurX := NewX;
+    CurY := NewY;
+  end;
+  if Assigned(FUndoList) and FixUndo then
+    FUndoList.Add(TGLSMEmoDelLineUndo.Create(Index, OldX, OldY, NewX, NewY, s));
+end;
+
+//--------------------------------------------------------------
+//        BACK SPACE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.BackSpace;
+var
+  OldX, OldY: integer;
+begin
+  OldX := CurX;
+  OldY := CurY;
+  MoveCursor(-1, 0, []);
+  if (OldX = CurX) and (OldY = CurY) then
+    Exit;
+  DeleteChar(OldX, OldY);
+end;
+
+//--------------------------------------------------------------
+//        BACK SPACE WORD
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.BackSpaceWord;
+begin
+  ClearSelection;
+  MoveCursor(-1, 0, [ssShift, ssCtrl]);
+  DeleteSelection(True);
+end;
+
+//--------------------------------------------------------------
+//        INDENT CURR LINE
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.IndentCurrLine: string;
+var
+  Len, Count: integer;
+  CurS: string;
+begin
+  Result := '';
+  if not AutoIndent then
+    Exit;
+  CurS := Lines[CurY];
+  Len := Length(CurS);
+  Count := 0;
+  while (Count < CurX) and (Count < Len) do
+  begin
+    if CurS[Count + 1] <> ' ' then
+      break;
+    Inc(Count);
+  end;
+  Result := StringOfChar(' ', Count);
+end;
+
+//--------------------------------------------------------------
+//        NEW LINE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.NewLine;
+var
+  S, sIndent: string;
+  OldX, OldY: integer;
+begin
+  OldX := CurX;
+  OldY := CurY;
+  S := Lines[CurY];
+  sIndent := IndentCurrLine;
+  Lines[CurY] := Copy(S, 1, CurX);
+
+  S := TrimRight(Copy(S, CurX + 1, Length(S)));
+  if AutoIndent then
+    while (Length(S) > 0) and (S[1] = ' ') do
+      Delete(S, 1, 1);
+
+  TGLSMemoStrings(Lines).DoInsert(CurY + 1, sIndent + S);
+  GoHome([]);
+  MoveCursor(0, 1, []);
+  CurX := Length(sIndent);
+  ClearSelection;
+  if Assigned(FUndoList) then
+    FUndoList.Add(TGLSMemoInsCharUndo.Create(OldX, OldY, CurX, CurY, #13 +
+      sIndent));
+  Invalidate;
+  Changed(CurY - 1, -1);
+end;
+
+//--------------------------------------------------------------
+//        ADD STRING
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.AddString(const S: string): integer;
+begin
+  if Lines.Count = 0 then
+    TGLSMemoStrings(Lines).DoAdd('');
+  MovePage(1, [ssCtrl]); // end of text
+  if not ((Lines.Count = 1) and (Lines[0] = '')) then
+  begin
+    TGLSMemoStrings(Lines).DoAdd('');
+    CurX := 0;
+    CurY := Lines.Count;
+    ClearSelection;
+    // S := #13#10 + S;
+  end;
+  SetSelText(S);
+  Result := Lines.Count - 1;
+end;
+
+//--------------------------------------------------------------
+//        INSERT STRING
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.InsertString(Index: integer; S: string);
+begin
+  CurY := Index;
+  CurX := 0;
+  ClearSelection;
+  if not ((Lines.Count = 1) and (Lines[0] = '')) then
+    S := S + #13#10;
+  SetSelText(S);
+end;
+
+//--------------------------------------------------------------
+//        DO COMMAND
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DoCommand(cmd: TCommand; const AShift: TShiftState);
+begin
+  case cmd of
+    cmDelete: if not FReadOnly then
+      begin
+        if ssShift in AShift then
+          CutToClipboard
+        else if FDelErase and
+          (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY))) then
+          DeleteSelection(True)
+        else
+          DeleteChar(-1, -1);
+      end;
+    cmBackSpace: BackSpace;
+    cmWordBackSpace: BackSpaceWord;
+    cmNewLine: NewLine;
+    cmDelLine: DeleteLine(-1, -1, -1, -1, -1, True);
+    cmCopy: CopyToClipboard;
+    cmCut: CutToClipboard;
+    cmPaste: PasteFromClipboard;
+    cmHome: GoHome(AShift);
+    cmEnd: GoEnd(AShift);
+    cmPageDown: MovePage(1, AShift);
+    cmPageUp: MovePage(-1, AShift);
+    cmInsert:
+      begin
+        if ssShift in AShift then
+          PasteFromClipboard;
+        if ssCtrl in AShift then
+          CopyToClipboard;
+      end;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        KEY DOWN
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.KeyDown(var Key: Word; Shift: TShiftState);
+begin
+  ShowCaret(False);
+  inherited;
+  case Key of
+    VK_LEFT: MoveCursor(-1, 0, Shift);
+    VK_RIGHT: MoveCursor(1, 0, Shift);
+    VK_UP: MoveCursor(0, -1, Shift);
+    VK_DOWN: MoveCursor(0, 1, Shift);
+    VK_HOME, VK_END,
+      VK_DELETE: DoCommand(Key, Shift);
+    VK_PRIOR, VK_NEXT:
+      DoCommand(Key, Shift);
+    VK_INSERT: DoCommand(Key, Shift);
+  end;
+  ShowCaret(True);
+end;
+
+//--------------------------------------------------------------
+//        KEY PRESS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.KeyPress(var Key: Char);
+begin
+  if FReadOnly then
+    Exit;
+  ShowCaret(False);
+  inherited;
+  if (ord(Key) in [9, 32..255]) and (ord(Key) <> 127) then
+  begin
+    if FDelErase and (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY)))
+      then
+      DeleteSelection(True);
+    InsertChar(Key);
+  end
+  else
+    DoCommand(Ord(Key), []);
+  ShowCaret(True);
+end;
+
+//--------------------------------------------------------------
+//        MOUSE DOWN
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.MouseDown(Button: TMouseButton; Shift: TShiftState;
+  X, Y: Integer);
+var
+  newPos: TCellPos;
+  charPos: TFullPos;
+  Selecting: Boolean;
+begin
+  inherited;
+  if not Focused then
+  begin
+    SetFocus;
+    //     Exit;
+  end;
+
+  if FAfterDoubleClick then
+  begin
+    FAfterDoubleClick := False;
+    Exit;
+  end;
+
+  if Button <>mbLeft then
+    Exit;
+
+
+  if sbVert.MouseDown(Button, Shift, X, Y) then
+    Exit;
+  if sbHorz.MouseDown(Button, Shift, X, Y) then
+    Exit;
+
+  if PointInRect(Point(X, Y), EditorRect) then
+  begin
+    ShowCaret(False);
+    newPos := CellFromPos(X, Y);
+    CurY := newPos.Y + FTopLine;
+    CurX := newPos.X + FLeftCol;
+    if Assigned(FOnMoveCursor) then
+      FOnMoveCursor(Self);
+
+    Selecting := ssShift in Shift;
+    if Button = mbLeft then
+    begin
+      if Selecting then
+        ExpandSelection
+      else
+        ClearSelection;
+      FLeftButtonDown := True;
+    end
+    else
+      ShowCaret(True);
+  end;
+
+  if Assigned(FOnGutterClick) then
+    if PointInRect(Point(X, Y), FGutter.FullRect) then
+    begin
+      charPos := CharFromPos(X, Y);
+      if charPos.LineNo < Lines.Count then
+        FOnGutterClick(Self, charPos.LineNo);
+    end;
+end;
+
+//--------------------------------------------------------------
+//        MOUSE MOVE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
+var
+  newPos: TCellPos;
+begin
+  inherited;
+  if sbVert.MouseMove(Shift, X, Y) then
+    Exit;
+  if sbHorz.MouseMove(Shift, X, Y) then
+    Exit;
+  if PointInRect(Point(X, Y), EditorRect) then
+  begin
+    if (ssLeft in Shift) and FLeftButtonDown then
+    begin
+      newPos := CellFromPos(X, Y);
+      CurY := newPos.Y + FTopLine;
+      CurX := newPos.X + FLeftCol;
+      ExpandSelection;
+    end;
+  end
+end;
+
+//--------------------------------------------------------------
+//        MOUSE UP
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:
+  Integer);
+begin
+  inherited;
+  if sbVert.MouseUp(Button, Shift, X, Y) then
+    Exit;
+  if sbHorz.MouseUp(Button, Shift, X, Y) then
+    Exit;
+  if Button = mbLeft then
+    ShowCaret(True);
+  FLeftButtonDown := False;
+  FLastMouseUpX := X;
+  FLastMouseUpY := Y;
+end;
+
+//--------------------------------------------------------------
+//        DBL CLICK
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DblClick;
+var
+  clickPos: TCellPos;
+  clickX, clickY: integer;
+  //------------------------------------------------------------
+  //   SELECT WORD
+  //------------------------------------------------------------
+  procedure SelectWord;
+  const
+    stopChars: TSysCharSet = [' ', ';', '.', ',', ':', '?', '!', '''', '"',
+      '<', '>', '/', '*', '+', '-', '=', '(', ')',
+      '[', ']', '{', '}', '@', '#', '$', '%', '^',
+      '&', '|', '\'];
+  var
+    s: string;
+    i: integer;
+    rct: TRect;
+  begin
+    CurX := clickX;
+    CurY := clickY;
+    if (CurX = clickX) and (CurY = clickY) then
+    begin
+      s := Lines[clickY];
+      if s[clickX + 1] = ' ' then
+        Exit;
+
+      i := clickX;
+      while (i >= 0) and not CharInSet(s[i + 1], stopChars) do
+        Dec(i);
+      FSelStartY := clickY;
+      FSelStartX := i + 1;
+
+      i := clickX;
+      while (i < Length(s)) and not CharInSet(s[i + 1], stopChars) do
+        Inc(i);
+      FSelEndY := clickY;
+      FSelEndX := i;
+
+      if FSelEndX <> FSelStartX then
+      begin
+        FAfterDoubleClick := True;
+        rct := LineRangeRect(CurY, CurY);
+        SelectionChanged;
+        InvalidateRect(Handle, @rct, true);
+      end;
+    end;
+  end;
+  //------------------------------------------------------------
+begin
+
+  if PointInRect(Point(FLastMouseUpX, FLastMouseUpY), EditorRect) then
+  begin
+    clickPos := CellFromPos(FLastMouseUpX, FLastMouseUpY);
+    clickX := clickPos.X + FLeftCol;
+    clickY := clickPos.Y + FTopLine;
+    SelectWord;
+  end;
+  inherited;
+end;
+
+//--------------------------------------------------------------
+//        WM_GETDLGCODE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.WMGetDlgCode(var Msg: TWMGetDlgCode);
+begin
+  Msg.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
+end;
+
+//--------------------------------------------------------------
+//        WM_ERASEBKGND
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.WMEraseBkgnd(var Msg: TWmEraseBkgnd);
+begin
+  Msg.Result := 1;
+end;
+
+//--------------------------------------------------------------
+//        WM_SIZE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.WMSize(var Msg: TWMSize);
+begin
+  if not (csLoading in ComponentState) then
+    try
+      ResizeEditor;
+    except
+    end;
+end;
+
+//--------------------------------------------------------------
+//        WM_SETCURSOR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.WMSetCursor(var Msg: TWMSetCursor);
+var
+  P: TPoint;
+begin
+  Msg.Result := 1;
+  GetCursorPos(P);
+  P := ScreenToClient(P);
+  if PointInRect(P, EditorRect) then
+    Winapi.Windows.SetCursor(Screen.Cursors[crIBeam])
+  else
+    Winapi.Windows.SetCursor(Screen.Cursors[crArrow]);
+end;
+
+//--------------------------------------------------------------
+//        WM_SETFOCUS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.WMSetFocus(var Msg: TWMSetFocus);
+begin
+  if FCellSize.H = 0 then
+    SetFont(FFont);
+  CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
+  ShowCaret(true);
+end;
+
+//--------------------------------------------------------------
+//        WM_KILLFOCUS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.WMKillFocus(var Msg: TWMSetFocus);
+begin
+  DestroyCaret;
+  FCaretVisible := False;
+  inherited;
+end;
+
+//--------------------------------------------------------------
+//        SHOW CARET
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ShowCaret(State: Boolean);
+var
+  rct: TRect;
+begin
+  FCaretVisible := False;
+  if not State then
+    HideCaret(Handle)
+  else if Focused and not HiddenCaret then
+  begin
+    rct := CellRect(CurX - FLeftCol, CurY - FTopLine);
+    SetCaretPos(rct.Left, rct.Top + 1);
+    Winapi.Windows.ShowCaret(Handle);
+    FCaretVisible := True;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        CELL RECT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.CellRect(ACol, ARow: integer): TRect;
+var
+  rct: TRect;
+begin
+  rct := EditorRect;
+  with FCellSize do
+    Result := Rect(rct.Left + W * ACol, rct.Top + H * ARow,
+      rct.Left + W * (ACol + 1), rct.Top + H * (ARow + 1));
+end;
+
+//--------------------------------------------------------------
+//        LINE RECT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.LineRect(ARow: integer): TRect;
+var
+  rct: TRect;
+begin
+  rct := EditorRect;
+  ARow := ARow - FTopLine;
+  with FCellSize do
+    Result := Rect(rct.Left, rct.Top + H * ARow, rct.Right, rct.Top + H * (ARow
+      + 1));
+end;
+
+//--------------------------------------------------------------
+//        COL RECT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.ColRect(ACol: integer): TRect;
+var
+  rct: TRect;
+begin
+  rct := EditorRect;
+  ACol := ACol - FLeftCol;
+  with FCellSize do
+    Result := Rect(rct.Left + W * ACol, rct.Top, rct.Left + W * (ACol + 1),
+      rct.Bottom);
+end;
+
+//--------------------------------------------------------------
+//        LINE RANGE RECT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.LineRangeRect(FromLine, ToLine: integer): TRect;
+var
+  rct1, rct2: TRect;
+begin
+  rct1 := LineRect(FromLine);
+  rct2 := LineRect(ToLine);
+  Result := TotalRect(rct1, rct2);
+end;
+
+//--------------------------------------------------------------
+//        INVALIDATE LINE RANGE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.InvalidateLineRange(FromLine, ToLine: integer);
+var
+  rct: TRect;
+begin
+  if ToLine < FromLine then
+    ToLine := Lines.Count - 1;
+  rct := LineRangeRect(FromLine, ToLine);
+  if GutterWidth > 2 then
+    rct.Left := FGutter.Left;
+  InvalidateRect(Handle, @rct, True);
+end;
+
+//--------------------------------------------------------------
+//        COL RANGE RECT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.ColRangeRect(FromCol, ToCol: integer): TRect;
+var
+  rct1, rct2: TRect;
+begin
+  rct1 := ColRect(FromCol);
+  rct2 := ColRect(ToCol);
+  Result := TotalRect(rct1, rct2);
+end;
+
+//--------------------------------------------------------------
+//        CELL and CHAR FROM POS
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.CellFromPos(X, Y: integer): TCellPos;
+var
+  rct: TRect;
+begin
+  rct := EditorRect;
+  if (FCellSize.H = 0) and Assigned(FFont) then
+    SetFont(FFont);
+  if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
+  begin
+    Result.X := (X - rct.Left) div FCellSize.W;
+    Result.Y := (Y - rct.Top) div FCellSize.H;
+  end
+  else
+  begin
+    Result.X := 0;
+    Result.Y := 0;
+  end;
+end;
+
+function TGLSCustomMemo.CharFromPos(X, Y: integer): TFullPos;
+var
+  rct: TRect;
+begin
+  rct := EditorRect;
+  if (FCellSize.H = 0) and Assigned(FFont) then
+    SetFont(FFont);
+  if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
+  begin
+    Result.Pos := (X - rct.Left) div FCellSize.W + FLeftCol;
+    Result.LineNo := (Y - rct.Top) div FCellSize.H + FTopLine;
+  end
+  else
+  begin
+    Result.Pos := 1;
+    Result.LineNo := 1;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SET COLOR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetColor(Index: integer; Value: TColor);
+var
+  eRect: TRect;
+  Changed: Boolean;
+begin
+  Changed := False;
+  case Index of
+    0: if FBkColor <> Value then
+      begin
+        FBkColor := Value;
+        FStyles.BkColor[0] := Value;
+        Changed := True;
+      end;
+    1: if FSelColor <> Value then
+      begin
+        FSelColor := Value;
+        Changed := True;
+      end;
+    2: if FSelBkColor <> Value then
+      begin
+        FSelBkColor := Value;
+        Changed := True;
+      end;
+  end;
+  if Changed then
+  begin
+    eRect := EditorRect;
+    InvalidateRect(Handle, @eRect, True);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SET FONT
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetFont(Value: TFont);
+var
+  wW, wi: integer;
+  OldFontName: string;
+  eRect: TRect;
+begin
+  OldFontName := Canvas.Font.Name;
+  Canvas.Font.Name := Value.Name;
+  wW := Canvas.TextWidth('W');
+  wi := Canvas.TextWidth('i');
+  Canvas.Font.Name := OldFontName;
+
+  if wW <> wi then
+    raise EAbort.Create('Monospace font required');
+
+  FFont.Assign(Value);
+  Canvas.Font.Assign(Value);
+  FCellSize.W := Canvas.TextWidth('W');
+  FCellSize.H := Canvas.TextHeight('W') + 1;
+
+  if FCaretVisible then
+  begin
+    ShowCaret(False);
+    DestroyCaret;
+    CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
+    ShowCaret(true);
+  end;
+
+  FStyles.TextColor[0] := FFont.Color;
+  FStyles.Style[0] := FFont.Style;
+
+  eRect := EditorRect;
+  InvalidateRect(Handle, @eRect, True);
+end;
+
+//--------------------------------------------------------------
+//        SET GUTTER WIDTH
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetGutterWidth(Value: integer);
+begin
+  FGutterWidth := Value;
+  FGutter.FWidth := Value;
+  if not (csLoading in ComponentState) then
+    ResizeEditor;
+end;
+
+//--------------------------------------------------------------
+//        SET GUTTER COLOR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetGutterColor(Value: TColor);
+begin
+  if FGutter.FColor <> Value then
+  begin
+    FGutter.FColor := Value;
+    FGutter.Invalidate;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        GET GUTTER COLOR
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetGutterColor: TColor;
+begin
+  Result := FGutter.FColor;
+end;
+
+//--------------------------------------------------------------
+//        CHAR STYLE NO
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.CharStyleNo(LineNo, Pos: integer): integer;
+var
+  ChStyle: string;
+begin
+  Result := 0;
+  if (LineNo < 0) or (LineNo >= Lines.Count) then
+    Exit;
+
+  ChStyle := CharAttrs[LineNo];
+  if (Pos <= 0) or (Pos > Length(ChStyle)) then
+    Exit;
+
+  Result := integer(ChStyle[Pos]);
+end;
+
+//--------------------------------------------------------------
+//        DRAW LINE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DrawLine(LineNo: integer);
+var
+  eRect, rct0, rct1, rct, lineRct: TRect;
+  LineSelStart, LineSelEnd, LineStyleNo, pos: integer;
+  S, S1, S2, S3, ChStyle: string;
+  //--------- FIND LINE SELECTION -------------
+  procedure FindLineSelection;
+  var
+    len: integer;
+    xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+  begin
+    xSelStartX := FSelStartX;
+    xSelStartY := FSelStartY;
+    xSelEndX := FSelEndX;
+    xSelEndY := FSelEndY;
+    OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+    len := Length(Lines[LineNo]);
+    LineSelStart := 0;
+    LineSelEnd := 0;
+    if xSelStartY = Lineno then
+    begin
+      LineSelStart := xSelStartX - FLeftCol;
+      LineSelEnd := len - FLeftCol;
+    end
+    else if (xSelStartY < LineNo) and (LineNo < xSelEndY) then
+    begin
+      LineSelStart := 0;
+      LineSelEnd := len - FLeftCol;
+    end;
+
+    if xSelEndY = LineNo then
+      LineSelEnd := xSelEndX - FLeftCol;
+
+    if LineSelEnd < LineSelStart then
+      Swap(LineSelEnd, LineSelStart);
+
+    if LineSelStart < 0 then
+      LineSelStart := 0;
+    S := Copy(Lines[LineNo], FLeftCol + 1, len);
+    S1 := Copy(S, 1, LineSelStart);
+    S2 := Copy(S, LineSelStart + 1, LineSelEnd - LineSelStart);
+    S3 := Copy(S, LineSelEnd + 1, len);
+  end;
+  //------------- DRAW PART ---------------------
+  procedure DrawPart(const Part: string; PartStyle, StartPos: integer;
+    var rct: TRect; IsSelection: Boolean);
+  var
+    len, w: integer;
+    rctInternal: TRect;
+  begin
+    len := Length(Part);
+    if len > 0 then
+      with FLineBitmap.Canvas do
+      begin
+        w := FCellSize.W * len;
+        Font.Style := FStyles.Style[PartStyle];
+        if IsSelection then
+        begin
+          Font.Color := SelColor;
+          Brush.Color := SelBkColor;
+        end
+        else
+        begin
+          if LineStyleNo = 0 then
+          begin
+            Font.Color := FStyles.TextColor[PartStyle];
+            Brush.Color := FStyles.BkColor[PartStyle];
+          end
+          else
+          begin
+            if (LineNo = FSelCharPos.LineNo) and
+              (StartPos = FSelCharPos.Pos + 1) and (Length(Part) = 1) then
+            begin
+              Font.Color := FStyles.TextColor[PartStyle];
+              Brush.Color := FStyles.BkColor[PartStyle];
+            end
+            else
+            begin
+              Font.Color := FStyles.TextColor[LineStyleNo];
+              Brush.Color := FStyles.BkColor[LineStyleNo];
+              Font.Style := FStyles.Style[LineStyleNo];
+            end;
+          end;
+        end;
+        rct.Right := rct.Left + w;
+        rctInternal := rct;
+        rctInternal.Left := rctInternal.Left - eRect.Left;
+        rctInternal.Right := rctInternal.Right - eRect.Left;
+        rctInternal.Top := rctInternal.Top - rct.Top;
+        rctInternal.Bottom := rctInternal.Bottom - rct.Top;
+        FillRect(rctInternal);
+        DrawText(Handle, PChar(Part), len, rctInternal, DT_LEFT
+          or DT_SINGLELINE or DT_NOPREFIX);
+        rct0.Left := rct.Left + w;
+        rct := rct0;
+      end;
+  end;
+  //------------- DRAW SEGMENTS ---------------------
+  procedure DrawSegments(S: string; WorkPos: integer;
+    var rct: TRect; IsSelection: Boolean);
+  var
+    i, len, ThisStyle: integer;
+  begin
+    while True do
+    begin
+      Len := Length(S);
+      if Len = 0 then
+        Exit;
+      ThisStyle := Ord(ChStyle[WorkPos]);
+      i := 1;
+      while (i <= Len) and
+        (ThisStyle = Ord(ChStyle[WorkPos + i - 1])) do
+        Inc(i);
+      DrawPart(Copy(S, 1, i - 1), ThisStyle, WorkPos, rct, IsSelection);
+      Inc(WorkPos, i - 1);
+      s := Copy(s, i, Len);
+    end;
+  end;
+  //---------------------------------------------
+begin
+  eRect := EditorRect;
+  rct := CellRect(0, LineNo - FTopLine);
+  rct0 := Rect(eRect.Left, rct.Top, eRect.Right, rct.Bottom);
+  lineRct := rct0;
+
+  if LineNo < Lines.Count then
+  begin
+
+    rct := rct0;
+    S := Lines[LineNo];
+    LineStyleNo := LineStyle[LineNo];
+    ChStyle := CharAttrs[LineNo];
+    FindLineSelection;
+
+    if not Assigned(FOnGetLineAttrs) then
+      ChStyle := StringOfChar(#0, Length(Lines[LineNo]));
+
+    if Length(S) > 0 then
+      if (FSelCharStyle >= 0) and (LineNo = FSelCharPos.LineNo) then
+        ChStyle[FSelCharPos.Pos + 1] := Char(FSelCharStyle);
+
+    pos := FLeftCol + 1; // 1
+    DrawSegments(S1, pos, rct, False);
+    Inc(pos, Length(S1));
+    DrawSegments(S2, pos, rct, True);
+    Inc(pos, Length(S2));
+    DrawSegments(S3, pos, rct, False);
+
+    //       else begin
+    //            DrawPart(S1,StyleNo,rct,False);
+    //            DrawPart(S2,StyleNo,rct,True);
+    //            DrawPart(S3,StyleNo,rct,False);
+    //       end;
+
+    rct1 := rct;
+    rct1.Left := rct1.Left - eRect.Left;
+    rct1.Right := rct1.Right - eRect.Left;
+    rct1.Top := rct1.Top - rct.Top;
+    rct1.Bottom := rct1.Bottom - rct.Top;
+    with FLineBitmap.Canvas do
+    begin
+      Brush.Color := FStyles.BkColor[LineStyleNo];
+      FillRect(rct1);
+    end;
+
+    with LineRct do
+      BitBlt(Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
+        FLineBitmap.Canvas.Handle, 0, 0, SRCCOPY);
+  end
+  else
+    with Canvas do
+    begin
+      Brush.Color := BkColor;
+      FillRect(rct0);
+    end;
+end;
+
+//--------------------------------------------------------------
+//        SET HIDDEN CARET
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetHiddenCaret(Value: Boolean);
+begin
+  if Value <> FHiddenCaret then
+  begin
+    FHiddenCaret := Value;
+    if Focused then
+      if FHiddenCaret = FCaretVisible then
+        ShowCaret(not FHiddenCaret);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        BORDER
+//--------------------------------------------------------------
+
+procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
+const
+  Colors: array[TBorderType] of array[1..4] of TColor
+    = (($D0D0D0, clWhite, clGray, clBlack),
+    (clGray, clBlack, $D0D0D0, clWhite),
+    (clWhite, clWhite, clWhite, clGray),
+    (clGray, clWhite, clWhite, clGray));
+begin
+  with Canvas do
+  begin
+    Pen.Color := Colors[BorderType][1];
+    MoveTo(rct.Left, rct.Bottom - 1);
+    LineTo(rct.Left, rct.Top);
+    LineTo(rct.Right, rct.Top);
+    if BorderType in [btRaised, btLowered] then
+    begin
+      Pen.Color := Colors[BorderType][2];
+      MoveTo(rct.Left + 1, rct.Bottom);
+      LineTo(rct.Left + 1, rct.Top + 1);
+      LineTo(rct.Right, rct.Top + 1);
+      Pen.Color := Colors[BorderType][3];
+      MoveTo(rct.Left + 1, rct.Bottom - 2);
+      LineTo(rct.Right - 2, rct.Bottom - 2);
+      LineTo(rct.Right - 2, rct.Top + 1);
+    end;
+    Pen.Color := Colors[BorderType][4];
+    MoveTo(rct.Left, rct.Bottom - 1);
+    LineTo(rct.Right - 1, rct.Bottom - 1);
+    LineTo(rct.Right - 1, rct.Top);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        EDITOR RECT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.EditorRect: TRect;
+var
+  l, t, r, b: integer;
+begin
+  l := 2;
+  r := Width - 2;
+  t := 2;
+  b := Height - 2;
+  if GutterWidth > 2 then
+    l := l + GutterWidth;
+  if FScrollBars in [ssBoth, ssVertical] then
+    r := r - FScrollBarWidth;
+  if FScrollBars in [ssBoth, ssHorizontal] then
+    b := b - FScrollBarWidth;
+  Result := Rect(l + FMargin, t, r, b);
+end;
+
+//--------------------------------------------------------------
+//        DRAW MARGIN
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DrawMargin;
+var
+  eRect: TRect;
+  i: integer;
+begin
+  eRect := EditorRect;
+  with Canvas do
+  begin
+    Pen.Color := clWhite;
+    for i := 1 to FMargin do
+    begin
+      MoveTo(eRect.Left - i, eRect.Top);
+      LineTo(eRect.Left - i, eRect.Bottom + 1);
+    end;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        DRAW GUTTER
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DrawGutter;
+begin
+  if GutterWidth < 2 then
+    Exit;
+  ResizeGutter;
+  FGutter.PaintTo(Canvas);
+end;
+
+//--------------------------------------------------------------
+//        DRAW SCROLLBARS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.DrawScrollBars;
+begin
+  ResizeScrollBars;
+  if FScrollBars in [ssBoth, ssVertical] then
+    sbVert.PaintTo(Canvas);
+  if FScrollBars in [ssBoth, ssHorizontal] then
+    sbHorz.PaintTo(Canvas);
+  if FScrollBars = ssBoth then
+    with Canvas do
+    begin
+      Brush.Color := clSilver;
+      FillRect(Rect(sbVert.Left, sbHorz.Top + 1,
+        sbVert.Left + sbVert.Width, sbHorz.Top + sbHorz.Height));
+    end;
+end;
+
+//--------------------------------------------------------------
+//        FRESH LINE BITMAP
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.FreshLineBitmap;
+var
+  eRect: TRect;
+begin
+  eRect := EditorRect;
+  with FLineBitmap do
+  begin
+    Width := eRect.Right - eRect.Left;
+    Height := FCellSize.H;
+    FLineBitmap.Canvas.Font.Assign(Self.Canvas.Font);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        PAINT
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.Paint;
+var
+  pTop, pBottom: TFullPos;
+  rct, eRect: TRect;
+  i: integer;
+  clipRgn: HRGN;
+  Attrs: string;
+begin
+  if TGLSMemoStrings(Lines).FLockCount > 0 then
+    Exit;
+  with Canvas do
+  begin
+    if FCellSize.H = 0 then
+      SetFont(FFont);
+    FreshLineBitmap;
+
+    Border(Canvas, Rect(0, 0, Width, Height), btLowered);
+    DrawMargin;
+    DrawGutter;
+    DrawScrollBars;
+
+    eRect := EditorRect;
+    clipRgn := CreateRectRgn(eRect.Left, eRect.Top, eRect.Right, eRect.Bottom);
+    ExtSelectClipRgn(Canvas.Handle, clipRgn, RGN_AND);
+    DeleteObject(clipRgn);
+
+    rct := Canvas.ClipRect;
+    pTop := CharFromPos(rct.Left, rct.Top);
+    pBottom := CharFromPos(rct.Left, rct.Bottom);
+
+    if Assigned(FOnGetLineAttrs) then
+      for i := 0 to Lines.Count - 1 do
+        if not ValidAttrs[i] then
+        begin
+          FOnGetLineAttrs(Self, i, Attrs);
+          CharAttrs[i] := Attrs;
+          ValidAttrs[i] := True;
+        end;
+
+    for i := pTop.LineNo to pBottom.LineNo do
+      DrawLine(i);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        GET VISIBLE
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.GetVisible(Index: integer): integer;
+var
+  Coord: TFullPos;
+  Cell: TCellPos;
+  eRect: TRect;
+begin
+  eRect := EditorRect;
+  Coord := CharFromPos(eRect.Right - 1, eRect.Bottom - 1);
+  Cell := CellFromPos(eRect.Right - 1, eRect.Bottom - 1);
+  case Index of
+    0: Result := Cell.X;
+    1: Result := Cell.Y;
+    2: Result := Coord.Pos - 1;
+    3: Result := Coord.LineNo - 1;
+  else
+    Result := 0;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        IS LINE VISIBLE
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.IsLineVisible(LineNo: integer): Boolean;
+begin
+  if FCellSize.H = 0 then
+    SetFont(FFont);
+  Result := (FTopLine <= LineNo) and (LineNo <= LastVisibleLine + 1);
+end;
+
+//--------------------------------------------------------------
+//        MAKE VISIBLE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.MakeVisible;
+var
+  Modified: Boolean;
+begin
+  Modified := False;
+  if CurX < FLeftCol then
+  begin
+    FLeftCol := CurX - 2;
+    if FLeftCol < 0 then
+      FLeftCol := 0;
+    Modified := True;
+  end;
+  if CurX > LastVisiblePos then
+  begin
+    if (FScrollBars in [ssBoth, ssHorizontal]) or
+      (ScrollMode = smAuto) then
+    begin
+      FLeftCol := FLeftCol + CurX - LastVisiblePos + 2;
+    end
+    else
+      CurX := LastVisiblePos;
+    Modified := True;
+  end;
+  if CurY < FTopLine then
+  begin
+    FTopLine := CurY;
+    if FTopLine < 0 then
+      FTopLine := 0;
+    Modified := True;
+  end;
+  if CurY > LastVisibleLine then
+  begin
+    if (FScrollBars in [ssBoth, ssVertical]) or
+      (ScrollMode = smAuto) then
+    begin
+      FTopLine := FTopLine + CurY - LastVisibleLine;
+    end
+    else
+      CurY := LastVisibleLine;
+    Modified := True;
+  end;
+  if Modified then
+    Invalidate;
+end;
+
+//--------------------------------------------------------------
+//        RESIZE EDITOR
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ResizeEditor;
+begin
+  ResizeScrollBars;
+  ResizeGutter;
+  MakeVisible;
+  Invalidate;
+end;
+
+//--------------------------------------------------------------
+//        FIND TEXT
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.FindText(Text: string; Options: TFindOptions; Select:
+  Boolean): Boolean;
+var
+  i, p: integer;
+  s1, s0, s: string;
+  //-----------------------------------------------------------
+  function LastPos(const Substr, s: string): integer;
+  var
+    i, j, lenSub: integer;
+  begin
+    Result := 0;
+    lenSub := Length(Substr);
+    i := Length(s) - lenSub + 1;
+    while i > 0 do
+    begin
+      if s[i] = Substr[1] then
+      begin
+        Result := i;
+        for j := i + 1 to i + lenSub - 1 do
+          if s[j] <> Substr[j - i + 1] then
+          begin
+            Result := 0;
+            break;
+          end;
+      end;
+      if Result <> 0 then
+        break;
+      Dec(i);
+    end;
+  end;
+  //-----------------------------------------------------------
+begin
+  Result := False;
+  if not (frMatchCase in Options) then
+    Text := AnsiLowerCase(Text);
+
+  if SelLength > 0 then
+    ClearSelection;
+  s := Lines[CurY];
+  s0 := Copy(s, 1, CurX);
+  s1 := Copy(s, CurX + 1, Length(s));
+  i := CurY;
+
+  while True do
+  begin
+
+    if not (frMatchCase in Options) then
+    begin
+      s0 := AnsiLowerCase(s0);
+      s1 := AnsiLowerCase(s1);
+    end;
+
+    if frDown in Options then
+      p := Pos(Text, s1)
+    else
+      p := LastPos(Text, s0);
+
+    if p > 0 then
+    begin
+      Result := True;
+      CurY := i;
+      if frDown in Options then
+        CurX := Length(s0) + p - 1
+      else
+        CurX := p - 1;
+      if Select then
+      begin
+        if not (frDown in Options) then
+          CurX := CurX + Length(Text);
+        ClearSelection;
+        if frDown in Options then
+          CurX := CurX + Length(Text)
+        else
+          CurX := CurX - Length(Text);
+        ExpandSelection;
+      end;
+      break;
+    end;
+
+    if frDown in Options then
+      Inc(i)
+    else
+      Dec(i);
+    if (i < 0) or (i > Lines.Count - 1) then
+      break;
+    if frDown in Options then
+    begin
+      s0 := '';
+      s1 := Lines[i];
+    end
+    else
+    begin
+      s0 := Lines[i];
+      s1 := '';
+    end;
+
+  end;
+
+end;
+
+//--------------------------------------------------------------
+//        RESIZE SCROLLBARS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ResizeScrollBars;
+var
+  eRect, sbRect: TRect;
+  MaxLen, OldMax, NewTop, Margin: integer;
+begin
+  eRect := EditorRect;
+  if FScrollBars in [ssBoth, ssVertical] then
+  begin
+    with sbVert do
+    begin
+      Width := 16;
+      Height := eRect.Bottom - eRect.Top + 1;
+      Left := eRect.Right;
+      Top := eRect.Top;
+      OldMax := MaxPosition;
+      MaxPosition := (Lines.Count - 1) - (LastVisibleLine - FTopLine);
+      NewTop := FTopLine;
+      if (FTopLine > 0) and (LastVisibleLine > Lines.Count - 1) then
+      begin
+        Dec(NewTop, LastVisibleLine - (Lines.Count - 1));
+        if NewTop < 0 then
+          NewTop := 0;
+        MaxPosition := NewTop;
+      end;
+      if MaxPosition < 0 then
+        MaxPosition := 0;
+      Position := NewTop;
+      Total := Lines.Count;
+      if OldMax <> MaxPosition then
+      begin
+        if NewTop <> FTopLine then
+        begin
+          DoScroll(sbVert, NewTop - FTopLine);
+          FGutter.Invalidate;
+        end;
+        sbRect := sbVert.FullRect;
+        InvalidateRect(Handle, @sbRect, True);
+      end;
+    end;
+  end;
+  if FScrollBars in [ssBoth, ssHorizontal] then
+  begin
+    MaxLen := MaxLength;
+    with sbHorz do
+    begin
+      Width := Self.Width - 4;
+      if FScrollBars = ssBoth then
+        Width := Width - sbVert.Width;
+      Height := 16;
+      Left := 2;
+      Top := eRect.Bottom;
+      OldMax := MaxPosition;
+
+      Margin := LastVisiblePos - MaxLen;
+      if Margin < 2 then
+        Margin := 2;
+      MaxPosition := MaxLen - (LastVisiblePos - FLeftCol) + Margin;
+
+      if MaxPosition < 0 then
+        MaxPosition := 0;
+      Position := FLeftCol;
+      Total := MaxLen;
+      if OldMax <> MaxPosition then
+      begin
+        if MaxPosition = 0 then
+        begin
+          FLeftCol := 0;
+          InvalidateRect(Handle, @eRect, True);
+          ;
+          FGutter.Invalidate;
+        end;
+        sbRect := sbHorz.FullRect;
+        InvalidateRect(Handle, @sbRect, True);
+      end;
+    end;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        RESIZE GUTTER
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ResizeGutter;
+var
+  eRect: TRect;
+begin
+  eRect := EditorRect;
+  with FGutter do
+  begin
+    Height := eRect.Bottom - eRect.Top;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        CREATE PARAMS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.CreateParams(var Params: TCreateParams);
+begin
+  inherited;
+end;
+
+//--------------------------------------------------------------
+//        UNDO, REDO
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.Undo;
+begin
+  FUndoList.Undo;
+end;
+
+procedure TGLSCustomMemo.Redo;
+begin
+  FUndoList.Redo;
+end;
+
+//--------------------------------------------------------------
+//        SET UNDO LIMIT
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetUndoLimit(Value: integer);
+begin
+  if (FUndoLimit <> Value) then
+  begin
+    if Value <= 0 then
+      Value := 1;
+    if Value > 100 then
+      Value := 100;
+    FUndoLimit := Value;
+    FUndoList.Limit := Value;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        UNDO (REDO) CHANGE
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.UndoChange;
+begin
+  if Assigned(FOnUndoChange) then
+    FOnUndoChange(Self, FUndoList.Pos < FUndoList.Count,
+      FUndoList.Pos > 0);
+end;
+
+//--------------------------------------------------------------
+//        CAN UNDO
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.CanUndo: boolean;
+begin
+  Result := FUndoList.FPos < FUndoList.Count;
+end;
+
+//--------------------------------------------------------------
+//        CAN REDO
+//--------------------------------------------------------------
+
+function TGLSCustomMemo.CanRedo: Boolean;
+begin
+  Result := FUndoList.FPos > 0;
+end;
+
+//--------------------------------------------------------------
+//        CLEAR UNDO LIST
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.ClearUndoList;
+begin
+  if Assigned(FUndoList) then
+    FUndoList.Clear;
+end;
+
+//--------------------------------------------------------------
+//        SET SCROLL BARS
+//--------------------------------------------------------------
+
+procedure TGLSCustomMemo.SetScrollBars(Value: System.UITypes.TScrollStyle);
+begin
+  if FScrollBars <> Value then
+  begin
+    FScrollBars := Value;
+    if not (csLoading in ComponentState) then
+      ResizeEditor;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        CREATE
+//--------------------------------------------------------------
+
+constructor TGLSCustomMemo.Create(AOwner: TComponent);
+begin
+  inherited;
+
+  ControlStyle := [csCaptureMouse, csClickEvents,
+    csDoubleClicks, csReplicatable];
+  Width := 100;
+  Height := 40;
+  TabStop := True;
+  Cursor := crIBeam;
+
+  FFont := TFont.Create;
+  FFont.Name := 'Courier New';
+  FFont.Size := 10;
+  Canvas.Font.Assign(FFont);
+
+  FHiddenCaret := False;
+  FCaretVisible := False;
+
+  FCurX := 0;
+  FCurY := 0;
+  FLeftCol := 0;
+  FTopLine := 0;
+  FTabSize := 4;
+  FMargin := 2;
+  FAutoIndent := True;
+  FLines := TGLSMemoStrings.Create;
+  TGLSMemoStrings(FLines).FMemo := Self;
+
+  FScrollBars := ssBoth;
+  FScrollBarWidth := 16;
+  sbVert := TGLSMemoScrollBar.Create(Self, sbVertical);
+  sbVert.Width := FScrollBarWidth;
+  sbHorz := TGLSMemoScrollBar.Create(Self, sbHorizontal);
+  sbHorz.Height := FScrollBarWidth;
+
+  FGutter := TGLSMemoGutter.Create;
+  with FGutter do
+  begin
+    FLeft := 2;
+    FTop := 2;
+    FWidth := 0;
+    FHeight := 0;
+    FColor := clBtnFace;
+    FMemo := Self;
+  end;
+
+  FSelStartX := 0;
+  FSelStartY := 0;
+  FSelEndX := 0;
+  FSelEndY := 0;
+
+  FBkColor := clWhite;
+  FSelColor := clWhite;
+  FSelBkColor := clNavy;
+
+  FStyles := TStyleList.Create;
+  FStyles.Add(clBlack, clWhite, []);
+
+  FSelCharPos.LineNo := -1;
+  FSelCharPos.Pos := -1;
+  FSelCharStyle := -1;
+
+  FLineBitmap := TBitmap.Create;
+
+  FLeftButtonDown := False;
+  FScrollMode := smAuto;
+
+  FUndoList := TGLSMemoUndoList.Create;
+  FFirstUndoList := FUndoList;
+  FUndoList.Memo := Self;
+
+  FUndoLimit := 100;
+
+  TGLSMemoStrings(FLines).DoAdd('');
+
+  FAfterDoubleClick := False;
+
+end;
+
+//--------------------------------------------------------------
+//        DESTROY
+//--------------------------------------------------------------
+
+destructor TGLSCustomMemo.Destroy;
+begin
+  FFont.Free;
+  FLines.Free;
+  FGutter.Free;
+  sbVert.Free;
+  sbHorz.Free;
+  FStyles.Free;
+  FLineBitmap.Free;
+  FFirstUndoList.Free;
+  inherited;
+end;
+
+ 
+
+// ---------------------TGLSMemoScrollBar functions 
+
+procedure TGLSMemoScrollBar.SetParams(Index: integer; Value: integer);
+begin
+  case Index of
+    0: if Left <> Value then
+        FLeft := Value;
+    1: if Top <> Value then
+        FTop := Value;
+    2: if Width <> Value then
+        FWidth := Value;
+    3: if Height <> Value then
+        FHeight := Value;
+    4: if Total <> Value then
+        FTotal := Value;
+    5: if MaxPosition <> Value then
+        FMaxPosition := Value;
+    6: if Position <> Value then
+        FPosition := Value;
+  end;
+end;
+//-------------------- CREATE ------------------------------
+
+constructor TGLSMemoScrollBar.Create(AParent: TGLSMemoAbstractScrollableObject;
+  AKind: TScrollBarKind);
+begin
+  FParent := AParent;
+  FButtonLength := 16;
+  FKind := AKind;
+  FState := sbsWait;
+end;
+//-------------------- RECT -----------------------
+
+function TGLSMemoScrollBar.GetRect: TRect;
+begin
+  Result := Rect(Left, Top, Left + Width, Top + Height);
+end;
+//-------------------- GET THUMB RECT -----------------------
+
+function TGLSMemoScrollBar.GetThumbRect: TRect;
+var
+  TotalLen, FreeLen, ThumbLen, ThumbOffset, ThumbCoord: integer;
+  K: double;
+begin
+  if MaxPosition <= 0 then
+  begin
+    Result := Rect(0, 0, 0, 0);
+    Exit;
+  end;
+  if Kind = sbVertical then
+    TotalLen := Height
+  else
+    TotalLen := Width;
+  FreeLen := TotalLen - 2 * FButtonLength;
+
+  K := (Total - MaxPosition) / MaxPosition;
+  if K > 0 then
+  begin
+    ThumbLen := round(FreeLen * K / (1 + K));
+    if ThumbLen < 8 then
+      ThumbLen := 8;
+  end
+  else
+    ThumbLen := 8;
+
+  if ThumbLen >= FreeLen then
+    Result := Rect(0, 0, 0, 0)
+  else
+  begin
+    ThumbOffset := round((FreeLen - ThumbLen) * Position / MaxPosition);
+    ThumbCoord := FButtonLength + ThumbOffset;
+    if Kind = sbVertical then
+      Result := Rect(Left + 1, Top + ThumbCoord, Left + Width, Top + ThumbCoord
+        + ThumbLen)
+    else
+      Result := Rect(Left + ThumbCoord, Top + 1, Left + ThumbCoord + ThumbLen,
+        Top + Height);
+  end;
+end;
+//-------------------- GET Back RECT -----------------------
+
+function TGLSMemoScrollBar.GetBackRect: TRect;
+begin
+  if Kind = sbVertical then
+    Result := Rect(Left + 1, Top, Left + Width, Top + FButtonLength)
+  else
+    Result := Rect(Left, Top + 1, Left + FButtonLength, Top + Height);
+end;
+//-------------------- GET MIDDLE RECT -----------------------
+
+function TGLSMemoScrollBar.GetMiddleRect: TRect;
+var
+  bRect, fRect: TRect;
+begin
+  bRect := BackRect;
+  fRect := ForwardRect;
+  if Kind = sbVertical then
+    Result := Rect(Left + 1, bRect.Bottom, Left + Width, fRect.Top)
+  else
+    Result := Rect(bRect.Right, Top + 1, fRect.Left, Top + Height);
+end;
+//-------------------- GET Forward RECT -----------------------
+
+function TGLSMemoScrollBar.GetForwardRect: TRect;
+begin
+  if Kind = sbVertical then
+    Result := Rect(Left + 1, Top + Height - FButtonLength, Left + Width, Top +
+      Height)
+  else
+    Result := Rect(Left + Width - FButtonLength, Top + 1, Left + Width, Top +
+      Height);
+end;
+//-------------------- GET PAGE BACK RECT -----------------------
+
+function TGLSMemoScrollBar.GetPgBackRect: TRect;
+var
+  thRect: TRect;
+begin
+  thRect := GetThumbRect;
+  if thRect.Bottom = 0 then
+  begin
+    Result := Rect(0, 0, 0, 0);
+    Exit;
+  end;
+  if Kind = sbVertical then
+    Result := Rect(Left + 1, Top + FButtonLength, Left + Width, thRect.Top - 1)
+  else
+    Result := Rect(Left + FButtonLength, Top + 1, thRect.Left - 1, Top +
+      Height);
+end;
+//-------------------- GET PG FORWARD RECT -----------------------
+
+function TGLSMemoScrollBar.GetPgForwardRect: TRect;
+var
+  thRect: TRect;
+begin
+  thRect := GetThumbRect;
+  if thRect.Bottom = 0 then
+  begin
+    Result := Rect(0, 0, 0, 0);
+    Exit;
+  end;
+  if Kind = sbVertical then
+    Result := Rect(Left + 1, thRect.Bottom, Left + Width, Top + Height -
+      FButtonLength)
+  else
+    Result := Rect(thRect.Right, Top + 1, Left + Width - FButtonLength, Top +
+      Height);
+end;
+//-------------------- PAINT TO -----------------------
+
+procedure TGLSMemoScrollBar.PaintTo(ACanvas: TCanvas);
+var
+  sRect, mRect, gRect, thRect: TRect;
+  iconX, iconY, shift: integer;
+begin
+  with ACanvas do
+  begin
+    if Kind = sbVertical then
+    begin
+      Pen.Color := clSilver;
+      MoveTo(Left, Top);
+      LineTo(Left, Top + Height);
+
+      sRect := BackRect;
+      Brush.Color := clSilver;
+      FillRect(sRect);
+      if State = sbsBack then
+      begin
+        shift := 1;
+        Pen.Color := clGray;
+        with sRect do
+          Rectangle(Left, Top, Right, Bottom);
+      end
+      else
+      begin
+        shift := 0;
+        Border(ACanvas, sRect, btFlatRaised);
+      end;
+      iconX := sRect.Left + (Width - 1 - 7) div 2;
+      iconY := sRect.Top + (FButtonLength - 8) div 2;
+      Draw(iconX + shift, iconY + shift, bmScrollBarUp);
+
+      gRect := ForwardRect;
+      Brush.Color := clSilver;
+      FillRect(gRect);
+      if State = sbsForward then
+      begin
+        shift := 1;
+        Pen.Color := clGray;
+        with gRect do
+          Rectangle(Left, Top, Right, Bottom);
+      end
+      else
+      begin
+        shift := 0;
+        Border(ACanvas, gRect, btFlatRaised);
+      end;
+      iconX := gRect.Left + (Width - 1 - 7) div 2;
+      iconY := gRect.Top + (FButtonLength - 8) div 2;
+      Draw(iconX + shift, iconY + shift, bmScrollBarDown);
+
+      mRect := Rect(sRect.Left, sRect.Bottom, gRect.Right, gRect.Top);
+    end
+    else
+    begin
+      Pen.Color := clSilver;
+      MoveTo(Left, Top);
+      LineTo(Left + Width, Top);
+
+      sRect := BackRect;
+      Brush.Color := clSilver;
+      FillRect(sRect);
+      if State = sbsBack then
+      begin
+        shift := 1;
+        Pen.Color := clGray;
+        with sRect do
+          Rectangle(Left, Top, Right, Bottom);
+      end
+      else
+      begin
+        shift := 0;
+        Border(ACanvas, sRect, btFlatRaised);
+      end;
+      iconX := sRect.Left + shift + (FButtonLength - 8) div 2;
+      iconY := sRect.Top + shift + (Height - 1 - 7) div 2;
+      Draw(iconX + shift, iconY + shift, bmScrollBarLeft);
+
+      gRect := ForwardRect;
+      Brush.Color := clSilver;
+      FillRect(gRect);
+      if State = sbsForward then
+      begin
+        shift := 1;
+        Pen.Color := clGray;
+        with gRect do
+          Rectangle(Left, Top, Right, Bottom);
+      end
+      else
+      begin
+        shift := 0;
+        Border(ACanvas, gRect, btFlatRaised);
+      end;
+      iconX := gRect.Left + (FButtonLength - 8) div 2;
+      iconY := gRect.Top + (Height - 1 - 7) div 2;
+      Draw(iconX + shift, iconY + shift, bmScrollBarRight);
+
+      mRect := Rect(sRect.Right, sRect.Top, gRect.Left, gRect.Bottom);
+    end;
+
+    Brush.Bitmap := bmScrollBarFill;
+    FillRect(mRect);
+    Brush.Bitmap := nil;
+    if State = sbsPageBack then
+    begin
+      Brush.Color := clGray;
+      FillRect(PageBackRect);
+    end;
+    if State = sbsPageForward then
+    begin
+      Brush.Color := clGray;
+      FillRect(PageForwardRect);
+    end;
+
+    thRect := ThumbRect;
+    Brush.Color := clSilver;
+    FillRect(thRect);
+    Border(ACanvas, thRect, btFlatRaised);
+  end;
+end;
+//-------------------- SET STATE ----------
+
+procedure TGLSMemoScrollBar.SetState(Value: TsbState);
+begin
+  if FState <> Value then
+  begin
+    FState := Value;
+  end;
+end;
+//-------------------- MOUSE DOWN ------------
+
+function TGLSMemoScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
+  X,
+  Y: Integer):
+  Boolean;
+var
+  sRect, gRect, thRect, pbRect, pfRect: TRect;
+begin
+  Result := False;
+  if (Width = 0) or (Height = 0) then
+    Exit;
+  sRect := BackRect;
+  gRect := ForwardRect;
+  pbRect := PageBackRect;
+  pfRect := PageForwardRect;
+  thRect := ThumbRect;
+  if PointInRect(Point(X, Y), sRect) then
+  begin
+    State := sbsBack;
+    InvalidateRect(Parent.Handle, @sRect, True);
+    Result := True;
+    Exit;
+  end;
+  if PointInRect(Point(X, Y), gRect) then
+  begin
+    State := sbsForward;
+    InvalidateRect(Parent.Handle, @gRect, True);
+    Result := True;
+    Exit;
+  end;
+  if PointInRect(Point(X, Y), pbRect) then
+  begin
+    State := sbsPageBack;
+    InvalidateRect(Parent.Handle, @pbRect, True);
+    Result := True;
+    Exit;
+  end;
+  if PointInRect(Point(X, Y), pfRect) then
+  begin
+    State := sbsPageForward;
+    InvalidateRect(Parent.Handle, @pfRect, True);
+    Result := True;
+    Exit;
+  end;
+  if PointInRect(Point(X, Y), thRect) then
+  begin
+    State := sbsDragging;
+    FXOffset := X - thRect.Left;
+    FYOffset := Y - thRect.Top;
+    Result := True;
+    Exit;
+  end;
+
+end;
+//-------------------- MOUSE UP ----------
+
+function TGLSMemoScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
+  Y:
+  Integer):
+  Boolean;
+var
+  sRect, gRect, thRect, pbRect, pfRect: TRect;
+begin
+  Result := False;
+  if (Width = 0) or (Height = 0) then
+    Exit;
+  sRect := BackRect;
+  gRect := ForwardRect;
+  pbRect := PageBackRect;
+  pfRect := PageForwardRect;
+  thRect := ThumbRect;
+  case State of
+    sbsBack:
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @sRect, True);
+        FParent.DoScroll(Self, -1);
+        Result := True;
+        Exit;
+      end;
+    sbsForward:
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @gRect, True);
+        FParent.DoScroll(Self, 1);
+        Result := True;
+        Exit;
+      end;
+    sbsPageBack:
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @pbRect, True);
+        FParent.DoScrollPage(Self, -1);
+        Result := True;
+        Exit;
+      end;
+    sbsPageForward:
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @pfRect, True);
+        FParent.DoScrollPage(Self, 1);
+        Result := True;
+        Exit;
+      end;
+    sbsDragging:
+      begin
+        State := sbsWait;
+        Result := True;
+        Exit;
+      end;
+  end;
+end;
+//-------------------- MOUSE MOVE -----------
+
+function TGLSMemoScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer):
+  Boolean;
+var
+  sRect, gRect, thRect, pbRect, pfRect: TRect;
+begin
+  Result := False;
+  if (Width = 0) or (Height = 0) then
+    Exit;
+  sRect := BackRect;
+  gRect := ForwardRect;
+  pbRect := PageBackRect;
+  pfRect := PageForwardRect;
+  thRect := ThumbRect;
+  case State of
+    sbsBack:
+      if not PointInRect(Point(X, Y), sRect) then
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @sRect, True);
+        Result := True;
+        Exit;
+      end;
+    sbsForward:
+      if not PointInRect(Point(X, Y), gRect) then
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @gRect, True);
+        Result := True;
+        Exit;
+      end;
+    sbsPageBack:
+      if not PointInRect(Point(X, Y), pbRect) then
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @pbRect, True);
+        Result := True;
+        Exit;
+      end;
+    sbsPageForward:
+      if not PointInRect(Point(X, Y), pfRect) then
+      begin
+        State := sbsWait;
+        InvalidateRect(Parent.Handle, @pfRect, True);
+        Result := True;
+        Exit;
+      end;
+    sbsDragging:
+      begin
+        MoveThumbTo(X, Y);
+        Result := True;
+        Exit;
+      end;
+  end;
+end;
+//-------------------- MOVE THUMB TO ------------
+
+function TGLSMemoScrollBar.MoveThumbTo(X, Y: Integer): integer;
+var
+  thRect, mRect: TRect;
+  FreeLen, ThumbLen, NewPosition, NewOffset: integer;
+begin
+  thRect := ThumbRect;
+  mRect := MiddleRect;
+  NewOffset := 0;
+  FreeLen := 0;
+  ThumbLen := 0;
+  case Kind of
+    sbVertical:
+      begin
+        FreeLen := mRect.Bottom - mRect.Top;
+        ThumbLen := thRect.Bottom - thRect.Top;
+        NewOffset := Y - FYOffset - (Top + FButtonLength);
+      end;
+    sbHorizontal:
+      begin
+        FreeLen := mRect.Right - mRect.Left;
+        ThumbLen := thRect.Right - thRect.Left;
+        NewOffset := X - FXOffset - (Left + FButtonLength);
+      end
+  end;
+  NewPosition := round(NewOffset * MaxPosition / (FreeLen - ThumbLen));
+  Result := NewPosition - Position;
+  if NewPosition <> Position then
+  begin
+    Parent.DoScroll(Self, NewPosition - Position);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        GUTTER
+//--------------------------------------------------------------
+//-------------------- SET PARAMS -----------------------
+
+procedure TGLSMemoGutter.SetParams(Index: integer; Value: integer);
+begin
+  case Index of
+    0: FLeft := Value;
+    1: FTop := Value;
+    2: FWidth := Value;
+    3: FHeight := Value;
+  end;
+end;
+//-------------------- PAINT TO -----------------------
+
+procedure TGLSMemoGutter.PaintTo(ACanvas: TCanvas);
+var
+  LineNo, T, H: integer;
+begin
+  with ACanvas do
+  begin
+    Pen.Color := clGray;
+    MoveTo(Left + Width - 1, Top);
+    LineTo(Left + Width - 1, Top + Height);
+    Pen.Color := clWhite;
+    MoveTo(Left + Width - 2, Top);
+    LineTo(Left + Width - 2, Top + Height);
+    Brush.Color := Self.FColor;
+    FillRect(Rect(Left, Top, Left + Width - 2, Top + Height));
+    if Assigned(FMemo.OnGutterDraw) then
+    begin
+      T := Top;
+      H := FMemo.FCellSize.H;
+      LineNo := FMemo.FTopLine;
+      while T < Top + Height do
+      begin
+        FMemo.OnGutterDraw(FMemo, ACanvas, LineNo,
+          Rect(Left, T, Left + Width - 2, T + H));
+        T := T + H;
+        Inc(LineNo);
+        if LineNo >= FMemo.Lines.Count then
+          break;
+      end;
+    end;
+  end;
+end;
+
+//-------------------- INVALIDATE -----------------------
+
+procedure TGLSMemoGutter.Invalidate;
+var
+  gRect: TRect;
+begin
+  gRect := Rect(Left, Top, Left + Width, Top + Height);
+  InvalidateRect(FMemo.Handle, @gRect, True);
+end;
+
+//-------------------- GET RECT -----------------------
+
+function TGLSMemoGutter.GetRect: TRect;
+begin
+  Result := Rect(Left, Top, Left + Width, Top + Height);
+end;
+
+ 
+
+// ---------------------TStyleList 
+
+procedure TStyleList.CheckRange(Index: integer);
+begin
+  if (Index < 0) or (Index >= Count) then
+    raise EListError.Create('Incorrect list item index ' + IntToStr(Index));
+end;
+//-------------------- DESTROY ---------------------------
+
+destructor TStyleList.Destroy;
+begin
+  Clear;
+  inherited;
+end;
+//-------------------- CHANGE ---------------------------
+
+procedure TStyleList.Change(Index: integer; ATextColor, ABkCOlor: TColor;
+  AStyle: TFontStyles);
+var
+  P: TCharStyle;
+begin
+  CheckRange(Index);
+  P := TCharStyle(Items[Index]);
+  P.TextColor := ATextColor;
+  P.BkColor := ABkColor;
+  P.Style := AStyle;
+end;
+//-------------------- ADD ---------------------------
+
+function TStyleList.Add(ATextColor, ABkColor: TColor; AStyle: TFontStyles):
+  Integer;
+var
+  P: TCharStyle;
+begin
+  P := TCharStyle.Create;
+  with P do
+  begin
+    TextColor := ATextColor;
+    BkColor := ABkColor;
+    Style := AStyle;
+  end;
+  Result := inherited Add(P);
+end;
+//-------------------- CLEAR ---------------------------
+
+procedure TStyleList.Clear;
+begin
+  while Count > 0 do
+    Delete(0);
+end;
+//-------------------- DELETE ---------------------------
+
+procedure TStyleList.Delete(Index: Integer);
+var
+  P: TCharStyle;
+begin
+  CheckRange(Index);
+  P := TCharStyle(Items[Index]);
+  P.Free;
+  inherited;
+end;
+//-------------------- GET/SET TEXT COLOR ---------------------------
+
+function TStyleList.GetTextColor(Index: Integer): TColor;
+begin
+  CheckRange(Index);
+  Result := TCharStyle(Items[Index]).TextColor;
+end;
+
+procedure TStyleList.SetTextColor(Index: Integer; Value: TColor);
+begin
+  CheckRange(Index);
+  TCharStyle(Items[Index]).TextColor := Value;
+end;
+//-------------------- GET/SET BK COLOR ---------------------------
+
+function TStyleList.GetBkColor(Index: Integer): TColor;
+begin
+  CheckRange(Index);
+  Result := TCharStyle(Items[Index]).BkColor;
+end;
+
+procedure TStyleList.SetBkColor(Index: Integer; Value: TColor);
+begin
+  CheckRange(Index);
+  TCharStyle(Items[Index]).BkColor := Value;
+end;
+//-------------------- GET/SET STYLE ---------------------------
+
+function TStyleList.GetStyle(Index: Integer): TFontStyles;
+begin
+  CheckRange(Index);
+  Result := TCharStyle(Items[Index]).Style;
+end;
+
+procedure TStyleList.SetStyle(Index: Integer; Value: TFontStyles);
+begin
+  CheckRange(Index);
+  TCharStyle(Items[Index]).Style := Value;
+end;
+
+ 
+
+// ---------------------TGLSMemoStrings 
+
+destructor TGLSMemoStrings.Destroy;
+var
+  P: TObject;
+begin
+  while Count > 0 do
+  begin
+    P := inherited GetObject(0);
+    P.Free;
+    inherited Delete(0);
+  end;
+  inherited;
+end;
+//-------------------- CLEAR ----------------------
+
+procedure TGLSMemoStrings.Clear;
+begin
+  while Count > 0 do
+  begin
+    Delete(0);
+    if (Count = 1) and (Strings[0] = '') then
+      break;
+  end;
+end;
+
+//-------------------- ASSIGN ----------------------
+
+procedure TGLSMemoStrings.Assign(Source: TPersistent);
+var
+  P: TObject;
+begin
+  if Source is TStrings then
+  begin
+    BeginUpdate;
+    try
+      while Count > 0 do
+      begin
+        P := inherited GetObject(0);
+        P.Free;
+        inherited Delete(0);
+      end;
+      //      inherited Clear;
+      AddStrings(TStrings(Source));
+    finally
+      EndUpdate;
+    end;
+    Exit;
+  end;
+  inherited Assign(Source);
+end;
+
+//-------------------- ADD ----------------------
+
+function TGLSMemoStrings.DoAdd(const S: string): Integer;
+begin
+  Result := inherited AddObject(S, nil);
+end;
+//-------------------- ADD ----------------------
+
+function TGLSMemoStrings.Add(const S: string): Integer;
+begin
+  if Assigned(FMemo.Parent) then
+    Result := FMemo.AddString(S)
+  else
+    Result := DoAdd(S);
+end;
+//-------------------- OBJECT ----------------------
+
+function TGLSMemoStrings.AddObject(const S: string; AObject: TObject): Integer;
+begin
+  if AObject <> nil then
+    raise EInvalidOp.Create(SObjectsNotSupported);
+  Result := DoAdd(S);
+end;
+//-------------------- INSERT ----------------------
+
+procedure TGLSMemoStrings.InsertObject(Index: Integer;
+  const S: string; AObject: TObject);
+begin
+  if AObject <> nil then
+    raise EInvalidOp.Create(SObjectsNotSupported);
+  DoInsert(Index, S);
+end;
+//-------------------- DO INSERT ----------------------
+
+procedure TGLSMemoStrings.DoInsert(Index: Integer; const S: string);
+begin
+  InsertItem(Index, S, nil);
+end;
+//-------------------- INSERT ----------------------
+
+procedure TGLSMemoStrings.Insert(Index: Integer; const S: string);
+begin
+  if Assigned(FMemo) then
+    FMemo.InsertString(Index, S)
+  else
+    DoInsert(Index, S);
+end;
+//-------------------- DELETE ----------------------
+
+procedure TGLSMemoStrings.Delete(Index: Integer);
+var
+  P: TObject;
+begin
+  if (Index < 0) or (Index > Count - 1) then
+    Exit;
+  if FDeleting or (not Assigned(FMemo)) then
+  begin
+    P := inherited GetObject(Index);
+    P.Free;
+    inherited;
+  end
+  else
+  begin
+    FMemo.DeleteLine(Index, -1, -1, -1, -1, True);
+  end;
+end;
+//-------------------- LOAD FROM FILE ----------------------
+
+procedure TGLSMemoStrings.LoadFromFile(const FileName: string);
+begin
+  with FMemo do
+  begin
+    ClearSelection;
+    ClearUndoList;
+    CurX := 0;
+    CurY := 0;
+  end;
+  Clear;
+  inherited;
+  FMemo.Invalidate;
+end;
+//-------------------- SET UPDATE STATE ----------------------
+
+procedure TGLSMemoStrings.SetUpdateState(Updating: Boolean);
+begin
+  if Updating then
+    Inc(FLockCount)
+  else if FLockCount > 0 then
+    Dec(FLockCount);
+end;
+//-------------------- CHECK RANGE ---------------------------
+
+procedure TGLSMemoStrings.CheckRange(Index: integer);
+begin
+  if (Index < 0) or (Index >= Count) then
+    raise EListError('Incorrect index of list item ' + IntToStr(Index));
+end;
+//-------------------- GET OBJECT ---------------------------
+
+function TGLSMemoStrings.GetObject(Index: Integer): TObject;
+begin
+  CheckRange(Index);
+  Result := inherited GetObject(Index);
+  if Assigned(Result) and (Result is TLineProp) then
+    Result := TLineProp(Result).FObject;
+end;
+//-------------------- PUT OBJECT ---------------------------
+
+procedure TGLSMemoStrings.PutObject(Index: Integer; AObject: TObject);
+var
+  P: TObject;
+begin
+  CheckRange(Index);
+  P := Objects[Index];
+  if Assigned(P) and (P is TLineProp) then
+    TLineProp(P).FObject := AObject
+  else
+    inherited PutObject(Index, AObject);
+end;
+//-------------------- GET LINE PROP ---------------------------
+
+function TGLSMemoStrings.GetLineProp(Index: integer): TLineProp;
+var
+  P: TObject;
+begin
+  CheckRange(Index);
+  Result := nil;
+  P := inherited GetObject(Index);
+  if Assigned(P) and (P is TLineProp) then
+    Result := TLineProp(P);
+end;
+
+//-------------------- CREATE PROP --------------------------
+
+function TGLSMemoStrings.CreateProp(Index: integer): TLineProp;
+begin
+  Result := TLineProp.Create;
+  with Result do
+  begin
+    FStyleNo := 0;
+    FInComment := False;
+    FInBrackets := -1;
+    FValidAttrs := False;
+    FCharAttrs := '';
+    FObject := Objects[Index];
+  end;
+  inherited PutObject(Index, Result);
+end;
+
+//-------------------- GET LINE STYLE --------------------------
+
+function TGLSMemoStrings.GetLineStyle(Index: integer): integer;
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    Result := 0
+  else
+    Result := P.FStyleNo;
+end;
+
+//-------------------- SET LINE STYLE --------------------------
+
+procedure TGLSMemoStrings.SetLineStyle(Index: integer; Value: integer);
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    P := CreateProp(Index);
+  P.FStyleNo := Value;
+end;
+
+//-------------------- GET/SET IN COMMENT ---------------------------
+
+function TGLSMemoStrings.GetInComment(Index: Integer): Boolean;
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    Result := False
+  else
+    Result := P.FInComment;
+end;
+
+procedure TGLSMemoStrings.SetInComment(Index: Integer; Value: Boolean);
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    P := CreateProp(Index);
+  P.FInComment := Value;
+end;
+
+//-------------------- GET/SET IN BRACKETS ---------------------------
+
+function TGLSMemoStrings.GetInBrackets(Index: Integer): integer;
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    Result := -1
+  else
+    Result := P.FInBrackets;
+end;
+
+procedure TGLSMemoStrings.SetInBrackets(Index: Integer; Value: integer);
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    P := CreateProp(Index);
+  P.FInBrackets := Value;
+end;
+
+//-------------------- GET/SET VALID ATTRS ---------------------------
+
+function TGLSMemoStrings.GetValidAttrs(Index: Integer): Boolean;
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    Result := False
+  else
+    Result := P.FValidAttrs;
+end;
+
+procedure TGLSMemoStrings.SetValidAttrs(Index: Integer; Value: Boolean);
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    P := CreateProp(Index);
+  P.FValidAttrs := Value;
+end;
+//-------------------- GET/SET CHAR ATTRS ---------------------------
+
+function TGLSMemoStrings.GetCharAttrs(Index: Integer): string;
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    Result := ''
+  else
+    Result := P.FCharAttrs;
+end;
+
+procedure TGLSMemoStrings.SetCharAttrs(Index: Integer; const Value: string);
+var
+  P: TLineProp;
+begin
+  P := LineProp[Index];
+  if P = nil then
+    P := CreateProp(Index);
+  P.FCharAttrs := Value;
+end;
+
+ 
+
+// ---------------------TGLSMemoUndo 
+
+constructor TGLSMemoUndo.Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
+  string);
+begin
+  inherited Create;
+  FUndoCurX0 := ACurX0;
+  FUndoCurY0 := ACurY0;
+  FUndoCurX := ACurX;
+  FUndoCurY := ACurY;
+  FUndoText := AText;
+end;
+
+procedure TGLSMemoUndo.Undo;
+begin
+  if Assigned(FMemo) then
+    with FMemo do
+    begin
+      CurY := FUndoCurY;
+      CurX := FUndoCurX;
+      PerformUndo;
+      CurY := FUndoCurY0;
+      CurX := FUndoCurX0;
+    end;
+end;
+
+procedure TGLSMemoUndo.Redo;
+begin
+  if Assigned(FMemo) then
+    with FMemo do
+    begin
+      CurY := FUndoCurY0;
+      CurX := FUndoCurX0;
+      PerformRedo;
+      CurY := FUndoCurY;
+      CurX := FUndoCurX;
+    end;
+end;
+
+function TGLSMemoUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
+begin
+  Result := False;
+end;
+
+//----------------  TINSERT CHAR UNDO --------------------------
+
+procedure TGLSMemoInsCharUndo.PerformUndo;
+var
+  i: integer;
+  CurrLine: string;
+begin
+  for i := Length(FUndoText) downto 1 do
+  begin
+    CurrLine := FMemo.Lines[FMemo.CurY];
+    if ((FUndoText[i] = #13) and (FMemo.CurX = 0)) or
+      (FUndoText[i] = CurrLine[FMemo.CurX]) then
+      FMemo.BackSpace;
+  end;
+end;
+
+procedure TGLSMemoInsCharUndo.PerformRedo;
+var
+  i: integer;
+begin
+  with FMemo do
+    for i := 1 to Length(FUndoText) do
+      if FUndoText[i] = #13 then
+        NewLine
+      else
+        InsertChar(FUndoText[i]);
+end;
+
+function TGLSMemoInsCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
+begin
+  Result := False;
+  if not ((NewUndo is TGLSMemoInsCharUndo) and
+    (NewUndo.UndoCurX0 = FUndoCurX) and
+    (NewUndo.UndoCurY0 = FUndoCurY)) then
+    Exit;
+  FUndoText := FUndoText + NewUndo.FUndoText;
+  FUndoCurX := NewUndo.UndoCurX;
+  FUndoCurY := NewUndo.UndoCurY;
+  Result := True;
+end;
+
+//----------------  TDELETE CHAR UNDO --------------------------
+
+procedure TGLSMemoDelCharUndo.PerformUndo;
+var
+  i: integer;
+begin
+  with FMemo do
+    for i := 1 to Length(FUndoText) do
+    begin
+      if not FIsBackspace then
+      begin
+        CurY := FUndoCurY0;
+        CurX := FUndoCurX0;
+      end;
+      if FUndoText[i] = #13 then
+        NewLine
+      else
+        InsertChar(FUndoText[i]);
+    end;
+end;
+
+procedure TGLSMemoDelCharUndo.PerformRedo;
+var
+  i: integer;
+begin
+  with FMemo do
+    for i := 1 to Length(FUndoText) do
+      if FIsBackspace then
+        BackSpace
+      else
+        DeleteChar(-1, -1);
+end;
+
+function TGLSMemoDelCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
+begin
+  Result := False;
+  if not ((NewUndo is TGLSMemoDelCharUndo) and
+    (NewUndo.UndoCurX0 = FUndoCurX) and
+    (NewUndo.UndoCurY0 = FUndoCurY)) then
+    Exit;
+  if TGLSMemoDelCharUndo(NewUndo).FIsBackspace <> FIsBackspace then
+    Exit;
+  FUndoText := NewUndo.FUndoText + FUndoText;
+  FUndoCurX := NewUndo.UndoCurX;
+  FUndoCurY := NewUndo.UndoCurY;
+  Result := True;
+end;
+
+//----------------  TDELETE BUF, LINE UNDO --------------------------
+
+constructor TGLSMemoDelLineUndo.Create(AIndex, ACurX0, ACurY0, ACurX, ACurY:
+  integer; const AText: string);
+begin
+  inherited Create(ACurX0, ACurY0, ACurX, ACurY, AText);
+  FIndex := AIndex;
+end;
+
+procedure TGLSMemoDelLineUndo.PerformUndo;
+var
+  SaveCurX: integer;
+begin
+  with FMemo do
+  begin
+    SaveCurX := CurX;
+    CurX := 0;
+    ClearSelection;
+    SetSelText(PChar(FUndoText + #13#10));
+    CurX := SaveCurX;
+  end;
+end;
+
+procedure TGLSMemoDelLineUndo.PerformRedo;
+begin
+  FMemo.DeleteLine(FIndex, FUndoCurX0, FUndoCurY0, FUndoCurX, FUndoCurY, True);
+end;
+
+procedure TGLSMemoDeleteBufUndo.PerformUndo;
+begin
+  with FMemo do
+  begin
+    ClearSelection;
+    SetSelText(PChar(FUndoText));
+  end;
+end;
+
+procedure TGLSMemoDeleteBufUndo.PerformRedo;
+begin
+  with FMemo do
+  begin
+    FSelStartX := FUndoSelStartX;
+    FSelStartY := FUndoSelStartY;
+    FSelEndX := FUndoSelEndX;
+    FSelEndY := FUndoSelEndY;
+    DeleteSelection(True);
+  end;
+end;
+
+//----------------  TPASTE UNDO --------------------------
+
+procedure TGLSMemoPasteUndo.PerformUndo;
+begin
+  with FMemo do
+  begin
+    FSelStartX := FUndoCurX0;
+    FSelStartY := FUndoCurY0;
+    FSelEndX := FUndoCurX;
+    FSelEndY := FUndoCurY;
+    DeleteSelection(True);
+  end;
+end;
+
+procedure TGLSMemoPasteUndo.PerformRedo;
+begin
+  with FMemo do
+  begin
+    ClearSelection;
+    SetSelText(PChar(FUndoText));
+  end;
+end;
+
+//----------------  TUNDO LIST --------------------------
+
+constructor TGLSMemoUndoList.Create;
+begin
+  inherited;
+  FPos := 0;
+  FIsPerforming := False;
+  FLimit := 100;
+end;
+
+destructor TGLSMemoUndoList.Destroy;
+begin
+  Clear;
+  inherited;
+end;
+
+function TGLSMemoUndoList.Get(Index: Integer): TGLSMemoUndo;
+begin
+  Result := TGLSMemoUndo(inherited Get(Index));
+end;
+
+function TGLSMemoUndoList.Add(Item: Pointer): Integer;
+begin
+  Result := -1;
+  if FIsPerforming then
+  begin
+    TGLSMemoUndo(Item).Free;
+    Exit;
+  end;
+
+  if (Count > 0) and
+    Items[0].Append(TGLSMemoUndo(Item)) then
+  begin
+    TGLSMemoUndo(Item).Free;
+    Exit;
+  end;
+
+  TGLSMemoUndo(Item).FMemo := Self.FMemo;
+  if FPos > 0 then
+    while FPos > 0 do
+    begin
+      Delete(0);
+      Dec(FPos);
+    end;
+  Insert(0, Item);
+  if Count > FLimit then
+    Delete(Count - 1);
+  Memo.UndoChange;
+  Result := 0;
+end;
+
+procedure TGLSMemoUndoList.Clear;
+begin
+  while Count > 0 do
+    Delete(0);
+  FPos := 0;
+  with Memo do
+    if not (csDestroying in ComponentState) then
+      UndoChange;
+end;
+
+procedure TGLSMemoUndoList.Delete(Index: Integer);
+begin
+  TGLSMemoUndo(Items[Index]).Free;
+  inherited;
+end;
+
+procedure TGLSMemoUndoList.Undo;
+var
+  OldAutoIndent: Boolean;
+begin
+  if FPos < Count then
+  begin
+    OldAutoIndent := Memo.AutoIndent;
+    Memo.AutoIndent := False;
+    FIsPerforming := True;
+    Items[FPos].Undo;
+    Inc(FPos);
+    FIsPerforming := False;
+    Memo.AutoIndent := OldAutoIndent;
+    Memo.UndoChange;
+  end;
+end;
+
+procedure TGLSMemoUndoList.Redo;
+var
+  OldAutoIndent: Boolean;
+begin
+  if FPos > 0 then
+  begin
+    OldAutoIndent := Memo.AutoIndent;
+    Memo.AutoIndent := False;
+    FIsPerforming := True;
+    Dec(FPos);
+    Items[FPos].Redo;
+    FIsPerforming := False;
+    Memo.AutoIndent := OldAutoIndent;
+    Memo.UndoChange;
+  end;
+end;
+
+procedure TGLSMemoUndoList.SetLimit(Value: integer);
+begin
+  if FLimit <> Value then
+  begin
+    if Value <= 0 then
+      Value := 10;
+    if Value > 0 then
+      Value := 100;
+    FLimit := Value;
+    Clear;
+  end;
+end;
+
+procedure TGLSSynHiMemo.Paint;
+begin
+  FIsPainting := True;
+  try
+    DelimiterStyle := FDelimiterStyle;
+    CommentStyle := FCommentStyle;
+    NumberStyle := FNumberStyle;
+    inherited;
+  finally
+    FIsPainting := False;
+  end;
+end;
+
+ 
+
+// ---------------------TGLSSynHiMemo 
+
+procedure TGLSSynHiMemo.SetStyle(Index: integer; Value: TCharStyle);
+var
+  No: integer;
+  eRect: TRect;
+begin
+  No := -1;
+  case Index of
+    0: No := FDelimiterStyleNo;
+    1: No := FCommentStyleNo;
+    2: No := FNumberStyleNo;
+  end;
+  with Value do
+    Styles.Change(No, TextColor, BkColor, Style);
+  if not FIsPainting then
+  begin
+    eRect := EditorRect;
+    InvalidateRect(Handle, @eRect, True);
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - SET WORD LIST
+//--------------------------------------------------------------
+
+procedure TGLSSynHiMemo.SetWordList(Value: TGLSMemoStringList);
+begin
+  FWordList.Assign(Value);
+end;
+
+procedure TGLSSynHiMemo.SetSpecialList(Value: TGLSMemoStringList);
+begin
+  FSpecialList.Assign(Value);
+end;
+
+procedure TGLSSynHiMemo.SetBracketList(Value: TGLSMemoStringList);
+begin
+  FBracketList.Assign(Value);
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - SET CASE SENSITIVE
+//--------------------------------------------------------------
+
+procedure TGLSSynHiMemo.SetCaseSensitive(Value: Boolean);
+var
+  LineNo: integer;
+begin
+  if Value <> FCaseSensitive then
+  begin
+    FCaseSensitive := Value;
+    for LineNo := 0 to Lines.Count - 1 do
+      ValidAttrs[LineNo] := False;
+    Invalidate;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - GET TOKEN
+//--------------------------------------------------------------
+
+function TGLSSynHiMemo.GetToken(const S: string; var From: integer;
+  out TokenType: TTokenType; out StyleNo: integer): string;
+var
+  i, toStart, toEnd, Len, LenSpec: integer;
+  Done: Boolean;
+  Brackets: string;
+  IntPart: integer;
+  WasPoint: Boolean;
+  //-------------------------------------------------------------
+  function StartsFrom(const S: string; Pos: integer; const S0: string): Boolean;
+  begin
+    Result := (StrLComp(PChar(S) + Pos - 1, PChar(S0), Length(S0)) = 0);
+  end;
+  //-------------------------------------------------------------
+  function Equal(const s1, s2: string): Boolean;
+  begin
+    if FCaseSensitive then
+      Result := s1 = s2
+    else
+      Result := AnsiLowerCase(s1) = AnsiLowerCase(s2);
+  end;
+begin
+  toStart := From;
+  toEnd := From;
+  TokenType := ttOther;
+  StyleNo := 0;
+  Len := Length(S);
+  // End of line
+  if From > Len then
+  begin
+    From := -1;
+    Result := '';
+    TokenType := ttEOL;
+    StyleNo := 0;
+    Exit;
+  end;
+  // Begin of multiline comment
+  if (MultiCommentLeft <> '') and (MultiCommentRight <> '') and
+    StartsFrom(S, From, MultiCommentLeft) then
+  begin
+    Result := MultiCommentLeft;
+    FInComment := True;
+    TokenType := ttComment;
+    StyleNo := FCommentStyleNo;
+    Inc(From, Length(MultiCommentLeft));
+    Exit;
+  end;
+  // Inside multiline comment
+  if FInComment then
+  begin
+    toEnd := toStart;
+    while (toEnd <= Len) and (not StartsFrom(S, toEnd, MultiCommentRight)) do
+      Inc(toEnd);
+    if toEnd > Len then
+    begin
+      Result := Copy(S, From, toEnd - From);
+      From := toEnd;
+    end
+    else
+    begin
+      FInComment := False;
+      toEnd := toEnd + Length(MultiCommentRight);
+      Result := Copy(S, From, toEnd - From);
+      From := toEnd;
+    end;
+    TokenType := ttComment;
+    StyleNo := FCommentStyleNo;
+    Exit;
+  end;
+
+  // Inside brikets
+  if FInBrackets >= 0 then
+  begin
+    Brackets := FBracketList[FInBrackets];
+    toEnd := toStart + 1;
+    while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
+      Inc(toEnd);
+    StyleNo := integer(FBracketList.Objects[FInBrackets]);
+    if toEnd <= Len then
+    begin
+      FInBrackets := -1;
+      From := toEnd + 1;
+    end
+    else
+      From := toEnd;
+    Result := Copy(S, toStart, toEnd - toStart + 1);
+    TokenType := ttBracket;
+    Exit;
+  end;
+  // Spaces
+  while (toStart <= Len) and (S[toStart] = ' ') do
+    Inc(toStart);
+  if toStart > From then
+  begin
+    Result := Copy(S, From, toStart - From);
+    From := toStart;
+    TokenType := ttSpace;
+    StyleNo := 0;
+    Exit;
+  end;
+  // Comment
+  if (FLineComment <> '') and StartsFrom(S, From, FLineComment) then
+  begin
+    Result := Copy(S, From, Len);
+    From := Len + 1;
+    TokenType := ttComment;
+    StyleNo := FCommentStyleNo;
+    Exit;
+  end;
+
+  // Special keyword
+  Done := False;
+  for i := 0 to FSpecialList.Count - 1 do
+  begin
+    LenSpec := Length(FSpecialList[i]);
+    if StrLComp(PChar(S) + toStart - 1,
+      PChar(FSpecialList[i]), LenSpec) = 0 then
+    begin
+      toEnd := toStart + LenSpec - 1;
+      StyleNo := integer(FSpecialList.Objects[i]);
+      TokenType := ttSpecial;
+      From := toEnd + 1;
+      Done := True;
+      break;
+    end;
+  end;
+  // Brickets
+  if not Done then
+  begin
+    for i := 0 to FBracketList.Count - 1 do
+    begin
+      Brackets := FBracketList[i];
+      if S[toStart] = Brackets[1] then
+      begin
+        FInBrackets := i;
+        toEnd := toStart + 1;
+        while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
+          Inc(toEnd);
+        if toEnd <= Len then
+          FInBrackets := -1
+        else
+          Dec(toEnd);
+        StyleNo := integer(FBracketList.Objects[i]);
+        TokenType := ttBracket;
+        Done := True;
+        break;
+      end;
+    end;
+  end;
+  // Delimeters
+  if not Done and CharInSet(S[toStart], Delimiters) then
+  begin
+    toEnd := toStart;
+    StyleNo := FDelimiterStyleNo;
+    TokenType := ttDelimiter;
+    Done := True;
+  end;
+  // --- Integer or float type
+  if not Done and CharInSet(S[toStart], ['0'..'9', '.']) then
+  begin
+    IntPart := 0;
+    WasPoint := False;
+    toEnd := toStart;
+    Done := True;
+    TokenType := ttInteger;
+    StyleNo := FNumberStyleNo;
+    while (toEnd <= Len) and CharInSet(S[toEnd], ['0'..'9', '.']) do
+    begin
+      if S[toEnd] = '.' then
+      begin
+        if not WasPoint then
+        begin
+          WasPoint := True;
+          TokenType := ttFloat;
+        end
+        else
+        begin
+          TokenType := ttWrongNumber;
+          Color := clRed;
+        end;
+      end
+      else if not WasPoint then
+        try
+          IntPart := IntPart * 10 + Ord(S[toEnd]) - Ord('0');
+        except
+          IntPart := MaxInt;
+        end;
+      Inc(toEnd);
+    end;
+    Dec(toEnd);
+  end;
+  // Select word
+  if not Done then
+  begin
+    toEnd := toStart;
+    while (toEnd <= Len) and not CharInSet(S[toEnd], Delimiters) do
+      Inc(toEnd);
+    Dec(toEnd);
+  end;
+  // Find in dictionary
+  Result := Copy(S, toStart, toEnd - toStart + 1);
+  for i := 0 to FWordList.Count - 1 do
+    if Equal(Result, FWordList[i]) then
+    begin
+      StyleNo := integer(FWordList.Objects[i]);
+      TokenType := ttWord;
+      break;
+    end;
+  From := toEnd + 1;
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - FIND LINE ATTRS
+//--------------------------------------------------------------
+
+procedure TGLSSynHiMemo.FindLineAttrs(Sender: TObject; LineNo: integer;
+  var Attrs: string);
+var
+  i, From, TokenLen: integer;
+  S, Token: string;
+  TokenType: TTokenType;
+  StyleNo, OldInBrackets: integer;
+  OldInComment: Boolean;
+begin
+  S := Lines[LineNo];
+  SetLength(Attrs, Length(S));
+  FInComment := InComment[LineNo];
+  FInBrackets := InBrackets[LineNo];
+  From := 1;
+  while True do
+  begin
+    Token := GetToken(S, From, TokenType, StyleNo);
+    if TokenType = ttEOL then
+      break;
+    TokenLen := Length(Token);
+    for i := From - TokenLen to From - 1 do
+      Attrs[i] := Char(StyleNo);
+  end;
+  if LineNo < Lines.Count - 1 then
+  begin
+    OldInComment := InComment[LineNo + 1];
+    OldInBrackets := InBrackets[LineNo + 1];
+    if OldInComment <> FInComment then
+    begin
+      InComment[LineNo + 1] := FInComment;
+      ValidAttrs[LineNo + 1] := False;
+    end;
+    if OldInBrackets <> FInBrackets then
+    begin
+      InBrackets[LineNo + 1] := FInBrackets;
+      ValidAttrs[LineNo + 1] := False;
+    end;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - ADD WORD
+//--------------------------------------------------------------
+
+procedure TGLSSynHiMemo.AddWord(StyleNo: integer; const ArrS: array of string);
+var
+  i: integer;
+begin
+  for i := Low(ArrS) to high(ArrS) do
+    FWordList.AddObject(ArrS[i], TObject(StyleNo));
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - ADD SPECIAL
+//--------------------------------------------------------------
+
+procedure TGLSSynHiMemo.AddSpecial(StyleNo: integer; const ArrS: array of string);
+var
+  i: integer;
+begin
+  for i := Low(ArrS) to high(ArrS) do
+    FSpecialList.AddObject(ArrS[i], TObject(StyleNo));
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - ADD BRACKETS
+//--------------------------------------------------------------
+
+procedure TGLSSynHiMemo.AddBrackets(StyleNo: integer; const ArrS: array of string);
+var
+  i: integer;
+begin
+  for i := Low(ArrS) to high(ArrS) do
+    FBracketList.AddObject(ArrS[i], TObject(StyleNo));
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - CREATE
+//--------------------------------------------------------------
+
+constructor TGLSSynHiMemo.Create(AOwner: TComponent);
+begin
+  inherited;
+  FInBrackets := -1;
+  FIsPainting := False;
+  FInComment := False;
+  FWordList := TGLSMemoStringList.Create;
+  FSpecialList := TGLSMemoStringList.Create;
+  FBracketList := TGLSMemoStringList.Create;
+
+  FDelimiterStyle := TCharStyle.Create;
+  with FDelimiterStyle do
+  begin
+    TextColor := clBlue;
+    BkColor := clWhite;
+    Style := [];
+  end;
+
+  FCommentStyle := TCharStyle.Create;
+  with FCommentStyle do
+  begin
+    TextColor := clYellow;
+    BkColor := clSkyBlue;
+    Style := [fsItalic];
+  end;
+
+  FNumberStyle := TCharStyle.Create;
+  with FNumberStyle do
+  begin
+    TextColor := clNavy;
+    BkColor := clWhite;
+    Style := [fsBold];
+  end;
+
+  FDelimiterStyleNo := Styles.Add(clBlue, clWhite, []);
+  FCommentStyleNo := Styles.Add(clSilver, clWhite, [fsItalic]);
+  FNumberStyleNo := Styles.Add(clNavy, clWhite, [fsBold]);
+  OnGetLineAttrs := FindLineAttrs;
+  Delimiters := [' ', ',', ';', ':', '.', '(', ')', '{', '}', '[', ']',
+    '=', '+', '-', '*', '/', '^', '%', '<', '>',
+    '"', '''', #13, #10];
+end;
+
+//--------------------------------------------------------------
+//        SYNTAX MEMO - DESTROY
+//--------------------------------------------------------------
+
+destructor TGLSSynHiMemo.Destroy;
+begin
+  FWordList.Free;
+  FSpecialList.Free;
+  FBracketList.Free;
+  FDelimiterStyle.Free;
+  FCommentStyle.Free;
+  FNumberStyle.Free;
+  inherited;
+end;
+
+// ---------------------TGLSMemoStringList
+
+procedure TGLSMemoStringList.ReadStrings(Reader: TReader);
+var
+  i: Integer;
+begin
+  try
+    Reader.ReadListBegin;
+    Clear;
+    while not Reader.EndOfList do
+    begin
+      i := Add(Reader.ReadString);
+      Objects[i] := TObject(Reader.ReadInteger);
+    end;
+    Reader.ReadListEnd;
+  finally
+  end;
+end;
+
+//--------------------------------------------------------------
+//        STRING LIST - WRITE STRINGS
+//--------------------------------------------------------------
+
+procedure TGLSMemoStringList.WriteStrings(Writer: TWriter);
+var
+  i: Integer;
+begin
+  with Writer do
+  begin
+    WriteListBegin;
+    for i := 0 to Count - 1 do
+    begin
+      WriteString(Strings[i]);
+      WriteInteger(Integer(Objects[i]));
+    end;
+    WriteListEnd;
+  end;
+end;
+
+//--------------------------------------------------------------
+//        STRING LIST - DEFINE PROPERTIES
+//--------------------------------------------------------------
+
+procedure TGLSMemoStringList.DefineProperties(Filer: TFiler);
+begin
+  Filer.DefineProperty('Strings', ReadStrings, WriteStrings, Count > 0);
+end;
+
+ 
+
+// ---------------------ScrollBar bitmaps 
+
+procedure CreateScrollBarBitmaps;
+var
+  i, j: integer;
+begin
+  bmScrollBarFill := TBitmap.Create;
+  with bmScrollBarFill, Canvas do
+  begin
+    Width := 8;
+    Height := 8;
+    Transparent := False;
+    for i := 0 to 7 do
+      for j := 0 to 7 do
+        if Odd(i + j) then
+          Pixels[i, j] := clSilver;
+  end;
+
+  bmScrollBarUp := TBitmap.Create;
+  with bmScrollBarUp, Canvas do
+  begin
+    Width := 7;
+    Height := 8;
+    Brush.Color := clSilver;
+    FillRect(Rect(0, 0, Width, Height));
+    Pixels[3, 2] := clBlack;
+    MoveTo(2, 3);
+    LineTo(5, 3);
+    MoveTo(1, 4);
+    LineTo(6, 4);
+    MoveTo(0, 5);
+    LineTo(7, 5);
+  end;
+
+  bmScrollBarDown := TBitmap.Create;
+  with bmScrollBarDown, Canvas do
+  begin
+    Width := 7;
+    Height := 8;
+    Brush.Color := clSilver;
+    FillRect(Rect(0, 0, Width, Height));
+    MoveTo(0, 2);
+    LineTo(7, 2);
+    MoveTo(1, 3);
+    LineTo(6, 3);
+    MoveTo(2, 4);
+    LineTo(5, 4);
+    Pixels[3, 5] := clBlack;
+  end;
+
+  bmScrollBarLeft := TBitmap.Create;
+  with bmScrollBarLeft, Canvas do
+  begin
+    Width := 8;
+    Height := 7;
+    Brush.Color := clSilver;
+    FillRect(Rect(0, 0, Width, Height));
+    Pixels[2, 3] := clBlack;
+    MoveTo(3, 2);
+    LineTo(3, 5);
+    MoveTo(4, 1);
+    LineTo(4, 6);
+    MoveTo(5, 0);
+    LineTo(5, 7);
+  end;
+  bmScrollBarRight := TBitmap.Create;
+  with bmScrollBarRight, Canvas do
+  begin
+    Width := 8;
+    Height := 7;
+    Brush.Color := clSilver;
+    FillRect(Rect(0, 0, Width, Height));
+    MoveTo(2, 0);
+    LineTo(2, 7);
+    MoveTo(3, 1);
+    LineTo(3, 6);
+    MoveTo(4, 2);
+    LineTo(4, 5);
+    Pixels[5, 3] := clBlack;
+  end;
+end;
+
+//------------------ FREE SCROLL BAR BITMAPs -------------------
+
+procedure FreeScrollBarBitmaps;
+begin
+  bmScrollBarFill.Free;
+  bmScrollBarUp.Free;
+  bmScrollBarDown.Free;
+  bmScrollBarLeft.Free;
+  bmScrollBarRight.Free;
+end;
+
+
+//----------------------------------
+initialization
+//----------------------------------
+
+  RegisterClasses([TGLSSynHiMemo]);
+  CreateScrollBarBitmaps;
+  IntelliMouseInit;
+
+//----------------------------------
+finalization
+//----------------------------------
+
+  FreeScrollBarBitmaps;
+
+end.
+

+ 1 - 1
Source/GLS.ParallelRegister.pas

@@ -4,7 +4,7 @@
 
 
 unit GLS.ParallelRegister;
 unit GLS.ParallelRegister;
 
 
-(*  Registration unit for GLScene GPU Computing package *)
+(*  Registration unit for GPU Computing package *)
 
 
 interface
 interface
 
 

+ 416 - 402
Source/GLPlugInManager.pas → Source/GLS.PlugInManager.pas

@@ -1,402 +1,416 @@
-//
-// This unit is part of the GLScene Engine, http://glscene.org
-//
-{
-  An old PlugIn Manager unit. Don't know if if ever wa used... 
-}
-unit GLPlugInManager;
-
-interface
-
-{$I GLScene.inc}
-
-uses
-  Winapi.Windows, 
-  System.Classes, 
-  System.SysUtils,
-  VCL.Dialogs, 
-  VCL.Forms,
-  GLPlugInIntf;
-
-
-type
-  PPlugInEntry = ^TGLPlugInEntry;
-
-  TGLPlugInEntry = record
-    Path: TFileName;
-    Handle: HINST;
-    FileSize: Integer;
-    FileDate: TDateTime;
-    EnumResourcenames: TEnumResourceNames;
-    GetServices: TGetServices;
-    GetVendor: TGetVendor;
-    GetDescription: TGetDescription;
-    GetVersion: TGetVersion;
-  end;
-
-  TGLPlugInManager = class;
-
-  TGLResourceManager = class(TComponent)
-  public
-    procedure Notify(Sender: TGLPlugInManager; Operation: TOperation;
-      Service: TPIServiceType; PlugIn: Integer); virtual; abstract;
-  end;
-
-  TGLPlugInList = class(TStringList)
-  private
-    FOwner: TGLPlugInManager;
-    function GetPlugInEntry(Index: Integer): PPlugInEntry;
-    procedure SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
-  protected
-    procedure DefineProperties(Filer: TFiler); override;
-    procedure ReadPlugIns(Reader: TReader);
-    procedure WritePlugIns(Writer: TWriter);
-  public
-    constructor Create(AOwner: TGLPlugInManager); virtual;
-    procedure ClearList;
-    property Objects[Index: Integer]: PPlugInEntry read GetPlugInEntry
-      write SetPlugInEntry; default;
-    property Owner: TGLPlugInManager read FOwner;
-  end;
-
-  PResManagerEntry = ^TResManagerEntry;
-
-  TResManagerEntry = record
-    Manager: TGLResourceManager;
-    Services: TPIServices;
-  end;
-
-  TGLPlugInManager = class(TComponent)
-  private
-    FLibraryList: TGLPlugInList;
-    FResManagerList: TList;
-  protected
-    procedure DoNotify(Operation: TOperation; Service: TPIServiceType;
-      PlugIn: Integer);
-    function FindResManager(AManager: TGLResourceManager): PResManagerEntry;
-    function GetIndexFromFilename(FileName: String): Integer;
-    function GetPlugInFromFilename(FileName: String): PPlugInEntry;
-  public
-    constructor Create(AOwner: TComponent); override;
-    destructor Destroy; override;
-    function AddPlugIn(Path: TFileName): Integer;
-    procedure EditPlugInList;
-    procedure RegisterResourceManager(AManager: TGLResourceManager;
-      Services: TPIServices);
-    procedure RemovePlugIn(Index: Integer);
-    procedure UnRegisterRessourceManager(AManager: TGLResourceManager;
-      Services: TPIServices);
-  published
-    property PlugIns: TGLPlugInList read FLibraryList write FLibraryList;
-  end;
-
-// ------------------------------------------------------------------------------
-implementation
-// ------------------------------------------------------------------------------
-
-
-// ----------------- TGLPlugInList ------------------------------------------------
-
-constructor TGLPlugInList.Create(AOwner: TGLPlugInManager);
-
-begin
-  inherited Create;
-  FOwner := AOwner;
-  Sorted := False;
-  Duplicates := DupAccept;
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInList.ClearList;
-
-begin
-  while Count > 0 do
-    FOwner.RemovePlugIn(0);
-end;
-
-// ------------------------------------------------------------------------------
-
-function TGLPlugInList.GetPlugInEntry(Index: Integer): PPlugInEntry;
-
-begin
-  Result := PPlugInEntry( inherited Objects[Index]);
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInList.SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
-
-begin
-  inherited Objects[Index] := Pointer(AEntry);
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInList.WritePlugIns(Writer: TWriter);
-
-var
-  I: Integer;
-
-begin
-  Writer.WriteListBegin;
-  for I := 0 to Count - 1 do
-    Writer.WriteString(Objects[I].Path);
-  Writer.WriteListEnd;
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInList.ReadPlugIns(Reader: TReader);
-
-begin
-  ClearList;
-  Reader.ReadListBegin;
-  while not Reader.EndOfList do
-    FOwner.AddPlugIn(Reader.ReadString);
-  Reader.ReadListEnd;
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInList.DefineProperties(Filer: TFiler);
-
-begin
-  Filer.DefineProperty('Paths', ReadPlugIns, WritePlugIns, Count > 0);
-end;
-
-// ----------------- TGLPlugInManager ---------------------------------------------
-
-constructor TGLPlugInManager.Create(AOwner: TComponent);
-
-begin
-  inherited Create(AOwner);
-  FLibraryList := TGLPlugInList.Create(Self);
-  FResManagerList := TList.Create;
-end;
-
-// ------------------------------------------------------------------------------
-
-destructor TGLPlugInManager.Destroy;
-var
-  I: Integer;
-begin
-  FLibraryList.ClearList;
-  FLibraryList.Free;
-  for I := 0 to FResManagerList.Count - 1 do
-    FreeMem(PResManagerEntry(FResManagerList[I]), SizeOf(TResManagerEntry));
-  FResManagerList.Free;
-  inherited Destroy;
-end;
-
-// ------------------------------------------------------------------------------
-
-function TGLPlugInManager.AddPlugIn(Path: TFileName): Integer;
-
-// open the given DLL and read its properties, to identify
-// whether it's a valid plug-in or not
-
-var
-  NewPlugIn: PPlugInEntry;
-  OldError: Integer;
-  NewHandle: HINST;
-  ServiceFunc: TGetServices;
-  SearchRec: TSearchRec;
-  Service: TPIServiceType;
-  Services: TPIServices;
-
-begin
-  Result := -1;
-  OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
-  if Length(Path) > 0 then
-    try
-      Result := GetIndexFromFilename(Path);
-      // plug-in already registered?
-      if Result > -1 then
-        Exit;
-      // first step is loading the file into client memory
-      NewHandle := LoadLibrary(PChar(Path));
-      // loading failed -> exit
-      if NewHandle = 0 then
-        Abort;
-      // get the service function address to identify the plug-in
-      ServiceFunc := GetProcAddress(NewHandle, 'GetServices');
-      if not assigned(ServiceFunc) then
-      begin
-        // if address not found then the given library is not valid
-        // release it from client memory
-        FreeLibrary(NewHandle);
-        Abort;
-      end;
-      // all went fine so far, we just loaded a valid plug-in
-      // allocate a new entry for the plug-in list and fill it
-      New(NewPlugIn);
-      NewPlugIn.Path := Path;
-      with NewPlugIn^ do
-      begin
-        Handle := NewHandle;
-        FindFirst(Path, faAnyFile, SearchRec);
-        FileSize := SearchRec.Size;
-        FileDate := SearchRec.TimeStamp;
-        FindClose(SearchRec);
-        GetServices := ServiceFunc;
-        EnumResourcenames := GetProcAddress(Handle, 'EnumResourceNames');
-        GetVendor := GetProcAddress(Handle, 'GetVendor');
-        GetVersion := GetProcAddress(Handle, 'GetVersion');
-        GetDescription := GetProcAddress(Handle, 'GetDescription');
-      end;
-      Result := FLibraryList.Add(string(NewPlugIn.GetVendor));
-      FLibraryList.Objects[Result] := NewPlugIn;
-      // now notify (for all provided services) all registered resource managers
-      // for which these services are relevant
-      Services := NewPlugIn.GetServices;
-      for Service := Low(TPIServiceType) to High(TPIServiceType) do
-        if Service in Services then
-          DoNotify(opInsert, Service, Result);
-    finally
-      SetErrorMode(OldError);
-    end;
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInManager.DoNotify(Operation: TOperation;
-  Service: TPIServiceType; PlugIn: Integer);
-
-var
-  I: Integer;
-
-begin
-  for I := 0 TO FResManagerList.Count - 1 do
-    if Service in PResManagerEntry(FResManagerList[I]).Services then
-      PResManagerEntry(FResManagerList[I]).Manager.Notify(Self, Operation,
-        Service, PlugIn);
-end;
-
-// ------------------------------------------------------------------------------
-
-function TGLPlugInManager.FindResManager(AManager: TGLResourceManager)
-  : PResManagerEntry;
-
-var
-  I: Integer;
-
-begin
-  Result := nil;
-  for I := 0 to FResManagerList.Count - 1 do
-    if PResManagerEntry(FResManagerList[I]).Manager = AManager then
-    begin
-      Result := PResManagerEntry(FResManagerList[I]);
-      Exit;
-    end;
-end;
-
-// ------------------------------------------------------------------------------
-
-function TGLPlugInManager.GetIndexFromFilename(FileName: String): Integer;
-
-var
-  I: Integer;
-
-begin
-  Result := -1;
-  for I := 0 to FLibraryList.Count - 1 do
-    if CompareText(FLibraryList[I].Path, FileName) = 0 then
-    begin
-      Result := I;
-      Exit;
-    end;
-end;
-
-// ------------------------------------------------------------------------------
-
-function TGLPlugInManager.GetPlugInFromFilename(FileName: String): PPlugInEntry;
-
-var
-  I: Integer;
-
-begin
-  I := GetIndexFromFilename(FileName);
-  if I > -1 then
-    Result := FLibraryList[I]
-  else
-    Result := nil;
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInManager.RegisterResourceManager(AManager: TGLResourceManager;
-  Services: TPIServices);
-
-var
-  ManagerEntry: PResManagerEntry;
-
-begin
-  ManagerEntry := FindResManager(AManager);
-  if assigned(ManagerEntry) then
-    ManagerEntry.Services := ManagerEntry.Services + Services
-  else
-  begin
-    New(ManagerEntry);
-    ManagerEntry.Manager := AManager;
-    ManagerEntry.Services := Services;
-    FResManagerList.Add(ManagerEntry);
-  end;
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInManager.RemovePlugIn(Index: Integer);
-
-var
-  Entry: PPlugInEntry;
-  Service: TPIServiceType;
-  Services: TPIServices;
-
-begin
-  Entry := FLibraryList.Objects[Index];
-  Services := Entry.GetServices;
-  // notify for all services to be deleted all registered resource managers
-  // for which these services are relevant
-  for Service := Low(TPIServiceType) to High(TPIServiceType) do
-    if Service in Services then
-      DoNotify(opRemove, Service, Index);
-  FreeLibrary(Entry.Handle);
-  Dispose(Entry);
-  FLibraryList.Delete(Index);
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInManager.EditPlugInList;
-
-begin
-  ///TGLPlugInManagerEditor.EditPlugIns(Self);   //Circular call to edit Listbox items?
-end;
-
-// ------------------------------------------------------------------------------
-
-procedure TGLPlugInManager.UnRegisterRessourceManager(AManager: TGLResourceManager;
-  Services: TPIServices);
-
-var
-  ManagerEntry: PResManagerEntry;
-  Index: Integer;
-
-begin
-  ManagerEntry := FindResManager(AManager);
-  if assigned(ManagerEntry) then
-  begin
-    ManagerEntry.Services := ManagerEntry.Services - Services;
-    if ManagerEntry.Services = [] then
-    begin
-      Index := FResManagerList.IndexOf(ManagerEntry);
-      Dispose(ManagerEntry);
-      FResManagerList.Delete(Index);
-    end;
-  end;
-end;
-
-// ------------------------------------------------------------------------------
-
-end.
+//
+// This unit is part of the GLScene Engine, http://glscene.org
+//
+
+unit GLS.PlugInManager;
+
+(* An old PlugIn Manager unit. Yet not ever was used... *)
+
+interface
+
+{$I GLScene.inc}
+
+uses
+  Winapi.Windows, 
+  System.Classes, 
+  System.SysUtils,
+  VCL.Dialogs, 
+  VCL.Forms;
+
+
+type
+  TPIServiceType = (stRaw, stObject, stBitmap, stTexture, stImport, stExport);
+  TPIServices = set of TPIServiceType;
+
+  TEnumCallBack = procedure(Name: PAnsiChar); stdcall;
+
+  TEnumResourceNames = procedure(Service: TPIServiceType;
+    Callback: TEnumCallBack); stdcall;
+  TGetServices = function: TPIServices; stdcall;
+  TGetVendor = function: PAnsiChar; stdcall;
+  TGetDescription = function: PAnsiChar; stdcall;
+  TGetVersion = function: PAnsiChar; stdcall;
+
+
+type
+
+  PPlugInEntry = ^TGLPlugInEntry;
+
+  TGLPlugInEntry = record
+    Path: TFileName;
+    Handle: HINST;
+    FileSize: Integer;
+    FileDate: TDateTime;
+    EnumResourcenames: TEnumResourceNames;
+    GetServices: TGetServices;
+    GetVendor: TGetVendor;
+    GetDescription: TGetDescription;
+    GetVersion: TGetVersion;
+  end;
+
+  TGLPlugInManager = class;
+
+  TGLResourceManager = class(TComponent)
+  public
+    procedure Notify(Sender: TGLPlugInManager; Operation: TOperation;
+      Service: TPIServiceType; PlugIn: Integer); virtual; abstract;
+  end;
+
+  TGLPlugInList = class(TStringList)
+  private
+    FOwner: TGLPlugInManager;
+    function GetPlugInEntry(Index: Integer): PPlugInEntry;
+    procedure SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
+  protected
+    procedure DefineProperties(Filer: TFiler); override;
+    procedure ReadPlugIns(Reader: TReader);
+    procedure WritePlugIns(Writer: TWriter);
+  public
+    constructor Create(AOwner: TGLPlugInManager); virtual;
+    procedure ClearList;
+    property Objects[Index: Integer]: PPlugInEntry read GetPlugInEntry
+      write SetPlugInEntry; default;
+    property Owner: TGLPlugInManager read FOwner;
+  end;
+
+  PResManagerEntry = ^TResManagerEntry;
+
+  TResManagerEntry = record
+    Manager: TGLResourceManager;
+    Services: TPIServices;
+  end;
+
+  TGLPlugInManager = class(TComponent)
+  private
+    FLibraryList: TGLPlugInList;
+    FResManagerList: TList;
+  protected
+    procedure DoNotify(Operation: TOperation; Service: TPIServiceType;
+      PlugIn: Integer);
+    function FindResManager(AManager: TGLResourceManager): PResManagerEntry;
+    function GetIndexFromFilename(FileName: String): Integer;
+    function GetPlugInFromFilename(FileName: String): PPlugInEntry;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    function AddPlugIn(Path: TFileName): Integer;
+    procedure EditPlugInList;
+    procedure RegisterResourceManager(AManager: TGLResourceManager;
+      Services: TPIServices);
+    procedure RemovePlugIn(Index: Integer);
+    procedure UnRegisterRessourceManager(AManager: TGLResourceManager;
+      Services: TPIServices);
+  published
+    property PlugIns: TGLPlugInList read FLibraryList write FLibraryList;
+  end;
+
+// ------------------------------------------------------------------------------
+implementation
+// ------------------------------------------------------------------------------
+
+
+// ----------------- TGLPlugInList ------------------------------------------------
+
+constructor TGLPlugInList.Create(AOwner: TGLPlugInManager);
+
+begin
+  inherited Create;
+  FOwner := AOwner;
+  Sorted := False;
+  Duplicates := DupAccept;
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInList.ClearList;
+
+begin
+  while Count > 0 do
+    FOwner.RemovePlugIn(0);
+end;
+
+// ------------------------------------------------------------------------------
+
+function TGLPlugInList.GetPlugInEntry(Index: Integer): PPlugInEntry;
+
+begin
+  Result := PPlugInEntry( inherited Objects[Index]);
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInList.SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
+
+begin
+  inherited Objects[Index] := Pointer(AEntry);
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInList.WritePlugIns(Writer: TWriter);
+
+var
+  I: Integer;
+
+begin
+  Writer.WriteListBegin;
+  for I := 0 to Count - 1 do
+    Writer.WriteString(Objects[I].Path);
+  Writer.WriteListEnd;
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInList.ReadPlugIns(Reader: TReader);
+
+begin
+  ClearList;
+  Reader.ReadListBegin;
+  while not Reader.EndOfList do
+    FOwner.AddPlugIn(Reader.ReadString);
+  Reader.ReadListEnd;
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInList.DefineProperties(Filer: TFiler);
+
+begin
+  Filer.DefineProperty('Paths', ReadPlugIns, WritePlugIns, Count > 0);
+end;
+
+// ----------------- TGLPlugInManager ---------------------------------------------
+
+constructor TGLPlugInManager.Create(AOwner: TComponent);
+
+begin
+  inherited Create(AOwner);
+  FLibraryList := TGLPlugInList.Create(Self);
+  FResManagerList := TList.Create;
+end;
+
+// ------------------------------------------------------------------------------
+
+destructor TGLPlugInManager.Destroy;
+var
+  I: Integer;
+begin
+  FLibraryList.ClearList;
+  FLibraryList.Free;
+  for I := 0 to FResManagerList.Count - 1 do
+    FreeMem(PResManagerEntry(FResManagerList[I]), SizeOf(TResManagerEntry));
+  FResManagerList.Free;
+  inherited Destroy;
+end;
+
+// ------------------------------------------------------------------------------
+
+function TGLPlugInManager.AddPlugIn(Path: TFileName): Integer;
+
+// open the given DLL and read its properties, to identify
+// whether it's a valid plug-in or not
+
+var
+  NewPlugIn: PPlugInEntry;
+  OldError: Integer;
+  NewHandle: HINST;
+  ServiceFunc: TGetServices;
+  SearchRec: TSearchRec;
+  Service: TPIServiceType;
+  Services: TPIServices;
+
+begin
+  Result := -1;
+  OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
+  if Length(Path) > 0 then
+    try
+      Result := GetIndexFromFilename(Path);
+      // plug-in already registered?
+      if Result > -1 then
+        Exit;
+      // first step is loading the file into client memory
+      NewHandle := LoadLibrary(PChar(Path));
+      // loading failed -> exit
+      if NewHandle = 0 then
+        Abort;
+      // get the service function address to identify the plug-in
+      ServiceFunc := GetProcAddress(NewHandle, 'GetServices');
+      if not assigned(ServiceFunc) then
+      begin
+        // if address not found then the given library is not valid
+        // release it from client memory
+        FreeLibrary(NewHandle);
+        Abort;
+      end;
+      // all went fine so far, we just loaded a valid plug-in
+      // allocate a new entry for the plug-in list and fill it
+      New(NewPlugIn);
+      NewPlugIn.Path := Path;
+      with NewPlugIn^ do
+      begin
+        Handle := NewHandle;
+        FindFirst(Path, faAnyFile, SearchRec);
+        FileSize := SearchRec.Size;
+        FileDate := SearchRec.TimeStamp;
+        FindClose(SearchRec);
+        GetServices := ServiceFunc;
+        EnumResourcenames := GetProcAddress(Handle, 'EnumResourceNames');
+        GetVendor := GetProcAddress(Handle, 'GetVendor');
+        GetVersion := GetProcAddress(Handle, 'GetVersion');
+        GetDescription := GetProcAddress(Handle, 'GetDescription');
+      end;
+      Result := FLibraryList.Add(string(NewPlugIn.GetVendor));
+      FLibraryList.Objects[Result] := NewPlugIn;
+      // now notify (for all provided services) all registered resource managers
+      // for which these services are relevant
+      Services := NewPlugIn.GetServices;
+      for Service := Low(TPIServiceType) to High(TPIServiceType) do
+        if Service in Services then
+          DoNotify(opInsert, Service, Result);
+    finally
+      SetErrorMode(OldError);
+    end;
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInManager.DoNotify(Operation: TOperation;
+  Service: TPIServiceType; PlugIn: Integer);
+
+var
+  I: Integer;
+
+begin
+  for I := 0 TO FResManagerList.Count - 1 do
+    if Service in PResManagerEntry(FResManagerList[I]).Services then
+      PResManagerEntry(FResManagerList[I]).Manager.Notify(Self, Operation,
+        Service, PlugIn);
+end;
+
+// ------------------------------------------------------------------------------
+
+function TGLPlugInManager.FindResManager(AManager: TGLResourceManager)
+  : PResManagerEntry;
+
+var
+  I: Integer;
+
+begin
+  Result := nil;
+  for I := 0 to FResManagerList.Count - 1 do
+    if PResManagerEntry(FResManagerList[I]).Manager = AManager then
+    begin
+      Result := PResManagerEntry(FResManagerList[I]);
+      Exit;
+    end;
+end;
+
+// ------------------------------------------------------------------------------
+
+function TGLPlugInManager.GetIndexFromFilename(FileName: String): Integer;
+
+var
+  I: Integer;
+
+begin
+  Result := -1;
+  for I := 0 to FLibraryList.Count - 1 do
+    if CompareText(FLibraryList[I].Path, FileName) = 0 then
+    begin
+      Result := I;
+      Exit;
+    end;
+end;
+
+// ------------------------------------------------------------------------------
+
+function TGLPlugInManager.GetPlugInFromFilename(FileName: String): PPlugInEntry;
+
+var
+  I: Integer;
+
+begin
+  I := GetIndexFromFilename(FileName);
+  if I > -1 then
+    Result := FLibraryList[I]
+  else
+    Result := nil;
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInManager.RegisterResourceManager(AManager: TGLResourceManager;
+  Services: TPIServices);
+
+var
+  ManagerEntry: PResManagerEntry;
+
+begin
+  ManagerEntry := FindResManager(AManager);
+  if assigned(ManagerEntry) then
+    ManagerEntry.Services := ManagerEntry.Services + Services
+  else
+  begin
+    New(ManagerEntry);
+    ManagerEntry.Manager := AManager;
+    ManagerEntry.Services := Services;
+    FResManagerList.Add(ManagerEntry);
+  end;
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInManager.RemovePlugIn(Index: Integer);
+
+var
+  Entry: PPlugInEntry;
+  Service: TPIServiceType;
+  Services: TPIServices;
+
+begin
+  Entry := FLibraryList.Objects[Index];
+  Services := Entry.GetServices;
+  // notify for all services to be deleted all registered resource managers
+  // for which these services are relevant
+  for Service := Low(TPIServiceType) to High(TPIServiceType) do
+    if Service in Services then
+      DoNotify(opRemove, Service, Index);
+  FreeLibrary(Entry.Handle);
+  Dispose(Entry);
+  FLibraryList.Delete(Index);
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInManager.EditPlugInList;
+
+begin
+  ///TGLPlugInManagerEditor.EditPlugIns(Self);   //Circular call to edit Listbox items?
+end;
+
+// ------------------------------------------------------------------------------
+
+procedure TGLPlugInManager.UnRegisterRessourceManager(AManager: TGLResourceManager;
+  Services: TPIServices);
+
+var
+  ManagerEntry: PResManagerEntry;
+  Index: Integer;
+
+begin
+  ManagerEntry := FindResManager(AManager);
+  if assigned(ManagerEntry) then
+  begin
+    ManagerEntry.Services := ManagerEntry.Services - Services;
+    if ManagerEntry.Services = [] then
+    begin
+      Index := FResManagerList.IndexOf(ManagerEntry);
+      Dispose(ManagerEntry);
+      FResManagerList.Delete(Index);
+    end;
+  end;
+end;
+
+// ------------------------------------------------------------------------------
+
+end.

+ 56 - 70
Source/GLS.SceneRegister.pas

@@ -5,7 +5,7 @@
 unit GLS.SceneRegister;
 unit GLS.SceneRegister;
 
 
 (*
 (*
-  Registration unit for GLScene library components, property editors and
+  Registration unit for library components, property editors and
   IDE experts.
   IDE experts.
 *)
 *)
 
 
@@ -29,12 +29,12 @@ uses
   DesignEditors,
   DesignEditors,
   VCLEditors,
   VCLEditors,
 
 
-  GLScene,
-  GLStrings,
   GLContext,
   GLContext,
+  GLScene,
   GLColor,
   GLColor,
   GLCrossPlatform,
   GLCrossPlatform,
-  GLObjectManager;
+  GLObjectManager,
+  GLStrings;
 
 
 type
 type
   TGLLibMaterialNameProperty = class(TStringProperty)
   TGLLibMaterialNameProperty = class(TStringProperty)
@@ -287,6 +287,7 @@ uses
   FShaderUniformEditor,
   FShaderUniformEditor,
   FVectorEditor,
   FVectorEditor,
   FSceneEditor,
   FSceneEditor,
+
   GLAnimatedSprite,
   GLAnimatedSprite,
   GLApplicationFileIO,
   GLApplicationFileIO,
   GLAsmShader,
   GLAsmShader,
@@ -383,24 +384,22 @@ uses
   GLTimeEventsMgr,
   GLTimeEventsMgr,
   GLTrail,
   GLTrail,
   GLTree,
   GLTree,
-  GLTypes,
-  GLFileTIN,
   GLUserShader,
   GLUserShader,
   GLUtils,
   GLUtils,
   GLVectorFileObjects,
   GLVectorFileObjects,
-  GLVfsPAK,
   GLWin32Viewer,
   GLWin32Viewer,
   GLWaterPlane,
   GLWaterPlane,
   GLWindows,
   GLWindows,
   GLWindowsFont,
   GLWindowsFont,
   GLzBuffer,
   GLzBuffer,
-  GLSMemo,
+  GLS.Memo,
   GLVectorTypes,
   GLVectorTypes,
   GLVectorGeometry,
   GLVectorGeometry,
-  // Image file formats
+//----------------- File formats
+  GLFileVfsPAK,
   FileDDSImage,
   FileDDSImage,
   FileTGA,
   FileTGA,
-  // Vector file formats
+//------------------ Vector file formats
   GLFile3DS,
   GLFile3DS,
   GLFileASE,
   GLFileASE,
   GLFileB3D,
   GLFileB3D,
@@ -423,11 +422,11 @@ uses
   GLFileSTL,
   GLFileSTL,
   GLFileVRML,
   GLFileVRML,
 
 
-  // Sound file formats
+//----------------- Sound file formats
   GLFileWAV,
   GLFileWAV,
   GLFileMP3,
   GLFileMP3,
 
 
-  // Raster file format
+//----------------- Raster file format
   GLFileDDS,
   GLFileDDS,
   GLFileO3TC,
   GLFileO3TC,
   GLFileHDR,
   GLFileHDR,
@@ -1327,14 +1326,14 @@ end;
 procedure GLRegisterPropertiesInCategories;
 procedure GLRegisterPropertiesInCategories;
 begin
 begin
   // property types
   // property types
-  // TGLScreenDepth in GLWin32FullScreenViewer
+  // ScreenDepth in Win32FullScreenViewer
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
      [TypeInfo(TGLCamera), TypeInfo(TGLSceneBuffer),
      [TypeInfo(TGLCamera), TypeInfo(TGLSceneBuffer),
      TypeInfo(TGLVSyncMode), TypeInfo(TGLScreenDepth)]);
      TypeInfo(TGLVSyncMode), TypeInfo(TGLScreenDepth)]);
-  // TGLSceneViewer
+  // SceneViewer
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLSceneViewer, ['*Render']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLSceneViewer, ['*Render']);
 
 
-  // GLScene
+  // Scene
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLObjectsSorting), TypeInfo(TGLProgressEvent),
     [TypeInfo(TGLObjectsSorting), TypeInfo(TGLProgressEvent),
     TypeInfo(TGLBehaviours), TypeInfo(TGLEffects),
     TypeInfo(TGLBehaviours), TypeInfo(TGLEffects),
@@ -1355,16 +1354,10 @@ begin
   RegisterPropertiesInCategory(strVisualCategoryName, TGLCamera, ['DepthOfView', 'SceneScale']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLCamera, ['DepthOfView', 'SceneScale']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLNonVisualViewer, ['*Render']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLNonVisualViewer, ['*Render']);
 
 
-  // GLObjects
+  // Objects
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLLinesNodes), TypeInfo(TGLLineNodesAspect),
     [TypeInfo(TGLLinesNodes), TypeInfo(TGLLineNodesAspect),
     TypeInfo(TGLLineSplineMode), TypeInfo(TGLLinesOptions)]);
     TypeInfo(TGLLineSplineMode), TypeInfo(TGLLinesOptions)]);
-  // GLSpaceText
-  RegisterPropertiesInCategory(strLayoutCategoryName, [TypeInfo(TGLTextAdjust)]);
-  RegisterPropertiesInCategory(strLocalizableCategoryName, [TypeInfo(TGLSpaceTextCharRange)]);
-  RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TGLLineSplineMode),
-    TypeInfo(TGLCapType), TypeInfo(TGLNormalSmoothing),
-    TypeInfo(TGLArrowHeadStyle), TypeInfo(TGLTextAdjust)]);
   // DummyCube
   // DummyCube
   RegisterPropertiesInCategory(strLayoutCategoryName, TGLDummyCube, ['VisibleAtRunTime']);
   RegisterPropertiesInCategory(strLayoutCategoryName, TGLDummyCube, ['VisibleAtRunTime']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLDummyCube, ['CubeSize', 'VisibleAtRunTime']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLDummyCube, ['CubeSize', 'VisibleAtRunTime']);
@@ -1377,7 +1370,12 @@ begin
     ['Antialiased', 'Division', 'Line*', 'NodeSize']);
     ['Antialiased', 'Division', 'Line*', 'NodeSize']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLCube, ['Cube*']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLCube, ['Cube*']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLFrustrum, ['ApexHeight', 'Base*']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLFrustrum, ['ApexHeight', 'Base*']);
-  // GLSpaceText
+  // SpaceText
+  RegisterPropertiesInCategory(strLayoutCategoryName, [TypeInfo(TGLTextAdjust)]);
+  RegisterPropertiesInCategory(strLocalizableCategoryName, [TypeInfo(TGLSpaceTextCharRange)]);
+  RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TGLLineSplineMode),
+    TypeInfo(TGLCapType), TypeInfo(TGLNormalSmoothing),
+    TypeInfo(TGLArrowHeadStyle), TypeInfo(TGLTextAdjust)]);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLSpaceText,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLSpaceText,
     ['AllowedDeviation', 'AspectRatio', 'Extrusion', 'Oblique', 'TextHeight']);
     ['AllowedDeviation', 'AspectRatio', 'Extrusion', 'Oblique', 'TextHeight']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLSphere,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLSphere,
@@ -1398,12 +1396,12 @@ begin
     ['Bottom*', 'Loops', 'Slices', 'Stacks', 'Top*']);
     ['Bottom*', 'Loops', 'Slices', 'Stacks', 'Top*']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPolygon, ['Division']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPolygon, ['Division']);
 
 
-  // GLMultiPolygon
+  // MultiPolygon
   RegisterPropertiesInCategory(strVisualCategoryName, TGLContour, ['Division']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLContour, ['Division']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLContourNodes),
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLContourNodes),
     TypeInfo(TGLContours)]);
     TypeInfo(TGLContours)]);
 
 
-  // GLExtrusion
+  // Extrusion
   RegisterPropertiesInCategory(strVisualCategoryName, TGLExtrusionSolid, ['Stacks']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLExtrusionSolid, ['Stacks']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPipeNode, ['RadiusFactor']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPipeNode, ['RadiusFactor']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPipe,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPipe,
@@ -1413,7 +1411,7 @@ begin
   RegisterPropertiesInCategory(strVisualCategoryName, TGLRevolutionSolid,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLRevolutionSolid,
     ['Division', 'Slices', 'YOffsetPerTurn']);
     ['Division', 'Slices', 'YOffsetPerTurn']);
 
 
-  // GLVectorFileObjects
+  // VectorFileObjects
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLActorAnimationMode), TypeInfo(TGLActorAnimations),
     [TypeInfo(TGLActorAnimationMode), TypeInfo(TGLActorAnimations),
     TypeInfo(TGLMeshAutoCenterings), TypeInfo(TGLActorFrameInterpolation),
     TypeInfo(TGLMeshAutoCenterings), TypeInfo(TGLActorFrameInterpolation),
@@ -1431,11 +1429,11 @@ begin
     ['*Frame*', 'Interval', 'OverlaySkeleton', 'UseMeshmaterials']);
     ['*Frame*', 'Interval', 'OverlaySkeleton', 'UseMeshmaterials']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLActor,  ['OverlaySkeleton']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLActor,  ['OverlaySkeleton']);
 
 
-  // GLMesh 
+  // Mesh
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLMeshMode), TypeInfo(TGLVertexMode)]);
     [TypeInfo(TGLMeshMode), TypeInfo(TGLVertexMode)]);
 
 
-  // GLGraph 
+  // Graph
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLHeightFieldOptions)]);
     [TypeInfo(TGLHeightFieldOptions)]);
   RegisterPropertiesInCategory(strVisualCategoryName,
   RegisterPropertiesInCategory(strVisualCategoryName,
@@ -1444,11 +1442,11 @@ begin
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLXYZGrid, ['Antialiased']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLXYZGrid, ['Antialiased']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLXYZGrid, ['Antialiased', 'Line*']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLXYZGrid, ['Antialiased', 'Line*']);
 
 
-  // GLParticles
+  // Particles
   RegisterPropertiesInCategory(strLayoutCategoryName, TGLParticles, ['VisibleAtRunTime']);
   RegisterPropertiesInCategory(strLayoutCategoryName, TGLParticles, ['VisibleAtRunTime']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLParticles, ['*Size', 'VisibleAtRunTime']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLParticles, ['*Size', 'VisibleAtRunTime']);
 
 
-  // GLSkydome
+  // Skydome
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLSkyDomeBands), TypeInfo(TGLSkyDomeOptions), TypeInfo(TGLSkyDomeStars)]);
     [TypeInfo(TGLSkyDomeBands), TypeInfo(TGLSkyDomeOptions), TypeInfo(TGLSkyDomeStars)]);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLSkyDomeBand, ['Slices', 'Stacks', '*Angle']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLSkyDomeBand, ['Slices', 'Stacks', '*Angle']);
@@ -1456,11 +1454,11 @@ begin
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLEarthSkyDome,
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLEarthSkyDome,
     ['Slices', 'Stacks', 'SunElevation', 'Turbidity']);
     ['Slices', 'Stacks', 'SunElevation', 'Turbidity']);
 
 
-  // GLMirror
+  // Mirror
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLMirrorOptions), TypeInfo(TGLBaseSceneObject)]);
     [TypeInfo(TGLMirrorOptions), TypeInfo(TGLBaseSceneObject)]);
 
 
-  // GLParticleFX 
+  // ParticleFX
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLBlendingMode)]);
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLBlendingMode)]);
   RegisterPropertiesInCategory(strVisualCategoryName,
   RegisterPropertiesInCategory(strVisualCategoryName,
     [TypeInfo(TGLBlendingMode), TypeInfo(TPFXLifeColors), TypeInfo(TSpriteColorMode)]);
     [TypeInfo(TGLBlendingMode), TypeInfo(TPFXLifeColors), TypeInfo(TSpriteColorMode)]);
@@ -1472,69 +1470,60 @@ begin
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPolygonPFXManager, ['NbSides']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPolygonPFXManager, ['NbSides']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPointLightPFXManager, ['TexMapSize']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLPointLightPFXManager, ['TexMapSize']);
 
 
-  // GLTerrainRenderer 
+  // TerrainRenderer
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLHeightDataSource)]);
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLHeightDataSource)]);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLTerrainRenderer,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLTerrainRenderer,
     ['*CLOD*', 'QualityDistance', 'Tile*']);
     ['*CLOD*', 'QualityDistance', 'Tile*']);
 
 
-  // GLzBuffer 
+  // zBuffer
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLMemoryViewer),
   RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLMemoryViewer),
     TypeInfo(TGLSceneViewer), TypeInfo(TOptimise)]);
     TypeInfo(TGLSceneViewer), TypeInfo(TOptimise)]);
   RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TOptimise)]);
   RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TOptimise)]);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLZShadows,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLZShadows,
     ['DepthFade', '*Shadow', 'Soft', 'Tolerance']);
     ['DepthFade', '*Shadow', 'Soft', 'Tolerance']);
 
 
-  // GLHUDObjects
+  // HUDObjects
   RegisterPropertiesInCategory(strLayoutCategoryName, [TypeInfo(TTextLayout)]);
   RegisterPropertiesInCategory(strLayoutCategoryName, [TypeInfo(TTextLayout)]);
   RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TGLBitmapFont), TypeInfo(TTextLayout)]);
   RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TGLBitmapFont), TypeInfo(TTextLayout)]);
   RegisterPropertiesInCategory(strLocalizableCategoryName,[TypeInfo(TGLBitmapFont)]);
   RegisterPropertiesInCategory(strLocalizableCategoryName,[TypeInfo(TGLBitmapFont)]);
 
 
-  // GLTexture
+  // Texture
   RegisterPropertiesInCategory(strOpenGLCategoryName,
   RegisterPropertiesInCategory(strOpenGLCategoryName,
     [TypeInfo(TGLMaterial), TypeInfo(TGLMaterialLibrary),
     [TypeInfo(TGLMaterial), TypeInfo(TGLMaterialLibrary),
     TypeInfo(TGLLibMaterials), TypeInfo(TGLTextureNeededEvent)]);
     TypeInfo(TGLLibMaterials), TypeInfo(TGLTextureNeededEvent)]);
-  RegisterPropertiesInCategory(strOpenGLCategoryName,
-    TGLLibMaterial, ['Texture2Name']);
+  RegisterPropertiesInCategory(strOpenGLCategoryName, TGLLibMaterial, ['Texture2Name']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLLibMaterial, ['TextureOffset', 'TextureScale']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLLibMaterial, ['TextureOffset', 'TextureScale']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLMaterialLibrary, ['TexturePaths']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLMaterialLibrary, ['TexturePaths']);
 
 
-  // GLCadencer
-  RegisterPropertiesInCategory(strOpenGLCategoryName,
-    [TypeInfo(TGLCadencer)]);
+  // Cadencer
+  RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLCadencer)]);
 
 
-  // GLCollision
-  RegisterPropertiesInCategory(strOpenGLCategoryName,
-    [TypeInfo(TObjectCollisionEvent)]);
+  // Collision
+  RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TObjectCollisionEvent)]);
 
 
-  // GLFireFX
+  // FireFX
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLFireFXManager,
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLFireFXManager,
     ['MaxParticles', 'NoZWrite', 'Paused', 'UseInterval']);
     ['MaxParticles', 'NoZWrite', 'Paused', 'UseInterval']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLFireFXManager,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLFireFXManager,
     ['Fire*', 'InitialDir', 'NoZWrite', 'Particle*', 'Paused']);
     ['Fire*', 'InitialDir', 'NoZWrite', 'Particle*', 'Paused']);
 
 
-  // GLThorFX
-  RegisterPropertiesInCategory(strOpenGLCategoryName,
-    [TypeInfo(TCalcPointEvent)]);
+  // ThorFX
+  RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TCalcPointEvent)]);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLThorFXManager,
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLThorFXManager,
     ['Maxpoints', 'Paused']);
     ['Maxpoints', 'Paused']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLThorFXManager,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLThorFXManager,
     ['Core', 'Glow*', 'Paused', 'Target', 'Vibrate', 'Wildness']);
     ['Core', 'Glow*', 'Paused', 'Target', 'Vibrate', 'Wildness']);
 
 
-  // GLBitmapFont 
-  RegisterPropertiesInCategory(strOpenGLCategoryName,
-    [TypeInfo(TGLMagFilter), TypeInfo(TGLMinFilter)]);
-  RegisterPropertiesInCategory(strLocalizableCategoryName,
-    [TypeInfo(TGLBitmapFontRanges)]);
-  RegisterPropertiesInCategory(strLocalizableCategoryName, TGLBitmapFontRange,
-    ['*ASCII']);
-  RegisterPropertiesInCategory(strLayoutCategoryName, TGLBitmapFont,
-    ['Char*', '*Interval*', '*Space']);
-  RegisterPropertiesInCategory(strLocalizableCategoryName, TGLBitmapFont,
-    ['Glyphs']);
+  // BitmapFont
+  RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLMagFilter), TypeInfo(TGLMinFilter)]);
+  RegisterPropertiesInCategory(strLocalizableCategoryName, [TypeInfo(TGLBitmapFontRanges)]);
+  RegisterPropertiesInCategory(strLocalizableCategoryName, TGLBitmapFontRange, ['*ASCII']);
+  RegisterPropertiesInCategory(strLayoutCategoryName, TGLBitmapFont, ['Char*', '*Interval*', '*Space']);
+  RegisterPropertiesInCategory(strLocalizableCategoryName, TGLBitmapFont, ['Glyphs']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLBitmapFont,
   RegisterPropertiesInCategory(strVisualCategoryName, TGLBitmapFont,
     ['Char*', '*Interval*', '*Space', 'Glyphs']);
     ['Char*', '*Interval*', '*Space', 'Glyphs']);
 
 
-  // GLHeightData
+  // HeightData
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLBitmapHDS, ['MaxPoolSize']);
   RegisterPropertiesInCategory(strOpenGLCategoryName, TGLBitmapHDS, ['MaxPoolSize']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLBitmapHDS, ['Picture']);
   RegisterPropertiesInCategory(strVisualCategoryName, TGLBitmapHDS, ['Picture']);
 end;
 end;
@@ -1663,17 +1652,12 @@ begin
   RegisterPropertyEditor(TypeInfo(TGLMaterialComponentName), TGLShaderModel5,
   RegisterPropertyEditor(TypeInfo(TGLMaterialComponentName), TGLShaderModel5,
     'LibTessEvalShaderName', TGLLibShaderNameProperty);
     'LibTessEvalShaderName', TGLLibShaderNameProperty);
 
 
-  RegisterPropertyEditor(TypeInfo(string), TGLTextureImageEx, 'SourceFile',
-    TPictureFileProperty);
-  RegisterPropertyEditor(TypeInfo(string), TGLShaderEx, 'SourceFile',
-    TShaderFileProperty);
-  RegisterPropertyEditor(TypeInfo(string), TGLASMVertexProgram, 'SourceFile',
-    TAsmProgFileProperty);
+  RegisterPropertyEditor(TypeInfo(string), TGLTextureImageEx, 'SourceFile', TPictureFileProperty);
+  RegisterPropertyEditor(TypeInfo(string), TGLShaderEx, 'SourceFile', TShaderFileProperty);
+  RegisterPropertyEditor(TypeInfo(string), TGLASMVertexProgram, 'SourceFile', TAsmProgFileProperty);
 
 
-  RegisterPropertyEditor(TypeInfo(Boolean), TGLBaseShaderModel,
-    'AutoFillOfUniforms', TUniformAutoSetProperty);
-  RegisterPropertyEditor(TypeInfo(TStringList), TGLShaderEx, 'Source',
-    TGLShaderEditorProperty);
+  RegisterPropertyEditor(TypeInfo(Boolean), TGLBaseShaderModel, 'AutoFillOfUniforms', TUniformAutoSetProperty);
+  RegisterPropertyEditor(TypeInfo(TStringList), TGLShaderEx, 'Source', TGLShaderEditorProperty);
 end;
 end;
 
 
 function GetGLSceneVersion: string;
 function GetGLSceneVersion: string;
@@ -1880,7 +1864,9 @@ begin
   RegisterSceneObject(TGLFBORenderer, 'OpenGL FrameBuffer', '', HInstance);
   RegisterSceneObject(TGLFBORenderer, 'OpenGL FrameBuffer', '', HInstance);
 end;
 end;
 
 
+//------------------------------------------------------
 finalization
 finalization
+//------------------------------------------------------
 
 
 ObjectManager.Free;
 ObjectManager.Free;
 
 

+ 1 - 1
Source/GLS.cgRegister.pas

@@ -4,7 +4,7 @@
 
 
 unit GLS.cgRegister;
 unit GLS.cgRegister;
 
 
-(*  Registration unit for CG shader *)
+(*  Registration unit for CG shader package *)
 
 
 interface
 interface
 
 

+ 2 - 3
Source/GLSCrossXML.pas

@@ -1,12 +1,11 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-  Cross XML routines
-}
 
 
 unit GLSCrossXML;
 unit GLSCrossXML;
 
 
+(* Cross XML routines *)
+
 interface
 interface
 
 
 uses
 uses

+ 1 - 0
Source/GLScene.pas

@@ -8093,3 +8093,4 @@ initialization
   QueryPerformanceFrequency(vCounterFrequency);
   QueryPerformanceFrequency(vCounterFrequency);
 
 
 end.
 end.
+

+ 1 - 1
Source/GLVectorFileObjects.pas

@@ -38,7 +38,7 @@ uses
   GLRenderContextInfo,
   GLRenderContextInfo,
   GLCoordinates,
   GLCoordinates,
   GLBaseClasses,
   GLBaseClasses,
-  GLTypes,
+  GLVectorRecTypes,
   GLTextureFormat;
   GLTextureFormat;
 
 
 type
 type

+ 29 - 15
Source/GLTypes.pas → Source/GLVectorRecTypes.pas

@@ -1,10 +1,10 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-{
-   Defines common vector types as advanced records.
-}
-unit GLTypes;
+
+unit GLVectorRecTypes;
+
+(* Defines common vector types as advanced records *)
 
 
 interface
 interface
 
 
@@ -325,14 +325,14 @@ type
 type
 type
   TxPolyhedron = array of TxPolygon3D;
   TxPolyhedron = array of TxPolygon3D;
 
 
-{
+(*
   TxPolyhedron = record
   TxPolyhedron = record
     Facets: array of TxPolygon3D;
     Facets: array of TxPolygon3D;
     function NetLength;
     function NetLength;
     function Area;
     function Area;
     function Volume;
     function Volume;
   end;
   end;
-}
+*)
 
 
 //--------------------------
 //--------------------------
 // Mesh simple record types
 // Mesh simple record types
@@ -775,7 +775,9 @@ begin
 end;
 end;
 
 
 
 
-{ TxVector }
+//-----------------------------
+// TxVector
+//-----------------------------
 
 
 constructor TxVector.Create(V: TAbstractVector);
 constructor TxVector.Create(V: TAbstractVector);
 begin
 begin
@@ -986,7 +988,9 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TxQuatHelper }
+//-----------------------------
+// TxQuatHelper
+//-----------------------------
 
 
 function TxQuatHelper.ToMatrix: TxMatrix;
 function TxQuatHelper.ToMatrix: TxMatrix;
 begin
 begin
@@ -1002,7 +1006,9 @@ begin
   Result[3, 3] := Sqr(FData[0]) - Sqr(FData[1]) - Sqr(FData[2]) + Sqr(FData[3]);
   Result[3, 3] := Sqr(FData[0]) - Sqr(FData[1]) - Sqr(FData[2]) + Sqr(FData[3]);
 end;
 end;
 
 
-{ TxVecHelper }
+//-----------------------------
+// TxVecHelper
+//-----------------------------
 
 
 function TxVecHelper.ToDiagMatrix: TxMatrix;
 function TxVecHelper.ToDiagMatrix: TxMatrix;
 var
 var
@@ -1079,7 +1085,9 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TxDim }
+//-----------------------------
+// TxDim
+//-----------------------------
 
 
 constructor TxDim.Create(ARowCount: Integer; AColCount: Integer = 0);
 constructor TxDim.Create(ARowCount: Integer; AColCount: Integer = 0);
 begin
 begin
@@ -1088,7 +1096,9 @@ begin
 end;
 end;
 
 
 
 
-{ TxPoint2D }
+//-----------------------------
+// TxPoint2D
+//-----------------------------
 
 
 function TxPoint2D.Create(X, Y : Single): TxPoint2D;
 function TxPoint2D.Create(X, Y : Single): TxPoint2D;
 begin
 begin
@@ -1129,7 +1139,9 @@ begin
   Result := Point.Distance(Center) <= Radius;
   Result := Point.Distance(Center) <= Radius;
 end;
 end;
 
 
-{ TxPoint3D }
+//-----------------------------
+// TxPoint3D
+//-----------------------------
 
 
 function TxPoint3D.Create(X, Y, Z: Single): TxPoint3D;
 function TxPoint3D.Create(X, Y, Z: Single): TxPoint3D;
 begin
 begin
@@ -1169,7 +1181,9 @@ begin
   Self.Z := Z;
   Self.Z := Z;
 end;
 end;
 
 
-{ TxVector2D }
+//-----------------------------
+// TxVector2D
+//-----------------------------
 
 
 function TxVector2D.Create(const AX, AY, AW: Single): TxVector2D;
 function TxVector2D.Create(const AX, AY, AW: Single): TxVector2D;
 begin
 begin
@@ -1226,7 +1240,7 @@ begin
 end;
 end;
 
 
 //---------------------------------
 //---------------------------------
-{ TxVector3D }
+// TxVector3D
 //---------------------------------
 //---------------------------------
 function TxVector3D.Create(const AX, AY, AZ, AW: Single): TxVector3D;
 function TxVector3D.Create(const AX, AY, AZ, AW: Single): TxVector3D;
 begin
 begin
@@ -1287,7 +1301,7 @@ begin
 end;
 end;
 
 
 //---------------------------------
 //---------------------------------
-{ TxQuaternion }
+// TxQuaternion
 //---------------------------------
 //---------------------------------
 
 
 function TxQuaternion.GetElement(Index: Byte): Extended;
 function TxQuaternion.GetElement(Index: Byte): Extended;

+ 0 - 452
Source/GLVfsPAK.pas

@@ -1,452 +0,0 @@
-//
-// This unit is part of the GLScene Engine, http://glscene.org
-//
-(*
-   Support-code for loading files from Quake II PAK Files.
-   When instance is created all LoadFromFile methods using
-   GLApplicationFileIO mechanism will be pointed into PAK file.
-   You can change current PAK file by ActivePak variable.
-
-*)
-unit GLVfsPAK;
-
-{$I GLScene.inc}
-
-interface
-
-uses
-  System.Classes,
-  System.Contnrs,
-  System.SysUtils,
-
-  GLStrings,
-  GLApplicationFileIO;
-
-const
-   SIGN = 'PACK'; //Signature for uncompressed - raw pak.
-   SIGN_COMPRESSED = 'PACZ'; //Signature for compressed pak.
-
-type
-
-   TZCompressedMode = (Good, Fast, Auto, None);
-
-   TPakHeader = record
-      Signature: array[0..3] of AnsiChar;
-      DirOffset: integer;
-      DirLength: integer;
-   end;
-
-   TFileSection = record
-      FileName: array[0..119] of AnsiChar;
-      FilePos: integer;
-      FileLength: integer;
-   end;
-
-   TGLVfsPAK = class (TComponent)
-   private
-      FPakFiles: TStringList;
-      FHeader: TPakHeader;
-      FHeaderList: array of TPakHeader;
-      FStream: TFileStream;
-      FStreamList: TObjectList;
-      FFiles: TStrings;
-      FFilesLists: TObjectList;
-      FFileName: string;
-      FCompressionLevel: TZCompressedMode;
-      FCompressed: Boolean;
-      function GetFileCount: integer;
-      procedure MakeFileList;
-      function GetStreamNumber: integer;
-      procedure SetStreamNumber(i:integer);
-   public
-      property PakFiles: TStringList read FPakFiles;
-      property Files: TStrings read FFiles;
-      property ActivePakNum: integer read GetStreamNumber write SetStreamNumber;
-      property FileCount: integer Read GetFileCount;
-      property PakFileName: string Read FFileName;
-      property Compressed: Boolean read FCompressed;
-      property CompressionLevel: TZCompressedMode read FCompressionLevel;
-      constructor Create(AOwner : TComponent); overload; override;
-      constructor Create(AOwner : TComponent; const CbrMode: TZCompressedMode); reintroduce; overload;
-      destructor Destroy; override;
-      // for Mode value search Delphi Help for "File open mode constants"
-      procedure LoadFromFile(const FileName: string; Mode: word);
-      procedure ClearPakFiles;
-      function FileExists(const FileName: string): boolean;
-      function GetFile(index: integer): TStream; overload;
-      function GetFile(const FileName: string): TStream; overload;
-      function GetFileSize(index: integer): integer; overload;
-      function GetFileSize(const FileName: string): integer; overload;
-      procedure AddFromStream(const FileName, Path: string; F: TStream);
-      procedure AddFromFile(const FileName, Path: string);
-      procedure AddEmptyFile(const FileName, Path: string);
-      procedure RemoveFile(index: integer); overload;
-      procedure RemoveFile(const FileName: string); overload;
-      procedure Extract(index: integer; const NewName: string); overload;
-      procedure Extract(const FileName, NewName: string); overload;
-   end;
-
-// for GLApplicationFileIO unit
-function PAKCreateFileStream(const fileName: string; mode: word): TStream;
-function PAKFileStreamExists(const fileName: string): boolean;
-
-var
-   ActiveVfsPAK: TGLVfsPak;
-
-//---------------------------------------------------------------------
-implementation
-//---------------------------------------------------------------------
-
-var
-   Dir: TFileSection;
-
-function BackToSlash(const s: string): string;
-var
-   i: integer;
-begin
-   SetLength(Result, Length(s));
-   for i := 1 to Length(s) do
-      if s[i] = '\' then
-         Result[i] := '/'
-      else
-         Result[i] := s[i];
-end;
-
-// GLApplicationFileIO begin
-function PAKCreateFileStream(const fileName: string; mode: word): TStream;
-var
-   i: integer;
-begin
-   with ActiveVfsPAK do
-   for i:=FStreamList.Count-1 downto 0 do begin
-      FFiles:=TStrings(FFilesLists[i]);
-      if FileExists(BackToSlash(fileName)) then begin
-         FHeader:=FHeaderList[i];
-         FStream:=TFileStream(FStreamList[i]);
-         Result:=GetFile(BackToSlash(fileName));
-         Exit;
-      end
-      else begin
-        if FileExists(fileName) then begin
-          Result := TFileStream.Create(FileName, fmOpenReadWrite or fmShareDenyWrite);
-          Exit;
-         end
-         else begin
-            Result := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
-            Exit;
-         end;
-      end;
-   end;
-   if FileExists(fileName) then begin
-      Result := TFileStream.Create(FileName, fmOpenReadWrite or fmShareDenyWrite);
-      Exit;
-   end
-   else begin
-      Result := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
-      Exit;
-   end;
-   Result:=nil;
-end;
-
-function PAKFileStreamExists(const fileName: string): boolean;
-var
-   i: integer;
-begin
-   with ActiveVfsPAK do
-   for i:=0 to FStreamList.Count-1 do begin
-      FFiles:=TStrings(FFilesLists[i]);
-      if FileExists(BackToSlash(fileName)) then begin
-         Result:=True;
-         Exit;
-      end;
-   end;
-   Result := FileExists(fileName);
-end;
-
-//--------------------------
-// TGLVfsPAK
-//--------------------------
-
-function TGLVfsPAK.GetStreamNumber: integer;
-begin
-   Result:=FStreamList.IndexOf(FStream);
-end;
-
-procedure TGLVfsPAK.SetStreamNumber(i:integer);
-begin
-   FStream:=TFileStream(FStreamList[i]);
-end;
-
-constructor TGLVfsPAK.Create(AOwner : TComponent);
-begin
-   inherited Create(AOwner);
-   FPakFiles := TStringList.Create;
-   FStreamList := TObjectList.Create(True);
-   FFilesLists := TObjectList.Create(True);
-   ActiveVfsPAK := Self;
-   vAFIOCreateFileStream := PAKCreateFileStream;
-   vAFIOFileStreamExists := PAKFileStreamExists;
-   FCompressionLevel := None;
-   FCompressed := False;
-end;
-
-constructor TGLVfsPAK.Create(AOwner : TComponent; const CbrMode: TZCompressedMode);
-begin
-   Self.Create(AOwner);
-   FCompressionLevel := None;
-   FCompressed := FCompressionLevel <> None;
-end;
-
-destructor TGLVfsPAK.Destroy;
-begin
-   vAFIOCreateFileStream := nil;
-   vAFIOFileStreamExists := nil;
-   SetLength(FHeaderList, 0);
-   FPakFiles.Free;
-   // Objects are automatically freed by TObjectList
-   FStreamList.Free;
-   FFilesLists.Free;
-   ActiveVfsPAK := nil;
-   inherited Destroy;
-end;
-
-function TGLVfsPAK.GetFileCount: integer;
-begin
-   Result := FHeader.DirLength div SizeOf(TFileSection);
-end;
-
-procedure TGLVfsPAK.MakeFileList;
-var
-   I: integer;
-begin
-   FStream.Seek(FHeader.DirOffset, soFromBeginning);
-   FFiles.Clear;
-   for i := 0 to FileCount - 1 do
-   begin
-      FStream.ReadBuffer(Dir, SizeOf(TFileSection));
-      FFiles.Add(string(Dir.FileName));
-   end;
-end;
-
-procedure TGLVfsPAK.LoadFromFile(const FileName: string; Mode: word);
-var
-   l: integer;
-begin
-   FFileName := FileName;
-   FPakFiles.Clear;
-   FPakFiles.Add(FileName);
-   FFiles := TStringList.Create;
-   FStream := TFileStream.Create(FileName, Mode);
-   if FStream.Size = 0 then
-   begin
-    if FCompressed then
-      FHeader.Signature := SIGN_COMPRESSED
-    else
-      FHeader.Signature := SIGN;
-    FHeader.DirOffset := SizeOf(TPakHeader);
-    FHeader.DirLength := 0;
-    if FHeader.Signature = SIGN_COMPRESSED then begin
-     FStream.Free;
-     raise Exception.Create(FileName + ' - This is a compressed PAK file. This version of software does not support Compressed Pak files.');
-     Exit;
-    end;
-    FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
-    FStream.Position := 0;
-   end;
-   FStream.ReadBuffer(FHeader, SizeOf(TPakHeader));
-   if (FHeader.Signature <> SIGN) and (FHeader.Signature <> SIGN_COMPRESSED) then
-   begin
-      FStream.Free;
-      raise Exception.Create(FileName+' - This is not PAK file');
-      Exit;
-   end;
-
-   //Set the compression flag property.
-   FCompressed := FHeader.Signature = SIGN_COMPRESSED;
-   if FCompressed then begin
-    FStream.Free;
-    raise Exception.Create(FileName + ' - This is a compressed PAK file. This version of software does not support Compressed Pak files.');
-    Exit;
-   end;
-   if FileCount <> 0 then
-      MakeFileList;
-   l:=Length(FHeaderList);
-   SetLength(FHeaderList, l+1);
-   FHeaderList[l]:=FHeader;
-   FFilesLists.Add(FFiles);
-   FStreamList.Add(FStream);
-end;
-
-procedure TGLVfsPAK.ClearPakFiles;
-begin
-   SetLength(FHeaderList, 0);
-   FPakFiles.Clear;
-   // Objects are automatically freed by TObjectList
-   FStreamList.Clear;
-   FFilesLists.Clear;
-   ActiveVfsPAK := nil;
-end;
-
-function TGLVfsPAK.GetFile(index: integer): TStream;
-begin
-   FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * index, soFromBeginning);
-   FStream.Read(Dir, SizeOf(TFileSection));
-   FStream.Seek(Dir.FilePos, soFromBeginning);
-   Result := TMemoryStream.Create;
-   Result.CopyFrom(FStream, Dir.FileLength);
-   Result.Position := 0;
-end;
-
-function TGLVfsPAK.FileExists(const FileName: string): boolean;
-begin
-   Result := (FFiles.IndexOf(FileName) > -1);
-end;
-
-function TGLVfsPAK.GetFile(const FileName: string): TStream;
-begin
-   Result := nil;
-   if Self.FileExists(FileName) then
-      Result := GetFile(FFiles.IndexOf(FileName));
-end;
-
-function TGLVfsPAK.GetFileSize(index: integer): integer;
-begin
-   FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * index, soFromBeginning);
-   FStream.Read(Dir, SizeOf(Dir));
-   Result := Dir.FileLength;
-end;
-
-function TGLVfsPAK.GetFileSize(const FileName: string): integer;
-begin
-   Result := -1;
-   if Self.FileExists(FileName) then
-      Result := GetFileSize(FFiles.IndexOf(FileName));
-end;
-
-{$WARNINGS OFF}
-procedure TGLVfsPAK.AddFromStream(const FileName, Path: string; F: TStream);
-var
-   Temp: TMemoryStream;
-begin
-   FStream.Position := FHeader.DirOffset;
-   if FHeader.DirLength > 0 then
-   begin
-      Temp := TMemoryStream.Create;
-      Temp.CopyFrom(FStream, FHeader.DirLength);
-      Temp.Position    := 0;
-      FStream.Position := FHeader.DirOffset;
-   end;
-   Dir.FilePos    := FHeader.DirOffset;
-
-   Dir.FileLength := F.Size;
-   FStream.CopyFrom(F, 0);
-   FHeader.DirOffset := FStream.Position;
-   if FHeader.DirLength > 0 then
-   begin
-      FStream.CopyFrom(Temp, 0);
-      Temp.Free;
-   end;
-   StrPCopy(Dir.FileName, Path + ExtractFileName(FileName));
-   FStream.WriteBuffer(Dir, SizeOf(TFileSection));
-   FHeader.DirLength := FHeader.DirLength + SizeOf(TFileSection);
-   FStream.Position  := 0;
-   FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
-   FFiles.Add(Dir.FileName);
-end;
-
-{$WARNINGS ON}
-
-procedure TGLVfsPAK.AddFromFile(const FileName, Path: string);
-var
-   F: TFileStream;
-begin
-   if not FileExists(FileName) then
-      exit;
-   F := TFileStream.Create(FileName, fmOpenRead);
-   try
-      AddFromStream(FileName, Path, F);
-   finally
-      F.Free;
-   end;
-end;
-
-procedure TGLVfsPAK.AddEmptyFile(const FileName, Path: string);
-var
-   F: TMemoryStream;
-begin
-   F := TMemoryStream.Create;
-   try
-      AddFromStream(FileName, Path, F);
-   finally
-      F.Free;
-   end;
-end;
-
-procedure TGLVfsPAK.RemoveFile(index: integer);
-var
-   Temp: TMemoryStream;
-   i:    integer;
-   f:    TFileSection;
-begin
-   Temp := TMemoryStream.Create;
-   FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * index, soFromBeginning);
-   FStream.ReadBuffer(Dir, SizeOf(TFileSection));
-   FStream.Seek(Dir.FilePos + Dir.FileLength, soFromBeginning);
-   Temp.CopyFrom(FStream, FStream.Size - FStream.Position);
-   FStream.Position := Dir.FilePos;
-   FStream.CopyFrom(Temp, 0);
-   FHeader.DirOffset := FHeader.DirOffset - dir.FileLength;
-   Temp.Clear;
-   for i := 0 to FileCount - 1 do
-      if i > index then
-      begin
-         FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * i, soFromBeginning);
-         FStream.ReadBuffer(f, SizeOf(TFileSection));
-         FStream.Position := FStream.Position - SizeOf(TFileSection);
-         f.FilePos := f.FilePos - dir.FileLength;
-         FStream.WriteBuffer(f, SizeOf(TFileSection));
-      end;
-
-   i := FHeader.DirOffset + SizeOf(TFileSection) * index;
-   FStream.Position := i + SizeOf(TFileSection);
-   if FStream.Position < FStream.Size then
-   begin
-      Temp.CopyFrom(FStream, FStream.Size - FStream.Position);
-      FStream.Position := i;
-      FStream.CopyFrom(Temp, 0);
-   end;
-   Temp.Free;
-   FHeader.DirLength := FHeader.DirLength - SizeOf(TFileSection);
-   FStream.Position  := 0;
-   FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
-   FStream.Size := FStream.Size - dir.FileLength - SizeOf(TFileSection);
-   MakeFileList;
-end;
-
-procedure TGLVfsPAK.RemoveFile(const FileName: string);
-begin
-   if Self.FileExists(FileName) then
-      RemoveFile(FFiles.IndexOf(FileName));
-end;
-
-procedure TGLVfsPAK.Extract(index: integer; const NewName: string);
-var
-   s: TFileStream;
-begin
-   if NewName = '' then
-      Exit;
-   if (index < 0) or (index >= FileCount) then
-      exit;
-   s := TFileStream.Create(NewName, fmCreate);
-   s.CopyFrom(GetFile(index), 0);
-   s.Free;
-end;
-
-procedure TGLVfsPAK.Extract(const FileName, NewName: string);
-begin
-   if Self.FileExists(FileName) then
-      Extract(FFiles.IndexOf(FileName), NewName);
-end;
-
-
-end.

+ 4 - 4
Source/OpenGLTokens.pas

@@ -1,18 +1,18 @@
 //
 //
 // This unit is part of the GLScene Engine, http://glscene.org
 // This unit is part of the GLScene Engine, http://glscene.org
 //
 //
-(*
-   OpenGL tokens
-*)
+
 unit OpenGLTokens;
 unit OpenGLTokens;
 
 
+(* OpenGL tokens *)
+
 interface
 interface
 
 
 {$I GLScene.inc}
 {$I GLScene.inc}
 
 
 uses
 uses
-  System.SysUtils,
   Winapi.Windows,
   Winapi.Windows,
+  System.SysUtils,
   GLVectorTypes;
   GLVectorTypes;
 
 
 type
 type