@@ -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 (__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 (__astcache) do if exist "%%R" (rd /s /q "%%R")
+for /r %1 %%R in (__astcache) do if exist "%%R" (rd /s /q "%%R")
@@ -104,11 +104,11 @@ contains
GLFileB3D in '..\..\Source\GLFileB3D.pas',
GLFileBMP in '..\..\Source\GLFileBMP.pas',
GLFileDDS in '..\..\Source\GLFileDDS.pas',
- GLFileDXF in '..\..\Source\GLFileDXF.pas',
+ GLS.FileDXF in '..\..\Source\GLS.FileDXF.pas',
GLFileGL2 in '..\..\Source\GLFileGL2.pas',
GLFileGLB in '..\..\Source\GLFileGLB.pas',
GLFileGLTF in '..\..\Source\GLFileGLTF.pas',
- GLFileGRD in '..\..\Source\GLFileGRD.pas',
+ GLS.FileGRD in '..\..\Source\GLS.FileGRD.pas',
GLFileGTS in '..\..\Source\GLFileGTS.pas',
GLFileHDR in '..\..\Source\GLFileHDR.pas',
GLFileJPEG in '..\..\Source\GLFileJPEG.pas',
@@ -132,7 +132,7 @@ contains
GLFileSMD in '..\..\Source\GLFileSMD.pas',
GLFileSTL in '..\..\Source\GLFileSTL.pas',
GLFileTGA in '..\..\Source\GLFileTGA.pas',
- GLFileTIN in '..\..\Source\GLFileTIN.pas',
+ GLS.FileTIN in '..\..\Source\GLS.FileTIN.pas',
GLFileVRML in '..\..\Source\GLFileVRML.pas',
GLFileWAV in '..\..\Source\GLFileWAV.pas',
GLFileX in '..\..\Source\GLFileX.pas',
@@ -196,7 +196,7 @@ contains
GLPhongShader in '..\..\Source\GLPhongShader.pas',
GLPictureRegisteredFormats in '..\..\Source\GLPictureRegisteredFormats.pas',
GLPipelineTransformation in '..\..\Source\GLPipelineTransformation.pas',
- GLPlugInManager in '..\..\Source\GLPlugInManager.pas',
+ GLS.PlugInManager in '..\..\Source\GLS.PlugInManager.pas',
GLPluginIntf in '..\..\Source\GLPluginIntf.pas',
GLPolyhedron in '..\..\Source\GLPolyhedron.pas',
GLPolynomials in '..\..\Source\GLPolynomials.pas',
@@ -229,7 +229,7 @@ contains
GLSLVertexDisplacementShader in '..\..\Source\GLSLVertexDisplacementShader.pas',
GLSLanguage in '..\..\Source\GLSLanguage.pas',
GLSLog in '..\..\Source\GLSLog.pas',
- GLSMemo in '..\..\Source\GLSMemo.pas',
+ GLS.Memo in '..\..\Source\GLS.Memo.pas',
GLSRGBE in '..\..\Source\GLSRGBE.pas',
GLSRedBlackTree in '..\..\Source\GLSRedBlackTree.pas',
GLScene in '..\..\Source\GLScene.pas',
@@ -272,7 +272,7 @@ contains
GLTrail in '..\..\Source\GLTrail.pas',
GLTree in '..\..\Source\GLTree.pas',
GLTriangulation in '..\..\Source\GLTriangulation.pas',
- GLTypes in '..\..\Source\GLTypes.pas',
+ GLVectorRecTypes in '..\..\Source\GLVectorRecTypes.pas',
GLUserShader in '..\..\Source\GLUserShader.pas',
GLUtils in '..\..\Source\GLUtils.pas',
GLVectorGeometry in '..\..\Source\GLVectorGeometry.pas',
@@ -283,7 +283,6 @@ contains
GLVerletHairClasses in '..\..\Source\GLVerletHairClasses.pas',
GLVerletSkeletonColliders in '..\..\Source\GLVerletSkeletonColliders.pas',
GLVerletTypes in '..\..\Source\GLVerletTypes.pas',
- GLVfsPAK in '..\..\Source\GLVfsPAK.pas',
GLWaterPlane in '..\..\Source\GLWaterPlane.pas',
GLWin32Context in '..\..\Source\GLWin32Context.pas',
GLWin32Viewer in '..\..\Source\GLWin32Viewer.pas',
@@ -293,7 +292,8 @@ contains
GLzBuffer in '..\..\Source\GLzBuffer.pas',
OpenGLAdapter in '..\..\Source\OpenGLAdapter.pas',
OpenGLTokens in '..\..\Source\OpenGLTokens.pas',
- XOpenGL in '..\..\Source\XOpenGL.pas';
+ XOpenGL in '..\..\Source\XOpenGL.pas',
+ GLFileVfsPAK in '..\..\Source\GLFileVfsPAK.pas';
end.
@@ -198,11 +198,11 @@
<DCCReference Include="..\..\Source\GLFileB3D.pas"/>
<DCCReference Include="..\..\Source\GLFileBMP.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\GLFileGLB.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\GLFileHDR.pas"/>
<DCCReference Include="..\..\Source\GLFileJPEG.pas"/>
@@ -226,7 +226,7 @@
<DCCReference Include="..\..\Source\GLFileSMD.pas"/>
<DCCReference Include="..\..\Source\GLFileSTL.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\GLFileWAV.pas"/>
<DCCReference Include="..\..\Source\GLFileX.pas"/>
@@ -290,7 +290,7 @@
<DCCReference Include="..\..\Source\GLPhongShader.pas"/>
<DCCReference Include="..\..\Source\GLPictureRegisteredFormats.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\GLPolyhedron.pas"/>
<DCCReference Include="..\..\Source\GLPolynomials.pas"/>
@@ -323,7 +323,7 @@
<DCCReference Include="..\..\Source\GLSLVertexDisplacementShader.pas"/>
<DCCReference Include="..\..\Source\GLSLanguage.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\GLSRedBlackTree.pas"/>
<DCCReference Include="..\..\Source\GLScene.pas"/>
@@ -366,7 +366,7 @@
<DCCReference Include="..\..\Source\GLTrail.pas"/>
<DCCReference Include="..\..\Source\GLTree.pas"/>
<DCCReference Include="..\..\Source\GLTriangulation.pas"/>
- <DCCReference Include="..\..\Source\GLTypes.pas"/>
+ <DCCReference Include="..\..\Source\GLVectorRecTypes.pas"/>
<DCCReference Include="..\..\Source\GLUserShader.pas"/>
<DCCReference Include="..\..\Source\GLUtils.pas"/>
<DCCReference Include="..\..\Source\GLVectorGeometry.pas"/>
@@ -377,7 +377,6 @@
<DCCReference Include="..\..\Source\GLVerletHairClasses.pas"/>
<DCCReference Include="..\..\Source\GLVerletSkeletonColliders.pas"/>
<DCCReference Include="..\..\Source\GLVerletTypes.pas"/>
- <DCCReference Include="..\..\Source\GLVfsPAK.pas"/>
<DCCReference Include="..\..\Source\GLWaterPlane.pas"/>
<DCCReference Include="..\..\Source\GLWin32Context.pas"/>
<DCCReference Include="..\..\Source\GLWin32Viewer.pas"/>
@@ -388,6 +387,7 @@
<DCCReference Include="..\..\Source\OpenGLAdapter.pas"/>
<DCCReference Include="..\..\Source\OpenGLTokens.pas"/>
<DCCReference Include="..\..\Source\XOpenGL.pas"/>
+ <DCCReference Include="..\..\Source\GLFileVfsPAK.pas"/>
<BuildConfiguration Include="Debug">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
@@ -196,8 +196,7 @@ contains
- GLPluginIntf in '..\..\Source\GLPluginIntf.pas',
GLPortal in '..\..\Source\GLPortal.pas',
@@ -228,7 +227,7 @@ contains
GLSLToonShader in '..\..\Source\GLSLToonShader.pas',
@@ -269,18 +268,17 @@ contains
GLVectorFileObjects in '..\..\Source\GLVectorFileObjects.pas',
GLVectorLists in '..\..\Source\GLVectorLists.pas',
GLVectorTypes in '..\..\Source\GLVectorTypes.pas',
GLVerletClothify in '..\..\Source\GLVerletClothify.pas',
@@ -291,7 +289,8 @@ contains
GLS.OpenGLx in '..\..\Source\GLS.OpenGLx.pas',
XCollection in '..\..\Source\XCollection.pas',
@@ -206,11 +206,11 @@
@@ -234,7 +234,7 @@
@@ -298,8 +298,7 @@
- <DCCReference Include="..\..\Source\GLPluginIntf.pas"/>
<DCCReference Include="..\..\Source\GLPortal.pas"/>
@@ -330,7 +329,7 @@
<DCCReference Include="..\..\Source\GLSLToonShader.pas"/>
@@ -371,18 +370,17 @@
<DCCReference Include="..\..\Source\GLVectorFileObjects.pas"/>
<DCCReference Include="..\..\Source\GLVectorLists.pas"/>
<DCCReference Include="..\..\Source\GLVectorTypes.pas"/>
<DCCReference Include="..\..\Source\GLVerletClothify.pas"/>
@@ -394,6 +392,7 @@
<DCCReference Include="..\..\Source\GLS.OpenGLx.pas"/>
<DCCReference Include="..\..\Source\XCollection.pas"/>
@@ -426,7 +425,7 @@
<Platform value="Win64">True</Platform>
</Platforms>
<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">
<RemoteName>GLScene_RT.bpl</RemoteName>
<Overwrite>true</Overwrite>
@@ -1,11 +1,11 @@
//
// This unit is part of the GLScene Engine, http://glscene.org
-{
- Need a short description of what it does here.
-}
+
unit FPlugInManagerEditor;
+(* Need a short description of what it does here *)
interface
{$I GLScene.inc}
@@ -24,8 +24,7 @@ uses
Vcl.ComCtrls,
Vcl.ToolWin,
- GLPlugInIntf,
- GLPlugInManager;
+ GLS.PlugInManager;
type
TGLPlugInManagerEditorForm = class(TForm)
@@ -1,14 +1,15 @@
- Shader code editor.
+unit FShaderMemo;
+(*
+ Shader code editor.
// TODO: need to decide how to load templates from external file
// and update it without package recompilation
-
-unit FShaderMemo;
+*)
@@ -33,7 +34,7 @@ uses
VCL.StdCtrls,
VCL.Graphics,
- GLSMemo;
+ GLS.Memo;
@@ -10,83 +10,84 @@ interface
-uses
- System.Classes,
+uses
+ System.Classes,
System.SysUtils,
GLVectorGeometry,
GLVectorTypes,
GLVectorLists;
- 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
- 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;
- POCTFace = ^TOCTFace;
- TOCTTexture = record
- id : Integer; // texture id
- Name : array [0..63] of AnsiChar; // texture name
- TOCTLightmap = record
- id : Integer; // lightmaps id
- map : array [0..49151] of Byte; // 128 x 128 raw RGB data
- POCTLightmap = ^TOCTLightmap;
- TOCTLight = record
- pos : TAffineVector; // Position
- color : TAffineVector; // Color (RGB)
- intensity : Integer; // Intensity
- 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);
-// ------------------------------------------------------------------
+ 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
+ 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;
+ POCTFace = ^TOCTFace;
+ TOCTTexture = record
+ id: Integer; // texture id
+ Name: array [0 .. 63] of AnsiChar; // texture name
+ TOCTLightmap = record
+ id: Integer; // lightmaps id
+ map: array [0 .. 49151] of Byte; // 128 x 128 raw RGB data
+ POCTLightmap = ^TOCTLightmap;
+ TOCTLight = record
+ pos: TAffineVector; // Position
+ color: TAffineVector; // Color (RGB)
+ intensity: Integer; // Intensity
+ 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);
+ // ------------------------------------------------------------------
implementation
// ------------------------------------------------------------------
GLMeshUtils;
// ------------------
@@ -95,104 +96,101 @@ uses
constructor TOCTFile.Create;
begin
- inherited Create;
+ inherited Create;
end;
-constructor TOCTFile.Create(octStream : TStream);
+constructor TOCTFile.Create(octStream: TStream);
- // 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))
+ // 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))
-procedure TOCTFile.SaveToStream(aStream : TStream);
+procedure TOCTFile.SaveToStream(aStream: TStream);
- 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))
+ 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))
-procedure TOCTFile.AddTriangles(vertexCoords : TAffineVectorList;
+procedure TOCTFile.AddTriangles(vertexCoords: TAffineVectorList;
var
- i : Integer;
- baseIdx, texIdx : Integer;
+ i: Integer;
+ baseIdx, texIdx: Integer;
- 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
+ pos := vertexCoords.List[i];
if Assigned(texMapCoords) then
- tv:=PTexPoint(@texMapCoords.List[i])^;
- 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]));
- Inc(i, 3);
+ tv := PTexPoint(@texMapCoords.List[i])^;
+ SetLength(Faces, vertexCoords.Count div 3);
+ i := 0;
+ while i < vertexCoords.Count do
+ with Faces[i div 3] do
+ start := baseIdx + i;
+ num := 3;
+ id := texIdx;
+ p := PlaneMake(vertexCoords[i], CalcPlaneNormal(vertexCoords[i + 0],
+ vertexCoords[i + 1], vertexCoords[i + 0]));
+ Inc(i, 3);
-procedure TOCTFile.AddLight(const lightPos : TAffineVector;
+procedure TOCTFile.AddLight(const lightPos: TAffineVector;
+ const lightColor: TVector; lightIntensity: Integer);
- n : Integer;
+ n: Integer;
- n:=Length(Lights);
- SetLength(Lights, n+1);
- with Lights[n] do begin
- pos:=lightPos;
- color:=PAffineVector(@lightColor)^;
- intensity:=lightIntensity;
+ n := Length(Lights);
+ SetLength(Lights, n + 1);
+ with Lights[n] do
+ pos := lightPos;
+ color := PAffineVector(@lightColor)^;
+ intensity := lightIntensity;
-(*
- Collision-detection management
-*)
unit GLCollision;
+(* Collision-detection management *)
@@ -958,7 +958,6 @@ end;
initialization
-// class registrations
RegisterXCollectionItemClass(TGLBCollision);
finalization
@@ -966,3 +965,4 @@ finalization
UnregisterXCollectionItemClass(TGLBCollision);
@@ -1,39 +1,38 @@
- Coordinate related classes.
unit GLCoordinates;
+(* Coordinate related classes *)
uses
- GLVectorGeometry,
- GLVectorTypes,
- OpenGLTokens,
+ GLVectorGeometry,
+ GLVectorTypes,
+ OpenGLTokens,
GLBaseClasses;
- { 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)
csPoint : un point (W=1)
csVector : un vecteur (W=0)
- csUnknown : aucune contrainte }
+ csUnknown : aucune contrainte *)
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
delphi property editors and editing in the IDE. Vector/Coordinates
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)
private
FCoords: TVector;
@@ -63,12 +62,12 @@ type
procedure ReadFromFiler(Reader: TReader);
procedure Initialize(const Value: TVector);
procedure NotifyChange(Sender: TObject); override;
- { Identifies the coordinates styles.
+ (* Identifies the coordinates styles.
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
to detect "misuses" or "misunderstandings" of what the homogeneous
- coordinates system implies. }
+ coordinates system implies. *)
property Style: TGLCoordinatesStyle read FStyle write FStyle;
procedure Translate(const TranslationVector: TVector); overload;
procedure Translate(const TranslationVector: TAffineVector); overload;
@@ -96,25 +95,25 @@ type
procedure SetPoint2D(const Vector: TVector2f); overload;
procedure SetToZero;
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,
- 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;
- { The coordinates viewed as an affine vector.
+ (* The coordinates viewed as an affine vector.
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;
- { The coordinates viewed as a 2D point.
+ (* The coordinates viewed as a 2D point.
property AsPoint2D: TVector2f read GetAsPoint2D write SetAsPoint2D;
property X: TGLFloat index 0 read GetCoordinate write SetCoordinate;
property Y: TGLFloat index 1 read GetCoordinate write SetCoordinate;
property Z: TGLFloat index 2 read GetCoordinate write SetCoordinate;
property W: TGLFloat index 3 read GetCoordinate write SetCoordinate;
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;
// Similar to AsVector but does not trigger notification events
property DirectVector: TVector read FCoords write SetDirectVector;
@@ -124,14 +123,14 @@ type
property DirectW: TGLFloat index 3 read GetDirectCoordinate write SetDirectCoordinate;
- { A TGLCustomCoordinates that publishes X, Y properties. }
+ // A TGLCustomCoordinates that publishes X, Y properties.
TGLCoordinates2 = class(TGLCustomCoordinates)
published
property X stored False;
property Y stored False;
- { A TGLCustomCoordinates that publishes X, Y, Z properties. }
+ // A TGLCustomCoordinates that publishes X, Y, Z properties.
TGLCoordinates3 = class(TGLCustomCoordinates)
@@ -139,7 +138,7 @@ type
property Z stored False;
- { A TGLCustomCoordinates that publishes X, Y, Z, W properties. }
+ // A TGLCustomCoordinates that publishes X, Y, Z, W properties.
TGLCoordinates4 = class(TGLCustomCoordinates)
@@ -1,12 +1,11 @@
- Bezier and B-Spline Curve and Surface Routines.
unit GLCurvesAndSurfaces;
+(* Bezier and B-Spline Curve and Surface Routines *)
@@ -1,17 +1,16 @@
- 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
-unit GLFileDXF;
@@ -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}
+ 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;
+ TFileSection = record
+ FileName: array [0 .. 119] of AnsiChar;
+ FilePos: integer;
+ FileLength: integer;
+ 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);
+ 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;
+function PAKCreateFileStream(const FileName: string; Mode: word): TStream;
+function PAKFileStreamExists(const FileName: string): Boolean;
+var
+ ActiveVfsPAK: TGLVfsPAK;
+// ---------------------------------------------------------------------
+implementation
+ Dir: TFileSection;
+function BackToSlash(const s: string): string;
+ 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;
+ with ActiveVfsPAK do
+ for i := FStreamList.Count - 1 downto 0 do
+ FFiles := TStrings(FFilesLists[i]);
+ if FileExists(BackToSlash(FileName)) then
+ FHeader := FHeaderList[i];
+ FStream := TFileStream(FStreamList[i]);
+ Result := GetFile(BackToSlash(FileName));
+ Exit;
+ end
+ if FileExists(FileName) then
+ Result := TFileStream.Create(FileName, fmOpenReadWrite or
+ fmShareDenyWrite);
+ Result := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
+ Result := TFileStream.Create(FileName, fmOpenReadWrite or fmShareDenyWrite);
+ Result.Free;
+ for i := 0 to FStreamList.Count - 1 do
+ Result := True;
+ Result := FileExists(FileName);
+// --------------------------
+// TGLVfsPAK
+function TGLVfsPAK.GetStreamNumber: integer;
+ Result := FStreamList.IndexOf(FStream);
+procedure TGLVfsPAK.SetStreamNumber(i: integer);
+constructor TGLVfsPAK.Create(AOwner: TComponent);
+ inherited Create(AOwner);
+ FPakFiles := TStringList.Create;
+ FStreamList := TObjectList.Create(True);
+ FFilesLists := TObjectList.Create(True);
+ ActiveVfsPAK := Self;
+ vAFIOCreateFileStream := PAKCreateFileStream;
+ vAFIOFileStreamExists := PAKFileStreamExists;
+ FCompressionLevel := None;
+ FCompressed := False;
+constructor TGLVfsPAK.Create(AOwner: TComponent;
+ const CbrMode: TZCompressedMode);
+ Self.Create(AOwner);
+ FCompressed := FCompressionLevel <> None;
+destructor TGLVfsPAK.Destroy;
+ vAFIOCreateFileStream := nil;
+ vAFIOFileStreamExists := nil;
+ SetLength(FHeaderList, 0);
+ FPakFiles.Free;
+ // Objects are automatically freed by TObjectList
+ FStreamList.Free;
+ FFilesLists.Free;
+ ActiveVfsPAK := nil;
+ inherited Destroy;
+function TGLVfsPAK.GetFileCount: integer;
+ Result := FHeader.DirLength div SizeOf(TFileSection);
+procedure TGLVfsPAK.MakeFileList;
+ FStream.Seek(FHeader.DirOffset, soFromBeginning);
+ FFiles.Clear;
+ for i := 0 to FileCount - 1 do
+ FStream.ReadBuffer(Dir, SizeOf(TFileSection));
+ FFiles.Add(string(Dir.FileName));
+procedure TGLVfsPAK.LoadFromFile(const FileName: string; Mode: word);
+ l: integer;
+ FFileName := FileName;
+ FPakFiles.Clear;
+ FPakFiles.Add(FileName);
+ FFiles := TStringList.Create;
+ FStream := TFileStream.Create(FileName, Mode);
+ if FStream.Size = 0 then
+ if FCompressed then
+ FHeader.Signature := SIGN_COMPRESSED
+ FHeader.Signature := SIGN;
+ FHeader.DirOffset := SizeOf(TPakHeader);
+ FHeader.DirLength := 0;
+ if FHeader.Signature = SIGN_COMPRESSED then
+ FStream.Free;
+ raise Exception.Create
+ (FileName +
+ ' - This is a compressed PAK file. This version of software does not support Compressed Pak files.');
+ FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
+ FStream.Position := 0;
+ FStream.ReadBuffer(FHeader, SizeOf(TPakHeader));
+ if (FHeader.Signature <> SIGN) and (FHeader.Signature <> SIGN_COMPRESSED) then
+ raise Exception.Create(FileName + ' - This is not PAK file');
+ // Set the compression flag property.
+ FCompressed := FHeader.Signature = SIGN_COMPRESSED;
+ if FileCount <> 0 then
+ MakeFileList;
+ l := Length(FHeaderList);
+ SetLength(FHeaderList, l + 1);
+ FHeaderList[l] := FHeader;
+ FFilesLists.Add(FFiles);
+ FStreamList.Add(FStream);
+procedure TGLVfsPAK.ClearPakFiles;
+ FStreamList.Clear;
+ FFilesLists.Clear;
+function TGLVfsPAK.GetFile(index: integer): TStream;
+ 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;
+function TGLVfsPAK.FileExists(const FileName: string): Boolean;
+ Result := (FFiles.IndexOf(FileName) > -1);
+function TGLVfsPAK.GetFile(const FileName: string): TStream;
+ Result := nil;
+ if Self.FileExists(FileName) then
+ Result := GetFile(FFiles.IndexOf(FileName));
+function TGLVfsPAK.GetFileSize(index: integer): integer;
+ FStream.Read(Dir, SizeOf(Dir));
+ Result := Dir.FileLength;
+function TGLVfsPAK.GetFileSize(const FileName: string): integer;
+ Result := -1;
+ Result := GetFileSize(FFiles.IndexOf(FileName));
+{$WARNINGS OFF}
+procedure TGLVfsPAK.AddFromStream(const FileName, Path: string; F: TStream);
+ Temp: TMemoryStream;
+ FStream.Position := FHeader.DirOffset;
+ if FHeader.DirLength > 0 then
+ Temp := TMemoryStream.Create;
+ Temp.CopyFrom(FStream, FHeader.DirLength);
+ Temp.Position := 0;
+ Dir.FilePos := FHeader.DirOffset;
+ Dir.FileLength := F.Size;
+ FStream.CopyFrom(F, 0);
+ FHeader.DirOffset := FStream.Position;
+ FStream.CopyFrom(Temp, 0);
+ Temp.Free;
+ StrPCopy(Dir.FileName, Path + ExtractFileName(FileName));
+ FStream.WriteBuffer(Dir, SizeOf(TFileSection));
+ FHeader.DirLength := FHeader.DirLength + SizeOf(TFileSection);
+ FFiles.Add(Dir.FileName);
+{$WARNINGS ON}
+procedure TGLVfsPAK.AddFromFile(const FileName, Path: string);
+ F: TFileStream;
+ if not FileExists(FileName) then
+ F := TFileStream.Create(FileName, fmOpenRead);
+ try
+ AddFromStream(FileName, Path, F);
+ finally
+ F.Free;
+procedure TGLVfsPAK.AddEmptyFile(const FileName, Path: string);
+ F: TMemoryStream;
+ F := TMemoryStream.Create;
+procedure TGLVfsPAK.RemoveFile(index: integer);
+ F: TFileSection;
+ FStream.Seek(Dir.FilePos + Dir.FileLength, soFromBeginning);
+ Temp.CopyFrom(FStream, FStream.Size - FStream.Position);
+ FStream.Position := Dir.FilePos;
+ FHeader.DirOffset := FHeader.DirOffset - Dir.FileLength;
+ Temp.Clear;
+ if i > index then
+ FStream.Seek(FHeader.DirOffset + SizeOf(TFileSection) * i,
+ FStream.ReadBuffer(F, SizeOf(TFileSection));
+ FStream.Position := FStream.Position - SizeOf(TFileSection);
+ F.FilePos := F.FilePos - Dir.FileLength;
+ FStream.WriteBuffer(F, SizeOf(TFileSection));
+ i := FHeader.DirOffset + SizeOf(TFileSection) * index;
+ FStream.Position := i + SizeOf(TFileSection);
+ if FStream.Position < FStream.Size then
+ FStream.Position := i;
+ FHeader.DirLength := FHeader.DirLength - SizeOf(TFileSection);
+ FStream.Size := FStream.Size - Dir.FileLength - SizeOf(TFileSection);
+procedure TGLVfsPAK.RemoveFile(const FileName: string);
+ RemoveFile(FFiles.IndexOf(FileName));
+procedure TGLVfsPAK.Extract(index: integer; const NewName: string);
+ s: TFileStream;
+ if NewName = '' then
+ if (index < 0) or (index >= FileCount) then
+ s := TFileStream.Create(NewName, fmCreate);
+ s.CopyFrom(GetFile(index), 0);
+ s.Free;
+procedure TGLVfsPAK.Extract(const FileName, NewName: string);
+ Extract(FFiles.IndexOf(FileName), NewName);
+end.
@@ -21,7 +21,7 @@ uses
GLObjects,
GLMultiPolygon,
GLCoordinates,
- GLTypes,
+ GLVectorRecTypes,
GLColor,
GLSpline,
GLspaceText,
@@ -42,7 +42,7 @@ uses
GLMesh,
GLVectorFileObjects,
- GLTypes;
+ GLVectorRecTypes;
const
ALLOC_SIZE = 65536;
@@ -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.
@@ -0,0 +1,904 @@
+unit GLS.FileDXF;
+ Turn on TwoSideLighting in your Buffer! DXF-Faces have no defined winding order
+ GLPersistentClasses,
+ GLApplicationFileIO,
+ GLVectorLists,
+ GLScene,
+ GLTexture,
+ GLVectorFileObjects,
+ GLMaterial;
+ TGLDXFVectorFile = class(TGLVectorFile)
+ // 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);
+ class function Capabilities: TGLDataFileCapabilities; override;
+ procedure LoadFromStream(aStream: TStream); override;
+procedure BuildNormals(m: TMeshObject); FORWARD;
+ 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);
+ 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;
+ result := ((bgr SHR 16) and $FF) or (bgr AND $FF00) or
+ ((bgr SHL 16) and $FF0000)
+ function StreamEOF(S: TStream): Boolean;
+ begin // Is the stream at its end?
+ result := (S.Position >= S.Size);
+ class function TGLDXFVectorFile.Capabilities: TGLDataFileCapabilities;
+ result := [dfcRead];
+ function TGLDXFVectorFile.ReadLine: STRING;
+ var
+ j: Integer;
+ FLine: STRING;
+ NewlineChar: CHAR;
+ procedure FillBuffer;
+ l: Integer;
+ l := FSourceStream.Size - FSourceStream.Position;
+ if l > BufSize then
+ l := BufSize;
+ SetLength(FBuffer, l);
+ FSourceStream.Read(FBuffer[1], l);
+ FBufPos := 1;
+ Inc(FLineNo);
+ if FBufPos < 1 then
+ FillBuffer;
+ j := 1;
+ while True do
+ if FBufPos > Length(FBuffer) then
+ if StreamEOF(FSourceStream) then
+ FEof := True;
+ break;
+ FillBuffer
+ case FBuffer[FBufPos] of
+ #10, #13:
+ NewlineChar := FBuffer[FBufPos];
+ Inc(FBufPos);
+ break
+ if ((FBuffer[FBufPos] = #10) or (FBuffer[FBufPos] = #13)) and
+ (FBuffer[FBufPos] <> NewlineChar) then
+ if j > Length(FLine) then
+ SetLength(FLine, Length(FLine) + LineLen);
+ if FBuffer[FBufPos] = #9 then
+ FLine[j] := #32
+ FLine[j] := FBuffer[FBufPos];
+ Inc(j);
+ SetLength(FLine, j - 1);
+ ReadLine := Trim(FLine);
+ procedure TGLDXFVectorFile.DoProgress (Stage: TGLProgressStage; PercentDone: single; RedrawNow: Boolean; const Msg: string);
+ var perc:BYTE;
+ // If the following line stops your compiler, just comment this function
+ if @owner.OnProgress<>NIL then
+ perc:=round(percentdone);
+ if (perc<>Flastpercentdone) or (msg<>'') or redrawnow then
+ owner.OnProgress (owner,stage,perc,redrawnow,msg);
+ Flastpercentdone:=perc;
+ procedure TGLDXFVectorFile.PushCode(code: Integer);
+ PushedCode := code;
+ HasPushedCode := True;
+ function TGLDXFVectorFile.GetCode: Integer;
+ S: STRING;
+ if HasPushedCode then
+ GetCode := PushedCode;
+ HasPushedCode := FALSE;
+ S := ReadLine;
+ result := StrToIntDef(S, -1);
+ if result = -1 then
+ raise Exception.create('Invalid DXF Code ' + S + ' on Line #' +
+ IntToStr(FLineNo));
+ function TGLDXFVectorFile.ReadDouble: double;
+ S: String;
+ c: CHAR;
+ c := FormatSettings.DecimalSeparator;
+ FormatSettings.DecimalSeparator := '.';
+ S := Trim(ReadLine);
+ result := StrToFloat(S);
+ FormatSettings.DecimalSeparator := c;
+ function TGLDXFVectorFile.ReadInt: Integer;
+ result := StrToInt(S);
+ procedure TGLDXFVectorFile.SkipSection;
+ code: Integer;
+ repeat
+ code := GetCode;
+ until (code = 0) and (S = 'ENDSEC');
+ procedure TGLDXFVectorFile.SkipTable;
+ until (code = 0) and (S = 'ENDTAB');
+ procedure TGLDXFVectorFile.ReadLayer;
+ layername, color: String;
+ color := '1';
+ case code of
+ 0:
+ ;
+ 2:
+ layername := ReadLine;
+ 70:
+ ReadLine; // freeze and lock flags
+ 62:
+ color := ReadLine;
+ ReadLine;
+ until code = 0;
+ PushCode(0);
+ FLayers.AddObject(layername, POINTER(StrToIntDef(color, 1)));
+ procedure TGLDXFVectorFile.ReadLayerTable;
+ if (code = 0) and (S = 'LAYER') then
+ ReadLayer;
+ procedure TGLDXFVectorFile.ReadTables;
+ if (code = 0) and (S = 'TABLE') then
+ if (code = 2) then
+ if S = 'LAYER' then
+ ReadLayerTable
+ SkipTable; // LTYPE, STYLE, UCS, and more currently skipped
+ procedure TGLDXFVectorFile.ReadBlocks;
+ blockname: String;
+ blockmesh: TGLFreeForm;
+ // This code reads blocks into orphaned TGLFreeForms.
+ // ReadInsert then either copies or parents this object to its parent
+ // unused blocks are freed upon completion
+ if (code = 0) and (S = 'BLOCK') then
+ blockmesh := TGLFreeForm.create(owner);
+ blockmesh.IgnoreMissingTextures := True;
+ blockmesh.MaterialLibrary := owner.MaterialLibrary;
+ blockmesh.OnProgress := NIL;
+ blockname := 'DXFBLOCK' + IntToStr(FBlocks.count);
+ blockname := ReadLine;
+ FBlocks.AddObject(blockname, blockmesh);
+ ReadEntities(blockmesh);
+ // basemesh.Direction.SetVector(0,1,0);
+ // code:=GetCode;
+ // s:=ReadLine;
+ // asm nop end;
+ procedure TGLDXFVectorFile.ReadInsert(basemesh: TGLBaseMesh);
+ 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;
+ blockname := '';
+ insertpoint := NullVector;
+ scale := XYZvector;
+ repeat // see ReadBlocks for details
+ 10:
+ insertpoint.X := ReadDouble;
+ 20:
+ insertpoint.Y := ReadDouble;
+ 30:
+ insertpoint.Z := ReadDouble;
+ 41:
+ scale.X := ReadDouble;
+ 42:
+ scale.Y := ReadDouble;
+ 43:
+ scale.Z := ReadDouble;
+ idx := FBlocks.IndexOf(blockname);
+ if idx >= 0 then
+ 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
+ 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
+ pt := mo_block.vertices[j];
+ ScaleVector(pt, scale);
+ AddVector(pt, insertpoint);
+ mo_base.vertices.Add(pt);
+ for j := 0 to mo_block.FaceGroups.count - 1 do
+ 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
+ fg_base.VertexIndices.Add(fg_block.VertexIndices[k] +
+ indexoffset);
+ // 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
+ blockmesh.Position.AsAffineVector:=insertpoint;
+ blockmesh.ShowAxes:=TRUE;
+ basemesh.AddChild(blockmesh);
+ for i:=0 to blockmesh.MeshObjects.Count-1 do
+ BuildNormals(blockmesh.MeshObjects[i]);
+ blockproxy:=TGLproxyObject.CreateAsChild(basemesh);
+ blockproxy.MasterObject:=blockmesh;
+ blockproxy.Position.AsAffineVector:=insertpoint;
+ blockproxy.ShowAxes:=TRUE;
+ *)
+ function TGLDXFVectorFile.NeedMesh(basemesh: TGLBaseMesh; layer: STRING)
+ : TMeshObject;
+ 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]
+ result := TMeshObject.CreateOwned(basemesh.MeshObjects);
+ result.mode := momFaceGroups;
+ result.name := layer;
+ function TGLDXFVectorFile.NeedFaceGroup(m: TMeshObject;
+ fgmode: TGLFaceGroupMeshMode; fgmat: STRING): TFGVertexIndexList;
+ acadcolor: LONGINT;
+ libmat: TGLLibMaterial;
+ fg: TFGVertexIndexList;
+ 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
+ if i < m.FaceGroups.count then
+ fg := m.FaceGroups[i] as TFGVertexIndexList
+ fg := TFGVertexIndexList.CreateOwned(m.FaceGroups);
+ fg.mode := fgmode;
+ fg.MaterialName := fgmat;
+ if owner.MaterialLibrary <> NIL then
+ libmat := owner.MaterialLibrary.Materials.GetLibMaterialByName(fgmat);
+ if libmat = NIL then // creates a colored material
+ acadcolor := StrToIntDef(fgmat, 0);
+ if acadcolor in [1 .. 255] then
+ libmat := owner.MaterialLibrary.Materials.Add;
+ libmat.name := fgmat;
+ libmat.Material.FrontProperties.Diffuse.AsWinColor :=
+ RGB2BGR(DXFcolorsRGB[acadcolor]);
+ libmat.Material.BackProperties.Diffuse.AsWinColor :=
+ libmat.Material.FaceCulling := fcNoCull;
+ result := fg;
+ procedure TGLDXFVectorFile.NeedMeshAndFaceGroup(basemesh: TGLBaseMesh;
+ layer: STRING; fgmode: TGLFaceGroupMeshMode; fgmat: STRING;
+ var m: TMeshObject; var fg: TFGVertexIndexList);
+ m := NeedMesh(basemesh, layer);
+ fg := NeedFaceGroup(m, fgmode, fgmat);
+ procedure TGLDXFVectorFile.ReadEntity3Dface(basemesh: TGLBaseMesh);
+ code, i: Integer;
+ pts: ARRAY [0 .. 3] of TAffineVector;
+ isquad: Boolean;
+ color, layer: STRING;
+ m: TMeshObject;
+ color := '';
+ layer := '';
+ isquad := FALSE;
+ for i := 0 to 3 do
+ pts[i] := NullVector;
+ 8:
+ layer := ReadLine; // Layer
+ pts[0].X := ReadDouble;
+ 11:
+ pts[1].X := ReadDouble;
+ 12:
+ pts[2].X := ReadDouble;
+ 13:
+ pts[3].X := ReadDouble;
+ isquad := True
+ pts[0].Y := ReadDouble;
+ 21:
+ pts[1].Y := ReadDouble;
+ 22:
+ pts[2].Y := ReadDouble;
+ 23:
+ pts[3].Y := ReadDouble;
+ pts[0].Z := ReadDouble;
+ 31:
+ pts[1].Z := ReadDouble;
+ 32:
+ pts[2].Z := ReadDouble;
+ 33:
+ pts[3].Z := ReadDouble;
+ color := ReadLine; // Color
+ 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)
+ 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]));
+ fg.Add(m.vertices.FindOrAdd(pts[3]));
+ procedure TGLDXFVectorFile.ReadEntityPolyLine(basemesh: TGLBaseMesh);
+ procedure ReadPolylineVertex(m: TMeshObject; vertexindexbase: Integer);
+ color: STRING;
+ pt: TAffineVector;
+ code, idx, i70, i71, i72, i73, i74: Integer;
+ pt := NullVector;
+ i70 := 0;
+ i71 := 0;
+ i72 := 0;
+ i73 := 0;
+ i74 := 0;
+ 5:
+ ReadLine; // ID :=ReadHex16;
+ ReadLine; // ignore per vertex layer. Polyline vertices cannot cross layers!
+ pt.X := ReadDouble;
+ pt.Y := ReadDouble;
+ pt.Z := ReadDouble;
+ 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?
+ if (color = '') or (color = '256') or (color = 'BYLAYER') then
+ idx := FLayers.IndexOf(m.name);
+ color := IntToStr(LONGINT(FLayers.Objects[idx]));
+ if i70 and 192 = 192 then
+ m.vertices.Add(pt);
+ else if i70 and 192 = 128 then
+ i71 := i71 - 1 + vertexindexbase;
+ i72 := i72 - 1 + vertexindexbase;
+ i73 := i73 - 1 + vertexindexbase;
+ if i74 = 0 then
+ fg := NeedFaceGroup(m, fgmmTriangles, color);
+ fg.Add(i71);
+ fg.Add(i72);
+ fg.Add(i73);
+ i74 := i74 - 1 + vertexindexbase;
+ fg := NeedFaceGroup(m, fgmmQuads, color);
+ fg.Add(i74);
+ // hmm?
+ code, vertexindexbase: Integer;
+ S, layer: STRING;
+ m := NIL;
+ vertexindexbase := 0;
+ if (code = 8) then
+ layer := S;
+ vertexindexbase := m.vertices.count;
+ if (code = 0) and (S = 'VERTEX') and (m <> NIL) then
+ ReadPolylineVertex(m, vertexindexbase);
+ until (code = 0) and (S = 'SEQEND');
+ if code <> 0 then
+ until (code = 0);
+ procedure TGLDXFVectorFile.ReadEntities(basemesh: TGLBaseMesh);
+ // DoProgress (psRunning,FSourceStream.Position/FSourceStream.Size*100,false,'');
+ 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
+ else if S = 'ENDBLK' then
+ asm
+ nop
+ end // put breakpoint here to catch other entities
+ until (code = 0) and ((S = 'ENDSEC') or (S = 'ENDBLK'));
+ // build normals
+ procedure BuildNormals(m: TMeshObject);
+ i, j: Integer;
+ v1, v2, v3, v4, n: TAffineVector;
+ 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:
+ for j := 0 to (VertexIndices.count div 3) - 1 do
+ 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);
+ fgmmQuads:
+ for j := 0 to (VertexIndices.count div 4) - 1 do
+ 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]];
+ 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);
+ for i := 0 to m.Normals.count - 1 do
+ m.Normals.items[i] := VectorNormalize(m.Normals.items[i]);
+ procedure TGLDXFVectorFile.LoadFromStream(aStream: TStream);
+ FLastpercentdone := 1;
+ /// DoProgress (psStarting,0,false,'Starting');
+ FEof := FALSE;
+ FSourceStream := aStream;
+ FLineNo := 0;
+ FLayers := TStringList.create;
+ FBlocks := TStringList.create;
+ while not FEof do
+ /// DoProgress (psStarting,FSourceStream.Position/FSourceStream.Size*90,false,'');
+ if (code = 0) then
+ if S = 'EOF' then
+ else if S = 'SECTION' then
+ if code <> 2 then
+ raise Exception.create('Name must follow Section' + ' on Line #' +
+ IntToStr(FLineNo))
+ if S = 'HEADER' then
+ SkipSection
+ else if S = 'BLOCKS' then
+ ReadBlocks
+ else if S = 'ENTITIES' then
+ ReadEntities(owner)
+ else if S = 'CLASSES' then
+ else if S = 'TABLES' then
+ ReadTables
+ else if S = 'OBJECTS' then
+ SkipSection;
+ raise Exception.create('SECTION/ENDSEC Mismatch' + ' on Line #' +
+ S := ReadLine; // raise Exception.create ('Invalid Group Code');
+ // 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,'');
+//----------------------------------------------
+initialization
+RegisterVectorFileFormat('dxf', 'AutoCAD Exchange Format', TGLDXFVectorFile);
@@ -1,247 +1,247 @@
-unit GLFileGRD;
-(* GRD (Grid Text Format) vector file format implementation *)
- System.SysUtils,
- GLVectorFileObjects,
- GLApplicationFileIO,
- GLGraph;
- (* 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)
- 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;
-// ------------------
-// ------------------ 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;
-var
- Count, I: Integer;
- 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;
-function TGLGRDVectorFile.ExtractWord(N: Integer; const S: string;
- I, Len: Integer;
- Len := 0;
- I := WordPosition(N, S, WordDelims);
- if (I <> 0) then
- // find the end of the current word
- // add the I'th character to result
- Inc(Len);
- SetLength(Result, Len);
- Result[Len] := S[I];
-procedure TGLGRDVectorFile.LoadFromStream(aStream: TStream);
- 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;
- Result := Sl[N];
- Inc(N);
- 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
- raise Exception.Create('Not a valid grd file !');
- Exit;
- 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
- Tl.DelimitedText := ReadLine;
- Nx := StrToInt(Tl[0]);
- Ny := StrToInt(Tl[1]);
- Xo := StrToFloat(Tl[0]);
- Xe := StrToFloat(Tl[1]);
- Yo := StrToFloat(Tl[0]);
- Ye := StrToFloat(Tl[1]);
- 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
- J := 0;
- // reading lines until Nx-1 Cols entries have been obtained
- while J <= Nx - 1 do
- StrLine := ReadLine;
- K := 1;
- StrVal := ExtractWord(K, StrLine, [' ']);
- while (StrVal <> '') do
- 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);
- if (J > Nx - 1) then
- Break;
- end
- else // ArcInfo ASCII grid
- 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
- Tl.DelimitedText := Sl[I + 6];
- for J := 0 to Ny - 1 do
- StrVal := Tl[J];
- 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;
-initialization
-RegisterVectorFileFormat('grd', 'ArcInfo/Surfer grids', TGLGRDVectorFile);
+unit GLS.FileGRD;
+(* GRD (Grid Text Format) vector file format implementation *)
+ GLGraph;
+ (* 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)
+ GLHeightField: TGLHeightField;
+ Nodes: array of TSingleArray;
+ 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;
+// ------------------------------------------------------------------
+// ------------------
+// ------------------ TGLGRDVectorFile ------------------
+ dSURFBLANKVAL = 1.70141E38; // default value in Surfer for blanking
+ NODATA_value = -9999; // default value in GIS ArcInfo for blanking
+class function TGLGRDVectorFile.Capabilities: TGLDataFileCapabilities;
+ Result := [dfcRead];
+function TGLGRDVectorFile.WordPosition(const N: Integer; const S: string;
+ Count, I: Integer;
+ Count := 0;
+ I := 1;
+ Result := 0;
+ while ((I <= Length(S)) and (Count <> N)) do
+ // 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)
+ Result := I;
+function TGLGRDVectorFile.ExtractWord(N: Integer; const S: string;
+ I, Len: Integer;
+ Len := 0;
+ I := WordPosition(N, S, WordDelims);
+ if (I <> 0) then
+ // find the end of the current word
+ // add the I'th character to result
+ Inc(Len);
+ SetLength(Result, Len);
+ Result[Len] := S[I];
+procedure TGLGRDVectorFile.LoadFromStream(aStream: TStream);
+ 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;
+ Result := Sl[N];
+ Inc(N);
+ Sl := TStringList.Create;
+ Tl := TStringList.Create;
+ Sl.LoadFromStream(aStream);
+ if (Copy(Sl[0], 1, 4) <> 'DSAA') and (Copy(Sl[0], 1, 5) <> 'ncols') then
+ raise Exception.Create('Not a valid grd file !');
+ 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
+ Tl.DelimitedText := ReadLine;
+ Nx := StrToInt(Tl[0]);
+ Ny := StrToInt(Tl[1]);
+ Xo := StrToFloat(Tl[0]);
+ Xe := StrToFloat(Tl[1]);
+ Yo := StrToFloat(Tl[0]);
+ Ye := StrToFloat(Tl[1]);
+ 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
+ J := 0;
+ // reading lines until Nx-1 Cols entries have been obtained
+ while J <= Nx - 1 do
+ StrLine := ReadLine;
+ K := 1;
+ StrVal := ExtractWord(K, StrLine, [' ']);
+ while (StrVal <> '') do
+ 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);
+ if (J > Nx - 1) then
+ Break;
+ else // ArcInfo ASCII grid
+ 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
+ Tl.DelimitedText := Sl[I + 6];
+ for J := 0 to Ny - 1 do
+ StrVal := Tl[J];
+ GLHeightField.XSamplingScale.Min := -(Nx div 2);
+ GLHeightField.XSamplingScale.Max := (Nx div 2);
+ GLHeightField.YSamplingScale.Min := -(Ny div 2);
+ GLHeightField.YSamplingScale.Max := (Ny div 2);
+ Tl.Free;
+ Sl.Free;
+RegisterVectorFileFormat('grd', 'ArcInfo/Surfer grids', TGLGRDVectorFile);
@@ -1,10 +1,10 @@
- TIN (Triangular Irregular Network) vector file format implementation.
-unit GLFileTIN;
+unit GLS.FileTIN;
+(* TIN (Triangular Irregular Network) vector file format implementation *)
@@ -19,7 +19,7 @@ uses
GLApplicationFileIO,
GLUtils,
@@ -1,5462 +1,5461 @@
- Memo for GLScene
-unit GLSMemo;
- WinApi.Windows,
- WinApi.Messages,
- System.UITypes,
- VCL.Graphics,
- VCL.Controls,
- VCL.Forms,
- VCL.Dialogs,
- VCL.ClipBrd,
- VCL.StdCtrls,
- VCL.ExtCtrls;
- TBorderType = (btRaised, btLowered, btFlatRaised, btFlatLowered);
- TCommand = Integer;
- TCellSize = record
- W, H: integer;
- TCellPos = record
- X, Y: integer;
- TFullPos = record
- LineNo, Pos: integer;
- TLineProp = class
- FObject: TObject;
- FStyleNo: integer;
- FInComment: Boolean;
- FInBrackets: integer;
- FValidAttrs: Boolean;
- FCharAttrs: string;
- TCharStyle = class(TPersistent)
- 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;
- TStyleList = class(TList)
- 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;
- 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);
- TGLAbstractMemoObject = class(TObject)
- function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
- Boolean; virtual; abstract;
- function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
- function MouseMove(Shift: TShiftState; X, Y: Integer):
- TGLSMemoScrollBar = class;
- TGLSMemoAbstractScrollableObject = class(TCustomControl)
- procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
- virtual; abstract;
- procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer);
- TGLSCustomMemo = class;
- TsbState =
- (
- sbsWait,
- sbsBack,
- sbsForward,
- sbsPageBack,
- sbsPageForward,
- sbsDragging
- );
- TGLSMemoScrollBar = class(TGLAbstractMemoObject)
- 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;
- constructor Create(AParent: TGLSMemoAbstractScrollableObject;
- AKind: TScrollBarKind);
- procedure PaintTo(ACanvas: TCanvas);
- 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;
- TGLSMemoStrings = class(TStringList)
- FMemo: TGLSCustomMemo;
- FLockCount: integer;
- FDeleting: Boolean;
- 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);
- 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;
- 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;
- TGLSMemoGutter = class(TObject)
- FColor: TColor;
- procedure Invalidate;
- TGLSMemoUndo = class
- FUndoCurX0, FUndoCurY0: integer;
- FUndoCurX, FUndoCurY: integer;
- FUndoText: string;
- 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;
- TGLSMemoInsCharUndo = class(TGLSMemoUndo)
- function Append(NewUndo: TGLSMemoUndo): Boolean; override;
- procedure PerformUndo; override;
- procedure PerformRedo; override;
- TGLSMemoDelCharUndo = class(TGLSMemoUndo)
- FIsBackspace: Boolean;
- property IsBackspace: Boolean read FIsBackspace write FIsBackspace;
- TGLSMEmoDelLineUndo = class(TGLSMemoUndo)
- FIndex: integer;
- constructor Create(AIndex, ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
- string);
- TGLSMemoSelUndo = class(TGLSMemoUndo)
- FUndoSelStartX, FUndoSelStartY,
- FUndoSelEndX, FUndoSelEndY: integer;
- 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;
- TGLSMemoDeleteBufUndo = class(TGLSMemoSelUndo)
- TGLSMemoPasteUndo = class(TGLSMemoUndo)
- TGLSMemoUndoList = class(TList)
- FPos: integer;
- FIsPerforming: Boolean;
- FLimit: integer;
- function Get(Index: Integer): TGLSMemoUndo;
- procedure SetLimit(Value: integer);
- constructor Create;
- function Add(Item: Pointer): Integer;
- 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;
- //--------------------------------------------------------------
- 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)
- 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);
- function GetInComment(Index: integer): Boolean;
- procedure SetInComment(Index: integer; Value: Boolean);
- 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);
- 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;
- 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;
- constructor Create(AOwner: TComponent); 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;
- 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
- property Styles: TStyleList read FStyles;
- property UndoList: TGLSMemoUndoList read FUndoList write FUndoList;
- TGLSMemo = class(TGLSCustomMemo)
- {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;
- TGLSMemoStringList = class(TStringList)
- procedure ReadStrings(Reader: TReader);
- procedure WriteStrings(Writer: TWriter);
- procedure DefineProperties(Filer: TFiler); override;
- TDelimiters = TSysCharSet;
- TTokenType =
- ttWord,
- ttBracket,
- ttSpecial,
- ttDelimiter,
- ttSpace,
- ttEOL,
- ttInteger,
- ttFloat,
- ttComment,
- ttOther,
- ttWrongNumber);
- // SYNTAX MEMO - declaration
- TGLSSynHiMemo = class(TGLSCustomMemo)
- FIsPainting: Boolean;
- FWordList: TGLSMemoStringList;
- FSpecialList: TGLSMemoStringList;
- FBracketList: TGLSMemoStringList;
- FDelimiters: TDelimiters;
- 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:
- procedure SetStyle(Index: integer; Value: TCharStyle);
- procedure SetCaseSensitive(Value: Boolean);
- 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;
- {TControl}
- {TCustomControl}
- {TGLSCustomMemo}
- {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;
-procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
-//==========================================================
- 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';
- 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;
- with rct do
- Result := (Left <= P.X) and (Top <= P.Y) and
- (Right >= P.X) and (Bottom >= P.Y);
-procedure Swap(var I1, I2: integer); inline;
- temp: integer;
- temp := I1;
- I1 := I2;
- I2 := temp;
-procedure OrderPos(var StartX, StartY, EndX, EndY: integer); inline;
- if (EndY < StartY) or
- ((EndY = StartY) and (EndX < StartX)) then
- Swap(StartX, EndX);
- Swap(StartY, EndY);
-function TotalRect(const rct1, rct2: TRect): TRect; inline;
- Result := rct1;
- with Result do
- 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;
-// ---------------------TGLSCustomMemo functions
-procedure TGLSCustomMemo.WndProc(var Message: TMessage);
- function GetShiftState: Integer;
- 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;
- //---------------------------------------------------
- if (Message.Msg = fIntelliMessage) and (fIntelliMessage <> wm_MouseWheel) then
- PostMessage(Handle, wm_MouseWheel, MakeLong(GetShiftState, Message.wParam),
- Message.lParam);
- inherited;
-//------------------------------------------------
-// INTELLIMOUSE INIT
-procedure IntelliMouseInit;
- hWndMouse: hWnd;
- mQueryScrollLines: UINT;
- //--------------------------------------------
- function NativeMouseWheelSupport: Boolean;
- var
- ver: TOSVersionInfo;
- 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;
- { Quick and dirty temporary hack for Windows 98 beta 3 }
- if (not Result) and (ver.szCSDVersion = ' Beta 3') then
- Result := True;
- if NativeMouseWheelSupport then
- fIntelliWheelSupport := Boolean(GetSystemMetrics(sm_MouseWheelPresent));
- SystemParametersInfo(spi_GetWheelScrollLines, 0, @fIntelliScrollLines, 0);
- fIntelliMessage := wm_MouseWheel;
- { Look for hidden mouse window }
- hWndMouse := FindWindow('MouseZ', 'Magellan MSWHEEL');
- if hWndMouse <> 0 then
- { 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');
- if (fIntelliScrollLines < 0) or (fIntelliScrollLines > 100) then
- fIntelliScrollLines := 3;
-// WM MOUSE WHEEL
-procedure TGLSCustomMemo.WMMouseWheel(var Message: TMessage);
-{$J+}
-{$IFOPT R+} {$DEFINE StoreRangeCheck} {$ENDIF} {$R-}
- Delta: SmallInt = 0;
- Delta := Delta + SmallInt(HiWord(Message.wParam));
- while Abs(Delta) >= 120 do
- if Delta < 0 then
- DoScroll(sbVert, fIntelliScrollLines);
- Delta := Delta + 120;
- DoScroll(sbVert, -fIntelliScrollLines);
- Delta := Delta - 120;
-{$J-}
-{$IFDEF StoreRangeCheck} {$R+} {$UNDEF StoreRangeCheck} {$ENDIF}
-//--------------------------------------------------------------
-// SET CURSOR
-procedure TGLSCustomMemo.SetCursor(ACurX, ACurY: Integer);
- ClearSelection;
- CurX := 0;
- CurY := ACurY;
- CurX := ACurX;
-// SELECT LINE, CHAR
-function TGLSCustomMemo.SelectLine(LineNo, StyleNo: Integer): integer;
- rct: TRect;
- Result := LineStyle[LineNo];
- LineStyle[LineNo] := StyleNo;
- rct := LineRect(LineNo);
- InvalidateRect(Handle, @rct, True);
-procedure TGLSCustomMemo.SelectLines(StartLine, EndLine: Integer);
- FSelStartX := 0;
- FSelStartY := StartLine;
- FSelEndX := Length(Lines[EndLine]);
- FSelEndY := EndLine;
- rct := LineRangeRect(FSelStartY, FSelEndY);
- SelectionChanged;
- InvalidateRect(Handle, @rct, true);
-procedure TGLSCustomMemo.SelectChar(LineNo, Pos, StyleNo: Integer);
- UnselectChar;
- FSelCharPos.LineNo := LineNo;
- FSelCharPos.Pos := Pos;
- FSelCharStyle := StyleNo;
-procedure TGLSCustomMemo.UnSelectChar;
- with FSelCharPos do
- if LineNo < 0 then
- LineNo := -1;
- Pos := -1;
- FSelCharStyle := -1;
-// CLEAR
-procedure TGLSCustomMemo.Clear;
- CurY := 0;
- FLeftCol := 0;
- FTopLine := 0;
- Lines.Clear;
- TGLSMemoStrings(Lines).DoAdd('');
- ClearUndoList;
- Invalidate;
-// SELECT ALL
-procedure TGLSCustomMemo.SelectAll;
- FSelStartY := 0;
- FSelEndY := Lines.Count - 1;
- FSelEndX := Length(Lines[Lines.Count - 1]);
-//-----------------------------------------------------------
-// SET CLIPBOARD CODE PAGE
-procedure SetClipboardCodePage(const CodePage: longint);
- Data: THandle;
- DataPtr: Pointer;
- // Define new code page for clipboard
- Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 4);
- DataPtr := GlobalLock(Data);
- Move(CodePage, DataPtr^, 4);
- SetClipboardData(CF_LOCALE, Data);
- GlobalUnlock(Data);
- except
- GlobalFree(Data);
-// COPY TO CLIPBOARD
-procedure CopyStringToClipboard(const Value: string);
- RusLocale = (SUBLANG_DEFAULT shl $A) or LANG_RUSSIAN;
- Clipboard.Open;
- SetClipboardCodePage(RusLocale);
- Clipboard.AsText := Value;
- Clipboard.Close;
-procedure TGLSCustomMemo.CopyToClipBoard;
- CopyStringToClipboard(GetSelText);
-// PASTE FROM CLIPBOARD
-procedure TGLSCustomMemo.PasteFromClipBoard;
- H, len: integer;
- Buff: string;
- H := ClipBoard.GetAsHandle(CF_TEXT);
- len := GlobalSize(H);
- if len = 0 then
- SetLength(Buff, len);
- SetLength(Buff, ClipBoard.GetTextBuf(PChar(Buff), len));
- AdjustLineBreaks(Buff);
- SetSelText(Buff);
-// DELETE SELECTION
-procedure TGLSCustomMemo.DeleteSelection(bRepaint: Boolean);
- xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
- i, len: integer;
- OldX, OldY: integer;
- S1, S2, S, AddSpaces: string;
- Undo: TGLSMemoDeleteBufUndo;
- if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
- OldX := CurX;
- OldY := CurY;
- xSelStartX := FSelStartX;
- xSelStartY := FSelStartY;
- xSelEndX := FSelEndX;
- xSelEndY := FSelEndY;
- OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
- if xSelStartY = xSelEndY then
- S1 := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX);
- S2 := '';
- AddSpaces := '';
- len := Length(Lines[xSelStartY]);
- S1 := Copy(Lines[xSelStartY], xSelStartX + 1, len);
- AddSpaces := StringOfChar(' ', xSelStartX - len);
- S2 := Copy(Lines[xSelEndY], 1, xSelEndX);
- 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
- S := S + #13#10;
- if i <> xSelEndY then
- S := S + Lines[xSelStartY + 1];
- DeleteLine(xSelStartY + 1, -1, -1, -1, -1, False);
- S := S + S2;
- CurY := xSelStartY;
- CurX := xSelStartX;
- Changed(xSelStartY, -1);
- if bRepaint then
- 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);
-// CUT TO CLIPBOARD
-procedure TGLSCustomMemo.CutToClipBoard;
- ClipBoard.SetTextBuf(PChar(GetSelText));
- DeleteSelection(True);
-// GET SEL TEXT
-function TGLSCustomMemo.GetSelText: string;
- i: integer;
- Result := '';
- Result := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX)
- 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);
-// GET SEL START
-function TGLSCustomMemo.GetSelStart: TPoint;
- Result := Point(xSelStartX, xSelStartY);
-// GET SEL END
-function TGLSCustomMemo.GetSelEnd: TPoint;
- Result := Point(xSelEndX, xSelEndY);
-// SET SEL TEXT
-procedure TGLSCustomMemo.SetSelText(const AValue: string);
- i, k: integer;
- Buff, S: string;
- Buff := AValue;
- DeleteSelection(False);
- i := Pos(#13#10, Buff);
- S := Lines[xSelStartY];
- if i = 0 then
- Lines[xSelStartY] := Copy(S, 1, xSelStartX) + Buff
- + Copy(S, xSelStartX + 1, Length(S));
- if Buff <> '' then
- CurX := CurX + Length(Buff);
- 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
- Buff := Copy(Buff, i + 2, Length(Buff));
- k := k + 1;
- break;
- TGLSMemoStrings(Lines).DoInsert(k, Copy(Buff, 1, i - 1));
- Lines[k] := Buff + Lines[k];
- CurY := k;
- CurX := Length(Buff);
- FUndoList.Add(TGLSMemoPasteUndo.Create(OldX, OldY, CurX, CurY, AValue));
-// GET SEL LENGTH
-function TGLSCustomMemo.GetSelLength: integer;
- Result := Length(GetSelText);
-// CHANGED
-procedure TGLSCustomMemo.Changed(FromLine, ToLine: integer);
- 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);
-// ATTR CHANGED
-procedure TGLSCustomMemo.AttrChanged(LineNo: integer);
- ValidAttrs[LineNo] := False;
- InvalidateLineRange(LineNo, LineNo);
- if Assigned(FOnAttrChange) then
- FOnAttrChange(Self);
-// SELECTION CHANGED
-procedure TGLSCustomMemo.SelectionChanged;
- if Assigned(FOnSelectionChange) then
- FOnSelectionChange(Self);
-// STATUS CHANGED
-procedure TGLSCustomMemo.StatusChanged;
- if Assigned(FOnStatusChange) then
- FOnStatusChange(Self);
-// CLEAR SELECTION
-procedure TGLSCustomMemo.ClearSelection;
- Changed: Boolean;
- Changed := not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY));
- FSelStartX := CurX;
- FSelStartY := CurY;
- FSelEndX := CurX;
- FSelEndY := CurY;
- FPrevSelX := CurX;
- FPrevSelY := CurY;
- if Changed then
- if Assigned(FOnMoveCursor) then
- FOnMoveCursor(Self);
-// EXPAND SELECTION
-procedure TGLSCustomMemo.ExpandSelection;
- rct := LineRangeRect(FPrevSelY, CurY);
-// MAX LENGTH
-function TGLSCustomMemo.MaxLength: integer;
- for i := 0 to Lines.Count - 1 do
- len := Length(Lines[i]);
- if len > Result then
- Result := len;
-// DO SCROLL
-procedure TGLSCustomMemo.DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
- eRect, scrRect, sbRect: TRect;
- Old: integer;
- eRect := EditorRect;
- case Sender.Kind of
- sbVertical:
- Old := FTopLine;
- FTopLine := FTopLine + ByValue;
- if FTopLine > Sender.MaxPosition then
- FTopLine := Sender.MaxPosition;
- if FTopLine < 0 then
- if Old <> FTopLine then
- 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);
- sbHorizontal:
- Old := FLeftCol;
- FLeftCol := FLeftCol + ByValue;
- if FLeftCol > Sender.MaxPosition then
- FLeftCol := Sender.MaxPosition;
- if FLeftCol < 0 then
- if Old <> FLeftCol then
- if CurX < FLeftCol then
- CurX := FLeftCol;
- if CurX > LastVisiblePos then
- CurX := LastVisiblePos;
- ScrollDC(Canvas.Handle, (Old - FLeftCol) * FCellSize.W, 0,
-// DO SCROLL PAGE
-procedure TGLSCustomMemo.DoScrollPage(Sender: TGLSMemoScrollBar; ByValue:
- integer);
- sbVertical: DoScroll(Sender, ByValue * VisibleLineCount);
- sbHorizontal: DoScroll(Sender, ByValue * VisiblePosCount);
-// SET LINES
-procedure TGLSCustomMemo.SetLines(ALines: TStrings);
- if ALines <> nil then
- FLines.Assign(ALines);
- Changed(0, -1);
-// SET/GET LINE STYLE
-procedure TGLSCustomMemo.SetLineStyle(Index: integer; Value: integer);
- TGLSMemoStrings(FLines).Style[Index] := Value;
- if IsLineVisible(Index) then
- AttrChanged(Index);
-function TGLSCustomMemo.GetLineStyle(Index: integer): integer;
- Result := TGLSMemoStrings(FLines).Style[Index];
-// GET/SET IN COMMENT
-function TGLSCustomMemo.GetInComment(Index: integer): Boolean;
- Result := TGLSMemoStrings(FLines).InComment[Index];
-procedure TGLSCustomMemo.SetInComment(Index: integer; Value: Boolean);
- TGLSMemoStrings(FLines).InComment[Index] := Value;
-// GET/SET IN BRACKETS
-function TGLSCustomMemo.GetInBrackets(Index: integer): integer;
- Result := TGLSMemoStrings(FLines).InBrackets[Index];
-procedure TGLSCustomMemo.SetInBrackets(Index: integer; Value: integer);
- TGLSMemoStrings(FLines).InBrackets[Index] := Value;
-// GET/SET VALID ATTRS
-function TGLSCustomMemo.GetValidAttrs(Index: integer): Boolean;
- Result := TGLSMemoStrings(FLines).ValidAttrs[Index];
-procedure TGLSCustomMemo.SetValidAttrs(Index: integer; Value: Boolean);
- TGLSMemoStrings(FLines).ValidAttrs[Index] := Value;
-// GET/SET CHAR ATTRS
-function TGLSCustomMemo.GetCharAttrs(Index: integer): string;
- Result := TGLSMemoStrings(FLines).CharAttrs[Index];
-procedure TGLSCustomMemo.SetCharAttrs(Index: integer; const Value: string);
- TGLSMemoStrings(FLines).CharAttrs[Index] := Value;
-// SET CUR X
-procedure TGLSCustomMemo.SetCurX(Value: integer);
- len: integer;
- WasVisible: Boolean;
- if Value < 0 then
- if CurY = 0 then
- Value := 0
- CurY := CurY - 1;
- Value := Length(Lines[CurY]);
- if (CurY >= 0) and (CurY < Lines.Count) then
- len := Length(Lines[CurY]);
- if Value > len then
- Lines[CurY] := Lines[CurY] + StringOfChar(' ', Value - len);
- // Value := len;
- ValidAttrs[CurY] := False;
- InvalidateLineRange(CurY, CurY);
- FCurX := Value;
- WasVisible := FCaretVisible;
- if WasVisible then
- MakeVisible;
- ResizeScrollBars;
- StatusChanged;
-// SET CUR Y
-procedure TGLSCustomMemo.SetCurY(Value: integer);
- Old := CurY;
- 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;
-// MOVE CURSOR
-procedure TGLSCustomMemo.MoveCursor(dX, dY: integer; Shift: TShiftState);
- Selecting: Boolean;
- //------------------------------------------------------------
- function IsDelimiter(c: char): Boolean;
- Result := Pos(c, ' .,;:/?!@#$%^&*(){}[]<>-+=|\') > 0;
- function IsStopChar(c, cThis: char): Boolean;
- Result := IsDelimiter(c) <> IsDelimiter(cThis);
- procedure MoveWordLeft;
- S: string;
- CurX := CurX - 1;
- S := TrimRight(Lines[CurY]);
- while CurX > 0 do
- if IsStopChar(S[CurX], S[CurX + 1]) then
- if (CurX < 0) then
- if CurY > 0 then
- CurX := Length(Lines[CurY]);
- procedure MoveWordRight;
- Len: integer;
- Len := Length(S);
- CurX := CurX + 1;
- while CurX < Len do
- if IsStopChar(S[CurX + 1], S[CurX]) then
- if CurX > Len then
- if CurY < Lines.Count - 1 then
- CurY := CurY + 1;
- Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
- and (CurY = FPrevSelY);
- if ssCtrl in Shift then
- if dX > 0 then
- MoveWordRight;
- if dX < 0 then
- MoveWordLeft;
- CurY := CurY + dY;
- CurX := CurX + dX;
- if Selecting then
- ExpandSelection
-// MOVE PAGE
-procedure TGLSCustomMemo.MovePage(dP: integer; Shift: TShiftState);
- eRect: TRect;
- LinesPerPage: integer;
- if FCellSize.H = 0 then
- LinesPerPage := (eRect.Bottom - eRect.Top) div FCellSize.H - 1;
- CurY := CurY + dP * LinesPerPage;
- if dP > 0 then
- CurY := Lines.Count - 1;
- CurX := Length(Lines[Lines.Count - 1]);
-// GO HOME
-procedure TGLSCustomMemo.GoHome(Shift: TShiftState);
-// GO END
-procedure TGLSCustomMemo.GoEnd(Shift: TShiftState);
- S, S1: string;
- 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;
-// INSERT CHAR
-procedure TGLSCustomMemo.InsertChar(C: Char);
- NewPlace: integer;
- CurX0, CurY0: integer;
- CurX0 := CurX;
- CurY0 := CurY;
- NewPlace := CurX + 1;
- if C = #9 then
- while (NewPlace mod TabSize) <> 0 do
- Inc(NewPlace);
- S1 := StringOfChar(' ', NewPlace - CurX);
- S1 := C;
- Insert(S1, S, CurX + 1);
- Lines[CurY] := S;
- CurX := NewPlace;
- rct := LineRect(CurY);
- Changed(CurY, CurY);
- FUndoList.Add(TGLSMemoInsCharUndo.Create(CurX0, CurY0, CurX, CurY, S1));
-// INSERT TEMPLATE
-procedure TGLSCustomMemo.InsertTemplate(AText: string);
- i, NewCurX, NewCurY: integer;
- Indent: string;
- FoundCursor: Boolean;
- Indent := IndentCurrLine;
- NewCurX := CurX;
- NewCurY := CurY;
- FoundCursor := False;
- i := 1;
- while i <= Length(AText) do
- if AText[i] = #13 then
- if (i = Length(AText)) or (AText[i + 1] <> #10) then
- Insert(#10 + Indent, AText, i + 1);
- if not FoundCursor then
- Inc(NewCurY);
- NewCurX := Length(Indent);
- Inc(i, 1 + Length(Indent));
- else if AText[i] = #7 then
- FoundCursor := True;
- Delete(AText, i, 1);
- Dec(i);
- else if Ord(AText[i]) < Ord(' ') then
- else if not FoundCursor then
- Inc(NewCurX);
- Inc(i);
- SetSelText(AText);
- SetCursor(NewCurX, NewCurY);
- SetFocus;
-// DELETE CHAR
-procedure TGLSCustomMemo.DeleteChar(OldX, OldY: integer);
- C: char;
- Undo: TGLSMemoDelCharUndo;
- IsBackspace: Boolean;
- if FReadOnly then
- if OldX < 0 then
- IsBackspace := False;
- IsBackspace := True;
- S1 := Copy(S, CurX + 1, Length(S));
- if not IsBackspace then
- S1 := TrimRight(S1);
- if CurX < Length(Lines[CurY]) then
- C := S[CurX + 1];
- Delete(S, CurX + 1, 1);
- Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, C);
- Undo.IsBackSpace := IsBackSpace;
- else if CurY < Lines.Count - 1 then
- S := Lines[CurY] + Lines[CurY + 1];
- DeleteLine(CurY + 1, OldX, OldY, CurX, CurY, False);
- Changed(CurY, -1);
- rct := EditorRect;
- Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, #13);
-// DELETE LINE
-procedure TGLSCustomMemo.DeleteLine(Index, OldX, OldY, NewX, NewY: integer;
- FixUndo: Boolean);
- s: string;
- if Index < 0 then
- Index := CurY;
- s := Lines[Index];
- TGLSMemoStrings(Lines).FDeleting := True;
- if Lines.Count = 1 then
- TGLSMemoStrings(Lines)[0] := ''
- Lines.Delete(Index);
- TGLSMemoStrings(Lines).FDeleting := False;
- if Index >= Lines.Count then
- Changed(Index - 1, -1)
- Changed(Index, -1);
- if NewX < 0 then
- if Length(Lines[0]) < CurX then
- CurX := Length(Lines[0]);
- CurY := Index - 1
- CurY := Index;
- NewX := CurX;
- NewY := CurY;
- CurX := NewX;
- CurY := NewY;
- if Assigned(FUndoList) and FixUndo then
- FUndoList.Add(TGLSMEmoDelLineUndo.Create(Index, OldX, OldY, NewX, NewY, s));
-// BACK SPACE
-procedure TGLSCustomMemo.BackSpace;
- MoveCursor(-1, 0, []);
- if (OldX = CurX) and (OldY = CurY) then
- DeleteChar(OldX, OldY);
-// BACK SPACE WORD
-procedure TGLSCustomMemo.BackSpaceWord;
- MoveCursor(-1, 0, [ssShift, ssCtrl]);
-// INDENT CURR LINE
-function TGLSCustomMemo.IndentCurrLine: string;
- Len, Count: integer;
- CurS: string;
- if not AutoIndent then
- CurS := Lines[CurY];
- Len := Length(CurS);
- while (Count < CurX) and (Count < Len) do
- if CurS[Count + 1] <> ' ' then
- Result := StringOfChar(' ', Count);
-// NEW LINE
-procedure TGLSCustomMemo.NewLine;
- S, sIndent: string;
- 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);
- FUndoList.Add(TGLSMemoInsCharUndo.Create(OldX, OldY, CurX, CurY, #13 +
- sIndent));
- Changed(CurY - 1, -1);
-// ADD STRING
-function TGLSCustomMemo.AddString(const S: string): integer;
- if Lines.Count = 0 then
- MovePage(1, [ssCtrl]); // end of text
- if not ((Lines.Count = 1) and (Lines[0] = '')) then
- CurY := Lines.Count;
- // S := #13#10 + S;
- SetSelText(S);
- Result := Lines.Count - 1;
-// INSERT STRING
-procedure TGLSCustomMemo.InsertString(Index: integer; S: string);
-// DO COMMAND
-procedure TGLSCustomMemo.DoCommand(cmd: TCommand; const AShift: TShiftState);
- case cmd of
- cmDelete: if not FReadOnly then
- if ssShift in AShift then
- CutToClipboard
- else if FDelErase and
- (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY))) then
- DeleteSelection(True)
- DeleteChar(-1, -1);
- 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:
- PasteFromClipboard;
- if ssCtrl in AShift then
- CopyToClipboard;
-// KEY DOWN
-procedure TGLSCustomMemo.KeyDown(var Key: Word; Shift: TShiftState);
- 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);
-// KEY PRESS
-procedure TGLSCustomMemo.KeyPress(var Key: Char);
- if (ord(Key) in [9, 32..255]) and (ord(Key) <> 127) then
- if FDelErase and (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY)))
- then
- InsertChar(Key);
- DoCommand(Ord(Key), []);
-// MOUSE DOWN
-procedure TGLSCustomMemo.MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer);
- newPos: TCellPos;
- charPos: TFullPos;
- if not Focused then
- // Exit;
- if FAfterDoubleClick then
- FAfterDoubleClick := False;
- if Button <>mbLeft then
- if sbVert.MouseDown(Button, Shift, X, Y) then
- if sbHorz.MouseDown(Button, Shift, X, Y) then
- if PointInRect(Point(X, Y), EditorRect) then
- newPos := CellFromPos(X, Y);
- CurY := newPos.Y + FTopLine;
- CurX := newPos.X + FLeftCol;
- Selecting := ssShift in Shift;
- if Button = mbLeft then
- FLeftButtonDown := True;
- if Assigned(FOnGutterClick) then
- if PointInRect(Point(X, Y), FGutter.FullRect) then
- charPos := CharFromPos(X, Y);
- if charPos.LineNo < Lines.Count then
- FOnGutterClick(Self, charPos.LineNo);
-// MOUSE MOVE
-procedure TGLSCustomMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
- if sbVert.MouseMove(Shift, X, Y) then
- if sbHorz.MouseMove(Shift, X, Y) then
- if (ssLeft in Shift) and FLeftButtonDown then
- ExpandSelection;
-// MOUSE UP
-procedure TGLSCustomMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:
- Integer);
- if sbVert.MouseUp(Button, Shift, X, Y) then
- if sbHorz.MouseUp(Button, Shift, X, Y) then
- FLeftButtonDown := False;
- FLastMouseUpX := X;
- FLastMouseUpY := Y;
-// DBL CLICK
-procedure TGLSCustomMemo.DblClick;
- clickPos: TCellPos;
- clickX, clickY: integer;
- // SELECT WORD
- procedure SelectWord;
- const
- stopChars: TSysCharSet = [' ', ';', '.', ',', ':', '?', '!', '''', '"',
- '<', '>', '/', '*', '+', '-', '=', '(', ')',
- '[', ']', '{', '}', '@', '#', '$', '%', '^',
- '&', '|', '\'];
- CurX := clickX;
- CurY := clickY;
- if (CurX = clickX) and (CurY = clickY) then
- s := Lines[clickY];
- if s[clickX + 1] = ' ' then
- i := clickX;
- while (i >= 0) and not CharInSet(s[i + 1], stopChars) do
- FSelStartY := clickY;
- FSelStartX := i + 1;
- while (i < Length(s)) and not CharInSet(s[i + 1], stopChars) do
- FSelEndY := clickY;
- FSelEndX := i;
- if FSelEndX <> FSelStartX then
- FAfterDoubleClick := True;
- rct := LineRangeRect(CurY, CurY);
- if PointInRect(Point(FLastMouseUpX, FLastMouseUpY), EditorRect) then
- clickPos := CellFromPos(FLastMouseUpX, FLastMouseUpY);
- clickX := clickPos.X + FLeftCol;
- clickY := clickPos.Y + FTopLine;
- SelectWord;
-// WM_GETDLGCODE
-procedure TGLSCustomMemo.WMGetDlgCode(var Msg: TWMGetDlgCode);
- Msg.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
-// WM_ERASEBKGND
-procedure TGLSCustomMemo.WMEraseBkgnd(var Msg: TWmEraseBkgnd);
- Msg.Result := 1;
-// WM_SIZE
-procedure TGLSCustomMemo.WMSize(var Msg: TWMSize);
- if not (csLoading in ComponentState) then
- ResizeEditor;
-// WM_SETCURSOR
-procedure TGLSCustomMemo.WMSetCursor(var Msg: TWMSetCursor);
- P: TPoint;
- GetCursorPos(P);
- P := ScreenToClient(P);
- if PointInRect(P, EditorRect) then
- Winapi.Windows.SetCursor(Screen.Cursors[crIBeam])
- Winapi.Windows.SetCursor(Screen.Cursors[crArrow]);
-// WM_SETFOCUS
-procedure TGLSCustomMemo.WMSetFocus(var Msg: TWMSetFocus);
- SetFont(FFont);
- CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
- ShowCaret(true);
-// WM_KILLFOCUS
-procedure TGLSCustomMemo.WMKillFocus(var Msg: TWMSetFocus);
- DestroyCaret;
- FCaretVisible := False;
-// SHOW CARET
-procedure TGLSCustomMemo.ShowCaret(State: Boolean);
- if not State then
- HideCaret(Handle)
- else if Focused and not HiddenCaret then
- rct := CellRect(CurX - FLeftCol, CurY - FTopLine);
- SetCaretPos(rct.Left, rct.Top + 1);
- Winapi.Windows.ShowCaret(Handle);
- FCaretVisible := True;
-// CELL RECT
-function TGLSCustomMemo.CellRect(ACol, ARow: integer): TRect;
- with FCellSize do
- Result := Rect(rct.Left + W * ACol, rct.Top + H * ARow,
- rct.Left + W * (ACol + 1), rct.Top + H * (ARow + 1));
-// LINE RECT
-function TGLSCustomMemo.LineRect(ARow: integer): TRect;
- ARow := ARow - FTopLine;
- Result := Rect(rct.Left, rct.Top + H * ARow, rct.Right, rct.Top + H * (ARow
- + 1));
-// COL RECT
-function TGLSCustomMemo.ColRect(ACol: integer): TRect;
- ACol := ACol - FLeftCol;
- Result := Rect(rct.Left + W * ACol, rct.Top, rct.Left + W * (ACol + 1),
- rct.Bottom);
-// LINE RANGE RECT
-function TGLSCustomMemo.LineRangeRect(FromLine, ToLine: integer): TRect;
- rct1, rct2: TRect;
- rct1 := LineRect(FromLine);
- rct2 := LineRect(ToLine);
- Result := TotalRect(rct1, rct2);
-// INVALIDATE LINE RANGE
-procedure TGLSCustomMemo.InvalidateLineRange(FromLine, ToLine: integer);
- rct := LineRangeRect(FromLine, ToLine);
- if GutterWidth > 2 then
- rct.Left := FGutter.Left;
-// COL RANGE RECT
-function TGLSCustomMemo.ColRangeRect(FromCol, ToCol: integer): TRect;
- rct1 := ColRect(FromCol);
- rct2 := ColRect(ToCol);
-// CELL and CHAR FROM POS
-function TGLSCustomMemo.CellFromPos(X, Y: integer): TCellPos;
- if (FCellSize.H = 0) and Assigned(FFont) then
- if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
- Result.X := (X - rct.Left) div FCellSize.W;
- Result.Y := (Y - rct.Top) div FCellSize.H;
- Result.X := 0;
- Result.Y := 0;
-function TGLSCustomMemo.CharFromPos(X, Y: integer): TFullPos;
- Result.Pos := (X - rct.Left) div FCellSize.W + FLeftCol;
- Result.LineNo := (Y - rct.Top) div FCellSize.H + FTopLine;
- Result.Pos := 1;
- Result.LineNo := 1;
-// SET COLOR
-procedure TGLSCustomMemo.SetColor(Index: integer; Value: TColor);
- Changed := False;
- case Index of
- 0: if FBkColor <> Value then
- FBkColor := Value;
- FStyles.BkColor[0] := Value;
- Changed := True;
- 1: if FSelColor <> Value then
- FSelColor := Value;
- 2: if FSelBkColor <> Value then
- FSelBkColor := Value;
- InvalidateRect(Handle, @eRect, True);
-// SET FONT
-procedure TGLSCustomMemo.SetFont(Value: TFont);
- wW, wi: integer;
- OldFontName: string;
- 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
- FStyles.TextColor[0] := FFont.Color;
- FStyles.Style[0] := FFont.Style;
-// SET GUTTER WIDTH
-procedure TGLSCustomMemo.SetGutterWidth(Value: integer);
- FGutterWidth := Value;
- FGutter.FWidth := Value;
-// SET GUTTER COLOR
-procedure TGLSCustomMemo.SetGutterColor(Value: TColor);
- if FGutter.FColor <> Value then
- FGutter.FColor := Value;
-// GET GUTTER COLOR
-function TGLSCustomMemo.GetGutterColor: TColor;
- Result := FGutter.FColor;
-// CHAR STYLE NO
-function TGLSCustomMemo.CharStyleNo(LineNo, Pos: integer): integer;
- ChStyle: string;
- if (LineNo < 0) or (LineNo >= Lines.Count) then
- ChStyle := CharAttrs[LineNo];
- if (Pos <= 0) or (Pos > Length(ChStyle)) then
- Result := integer(ChStyle[Pos]);
-// DRAW LINE
-procedure TGLSCustomMemo.DrawLine(LineNo: integer);
- eRect, rct0, rct1, rct, lineRct: TRect;
- LineSelStart, LineSelEnd, LineStyleNo, pos: integer;
- S, S1, S2, S3, ChStyle: string;
- //--------- FIND LINE SELECTION -------------
- procedure FindLineSelection;
- len := Length(Lines[LineNo]);
- LineSelStart := 0;
- LineSelEnd := 0;
- if xSelStartY = Lineno then
- LineSelStart := xSelStartX - FLeftCol;
- LineSelEnd := len - FLeftCol;
- else if (xSelStartY < LineNo) and (LineNo < xSelEndY) then
- if xSelEndY = LineNo then
- LineSelEnd := xSelEndX - FLeftCol;
- if LineSelEnd < LineSelStart then
- Swap(LineSelEnd, LineSelStart);
- if LineSelStart < 0 then
- 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);
- //------------- DRAW PART ---------------------
- procedure DrawPart(const Part: string; PartStyle, StartPos: integer;
- var rct: TRect; IsSelection: Boolean);
- len, w: integer;
- rctInternal: TRect;
- len := Length(Part);
- if len > 0 then
- with FLineBitmap.Canvas do
- w := FCellSize.W * len;
- Font.Style := FStyles.Style[PartStyle];
- if IsSelection then
- Font.Color := SelColor;
- Brush.Color := SelBkColor;
- if LineStyleNo = 0 then
- Font.Color := FStyles.TextColor[PartStyle];
- Brush.Color := FStyles.BkColor[PartStyle];
- if (LineNo = FSelCharPos.LineNo) and
- (StartPos = FSelCharPos.Pos + 1) and (Length(Part) = 1) then
- Font.Color := FStyles.TextColor[LineStyleNo];
- Brush.Color := FStyles.BkColor[LineStyleNo];
- Font.Style := FStyles.Style[LineStyleNo];
- 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;
- //------------- DRAW SEGMENTS ---------------------
- procedure DrawSegments(S: string; WorkPos: integer;
- i, len, ThisStyle: integer;
- if Len = 0 then
- ThisStyle := Ord(ChStyle[WorkPos]);
- while (i <= Len) and
- (ThisStyle = Ord(ChStyle[WorkPos + i - 1])) do
- DrawPart(Copy(S, 1, i - 1), ThisStyle, WorkPos, rct, IsSelection);
- Inc(WorkPos, i - 1);
- s := Copy(s, i, Len);
- //---------------------------------------------
- rct := CellRect(0, LineNo - FTopLine);
- rct0 := Rect(eRect.Left, rct.Top, eRect.Right, rct.Bottom);
- lineRct := rct0;
- if LineNo < Lines.Count then
- S := Lines[LineNo];
- LineStyleNo := LineStyle[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;
- FillRect(rct1);
- with LineRct do
- BitBlt(Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
- FLineBitmap.Canvas.Handle, 0, 0, SRCCOPY);
- with Canvas do
- Brush.Color := BkColor;
- FillRect(rct0);
-// SET HIDDEN CARET
-procedure TGLSCustomMemo.SetHiddenCaret(Value: Boolean);
- if Value <> FHiddenCaret then
- FHiddenCaret := Value;
- if Focused then
- if FHiddenCaret = FCaretVisible then
- ShowCaret(not FHiddenCaret);
-// BORDER
- 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));
- 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
- 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);
- Pen.Color := Colors[BorderType][4];
- LineTo(rct.Right - 1, rct.Bottom - 1);
- LineTo(rct.Right - 1, rct.Top);
-// EDITOR RECT
-function TGLSCustomMemo.EditorRect: TRect;
- l, t, r, b: integer;
- l := 2;
- r := Width - 2;
- t := 2;
- b := Height - 2;
- 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);
-// DRAW MARGIN
-procedure TGLSCustomMemo.DrawMargin;
- Pen.Color := clWhite;
- for i := 1 to FMargin do
- MoveTo(eRect.Left - i, eRect.Top);
- LineTo(eRect.Left - i, eRect.Bottom + 1);
-// DRAW GUTTER
-procedure TGLSCustomMemo.DrawGutter;
- if GutterWidth < 2 then
- ResizeGutter;
- FGutter.PaintTo(Canvas);
-// DRAW SCROLLBARS
-procedure TGLSCustomMemo.DrawScrollBars;
- sbVert.PaintTo(Canvas);
- sbHorz.PaintTo(Canvas);
- if FScrollBars = ssBoth then
- Brush.Color := clSilver;
- FillRect(Rect(sbVert.Left, sbHorz.Top + 1,
- sbVert.Left + sbVert.Width, sbHorz.Top + sbHorz.Height));
-// FRESH LINE BITMAP
-procedure TGLSCustomMemo.FreshLineBitmap;
- with FLineBitmap do
- Width := eRect.Right - eRect.Left;
- Height := FCellSize.H;
- FLineBitmap.Canvas.Font.Assign(Self.Canvas.Font);
-// PAINT
-procedure TGLSCustomMemo.Paint;
- pTop, pBottom: TFullPos;
- rct, eRect: TRect;
- clipRgn: HRGN;
- Attrs: string;
- if TGLSMemoStrings(Lines).FLockCount > 0 then
- FreshLineBitmap;
- Border(Canvas, Rect(0, 0, Width, Height), btLowered);
- DrawMargin;
- DrawGutter;
- DrawScrollBars;
- 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
- if not ValidAttrs[i] then
- FOnGetLineAttrs(Self, i, Attrs);
- CharAttrs[i] := Attrs;
- ValidAttrs[i] := True;
- for i := pTop.LineNo to pBottom.LineNo do
- DrawLine(i);
-// GET VISIBLE
-function TGLSCustomMemo.GetVisible(Index: integer): integer;
- Coord: TFullPos;
- Cell: TCellPos;
- Coord := CharFromPos(eRect.Right - 1, eRect.Bottom - 1);
- Cell := CellFromPos(eRect.Right - 1, eRect.Bottom - 1);
- 0: Result := Cell.X;
- 1: Result := Cell.Y;
- 2: Result := Coord.Pos - 1;
- 3: Result := Coord.LineNo - 1;
-// IS LINE VISIBLE
-function TGLSCustomMemo.IsLineVisible(LineNo: integer): Boolean;
- Result := (FTopLine <= LineNo) and (LineNo <= LastVisibleLine + 1);
-// MAKE VISIBLE
-procedure TGLSCustomMemo.MakeVisible;
- Modified: Boolean;
- Modified := False;
- FLeftCol := CurX - 2;
- Modified := True;
- if (FScrollBars in [ssBoth, ssHorizontal]) or
- (ScrollMode = smAuto) then
- FLeftCol := FLeftCol + CurX - LastVisiblePos + 2;
- FTopLine := CurY;
- if (FScrollBars in [ssBoth, ssVertical]) or
- FTopLine := FTopLine + CurY - LastVisibleLine;
- if Modified then
-// RESIZE EDITOR
-procedure TGLSCustomMemo.ResizeEditor;
-// FIND TEXT
-function TGLSCustomMemo.FindText(Text: string; Options: TFindOptions; Select:
- Boolean): Boolean;
- i, p: integer;
- s1, s0, s: string;
- //-----------------------------------------------------------
- function LastPos(const Substr, s: string): integer;
- i, j, lenSub: integer;
- lenSub := Length(Substr);
- i := Length(s) - lenSub + 1;
- while i > 0 do
- if s[i] = Substr[1] then
- Result := i;
- for j := i + 1 to i + lenSub - 1 do
- if s[j] <> Substr[j - i + 1] then
- if Result <> 0 then
- if not (frMatchCase in Options) then
- Text := AnsiLowerCase(Text);
- if SelLength > 0 then
- s := Lines[CurY];
- s0 := Copy(s, 1, CurX);
- s1 := Copy(s, CurX + 1, Length(s));
- i := CurY;
- s0 := AnsiLowerCase(s0);
- s1 := AnsiLowerCase(s1);
- if frDown in Options then
- p := Pos(Text, s1)
- p := LastPos(Text, s0);
- if p > 0 then
- CurY := i;
- CurX := Length(s0) + p - 1
- CurX := p - 1;
- if Select then
- if not (frDown in Options) then
- CurX := CurX + Length(Text);
- CurX := CurX + Length(Text)
- CurX := CurX - Length(Text);
- Inc(i)
- if (i < 0) or (i > Lines.Count - 1) then
- s0 := '';
- s1 := Lines[i];
- s0 := Lines[i];
- s1 := '';
-// RESIZE SCROLLBARS
-procedure TGLSCustomMemo.ResizeScrollBars;
- eRect, sbRect: TRect;
- MaxLen, OldMax, NewTop, Margin: integer;
- with sbVert do
- 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
- Dec(NewTop, LastVisibleLine - (Lines.Count - 1));
- if NewTop < 0 then
- NewTop := 0;
- MaxPosition := NewTop;
- if MaxPosition < 0 then
- MaxPosition := 0;
- Position := NewTop;
- Total := Lines.Count;
- if OldMax <> MaxPosition then
- if NewTop <> FTopLine then
- DoScroll(sbVert, NewTop - FTopLine);
- sbRect := sbVert.FullRect;
- MaxLen := MaxLength;
- with sbHorz do
- Width := Self.Width - 4;
- Width := Width - sbVert.Width;
- Height := 16;
- Left := 2;
- Top := eRect.Bottom;
- Margin := LastVisiblePos - MaxLen;
- if Margin < 2 then
- Margin := 2;
- MaxPosition := MaxLen - (LastVisiblePos - FLeftCol) + Margin;
- Position := FLeftCol;
- Total := MaxLen;
- if MaxPosition = 0 then
- ;
- sbRect := sbHorz.FullRect;
-// RESIZE GUTTER
-procedure TGLSCustomMemo.ResizeGutter;
- with FGutter do
- Height := eRect.Bottom - eRect.Top;
-// CREATE PARAMS
-procedure TGLSCustomMemo.CreateParams(var Params: TCreateParams);
-// UNDO, REDO
-procedure TGLSCustomMemo.Undo;
- FUndoList.Undo;
-procedure TGLSCustomMemo.Redo;
- FUndoList.Redo;
-// SET UNDO LIMIT
-procedure TGLSCustomMemo.SetUndoLimit(Value: integer);
- if (FUndoLimit <> Value) then
- if Value <= 0 then
- Value := 1;
- if Value > 100 then
- Value := 100;
- FUndoLimit := Value;
- FUndoList.Limit := Value;
-// UNDO (REDO) CHANGE
-procedure TGLSCustomMemo.UndoChange;
- if Assigned(FOnUndoChange) then
- FOnUndoChange(Self, FUndoList.Pos < FUndoList.Count,
- FUndoList.Pos > 0);
-// CAN UNDO
-function TGLSCustomMemo.CanUndo: boolean;
- Result := FUndoList.FPos < FUndoList.Count;
-// CAN REDO
-function TGLSCustomMemo.CanRedo: Boolean;
- Result := FUndoList.FPos > 0;
-// CLEAR UNDO LIST
-procedure TGLSCustomMemo.ClearUndoList;
- FUndoList.Clear;
-// SET SCROLL BARS
-procedure TGLSCustomMemo.SetScrollBars(Value: System.UITypes.TScrollStyle);
- if FScrollBars <> Value then
- FScrollBars := Value;
-// CREATE
-constructor TGLSCustomMemo.Create(AOwner: TComponent);
- 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;
- FCurX := 0;
- FCurY := 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;
- FLeft := 2;
- FTop := 2;
- FWidth := 0;
- FHeight := 0;
- FColor := clBtnFace;
- FMemo := Self;
- FSelEndX := 0;
- FSelEndY := 0;
- FBkColor := clWhite;
- FSelColor := clWhite;
- FSelBkColor := clNavy;
- FStyles := TStyleList.Create;
- FStyles.Add(clBlack, clWhite, []);
- FSelCharPos.LineNo := -1;
- FSelCharPos.Pos := -1;
- FLineBitmap := TBitmap.Create;
- FScrollMode := smAuto;
- FUndoList := TGLSMemoUndoList.Create;
- FFirstUndoList := FUndoList;
- FUndoList.Memo := Self;
- FUndoLimit := 100;
- TGLSMemoStrings(FLines).DoAdd('');
-// DESTROY
-destructor TGLSCustomMemo.Destroy;
- FFont.Free;
- FLines.Free;
- FGutter.Free;
- sbVert.Free;
- sbHorz.Free;
- FStyles.Free;
- FLineBitmap.Free;
- FFirstUndoList.Free;
-// ---------------------TGLSMemoScrollBar functions
-procedure TGLSMemoScrollBar.SetParams(Index: integer; Value: integer);
- 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;
-//-------------------- CREATE ------------------------------
-constructor TGLSMemoScrollBar.Create(AParent: TGLSMemoAbstractScrollableObject;
- FParent := AParent;
- FButtonLength := 16;
- FKind := AKind;
- FState := sbsWait;
-//-------------------- RECT -----------------------
-function TGLSMemoScrollBar.GetRect: TRect;
- Result := Rect(Left, Top, Left + Width, Top + Height);
-//-------------------- GET THUMB RECT -----------------------
-function TGLSMemoScrollBar.GetThumbRect: TRect;
- TotalLen, FreeLen, ThumbLen, ThumbOffset, ThumbCoord: integer;
- K: double;
- if MaxPosition <= 0 then
- Result := Rect(0, 0, 0, 0);
- if Kind = sbVertical then
- TotalLen := Height
- TotalLen := Width;
- FreeLen := TotalLen - 2 * FButtonLength;
- K := (Total - MaxPosition) / MaxPosition;
- if K > 0 then
- ThumbLen := round(FreeLen * K / (1 + K));
- if ThumbLen < 8 then
- ThumbLen := 8;
- if ThumbLen >= FreeLen then
- Result := Rect(0, 0, 0, 0)
- ThumbOffset := round((FreeLen - ThumbLen) * Position / MaxPosition);
- ThumbCoord := FButtonLength + ThumbOffset;
- Result := Rect(Left + 1, Top + ThumbCoord, Left + Width, Top + ThumbCoord
- + ThumbLen)
- Result := Rect(Left + ThumbCoord, Top + 1, Left + ThumbCoord + ThumbLen,
- Top + Height);
-//-------------------- GET Back RECT -----------------------
-function TGLSMemoScrollBar.GetBackRect: TRect;
- Result := Rect(Left + 1, Top, Left + Width, Top + FButtonLength)
- Result := Rect(Left, Top + 1, Left + FButtonLength, Top + Height);
-//-------------------- GET MIDDLE RECT -----------------------
-function TGLSMemoScrollBar.GetMiddleRect: TRect;
- bRect, fRect: TRect;
- bRect := BackRect;
- fRect := ForwardRect;
- Result := Rect(Left + 1, bRect.Bottom, Left + Width, fRect.Top)
- Result := Rect(bRect.Right, Top + 1, fRect.Left, Top + Height);
-//-------------------- GET Forward RECT -----------------------
-function TGLSMemoScrollBar.GetForwardRect: TRect;
- Result := Rect(Left + 1, Top + Height - FButtonLength, Left + Width, Top +
- Height)
- Result := Rect(Left + Width - FButtonLength, Top + 1, Left + Width, Top +
- Height);
-//-------------------- GET PAGE BACK RECT -----------------------
-function TGLSMemoScrollBar.GetPgBackRect: TRect;
- thRect: TRect;
- thRect := GetThumbRect;
- if thRect.Bottom = 0 then
- Result := Rect(Left + 1, Top + FButtonLength, Left + Width, thRect.Top - 1)
- Result := Rect(Left + FButtonLength, Top + 1, thRect.Left - 1, Top +
-//-------------------- GET PG FORWARD RECT -----------------------
-function TGLSMemoScrollBar.GetPgForwardRect: TRect;
- Result := Rect(Left + 1, thRect.Bottom, Left + Width, Top + Height -
- FButtonLength)
- Result := Rect(thRect.Right, Top + 1, Left + Width - FButtonLength, Top +
-//-------------------- PAINT TO -----------------------
-procedure TGLSMemoScrollBar.PaintTo(ACanvas: TCanvas);
- sRect, mRect, gRect, thRect: TRect;
- iconX, iconY, shift: integer;
- with ACanvas do
- Pen.Color := clSilver;
- MoveTo(Left, Top);
- LineTo(Left, Top + Height);
- sRect := BackRect;
- FillRect(sRect);
- if State = sbsBack then
- shift := 1;
- Pen.Color := clGray;
- with sRect do
- Rectangle(Left, Top, Right, Bottom);
- shift := 0;
- Border(ACanvas, sRect, btFlatRaised);
- iconX := sRect.Left + (Width - 1 - 7) div 2;
- iconY := sRect.Top + (FButtonLength - 8) div 2;
- Draw(iconX + shift, iconY + shift, bmScrollBarUp);
- gRect := ForwardRect;
- FillRect(gRect);
- if State = sbsForward then
- with gRect do
- Border(ACanvas, gRect, btFlatRaised);
- 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);
- LineTo(Left + Width, Top);
- iconX := sRect.Left + shift + (FButtonLength - 8) div 2;
- iconY := sRect.Top + shift + (Height - 1 - 7) div 2;
- Draw(iconX + shift, iconY + shift, bmScrollBarLeft);
- 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);
- Brush.Bitmap := bmScrollBarFill;
- FillRect(mRect);
- Brush.Bitmap := nil;
- if State = sbsPageBack then
- Brush.Color := clGray;
- FillRect(PageBackRect);
- if State = sbsPageForward then
- FillRect(PageForwardRect);
- thRect := ThumbRect;
- FillRect(thRect);
- Border(ACanvas, thRect, btFlatRaised);
-//-------------------- SET STATE ----------
-procedure TGLSMemoScrollBar.SetState(Value: TsbState);
- if FState <> Value then
- FState := Value;
-//-------------------- MOUSE DOWN ------------
-function TGLSMemoScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
- X,
- Y: Integer):
- Boolean;
- sRect, gRect, thRect, pbRect, pfRect: TRect;
- if (Width = 0) or (Height = 0) then
- pbRect := PageBackRect;
- pfRect := PageForwardRect;
- if PointInRect(Point(X, Y), sRect) then
- State := sbsBack;
- InvalidateRect(Parent.Handle, @sRect, True);
- if PointInRect(Point(X, Y), gRect) then
- State := sbsForward;
- InvalidateRect(Parent.Handle, @gRect, True);
- if PointInRect(Point(X, Y), pbRect) then
- State := sbsPageBack;
- InvalidateRect(Parent.Handle, @pbRect, True);
- if PointInRect(Point(X, Y), pfRect) then
- State := sbsPageForward;
- InvalidateRect(Parent.Handle, @pfRect, True);
- if PointInRect(Point(X, Y), thRect) then
- State := sbsDragging;
- FXOffset := X - thRect.Left;
- FYOffset := Y - thRect.Top;
-//-------------------- MOUSE UP ----------
-function TGLSMemoScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
- Y:
- Integer):
- case State of
- sbsBack:
- State := sbsWait;
- FParent.DoScroll(Self, -1);
- sbsForward:
- FParent.DoScroll(Self, 1);
- sbsPageBack:
- FParent.DoScrollPage(Self, -1);
- sbsPageForward:
- FParent.DoScrollPage(Self, 1);
- sbsDragging:
-//-------------------- MOUSE MOVE -----------
-function TGLSMemoScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer):
- if not PointInRect(Point(X, Y), sRect) then
- if not PointInRect(Point(X, Y), gRect) then
- if not PointInRect(Point(X, Y), pbRect) then
- if not PointInRect(Point(X, Y), pfRect) then
- MoveThumbTo(X, Y);
-//-------------------- MOVE THUMB TO ------------
-function TGLSMemoScrollBar.MoveThumbTo(X, Y: Integer): integer;
- thRect, mRect: TRect;
- FreeLen, ThumbLen, NewPosition, NewOffset: integer;
- mRect := MiddleRect;
- NewOffset := 0;
- FreeLen := 0;
- ThumbLen := 0;
- case Kind of
- FreeLen := mRect.Bottom - mRect.Top;
- ThumbLen := thRect.Bottom - thRect.Top;
- NewOffset := Y - FYOffset - (Top + FButtonLength);
- FreeLen := mRect.Right - mRect.Left;
- ThumbLen := thRect.Right - thRect.Left;
- NewOffset := X - FXOffset - (Left + FButtonLength);
- NewPosition := round(NewOffset * MaxPosition / (FreeLen - ThumbLen));
- Result := NewPosition - Position;
- if NewPosition <> Position then
- Parent.DoScroll(Self, NewPosition - Position);
-// GUTTER
-//-------------------- SET PARAMS -----------------------
-procedure TGLSMemoGutter.SetParams(Index: integer; Value: integer);
- 0: FLeft := Value;
- 1: FTop := Value;
- 2: FWidth := Value;
- 3: FHeight := Value;
-procedure TGLSMemoGutter.PaintTo(ACanvas: TCanvas);
- LineNo, T, H: integer;
- MoveTo(Left + Width - 1, Top);
- LineTo(Left + Width - 1, Top + Height);
- 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
- T := Top;
- H := FMemo.FCellSize.H;
- LineNo := FMemo.FTopLine;
- while T < Top + Height do
- FMemo.OnGutterDraw(FMemo, ACanvas, LineNo,
- Rect(Left, T, Left + Width - 2, T + H));
- T := T + H;
- Inc(LineNo);
- if LineNo >= FMemo.Lines.Count then
-//-------------------- INVALIDATE -----------------------
-procedure TGLSMemoGutter.Invalidate;
- gRect: TRect;
- gRect := Rect(Left, Top, Left + Width, Top + Height);
- InvalidateRect(FMemo.Handle, @gRect, True);
-//-------------------- GET RECT -----------------------
-function TGLSMemoGutter.GetRect: TRect;
-// ---------------------TStyleList
-procedure TStyleList.CheckRange(Index: integer);
- if (Index < 0) or (Index >= Count) then
- raise EListError.Create('Incorrect list item index ' + IntToStr(Index));
-//-------------------- DESTROY ---------------------------
-destructor TStyleList.Destroy;
- Clear;
-//-------------------- CHANGE ---------------------------
-procedure TStyleList.Change(Index: integer; ATextColor, ABkCOlor: TColor;
- AStyle: TFontStyles);
- P: TCharStyle;
- CheckRange(Index);
- P := TCharStyle(Items[Index]);
- P.TextColor := ATextColor;
- P.BkColor := ABkColor;
- P.Style := AStyle;
-//-------------------- ADD ---------------------------
-function TStyleList.Add(ATextColor, ABkColor: TColor; AStyle: TFontStyles):
- Integer;
- P := TCharStyle.Create;
- with P do
- TextColor := ATextColor;
- BkColor := ABkColor;
- Style := AStyle;
- Result := inherited Add(P);
-//-------------------- CLEAR ---------------------------
-procedure TStyleList.Clear;
- while Count > 0 do
- Delete(0);
-//-------------------- DELETE ---------------------------
-procedure TStyleList.Delete(Index: Integer);
- P.Free;
-//-------------------- GET/SET TEXT COLOR ---------------------------
-function TStyleList.GetTextColor(Index: Integer): TColor;
- Result := TCharStyle(Items[Index]).TextColor;
-procedure TStyleList.SetTextColor(Index: Integer; Value: TColor);
- TCharStyle(Items[Index]).TextColor := Value;
-//-------------------- GET/SET BK COLOR ---------------------------
-function TStyleList.GetBkColor(Index: Integer): TColor;
- Result := TCharStyle(Items[Index]).BkColor;
-procedure TStyleList.SetBkColor(Index: Integer; Value: TColor);
- TCharStyle(Items[Index]).BkColor := Value;
-//-------------------- GET/SET STYLE ---------------------------
-function TStyleList.GetStyle(Index: Integer): TFontStyles;
- Result := TCharStyle(Items[Index]).Style;
-procedure TStyleList.SetStyle(Index: Integer; Value: TFontStyles);
- TCharStyle(Items[Index]).Style := Value;
-// ---------------------TGLSMemoStrings
-destructor TGLSMemoStrings.Destroy;
- P: TObject;
- P := inherited GetObject(0);
- inherited Delete(0);
-//-------------------- CLEAR ----------------------
-procedure TGLSMemoStrings.Clear;
- if (Count = 1) and (Strings[0] = '') then
-//-------------------- ASSIGN ----------------------
-procedure TGLSMemoStrings.Assign(Source: TPersistent);
- if Source is TStrings then
- BeginUpdate;
- // inherited Clear;
- AddStrings(TStrings(Source));
- EndUpdate;
- inherited Assign(Source);
-//-------------------- ADD ----------------------
-function TGLSMemoStrings.DoAdd(const S: string): Integer;
- Result := inherited AddObject(S, nil);
-function TGLSMemoStrings.Add(const S: string): Integer;
- if Assigned(FMemo.Parent) then
- Result := FMemo.AddString(S)
- Result := DoAdd(S);
-//-------------------- OBJECT ----------------------
-function TGLSMemoStrings.AddObject(const S: string; AObject: TObject): Integer;
- if AObject <> nil then
- raise EInvalidOp.Create(SObjectsNotSupported);
-//-------------------- INSERT ----------------------
-procedure TGLSMemoStrings.InsertObject(Index: Integer;
- const S: string; AObject: TObject);
- DoInsert(Index, S);
-//-------------------- DO INSERT ----------------------
-procedure TGLSMemoStrings.DoInsert(Index: Integer; const S: string);
- InsertItem(Index, S, nil);
-procedure TGLSMemoStrings.Insert(Index: Integer; const S: string);
- if Assigned(FMemo) then
- FMemo.InsertString(Index, S)
-//-------------------- DELETE ----------------------
-procedure TGLSMemoStrings.Delete(Index: Integer);
- if (Index < 0) or (Index > Count - 1) then
- if FDeleting or (not Assigned(FMemo)) then
- P := inherited GetObject(Index);
- FMemo.DeleteLine(Index, -1, -1, -1, -1, True);
-//-------------------- LOAD FROM FILE ----------------------
-procedure TGLSMemoStrings.LoadFromFile(const FileName: string);
- with FMemo do
- FMemo.Invalidate;
-//-------------------- SET UPDATE STATE ----------------------
-procedure TGLSMemoStrings.SetUpdateState(Updating: Boolean);
- if Updating then
- Inc(FLockCount)
- else if FLockCount > 0 then
- Dec(FLockCount);
-//-------------------- CHECK RANGE ---------------------------
-procedure TGLSMemoStrings.CheckRange(Index: integer);
- raise EListError('Incorrect index of list item ' + IntToStr(Index));
-//-------------------- GET OBJECT ---------------------------
-function TGLSMemoStrings.GetObject(Index: Integer): TObject;
- Result := inherited GetObject(Index);
- if Assigned(Result) and (Result is TLineProp) then
- Result := TLineProp(Result).FObject;
-//-------------------- PUT OBJECT ---------------------------
-procedure TGLSMemoStrings.PutObject(Index: Integer; AObject: TObject);
- P := Objects[Index];
- if Assigned(P) and (P is TLineProp) then
- TLineProp(P).FObject := AObject
- inherited PutObject(Index, AObject);
-//-------------------- GET LINE PROP ---------------------------
-function TGLSMemoStrings.GetLineProp(Index: integer): TLineProp;
- Result := nil;
- Result := TLineProp(P);
-//-------------------- CREATE PROP --------------------------
-function TGLSMemoStrings.CreateProp(Index: integer): TLineProp;
- Result := TLineProp.Create;
- FStyleNo := 0;
- FInComment := False;
- FInBrackets := -1;
- FValidAttrs := False;
- FCharAttrs := '';
- FObject := Objects[Index];
- inherited PutObject(Index, Result);
-//-------------------- GET LINE STYLE --------------------------
-function TGLSMemoStrings.GetLineStyle(Index: integer): integer;
- P: TLineProp;
- P := LineProp[Index];
- if P = nil then
- Result := 0
- Result := P.FStyleNo;
-//-------------------- SET LINE STYLE --------------------------
-procedure TGLSMemoStrings.SetLineStyle(Index: integer; Value: integer);
- P := CreateProp(Index);
- P.FStyleNo := Value;
-//-------------------- GET/SET IN COMMENT ---------------------------
-function TGLSMemoStrings.GetInComment(Index: Integer): Boolean;
- Result := False
- Result := P.FInComment;
-procedure TGLSMemoStrings.SetInComment(Index: Integer; Value: Boolean);
- P.FInComment := Value;
-//-------------------- GET/SET IN BRACKETS ---------------------------
-function TGLSMemoStrings.GetInBrackets(Index: Integer): integer;
- Result := -1
- Result := P.FInBrackets;
-procedure TGLSMemoStrings.SetInBrackets(Index: Integer; Value: integer);
- P.FInBrackets := Value;
-//-------------------- GET/SET VALID ATTRS ---------------------------
-function TGLSMemoStrings.GetValidAttrs(Index: Integer): Boolean;
- Result := P.FValidAttrs;
-procedure TGLSMemoStrings.SetValidAttrs(Index: Integer; Value: Boolean);
- P.FValidAttrs := Value;
-//-------------------- GET/SET CHAR ATTRS ---------------------------
-function TGLSMemoStrings.GetCharAttrs(Index: Integer): string;
- Result := ''
- Result := P.FCharAttrs;
-procedure TGLSMemoStrings.SetCharAttrs(Index: Integer; const Value: string);
- P.FCharAttrs := Value;
-// ---------------------TGLSMemoUndo
-constructor TGLSMemoUndo.Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
- FUndoCurX0 := ACurX0;
- FUndoCurY0 := ACurY0;
- FUndoCurX := ACurX;
- FUndoCurY := ACurY;
- FUndoText := AText;
-procedure TGLSMemoUndo.Undo;
- CurY := FUndoCurY;
- CurX := FUndoCurX;
- PerformUndo;
- CurY := FUndoCurY0;
- CurX := FUndoCurX0;
-procedure TGLSMemoUndo.Redo;
- PerformRedo;
-function TGLSMemoUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
-//---------------- TINSERT CHAR UNDO --------------------------
-procedure TGLSMemoInsCharUndo.PerformUndo;
- CurrLine: string;
- for i := Length(FUndoText) downto 1 do
- CurrLine := FMemo.Lines[FMemo.CurY];
- if ((FUndoText[i] = #13) and (FMemo.CurX = 0)) or
- (FUndoText[i] = CurrLine[FMemo.CurX]) then
- FMemo.BackSpace;
-procedure TGLSMemoInsCharUndo.PerformRedo;
- for i := 1 to Length(FUndoText) do
- if FUndoText[i] = #13 then
- NewLine
- InsertChar(FUndoText[i]);
-function TGLSMemoInsCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
- if not ((NewUndo is TGLSMemoInsCharUndo) and
- (NewUndo.UndoCurX0 = FUndoCurX) and
- (NewUndo.UndoCurY0 = FUndoCurY)) then
- FUndoText := FUndoText + NewUndo.FUndoText;
- FUndoCurX := NewUndo.UndoCurX;
- FUndoCurY := NewUndo.UndoCurY;
-//---------------- TDELETE CHAR UNDO --------------------------
-procedure TGLSMemoDelCharUndo.PerformUndo;
- if not FIsBackspace then
-procedure TGLSMemoDelCharUndo.PerformRedo;
- if FIsBackspace then
- BackSpace
-function TGLSMemoDelCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
- if not ((NewUndo is TGLSMemoDelCharUndo) and
- if TGLSMemoDelCharUndo(NewUndo).FIsBackspace <> FIsBackspace then
- FUndoText := NewUndo.FUndoText + FUndoText;
-//---------------- TDELETE BUF, LINE UNDO --------------------------
-constructor TGLSMemoDelLineUndo.Create(AIndex, ACurX0, ACurY0, ACurX, ACurY:
- integer; const AText: string);
- inherited Create(ACurX0, ACurY0, ACurX, ACurY, AText);
- FIndex := AIndex;
-procedure TGLSMemoDelLineUndo.PerformUndo;
- SaveCurX: integer;
- SaveCurX := CurX;
- SetSelText(PChar(FUndoText + #13#10));
- CurX := SaveCurX;
-procedure TGLSMemoDelLineUndo.PerformRedo;
- FMemo.DeleteLine(FIndex, FUndoCurX0, FUndoCurY0, FUndoCurX, FUndoCurY, True);
-procedure TGLSMemoDeleteBufUndo.PerformUndo;
- SetSelText(PChar(FUndoText));
-procedure TGLSMemoDeleteBufUndo.PerformRedo;
- FSelStartX := FUndoSelStartX;
- FSelStartY := FUndoSelStartY;
- FSelEndX := FUndoSelEndX;
- FSelEndY := FUndoSelEndY;
-//---------------- TPASTE UNDO --------------------------
-procedure TGLSMemoPasteUndo.PerformUndo;
- FSelStartX := FUndoCurX0;
- FSelStartY := FUndoCurY0;
- FSelEndX := FUndoCurX;
- FSelEndY := FUndoCurY;
-procedure TGLSMemoPasteUndo.PerformRedo;
-//---------------- TUNDO LIST --------------------------
-constructor TGLSMemoUndoList.Create;
- FPos := 0;
- FIsPerforming := False;
- FLimit := 100;
-destructor TGLSMemoUndoList.Destroy;
-function TGLSMemoUndoList.Get(Index: Integer): TGLSMemoUndo;
- Result := TGLSMemoUndo(inherited Get(Index));
-function TGLSMemoUndoList.Add(Item: Pointer): Integer;
- Result := -1;
- if FIsPerforming then
- TGLSMemoUndo(Item).Free;
- if (Count > 0) and
- Items[0].Append(TGLSMemoUndo(Item)) then
- TGLSMemoUndo(Item).FMemo := Self.FMemo;
- if FPos > 0 then
- while FPos > 0 do
- Dec(FPos);
- Insert(0, Item);
- if Count > FLimit then
- Delete(Count - 1);
- Memo.UndoChange;
-procedure TGLSMemoUndoList.Clear;
- with Memo do
- if not (csDestroying in ComponentState) then
- UndoChange;
-procedure TGLSMemoUndoList.Delete(Index: Integer);
- TGLSMemoUndo(Items[Index]).Free;
-procedure TGLSMemoUndoList.Undo;
- OldAutoIndent: Boolean;
- if FPos < Count then
- OldAutoIndent := Memo.AutoIndent;
- Memo.AutoIndent := False;
- FIsPerforming := True;
- Items[FPos].Undo;
- Inc(FPos);
- Memo.AutoIndent := OldAutoIndent;
-procedure TGLSMemoUndoList.Redo;
- Items[FPos].Redo;
-procedure TGLSMemoUndoList.SetLimit(Value: integer);
- if FLimit <> Value then
- Value := 10;
- if Value > 0 then
- FLimit := Value;
-procedure TGLSSynHiMemo.Paint;
- FIsPainting := True;
- DelimiterStyle := FDelimiterStyle;
- CommentStyle := FCommentStyle;
- NumberStyle := FNumberStyle;
- FIsPainting := False;
-// ---------------------TGLSSynHiMemo
-procedure TGLSSynHiMemo.SetStyle(Index: integer; Value: TCharStyle);
- No: integer;
- No := -1;
- 0: No := FDelimiterStyleNo;
- 1: No := FCommentStyleNo;
- 2: No := FNumberStyleNo;
- with Value do
- Styles.Change(No, TextColor, BkColor, Style);
- if not FIsPainting then
-// SYNTAX MEMO - SET WORD LIST
-procedure TGLSSynHiMemo.SetWordList(Value: TGLSMemoStringList);
- FWordList.Assign(Value);
-procedure TGLSSynHiMemo.SetSpecialList(Value: TGLSMemoStringList);
- FSpecialList.Assign(Value);
-procedure TGLSSynHiMemo.SetBracketList(Value: TGLSMemoStringList);
- FBracketList.Assign(Value);
-// SYNTAX MEMO - SET CASE SENSITIVE
-procedure TGLSSynHiMemo.SetCaseSensitive(Value: Boolean);
- LineNo: integer;
- if Value <> FCaseSensitive then
- FCaseSensitive := Value;
- for LineNo := 0 to Lines.Count - 1 do
-// SYNTAX MEMO - GET TOKEN
-function TGLSSynHiMemo.GetToken(const S: string; var From: integer;
- 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;
- Result := (StrLComp(PChar(S) + Pos - 1, PChar(S0), Length(S0)) = 0);
- function Equal(const s1, s2: string): Boolean;
- if FCaseSensitive then
- Result := s1 = s2
- Result := AnsiLowerCase(s1) = AnsiLowerCase(s2);
- toStart := From;
- toEnd := From;
- TokenType := ttOther;
- StyleNo := 0;
- // End of line
- if From > Len then
- From := -1;
- TokenType := ttEOL;
- // Begin of multiline comment
- if (MultiCommentLeft <> '') and (MultiCommentRight <> '') and
- StartsFrom(S, From, MultiCommentLeft) then
- Result := MultiCommentLeft;
- FInComment := True;
- TokenType := ttComment;
- StyleNo := FCommentStyleNo;
- Inc(From, Length(MultiCommentLeft));
- // Inside multiline comment
- if FInComment then
- toEnd := toStart;
- while (toEnd <= Len) and (not StartsFrom(S, toEnd, MultiCommentRight)) do
- Inc(toEnd);
- if toEnd > Len then
- Result := Copy(S, From, toEnd - From);
- From := toEnd;
- toEnd := toEnd + Length(MultiCommentRight);
- // Inside brikets
- if FInBrackets >= 0 then
- Brackets := FBracketList[FInBrackets];
- toEnd := toStart + 1;
- while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
- StyleNo := integer(FBracketList.Objects[FInBrackets]);
- if toEnd <= Len then
- From := toEnd + 1;
- Result := Copy(S, toStart, toEnd - toStart + 1);
- TokenType := ttBracket;
- // Spaces
- while (toStart <= Len) and (S[toStart] = ' ') do
- Inc(toStart);
- if toStart > From then
- Result := Copy(S, From, toStart - From);
- From := toStart;
- TokenType := ttSpace;
- // Comment
- if (FLineComment <> '') and StartsFrom(S, From, FLineComment) then
- Result := Copy(S, From, Len);
- From := Len + 1;
- // Special keyword
- Done := False;
- for i := 0 to FSpecialList.Count - 1 do
- LenSpec := Length(FSpecialList[i]);
- if StrLComp(PChar(S) + toStart - 1,
- PChar(FSpecialList[i]), LenSpec) = 0 then
- toEnd := toStart + LenSpec - 1;
- StyleNo := integer(FSpecialList.Objects[i]);
- TokenType := ttSpecial;
- Done := True;
- // Brickets
- if not Done then
- for i := 0 to FBracketList.Count - 1 do
- Brackets := FBracketList[i];
- if S[toStart] = Brackets[1] then
- FInBrackets := i;
- FInBrackets := -1
- Dec(toEnd);
- StyleNo := integer(FBracketList.Objects[i]);
- // Delimeters
- if not Done and CharInSet(S[toStart], Delimiters) then
- StyleNo := FDelimiterStyleNo;
- TokenType := ttDelimiter;
- // --- Integer or float type
- if not Done and CharInSet(S[toStart], ['0'..'9', '.']) then
- IntPart := 0;
- WasPoint := False;
- TokenType := ttInteger;
- StyleNo := FNumberStyleNo;
- while (toEnd <= Len) and CharInSet(S[toEnd], ['0'..'9', '.']) do
- if S[toEnd] = '.' then
- if not WasPoint then
- WasPoint := True;
- TokenType := ttFloat;
- TokenType := ttWrongNumber;
- Color := clRed;
- else if not WasPoint then
- IntPart := IntPart * 10 + Ord(S[toEnd]) - Ord('0');
- IntPart := MaxInt;
- // Select word
- while (toEnd <= Len) and not CharInSet(S[toEnd], Delimiters) do
- // Find in dictionary
- for i := 0 to FWordList.Count - 1 do
- if Equal(Result, FWordList[i]) then
- StyleNo := integer(FWordList.Objects[i]);
- TokenType := ttWord;
-// SYNTAX MEMO - FIND LINE ATTRS
-procedure TGLSSynHiMemo.FindLineAttrs(Sender: TObject; LineNo: integer;
- var Attrs: string);
- i, From, TokenLen: integer;
- S, Token: string;
- TokenType: TTokenType;
- StyleNo, OldInBrackets: integer;
- OldInComment: Boolean;
- SetLength(Attrs, Length(S));
- FInComment := InComment[LineNo];
- FInBrackets := InBrackets[LineNo];
- From := 1;
- Token := GetToken(S, From, TokenType, StyleNo);
- if TokenType = ttEOL then
- TokenLen := Length(Token);
- for i := From - TokenLen to From - 1 do
- Attrs[i] := Char(StyleNo);
- if LineNo < Lines.Count - 1 then
- OldInComment := InComment[LineNo + 1];
- OldInBrackets := InBrackets[LineNo + 1];
- if OldInComment <> FInComment then
- InComment[LineNo + 1] := FInComment;
- ValidAttrs[LineNo + 1] := False;
- if OldInBrackets <> FInBrackets then
- InBrackets[LineNo + 1] := FInBrackets;
-// SYNTAX MEMO - ADD WORD
-procedure TGLSSynHiMemo.AddWord(StyleNo: integer; const ArrS: array of string);
- for i := Low(ArrS) to high(ArrS) do
- FWordList.AddObject(ArrS[i], TObject(StyleNo));
-// SYNTAX MEMO - ADD SPECIAL
-procedure TGLSSynHiMemo.AddSpecial(StyleNo: integer; const ArrS: array of string);
- FSpecialList.AddObject(ArrS[i], TObject(StyleNo));
-// SYNTAX MEMO - ADD BRACKETS
-procedure TGLSSynHiMemo.AddBrackets(StyleNo: integer; const ArrS: array of string);
- FBracketList.AddObject(ArrS[i], TObject(StyleNo));
-// SYNTAX MEMO - CREATE
-constructor TGLSSynHiMemo.Create(AOwner: TComponent);
- FWordList := TGLSMemoStringList.Create;
- FSpecialList := TGLSMemoStringList.Create;
- FBracketList := TGLSMemoStringList.Create;
- FDelimiterStyle := TCharStyle.Create;
- with FDelimiterStyle do
- TextColor := clBlue;
- BkColor := clWhite;
- Style := [];
- FCommentStyle := TCharStyle.Create;
- with FCommentStyle do
- TextColor := clYellow;
- BkColor := clSkyBlue;
- Style := [fsItalic];
- FNumberStyle := TCharStyle.Create;
- with FNumberStyle do
- TextColor := clNavy;
- Style := [fsBold];
- FDelimiterStyleNo := Styles.Add(clBlue, clWhite, []);
- FCommentStyleNo := Styles.Add(clSilver, clWhite, [fsItalic]);
- FNumberStyleNo := Styles.Add(clNavy, clWhite, [fsBold]);
- OnGetLineAttrs := FindLineAttrs;
- Delimiters := [' ', ',', ';', ':', '.', '(', ')', '{', '}', '[', ']',
- '=', '+', '-', '*', '/', '^', '%', '<', '>',
- '"', '''', #13, #10];
-// SYNTAX MEMO - DESTROY
-destructor TGLSSynHiMemo.Destroy;
- FWordList.Free;
- FSpecialList.Free;
- FBracketList.Free;
- FDelimiterStyle.Free;
- FCommentStyle.Free;
- FNumberStyle.Free;
-// ---------------------TGLSMemoStringList
-procedure TGLSMemoStringList.ReadStrings(Reader: TReader);
- i: Integer;
- Reader.ReadListBegin;
- while not Reader.EndOfList do
- i := Add(Reader.ReadString);
- Objects[i] := TObject(Reader.ReadInteger);
- Reader.ReadListEnd;
-// STRING LIST - WRITE STRINGS
-procedure TGLSMemoStringList.WriteStrings(Writer: TWriter);
- with Writer do
- WriteListBegin;
- for i := 0 to Count - 1 do
- WriteString(Strings[i]);
- WriteInteger(Integer(Objects[i]));
- WriteListEnd;
-// STRING LIST - DEFINE PROPERTIES
-procedure TGLSMemoStringList.DefineProperties(Filer: TFiler);
- Filer.DefineProperty('Strings', ReadStrings, WriteStrings, Count > 0);
-// ---------------------ScrollBar bitmaps
-procedure CreateScrollBarBitmaps;
- i, j: integer;
- bmScrollBarFill := TBitmap.Create;
- with bmScrollBarFill, Canvas do
- 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;
- bmScrollBarUp := TBitmap.Create;
- with bmScrollBarUp, Canvas do
- Width := 7;
- 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);
- bmScrollBarDown := TBitmap.Create;
- with bmScrollBarDown, Canvas do
- MoveTo(0, 2);
- LineTo(7, 2);
- MoveTo(1, 3);
- LineTo(6, 3);
- MoveTo(2, 4);
- LineTo(5, 4);
- Pixels[3, 5] := clBlack;
- bmScrollBarLeft := TBitmap.Create;
- with bmScrollBarLeft, Canvas do
- Height := 7;
- Pixels[2, 3] := clBlack;
- MoveTo(3, 2);
- LineTo(3, 5);
- MoveTo(4, 1);
- LineTo(4, 6);
- MoveTo(5, 0);
- LineTo(5, 7);
- bmScrollBarRight := TBitmap.Create;
- with bmScrollBarRight, Canvas do
- MoveTo(2, 0);
- LineTo(2, 7);
- MoveTo(3, 1);
- LineTo(3, 6);
- MoveTo(4, 2);
- LineTo(4, 5);
- Pixels[5, 3] := clBlack;
-//------------------ FREE SCROLL BAR BITMAPs -------------------
-procedure FreeScrollBarBitmaps;
- bmScrollBarFill.Free;
- bmScrollBarUp.Free;
- bmScrollBarDown.Free;
- bmScrollBarLeft.Free;
- bmScrollBarRight.Free;
- RegisterClasses([TGLSSynHiMemo]);
- CreateScrollBarBitmaps;
- IntelliMouseInit;
-finalization
- FreeScrollBarBitmaps;
+unit GLS.Memo;
+(* Memo for GLScene *)
+ WinApi.Windows,
+ WinApi.Messages,
+ System.UITypes,
+ VCL.Graphics,
+ VCL.Controls,
+ VCL.Forms,
+ VCL.Dialogs,
+ VCL.ClipBrd,
+ VCL.StdCtrls,
+ VCL.ExtCtrls;
+ TBorderType = (btRaised, btLowered, btFlatRaised, btFlatLowered);
+ TCommand = Integer;
+ TCellSize = record
+ W, H: integer;
+ TCellPos = record
+ X, Y: integer;
+ TFullPos = record
+ LineNo, Pos: integer;
+ TLineProp = class
+ FObject: TObject;
+ FStyleNo: integer;
+ FInComment: Boolean;
+ FInBrackets: integer;
+ FValidAttrs: Boolean;
+ FCharAttrs: string;
+ TCharStyle = class(TPersistent)
+ 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;
+ TStyleList = class(TList)
+ 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);
+ 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;
+ procedure Clear; override;
+ procedure Delete(Index: Integer);
+ function Add(ATextColor, ABkCOlor: TColor; AStyle: TFontStyles): Integer;
+ procedure Change(Index: integer; ATextColor, ABkColor: TColor; AStyle:
+ TFontStyles);
+ TGLAbstractMemoObject = class(TObject)
+ function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
+ Boolean; virtual; abstract;
+ function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer):
+ function MouseMove(Shift: TShiftState; X, Y: Integer):
+ TGLSMemoScrollBar = class;
+ TGLSMemoAbstractScrollableObject = class(TCustomControl)
+ procedure DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
+ virtual; abstract;
+ procedure DoScrollPage(Sender: TGLSMemoScrollBar; ByValue: integer);
+ TGLSCustomMemo = class;
+ TsbState =
+ (
+ sbsWait,
+ sbsBack,
+ sbsForward,
+ sbsPageBack,
+ sbsPageForward,
+ sbsDragging
+ );
+ TGLSMemoScrollBar = class(TGLAbstractMemoObject)
+ 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;
+ constructor Create(AParent: TGLSMemoAbstractScrollableObject;
+ AKind: TScrollBarKind);
+ procedure PaintTo(ACanvas: TCanvas);
+ 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;
+ TGLSMemoStrings = class(TStringList)
+ FMemo: TGLSCustomMemo;
+ FLockCount: integer;
+ FDeleting: Boolean;
+ 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);
+ 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;
+ 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;
+ TGLSMemoGutter = class(TObject)
+ FColor: TColor;
+ procedure Invalidate;
+ TGLSMemoUndo = class
+ FUndoCurX0, FUndoCurY0: integer;
+ FUndoCurX, FUndoCurY: integer;
+ FUndoText: string;
+ 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;
+ TGLSMemoInsCharUndo = class(TGLSMemoUndo)
+ function Append(NewUndo: TGLSMemoUndo): Boolean; override;
+ procedure PerformUndo; override;
+ procedure PerformRedo; override;
+ TGLSMemoDelCharUndo = class(TGLSMemoUndo)
+ FIsBackspace: Boolean;
+ property IsBackspace: Boolean read FIsBackspace write FIsBackspace;
+ TGLSMEmoDelLineUndo = class(TGLSMemoUndo)
+ FIndex: integer;
+ constructor Create(AIndex, ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
+ string);
+ TGLSMemoSelUndo = class(TGLSMemoUndo)
+ FUndoSelStartX, FUndoSelStartY,
+ FUndoSelEndX, FUndoSelEndY: integer;
+ 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;
+ TGLSMemoDeleteBufUndo = class(TGLSMemoSelUndo)
+ TGLSMemoPasteUndo = class(TGLSMemoUndo)
+ TGLSMemoUndoList = class(TList)
+ FPos: integer;
+ FIsPerforming: Boolean;
+ FLimit: integer;
+ function Get(Index: Integer): TGLSMemoUndo;
+ procedure SetLimit(Value: integer);
+ constructor Create;
+ function Add(Item: Pointer): Integer;
+ 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;
+ //--------------------------------------------------------------
+ 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)
+ 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);
+ function GetInComment(Index: integer): Boolean;
+ procedure SetInComment(Index: integer; Value: Boolean);
+ 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);
+ 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;
+ constructor Create(AOwner: TComponent); 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;
+ 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
+ property Styles: TStyleList read FStyles;
+ property UndoList: TGLSMemoUndoList read FUndoList write FUndoList;
+ TGLSMemo = class(TGLSCustomMemo)
+ {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;
+ TGLSMemoStringList = class(TStringList)
+ procedure ReadStrings(Reader: TReader);
+ procedure WriteStrings(Writer: TWriter);
+ procedure DefineProperties(Filer: TFiler); override;
+ TDelimiters = TSysCharSet;
+ TTokenType =
+ ttWord,
+ ttBracket,
+ ttSpecial,
+ ttDelimiter,
+ ttSpace,
+ ttEOL,
+ ttInteger,
+ ttFloat,
+ ttComment,
+ ttOther,
+ ttWrongNumber);
+ // SYNTAX MEMO - declaration
+ TGLSSynHiMemo = class(TGLSCustomMemo)
+ FIsPainting: Boolean;
+ FWordList: TGLSMemoStringList;
+ FSpecialList: TGLSMemoStringList;
+ FBracketList: TGLSMemoStringList;
+ FDelimiters: TDelimiters;
+ 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:
+ procedure SetStyle(Index: integer; Value: TCharStyle);
+ procedure SetCaseSensitive(Value: Boolean);
+ 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;
+ {TControl}
+ {TCustomControl}
+ {TGLSCustomMemo}
+ {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;
+procedure Border(Canvas: TCanvas; const rct: TRect; BorderType: TBorderType);
+//==========================================================
+ 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';
+ 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;
+ with rct do
+ Result := (Left <= P.X) and (Top <= P.Y) and
+ (Right >= P.X) and (Bottom >= P.Y);
+procedure Swap(var I1, I2: integer); inline;
+ temp: integer;
+ temp := I1;
+ I1 := I2;
+ I2 := temp;
+procedure OrderPos(var StartX, StartY, EndX, EndY: integer); inline;
+ if (EndY < StartY) or
+ ((EndY = StartY) and (EndX < StartX)) then
+ Swap(StartX, EndX);
+ Swap(StartY, EndY);
+function TotalRect(const rct1, rct2: TRect): TRect; inline;
+ Result := rct1;
+ with Result do
+ 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;
+// ---------------------TGLSCustomMemo functions
+procedure TGLSCustomMemo.WndProc(var Message: TMessage);
+ function GetShiftState: Integer;
+ 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;
+ //---------------------------------------------------
+ if (Message.Msg = fIntelliMessage) and (fIntelliMessage <> wm_MouseWheel) then
+ PostMessage(Handle, wm_MouseWheel, MakeLong(GetShiftState, Message.wParam),
+ Message.lParam);
+ inherited;
+//------------------------------------------------
+// INTELLIMOUSE INIT
+procedure IntelliMouseInit;
+ hWndMouse: hWnd;
+ mQueryScrollLines: UINT;
+ //--------------------------------------------
+ function NativeMouseWheelSupport: Boolean;
+ ver: TOSVersionInfo;
+ 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;
+ { Quick and dirty temporary hack for Windows 98 beta 3 }
+ if (not Result) and (ver.szCSDVersion = ' Beta 3') then
+ if NativeMouseWheelSupport then
+ fIntelliWheelSupport := Boolean(GetSystemMetrics(sm_MouseWheelPresent));
+ SystemParametersInfo(spi_GetWheelScrollLines, 0, @fIntelliScrollLines, 0);
+ fIntelliMessage := wm_MouseWheel;
+ { Look for hidden mouse window }
+ hWndMouse := FindWindow('MouseZ', 'Magellan MSWHEEL');
+ if hWndMouse <> 0 then
+ { 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');
+ if (fIntelliScrollLines < 0) or (fIntelliScrollLines > 100) then
+ fIntelliScrollLines := 3;
+// WM MOUSE WHEEL
+procedure TGLSCustomMemo.WMMouseWheel(var Message: TMessage);
+{$J+}
+{$IFOPT R+} {$DEFINE StoreRangeCheck} {$ENDIF} {$R-}
+ Delta: SmallInt = 0;
+ Delta := Delta + SmallInt(HiWord(Message.wParam));
+ while Abs(Delta) >= 120 do
+ if Delta < 0 then
+ DoScroll(sbVert, fIntelliScrollLines);
+ Delta := Delta + 120;
+ DoScroll(sbVert, -fIntelliScrollLines);
+ Delta := Delta - 120;
+{$J-}
+{$IFDEF StoreRangeCheck} {$R+} {$UNDEF StoreRangeCheck} {$ENDIF}
+//--------------------------------------------------------------
+// SET CURSOR
+procedure TGLSCustomMemo.SetCursor(ACurX, ACurY: Integer);
+ ClearSelection;
+ CurX := 0;
+ CurY := ACurY;
+ CurX := ACurX;
+// SELECT LINE, CHAR
+function TGLSCustomMemo.SelectLine(LineNo, StyleNo: Integer): integer;
+ rct: TRect;
+ Result := LineStyle[LineNo];
+ LineStyle[LineNo] := StyleNo;
+ rct := LineRect(LineNo);
+ InvalidateRect(Handle, @rct, True);
+procedure TGLSCustomMemo.SelectLines(StartLine, EndLine: Integer);
+ FSelStartX := 0;
+ FSelStartY := StartLine;
+ FSelEndX := Length(Lines[EndLine]);
+ FSelEndY := EndLine;
+ rct := LineRangeRect(FSelStartY, FSelEndY);
+ SelectionChanged;
+ InvalidateRect(Handle, @rct, true);
+procedure TGLSCustomMemo.SelectChar(LineNo, Pos, StyleNo: Integer);
+ UnselectChar;
+ FSelCharPos.LineNo := LineNo;
+ FSelCharPos.Pos := Pos;
+ FSelCharStyle := StyleNo;
+procedure TGLSCustomMemo.UnSelectChar;
+ with FSelCharPos do
+ if LineNo < 0 then
+ LineNo := -1;
+ Pos := -1;
+ FSelCharStyle := -1;
+// CLEAR
+procedure TGLSCustomMemo.Clear;
+ CurY := 0;
+ FLeftCol := 0;
+ FTopLine := 0;
+ Lines.Clear;
+ TGLSMemoStrings(Lines).DoAdd('');
+ ClearUndoList;
+ Invalidate;
+// SELECT ALL
+procedure TGLSCustomMemo.SelectAll;
+ FSelStartY := 0;
+ FSelEndY := Lines.Count - 1;
+ FSelEndX := Length(Lines[Lines.Count - 1]);
+//-----------------------------------------------------------
+// SET CLIPBOARD CODE PAGE
+procedure SetClipboardCodePage(const CodePage: longint);
+ Data: THandle;
+ DataPtr: Pointer;
+ // Define new code page for clipboard
+ Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 4);
+ DataPtr := GlobalLock(Data);
+ Move(CodePage, DataPtr^, 4);
+ SetClipboardData(CF_LOCALE, Data);
+ GlobalUnlock(Data);
+ except
+ GlobalFree(Data);
+// COPY TO CLIPBOARD
+procedure CopyStringToClipboard(const Value: string);
+ RusLocale = (SUBLANG_DEFAULT shl $A) or LANG_RUSSIAN;
+ Clipboard.Open;
+ SetClipboardCodePage(RusLocale);
+ Clipboard.AsText := Value;
+ Clipboard.Close;
+procedure TGLSCustomMemo.CopyToClipBoard;
+ CopyStringToClipboard(GetSelText);
+// PASTE FROM CLIPBOARD
+procedure TGLSCustomMemo.PasteFromClipBoard;
+ H, len: integer;
+ Buff: string;
+ H := ClipBoard.GetAsHandle(CF_TEXT);
+ len := GlobalSize(H);
+ if len = 0 then
+ SetLength(Buff, len);
+ SetLength(Buff, ClipBoard.GetTextBuf(PChar(Buff), len));
+ AdjustLineBreaks(Buff);
+ SetSelText(Buff);
+// DELETE SELECTION
+procedure TGLSCustomMemo.DeleteSelection(bRepaint: Boolean);
+ xSelStartX, xSelStartY, xSelEndX, xSelEndY: integer;
+ i, len: integer;
+ OldX, OldY: integer;
+ S1, S2, S, AddSpaces: string;
+ Undo: TGLSMemoDeleteBufUndo;
+ if (FSelStartY = FSelEndY) and (FSelStartX = FSelEndX) then
+ OldX := CurX;
+ OldY := CurY;
+ xSelStartX := FSelStartX;
+ xSelStartY := FSelStartY;
+ xSelEndX := FSelEndX;
+ xSelEndY := FSelEndY;
+ OrderPos(xSelStartX, xSelStartY, xSelEndX, xSelEndY);
+ if xSelStartY = xSelEndY then
+ S1 := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX);
+ S2 := '';
+ AddSpaces := '';
+ len := Length(Lines[xSelStartY]);
+ S1 := Copy(Lines[xSelStartY], xSelStartX + 1, len);
+ AddSpaces := StringOfChar(' ', xSelStartX - len);
+ S2 := Copy(Lines[xSelEndY], 1, xSelEndX);
+ 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
+ S := S + #13#10;
+ if i <> xSelEndY then
+ S := S + Lines[xSelStartY + 1];
+ DeleteLine(xSelStartY + 1, -1, -1, -1, -1, False);
+ S := S + S2;
+ CurY := xSelStartY;
+ CurX := xSelStartX;
+ Changed(xSelStartY, -1);
+ if bRepaint then
+ 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);
+// CUT TO CLIPBOARD
+procedure TGLSCustomMemo.CutToClipBoard;
+ ClipBoard.SetTextBuf(PChar(GetSelText));
+ DeleteSelection(True);
+// GET SEL TEXT
+function TGLSCustomMemo.GetSelText: string;
+ Result := '';
+ Result := Copy(Lines[xSelStartY], xSelStartX + 1, xSelEndX - xSelStartX)
+ 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);
+// GET SEL START
+function TGLSCustomMemo.GetSelStart: TPoint;
+ Result := Point(xSelStartX, xSelStartY);
+// GET SEL END
+function TGLSCustomMemo.GetSelEnd: TPoint;
+ Result := Point(xSelEndX, xSelEndY);
+// SET SEL TEXT
+procedure TGLSCustomMemo.SetSelText(const AValue: string);
+ i, k: integer;
+ Buff, S: string;
+ Buff := AValue;
+ DeleteSelection(False);
+ i := Pos(#13#10, Buff);
+ S := Lines[xSelStartY];
+ if i = 0 then
+ Lines[xSelStartY] := Copy(S, 1, xSelStartX) + Buff
+ + Copy(S, xSelStartX + 1, Length(S));
+ if Buff <> '' then
+ CurX := CurX + Length(Buff);
+ k := xSelStartY;
+ Lines[k] := Copy(S, 1, xSelStartX) + Copy(Buff, 1, i - 1);
+ TGLSMemoStrings(Lines).DoInsert(k + 1, Copy(S, xSelStartX + 1, Length(S)));
+ Buff := Copy(Buff, i + 2, Length(Buff));
+ k := k + 1;
+ TGLSMemoStrings(Lines).DoInsert(k, Copy(Buff, 1, i - 1));
+ Lines[k] := Buff + Lines[k];
+ CurY := k;
+ CurX := Length(Buff);
+ FUndoList.Add(TGLSMemoPasteUndo.Create(OldX, OldY, CurX, CurY, AValue));
+// GET SEL LENGTH
+function TGLSCustomMemo.GetSelLength: integer;
+ Result := Length(GetSelText);
+// CHANGED
+procedure TGLSCustomMemo.Changed(FromLine, ToLine: integer);
+ 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);
+// ATTR CHANGED
+procedure TGLSCustomMemo.AttrChanged(LineNo: integer);
+ ValidAttrs[LineNo] := False;
+ InvalidateLineRange(LineNo, LineNo);
+ if Assigned(FOnAttrChange) then
+ FOnAttrChange(Self);
+// SELECTION CHANGED
+procedure TGLSCustomMemo.SelectionChanged;
+ if Assigned(FOnSelectionChange) then
+ FOnSelectionChange(Self);
+// STATUS CHANGED
+procedure TGLSCustomMemo.StatusChanged;
+ if Assigned(FOnStatusChange) then
+ FOnStatusChange(Self);
+// CLEAR SELECTION
+procedure TGLSCustomMemo.ClearSelection;
+ Changed: Boolean;
+ Changed := not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY));
+ FSelStartX := CurX;
+ FSelStartY := CurY;
+ FSelEndX := CurX;
+ FSelEndY := CurY;
+ FPrevSelX := CurX;
+ FPrevSelY := CurY;
+ if Changed then
+ if Assigned(FOnMoveCursor) then
+ FOnMoveCursor(Self);
+// EXPAND SELECTION
+procedure TGLSCustomMemo.ExpandSelection;
+ rct := LineRangeRect(FPrevSelY, CurY);
+// MAX LENGTH
+function TGLSCustomMemo.MaxLength: integer;
+ for i := 0 to Lines.Count - 1 do
+ len := Length(Lines[i]);
+ if len > Result then
+ Result := len;
+// DO SCROLL
+procedure TGLSCustomMemo.DoScroll(Sender: TGLSMemoScrollBar; ByValue: integer);
+ eRect, scrRect, sbRect: TRect;
+ Old: integer;
+ eRect := EditorRect;
+ case Sender.Kind of
+ sbVertical:
+ Old := FTopLine;
+ FTopLine := FTopLine + ByValue;
+ if FTopLine > Sender.MaxPosition then
+ FTopLine := Sender.MaxPosition;
+ if FTopLine < 0 then
+ if Old <> FTopLine then
+ 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);
+ sbHorizontal:
+ Old := FLeftCol;
+ FLeftCol := FLeftCol + ByValue;
+ if FLeftCol > Sender.MaxPosition then
+ FLeftCol := Sender.MaxPosition;
+ if FLeftCol < 0 then
+ if Old <> FLeftCol then
+ if CurX < FLeftCol then
+ CurX := FLeftCol;
+ if CurX > LastVisiblePos then
+ CurX := LastVisiblePos;
+ ScrollDC(Canvas.Handle, (Old - FLeftCol) * FCellSize.W, 0,
+// DO SCROLL PAGE
+procedure TGLSCustomMemo.DoScrollPage(Sender: TGLSMemoScrollBar; ByValue:
+ integer);
+ sbVertical: DoScroll(Sender, ByValue * VisibleLineCount);
+ sbHorizontal: DoScroll(Sender, ByValue * VisiblePosCount);
+// SET LINES
+procedure TGLSCustomMemo.SetLines(ALines: TStrings);
+ if ALines <> nil then
+ FLines.Assign(ALines);
+ Changed(0, -1);
+// SET/GET LINE STYLE
+procedure TGLSCustomMemo.SetLineStyle(Index: integer; Value: integer);
+ TGLSMemoStrings(FLines).Style[Index] := Value;
+ if IsLineVisible(Index) then
+ AttrChanged(Index);
+function TGLSCustomMemo.GetLineStyle(Index: integer): integer;
+ Result := TGLSMemoStrings(FLines).Style[Index];
+// GET/SET IN COMMENT
+function TGLSCustomMemo.GetInComment(Index: integer): Boolean;
+ Result := TGLSMemoStrings(FLines).InComment[Index];
+procedure TGLSCustomMemo.SetInComment(Index: integer; Value: Boolean);
+ TGLSMemoStrings(FLines).InComment[Index] := Value;
+// GET/SET IN BRACKETS
+function TGLSCustomMemo.GetInBrackets(Index: integer): integer;
+ Result := TGLSMemoStrings(FLines).InBrackets[Index];
+procedure TGLSCustomMemo.SetInBrackets(Index: integer; Value: integer);
+ TGLSMemoStrings(FLines).InBrackets[Index] := Value;
+// GET/SET VALID ATTRS
+function TGLSCustomMemo.GetValidAttrs(Index: integer): Boolean;
+ Result := TGLSMemoStrings(FLines).ValidAttrs[Index];
+procedure TGLSCustomMemo.SetValidAttrs(Index: integer; Value: Boolean);
+ TGLSMemoStrings(FLines).ValidAttrs[Index] := Value;
+// GET/SET CHAR ATTRS
+function TGLSCustomMemo.GetCharAttrs(Index: integer): string;
+ Result := TGLSMemoStrings(FLines).CharAttrs[Index];
+procedure TGLSCustomMemo.SetCharAttrs(Index: integer; const Value: string);
+ TGLSMemoStrings(FLines).CharAttrs[Index] := Value;
+// SET CUR X
+procedure TGLSCustomMemo.SetCurX(Value: integer);
+ len: integer;
+ WasVisible: Boolean;
+ if Value < 0 then
+ if CurY = 0 then
+ Value := 0
+ CurY := CurY - 1;
+ Value := Length(Lines[CurY]);
+ if (CurY >= 0) and (CurY < Lines.Count) then
+ len := Length(Lines[CurY]);
+ if Value > len then
+ Lines[CurY] := Lines[CurY] + StringOfChar(' ', Value - len);
+ // Value := len;
+ ValidAttrs[CurY] := False;
+ InvalidateLineRange(CurY, CurY);
+ FCurX := Value;
+ WasVisible := FCaretVisible;
+ if WasVisible then
+ MakeVisible;
+ ResizeScrollBars;
+ StatusChanged;
+// SET CUR Y
+procedure TGLSCustomMemo.SetCurY(Value: integer);
+ Old := CurY;
+ 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;
+// MOVE CURSOR
+procedure TGLSCustomMemo.MoveCursor(dX, dY: integer; Shift: TShiftState);
+ Selecting: Boolean;
+ //------------------------------------------------------------
+ function IsDelimiter(c: char): Boolean;
+ Result := Pos(c, ' .,;:/?!@#$%^&*(){}[]<>-+=|\') > 0;
+ function IsStopChar(c, cThis: char): Boolean;
+ Result := IsDelimiter(c) <> IsDelimiter(cThis);
+ procedure MoveWordLeft;
+ S: string;
+ CurX := CurX - 1;
+ S := TrimRight(Lines[CurY]);
+ while CurX > 0 do
+ if IsStopChar(S[CurX], S[CurX + 1]) then
+ if (CurX < 0) then
+ if CurY > 0 then
+ CurX := Length(Lines[CurY]);
+ procedure MoveWordRight;
+ Len: integer;
+ Len := Length(S);
+ CurX := CurX + 1;
+ while CurX < Len do
+ if IsStopChar(S[CurX + 1], S[CurX]) then
+ if CurX > Len then
+ if CurY < Lines.Count - 1 then
+ CurY := CurY + 1;
+ Selecting := (ssShift in Shift) and (CurX = FPrevSelX)
+ and (CurY = FPrevSelY);
+ if ssCtrl in Shift then
+ if dX > 0 then
+ MoveWordRight;
+ if dX < 0 then
+ MoveWordLeft;
+ CurY := CurY + dY;
+ CurX := CurX + dX;
+ if Selecting then
+ ExpandSelection
+// MOVE PAGE
+procedure TGLSCustomMemo.MovePage(dP: integer; Shift: TShiftState);
+ eRect: TRect;
+ LinesPerPage: integer;
+ if FCellSize.H = 0 then
+ LinesPerPage := (eRect.Bottom - eRect.Top) div FCellSize.H - 1;
+ CurY := CurY + dP * LinesPerPage;
+ if dP > 0 then
+ CurY := Lines.Count - 1;
+ CurX := Length(Lines[Lines.Count - 1]);
+// GO HOME
+procedure TGLSCustomMemo.GoHome(Shift: TShiftState);
+// GO END
+procedure TGLSCustomMemo.GoEnd(Shift: TShiftState);
+ S, S1: string;
+ 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;
+// INSERT CHAR
+procedure TGLSCustomMemo.InsertChar(C: Char);
+ NewPlace: integer;
+ CurX0, CurY0: integer;
+ CurX0 := CurX;
+ CurY0 := CurY;
+ NewPlace := CurX + 1;
+ if C = #9 then
+ while (NewPlace mod TabSize) <> 0 do
+ Inc(NewPlace);
+ S1 := StringOfChar(' ', NewPlace - CurX);
+ S1 := C;
+ Insert(S1, S, CurX + 1);
+ Lines[CurY] := S;
+ CurX := NewPlace;
+ rct := LineRect(CurY);
+ Changed(CurY, CurY);
+ FUndoList.Add(TGLSMemoInsCharUndo.Create(CurX0, CurY0, CurX, CurY, S1));
+// INSERT TEMPLATE
+procedure TGLSCustomMemo.InsertTemplate(AText: string);
+ i, NewCurX, NewCurY: integer;
+ Indent: string;
+ FoundCursor: Boolean;
+ Indent := IndentCurrLine;
+ NewCurX := CurX;
+ NewCurY := CurY;
+ FoundCursor := False;
+ i := 1;
+ while i <= Length(AText) do
+ if AText[i] = #13 then
+ if (i = Length(AText)) or (AText[i + 1] <> #10) then
+ Insert(#10 + Indent, AText, i + 1);
+ if not FoundCursor then
+ Inc(NewCurY);
+ NewCurX := Length(Indent);
+ Inc(i, 1 + Length(Indent));
+ else if AText[i] = #7 then
+ FoundCursor := True;
+ Delete(AText, i, 1);
+ Dec(i);
+ else if Ord(AText[i]) < Ord(' ') then
+ else if not FoundCursor then
+ Inc(NewCurX);
+ SetSelText(AText);
+ SetCursor(NewCurX, NewCurY);
+ SetFocus;
+// DELETE CHAR
+procedure TGLSCustomMemo.DeleteChar(OldX, OldY: integer);
+ C: char;
+ Undo: TGLSMemoDelCharUndo;
+ IsBackspace: Boolean;
+ if FReadOnly then
+ if OldX < 0 then
+ IsBackspace := False;
+ IsBackspace := True;
+ S1 := Copy(S, CurX + 1, Length(S));
+ if not IsBackspace then
+ S1 := TrimRight(S1);
+ if CurX < Length(Lines[CurY]) then
+ C := S[CurX + 1];
+ Delete(S, CurX + 1, 1);
+ Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, C);
+ Undo.IsBackSpace := IsBackSpace;
+ else if CurY < Lines.Count - 1 then
+ S := Lines[CurY] + Lines[CurY + 1];
+ DeleteLine(CurY + 1, OldX, OldY, CurX, CurY, False);
+ Changed(CurY, -1);
+ rct := EditorRect;
+ Undo := TGLSMemoDelCharUndo.Create(OldX, OldY, CurX, CurY, #13);
+// DELETE LINE
+procedure TGLSCustomMemo.DeleteLine(Index, OldX, OldY, NewX, NewY: integer;
+ FixUndo: Boolean);
+ s: string;
+ if Index < 0 then
+ Index := CurY;
+ s := Lines[Index];
+ TGLSMemoStrings(Lines).FDeleting := True;
+ if Lines.Count = 1 then
+ TGLSMemoStrings(Lines)[0] := ''
+ Lines.Delete(Index);
+ TGLSMemoStrings(Lines).FDeleting := False;
+ if Index >= Lines.Count then
+ Changed(Index - 1, -1)
+ Changed(Index, -1);
+ if NewX < 0 then
+ if Length(Lines[0]) < CurX then
+ CurX := Length(Lines[0]);
+ CurY := Index - 1
+ CurY := Index;
+ NewX := CurX;
+ NewY := CurY;
+ CurX := NewX;
+ CurY := NewY;
+ if Assigned(FUndoList) and FixUndo then
+ FUndoList.Add(TGLSMEmoDelLineUndo.Create(Index, OldX, OldY, NewX, NewY, s));
+// BACK SPACE
+procedure TGLSCustomMemo.BackSpace;
+ MoveCursor(-1, 0, []);
+ if (OldX = CurX) and (OldY = CurY) then
+ DeleteChar(OldX, OldY);
+// BACK SPACE WORD
+procedure TGLSCustomMemo.BackSpaceWord;
+ MoveCursor(-1, 0, [ssShift, ssCtrl]);
+// INDENT CURR LINE
+function TGLSCustomMemo.IndentCurrLine: string;
+ Len, Count: integer;
+ CurS: string;
+ if not AutoIndent then
+ CurS := Lines[CurY];
+ Len := Length(CurS);
+ while (Count < CurX) and (Count < Len) do
+ if CurS[Count + 1] <> ' ' then
+ Result := StringOfChar(' ', Count);
+// NEW LINE
+procedure TGLSCustomMemo.NewLine;
+ S, sIndent: string;
+ 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);
+ FUndoList.Add(TGLSMemoInsCharUndo.Create(OldX, OldY, CurX, CurY, #13 +
+ sIndent));
+ Changed(CurY - 1, -1);
+// ADD STRING
+function TGLSCustomMemo.AddString(const S: string): integer;
+ if Lines.Count = 0 then
+ MovePage(1, [ssCtrl]); // end of text
+ if not ((Lines.Count = 1) and (Lines[0] = '')) then
+ CurY := Lines.Count;
+ // S := #13#10 + S;
+ SetSelText(S);
+ Result := Lines.Count - 1;
+// INSERT STRING
+procedure TGLSCustomMemo.InsertString(Index: integer; S: string);
+// DO COMMAND
+procedure TGLSCustomMemo.DoCommand(cmd: TCommand; const AShift: TShiftState);
+ case cmd of
+ cmDelete: if not FReadOnly then
+ if ssShift in AShift then
+ CutToClipboard
+ else if FDelErase and
+ (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY))) then
+ DeleteSelection(True)
+ DeleteChar(-1, -1);
+ 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:
+ PasteFromClipboard;
+ if ssCtrl in AShift then
+ CopyToClipboard;
+// KEY DOWN
+procedure TGLSCustomMemo.KeyDown(var Key: Word; Shift: TShiftState);
+ 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);
+// KEY PRESS
+procedure TGLSCustomMemo.KeyPress(var Key: Char);
+ if (ord(Key) in [9, 32..255]) and (ord(Key) <> 127) then
+ if FDelErase and (not ((FSelStartX = FSelEndX) and (FSelStartY = FSelEndY)))
+ then
+ InsertChar(Key);
+ DoCommand(Ord(Key), []);
+// MOUSE DOWN
+procedure TGLSCustomMemo.MouseDown(Button: TMouseButton; Shift: TShiftState;
+ X, Y: Integer);
+ newPos: TCellPos;
+ charPos: TFullPos;
+ if not Focused then
+ // Exit;
+ if FAfterDoubleClick then
+ FAfterDoubleClick := False;
+ if Button <>mbLeft then
+ if sbVert.MouseDown(Button, Shift, X, Y) then
+ if sbHorz.MouseDown(Button, Shift, X, Y) then
+ if PointInRect(Point(X, Y), EditorRect) then
+ newPos := CellFromPos(X, Y);
+ CurY := newPos.Y + FTopLine;
+ CurX := newPos.X + FLeftCol;
+ Selecting := ssShift in Shift;
+ if Button = mbLeft then
+ FLeftButtonDown := True;
+ if Assigned(FOnGutterClick) then
+ if PointInRect(Point(X, Y), FGutter.FullRect) then
+ charPos := CharFromPos(X, Y);
+ if charPos.LineNo < Lines.Count then
+ FOnGutterClick(Self, charPos.LineNo);
+// MOUSE MOVE
+procedure TGLSCustomMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
+ if sbVert.MouseMove(Shift, X, Y) then
+ if sbHorz.MouseMove(Shift, X, Y) then
+ if (ssLeft in Shift) and FLeftButtonDown then
+ ExpandSelection;
+// MOUSE UP
+procedure TGLSCustomMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:
+ Integer);
+ if sbVert.MouseUp(Button, Shift, X, Y) then
+ if sbHorz.MouseUp(Button, Shift, X, Y) then
+ FLeftButtonDown := False;
+ FLastMouseUpX := X;
+ FLastMouseUpY := Y;
+// DBL CLICK
+procedure TGLSCustomMemo.DblClick;
+ clickPos: TCellPos;
+ clickX, clickY: integer;
+ // SELECT WORD
+ procedure SelectWord;
+ const
+ stopChars: TSysCharSet = [' ', ';', '.', ',', ':', '?', '!', '''', '"',
+ '<', '>', '/', '*', '+', '-', '=', '(', ')',
+ '[', ']', '{', '}', '@', '#', '$', '%', '^',
+ '&', '|', '\'];
+ CurX := clickX;
+ CurY := clickY;
+ if (CurX = clickX) and (CurY = clickY) then
+ s := Lines[clickY];
+ if s[clickX + 1] = ' ' then
+ i := clickX;
+ while (i >= 0) and not CharInSet(s[i + 1], stopChars) do
+ FSelStartY := clickY;
+ FSelStartX := i + 1;
+ while (i < Length(s)) and not CharInSet(s[i + 1], stopChars) do
+ FSelEndY := clickY;
+ FSelEndX := i;
+ if FSelEndX <> FSelStartX then
+ FAfterDoubleClick := True;
+ rct := LineRangeRect(CurY, CurY);
+ if PointInRect(Point(FLastMouseUpX, FLastMouseUpY), EditorRect) then
+ clickPos := CellFromPos(FLastMouseUpX, FLastMouseUpY);
+ clickX := clickPos.X + FLeftCol;
+ clickY := clickPos.Y + FTopLine;
+ SelectWord;
+// WM_GETDLGCODE
+procedure TGLSCustomMemo.WMGetDlgCode(var Msg: TWMGetDlgCode);
+ Msg.Result := DLGC_WANTARROWS or DLGC_WANTTAB;
+// WM_ERASEBKGND
+procedure TGLSCustomMemo.WMEraseBkgnd(var Msg: TWmEraseBkgnd);
+ Msg.Result := 1;
+// WM_SIZE
+procedure TGLSCustomMemo.WMSize(var Msg: TWMSize);
+ if not (csLoading in ComponentState) then
+ ResizeEditor;
+// WM_SETCURSOR
+procedure TGLSCustomMemo.WMSetCursor(var Msg: TWMSetCursor);
+ P: TPoint;
+ GetCursorPos(P);
+ P := ScreenToClient(P);
+ if PointInRect(P, EditorRect) then
+ Winapi.Windows.SetCursor(Screen.Cursors[crIBeam])
+ Winapi.Windows.SetCursor(Screen.Cursors[crArrow]);
+// WM_SETFOCUS
+procedure TGLSCustomMemo.WMSetFocus(var Msg: TWMSetFocus);
+ SetFont(FFont);
+ CreateCaret(Handle, HBITMAP(0), 2, FCellSize.H - 2);
+ ShowCaret(true);
+// WM_KILLFOCUS
+procedure TGLSCustomMemo.WMKillFocus(var Msg: TWMSetFocus);
+ DestroyCaret;
+ FCaretVisible := False;
+// SHOW CARET
+procedure TGLSCustomMemo.ShowCaret(State: Boolean);
+ if not State then
+ HideCaret(Handle)
+ else if Focused and not HiddenCaret then
+ rct := CellRect(CurX - FLeftCol, CurY - FTopLine);
+ SetCaretPos(rct.Left, rct.Top + 1);
+ Winapi.Windows.ShowCaret(Handle);
+ FCaretVisible := True;
+// CELL RECT
+function TGLSCustomMemo.CellRect(ACol, ARow: integer): TRect;
+ with FCellSize do
+ Result := Rect(rct.Left + W * ACol, rct.Top + H * ARow,
+ rct.Left + W * (ACol + 1), rct.Top + H * (ARow + 1));
+// LINE RECT
+function TGLSCustomMemo.LineRect(ARow: integer): TRect;
+ ARow := ARow - FTopLine;
+ Result := Rect(rct.Left, rct.Top + H * ARow, rct.Right, rct.Top + H * (ARow
+ + 1));
+// COL RECT
+function TGLSCustomMemo.ColRect(ACol: integer): TRect;
+ ACol := ACol - FLeftCol;
+ Result := Rect(rct.Left + W * ACol, rct.Top, rct.Left + W * (ACol + 1),
+ rct.Bottom);
+// LINE RANGE RECT
+function TGLSCustomMemo.LineRangeRect(FromLine, ToLine: integer): TRect;
+ rct1, rct2: TRect;
+ rct1 := LineRect(FromLine);
+ rct2 := LineRect(ToLine);
+ Result := TotalRect(rct1, rct2);
+// INVALIDATE LINE RANGE
+procedure TGLSCustomMemo.InvalidateLineRange(FromLine, ToLine: integer);
+ rct := LineRangeRect(FromLine, ToLine);
+ if GutterWidth > 2 then
+ rct.Left := FGutter.Left;
+// COL RANGE RECT
+function TGLSCustomMemo.ColRangeRect(FromCol, ToCol: integer): TRect;
+ rct1 := ColRect(FromCol);
+ rct2 := ColRect(ToCol);
+// CELL and CHAR FROM POS
+function TGLSCustomMemo.CellFromPos(X, Y: integer): TCellPos;
+ if (FCellSize.H = 0) and Assigned(FFont) then
+ if (FCellSize.W <> 0) and (FCellSize.H <> 0) then
+ Result.X := (X - rct.Left) div FCellSize.W;
+ Result.Y := (Y - rct.Top) div FCellSize.H;
+ Result.X := 0;
+ Result.Y := 0;
+function TGLSCustomMemo.CharFromPos(X, Y: integer): TFullPos;
+ Result.Pos := (X - rct.Left) div FCellSize.W + FLeftCol;
+ Result.LineNo := (Y - rct.Top) div FCellSize.H + FTopLine;
+ Result.Pos := 1;
+ Result.LineNo := 1;
+// SET COLOR
+procedure TGLSCustomMemo.SetColor(Index: integer; Value: TColor);
+ Changed := False;
+ case Index of
+ 0: if FBkColor <> Value then
+ FBkColor := Value;
+ FStyles.BkColor[0] := Value;
+ Changed := True;
+ 1: if FSelColor <> Value then
+ FSelColor := Value;
+ 2: if FSelBkColor <> Value then
+ FSelBkColor := Value;
+ InvalidateRect(Handle, @eRect, True);
+// SET FONT
+procedure TGLSCustomMemo.SetFont(Value: TFont);
+ wW, wi: integer;
+ OldFontName: string;
+ 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
+ FStyles.TextColor[0] := FFont.Color;
+ FStyles.Style[0] := FFont.Style;
+// SET GUTTER WIDTH
+procedure TGLSCustomMemo.SetGutterWidth(Value: integer);
+ FGutterWidth := Value;
+ FGutter.FWidth := Value;
+// SET GUTTER COLOR
+procedure TGLSCustomMemo.SetGutterColor(Value: TColor);
+ if FGutter.FColor <> Value then
+ FGutter.FColor := Value;
+// GET GUTTER COLOR
+function TGLSCustomMemo.GetGutterColor: TColor;
+ Result := FGutter.FColor;
+// CHAR STYLE NO
+function TGLSCustomMemo.CharStyleNo(LineNo, Pos: integer): integer;
+ ChStyle: string;
+ if (LineNo < 0) or (LineNo >= Lines.Count) then
+ ChStyle := CharAttrs[LineNo];
+ if (Pos <= 0) or (Pos > Length(ChStyle)) then
+ Result := integer(ChStyle[Pos]);
+// DRAW LINE
+procedure TGLSCustomMemo.DrawLine(LineNo: integer);
+ eRect, rct0, rct1, rct, lineRct: TRect;
+ LineSelStart, LineSelEnd, LineStyleNo, pos: integer;
+ S, S1, S2, S3, ChStyle: string;
+ //--------- FIND LINE SELECTION -------------
+ procedure FindLineSelection;
+ len := Length(Lines[LineNo]);
+ LineSelStart := 0;
+ LineSelEnd := 0;
+ if xSelStartY = Lineno then
+ LineSelStart := xSelStartX - FLeftCol;
+ LineSelEnd := len - FLeftCol;
+ else if (xSelStartY < LineNo) and (LineNo < xSelEndY) then
+ if xSelEndY = LineNo then
+ LineSelEnd := xSelEndX - FLeftCol;
+ if LineSelEnd < LineSelStart then
+ Swap(LineSelEnd, LineSelStart);
+ if LineSelStart < 0 then
+ 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);
+ //------------- DRAW PART ---------------------
+ procedure DrawPart(const Part: string; PartStyle, StartPos: integer;
+ var rct: TRect; IsSelection: Boolean);
+ len, w: integer;
+ rctInternal: TRect;
+ len := Length(Part);
+ if len > 0 then
+ with FLineBitmap.Canvas do
+ w := FCellSize.W * len;
+ Font.Style := FStyles.Style[PartStyle];
+ if IsSelection then
+ Font.Color := SelColor;
+ Brush.Color := SelBkColor;
+ if LineStyleNo = 0 then
+ Font.Color := FStyles.TextColor[PartStyle];
+ Brush.Color := FStyles.BkColor[PartStyle];
+ if (LineNo = FSelCharPos.LineNo) and
+ (StartPos = FSelCharPos.Pos + 1) and (Length(Part) = 1) then
+ Font.Color := FStyles.TextColor[LineStyleNo];
+ Brush.Color := FStyles.BkColor[LineStyleNo];
+ Font.Style := FStyles.Style[LineStyleNo];
+ 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;
+ //------------- DRAW SEGMENTS ---------------------
+ procedure DrawSegments(S: string; WorkPos: integer;
+ i, len, ThisStyle: integer;
+ if Len = 0 then
+ ThisStyle := Ord(ChStyle[WorkPos]);
+ while (i <= Len) and
+ (ThisStyle = Ord(ChStyle[WorkPos + i - 1])) do
+ DrawPart(Copy(S, 1, i - 1), ThisStyle, WorkPos, rct, IsSelection);
+ Inc(WorkPos, i - 1);
+ s := Copy(s, i, Len);
+ //---------------------------------------------
+ rct := CellRect(0, LineNo - FTopLine);
+ rct0 := Rect(eRect.Left, rct.Top, eRect.Right, rct.Bottom);
+ lineRct := rct0;
+ if LineNo < Lines.Count then
+ S := Lines[LineNo];
+ LineStyleNo := LineStyle[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;
+ FillRect(rct1);
+ with LineRct do
+ BitBlt(Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
+ FLineBitmap.Canvas.Handle, 0, 0, SRCCOPY);
+ with Canvas do
+ Brush.Color := BkColor;
+ FillRect(rct0);
+// SET HIDDEN CARET
+procedure TGLSCustomMemo.SetHiddenCaret(Value: Boolean);
+ if Value <> FHiddenCaret then
+ FHiddenCaret := Value;
+ if Focused then
+ if FHiddenCaret = FCaretVisible then
+ ShowCaret(not FHiddenCaret);
+// BORDER
+ 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));
+ 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
+ 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);
+ Pen.Color := Colors[BorderType][4];
+ LineTo(rct.Right - 1, rct.Bottom - 1);
+ LineTo(rct.Right - 1, rct.Top);
+// EDITOR RECT
+function TGLSCustomMemo.EditorRect: TRect;
+ l, t, r, b: integer;
+ l := 2;
+ r := Width - 2;
+ t := 2;
+ b := Height - 2;
+ 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);
+// DRAW MARGIN
+procedure TGLSCustomMemo.DrawMargin;
+ Pen.Color := clWhite;
+ for i := 1 to FMargin do
+ MoveTo(eRect.Left - i, eRect.Top);
+ LineTo(eRect.Left - i, eRect.Bottom + 1);
+// DRAW GUTTER
+procedure TGLSCustomMemo.DrawGutter;
+ if GutterWidth < 2 then
+ ResizeGutter;
+ FGutter.PaintTo(Canvas);
+// DRAW SCROLLBARS
+procedure TGLSCustomMemo.DrawScrollBars;
+ sbVert.PaintTo(Canvas);
+ sbHorz.PaintTo(Canvas);
+ if FScrollBars = ssBoth then
+ Brush.Color := clSilver;
+ FillRect(Rect(sbVert.Left, sbHorz.Top + 1,
+ sbVert.Left + sbVert.Width, sbHorz.Top + sbHorz.Height));
+// FRESH LINE BITMAP
+procedure TGLSCustomMemo.FreshLineBitmap;
+ with FLineBitmap do
+ Width := eRect.Right - eRect.Left;
+ Height := FCellSize.H;
+ FLineBitmap.Canvas.Font.Assign(Self.Canvas.Font);
+// PAINT
+procedure TGLSCustomMemo.Paint;
+ pTop, pBottom: TFullPos;
+ rct, eRect: TRect;
+ clipRgn: HRGN;
+ Attrs: string;
+ if TGLSMemoStrings(Lines).FLockCount > 0 then
+ FreshLineBitmap;
+ Border(Canvas, Rect(0, 0, Width, Height), btLowered);
+ DrawMargin;
+ DrawGutter;
+ DrawScrollBars;
+ 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
+ if not ValidAttrs[i] then
+ FOnGetLineAttrs(Self, i, Attrs);
+ CharAttrs[i] := Attrs;
+ ValidAttrs[i] := True;
+ for i := pTop.LineNo to pBottom.LineNo do
+ DrawLine(i);
+// GET VISIBLE
+function TGLSCustomMemo.GetVisible(Index: integer): integer;
+ Coord: TFullPos;
+ Cell: TCellPos;
+ Coord := CharFromPos(eRect.Right - 1, eRect.Bottom - 1);
+ Cell := CellFromPos(eRect.Right - 1, eRect.Bottom - 1);
+ 0: Result := Cell.X;
+ 1: Result := Cell.Y;
+ 2: Result := Coord.Pos - 1;
+ 3: Result := Coord.LineNo - 1;
+// IS LINE VISIBLE
+function TGLSCustomMemo.IsLineVisible(LineNo: integer): Boolean;
+ Result := (FTopLine <= LineNo) and (LineNo <= LastVisibleLine + 1);
+// MAKE VISIBLE
+procedure TGLSCustomMemo.MakeVisible;
+ Modified: Boolean;
+ Modified := False;
+ FLeftCol := CurX - 2;
+ Modified := True;
+ if (FScrollBars in [ssBoth, ssHorizontal]) or
+ (ScrollMode = smAuto) then
+ FLeftCol := FLeftCol + CurX - LastVisiblePos + 2;
+ FTopLine := CurY;
+ if (FScrollBars in [ssBoth, ssVertical]) or
+ FTopLine := FTopLine + CurY - LastVisibleLine;
+ if Modified then
+// RESIZE EDITOR
+procedure TGLSCustomMemo.ResizeEditor;
+// FIND TEXT
+function TGLSCustomMemo.FindText(Text: string; Options: TFindOptions; Select:
+ Boolean): Boolean;
+ i, p: integer;
+ s1, s0, s: string;
+ //-----------------------------------------------------------
+ function LastPos(const Substr, s: string): integer;
+ i, j, lenSub: integer;
+ lenSub := Length(Substr);
+ i := Length(s) - lenSub + 1;
+ while i > 0 do
+ if s[i] = Substr[1] then
+ Result := i;
+ for j := i + 1 to i + lenSub - 1 do
+ if s[j] <> Substr[j - i + 1] then
+ if Result <> 0 then
+ if not (frMatchCase in Options) then
+ Text := AnsiLowerCase(Text);
+ if SelLength > 0 then
+ s := Lines[CurY];
+ s0 := Copy(s, 1, CurX);
+ s1 := Copy(s, CurX + 1, Length(s));
+ i := CurY;
+ s0 := AnsiLowerCase(s0);
+ s1 := AnsiLowerCase(s1);
+ if frDown in Options then
+ p := Pos(Text, s1)
+ p := LastPos(Text, s0);
+ if p > 0 then
+ CurY := i;
+ CurX := Length(s0) + p - 1
+ CurX := p - 1;
+ if Select then
+ if not (frDown in Options) then
+ CurX := CurX + Length(Text);
+ CurX := CurX + Length(Text)
+ CurX := CurX - Length(Text);
+ Inc(i)
+ if (i < 0) or (i > Lines.Count - 1) then
+ s0 := '';
+ s1 := Lines[i];
+ s0 := Lines[i];
+ s1 := '';
+// RESIZE SCROLLBARS
+procedure TGLSCustomMemo.ResizeScrollBars;
+ eRect, sbRect: TRect;
+ MaxLen, OldMax, NewTop, Margin: integer;
+ with sbVert do
+ 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
+ Dec(NewTop, LastVisibleLine - (Lines.Count - 1));
+ if NewTop < 0 then
+ NewTop := 0;
+ MaxPosition := NewTop;
+ if MaxPosition < 0 then
+ MaxPosition := 0;
+ Position := NewTop;
+ Total := Lines.Count;
+ if OldMax <> MaxPosition then
+ if NewTop <> FTopLine then
+ DoScroll(sbVert, NewTop - FTopLine);
+ sbRect := sbVert.FullRect;
+ MaxLen := MaxLength;
+ with sbHorz do
+ Width := Self.Width - 4;
+ Width := Width - sbVert.Width;
+ Height := 16;
+ Left := 2;
+ Top := eRect.Bottom;
+ Margin := LastVisiblePos - MaxLen;
+ if Margin < 2 then
+ Margin := 2;
+ MaxPosition := MaxLen - (LastVisiblePos - FLeftCol) + Margin;
+ Position := FLeftCol;
+ Total := MaxLen;
+ if MaxPosition = 0 then
+ sbRect := sbHorz.FullRect;
+// RESIZE GUTTER
+procedure TGLSCustomMemo.ResizeGutter;
+ with FGutter do
+ Height := eRect.Bottom - eRect.Top;
+// CREATE PARAMS
+procedure TGLSCustomMemo.CreateParams(var Params: TCreateParams);
+// UNDO, REDO
+procedure TGLSCustomMemo.Undo;
+ FUndoList.Undo;
+procedure TGLSCustomMemo.Redo;
+ FUndoList.Redo;
+// SET UNDO LIMIT
+procedure TGLSCustomMemo.SetUndoLimit(Value: integer);
+ if (FUndoLimit <> Value) then
+ if Value <= 0 then
+ Value := 1;
+ if Value > 100 then
+ Value := 100;
+ FUndoLimit := Value;
+ FUndoList.Limit := Value;
+// UNDO (REDO) CHANGE
+procedure TGLSCustomMemo.UndoChange;
+ if Assigned(FOnUndoChange) then
+ FOnUndoChange(Self, FUndoList.Pos < FUndoList.Count,
+ FUndoList.Pos > 0);
+// CAN UNDO
+function TGLSCustomMemo.CanUndo: boolean;
+ Result := FUndoList.FPos < FUndoList.Count;
+// CAN REDO
+function TGLSCustomMemo.CanRedo: Boolean;
+ Result := FUndoList.FPos > 0;
+// CLEAR UNDO LIST
+procedure TGLSCustomMemo.ClearUndoList;
+ FUndoList.Clear;
+// SET SCROLL BARS
+procedure TGLSCustomMemo.SetScrollBars(Value: System.UITypes.TScrollStyle);
+ if FScrollBars <> Value then
+ FScrollBars := Value;
+// CREATE
+constructor TGLSCustomMemo.Create(AOwner: TComponent);
+ 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;
+ FCurX := 0;
+ FCurY := 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;
+ FLeft := 2;
+ FTop := 2;
+ FWidth := 0;
+ FHeight := 0;
+ FColor := clBtnFace;
+ FMemo := Self;
+ FSelEndX := 0;
+ FSelEndY := 0;
+ FBkColor := clWhite;
+ FSelColor := clWhite;
+ FSelBkColor := clNavy;
+ FStyles := TStyleList.Create;
+ FStyles.Add(clBlack, clWhite, []);
+ FSelCharPos.LineNo := -1;
+ FSelCharPos.Pos := -1;
+ FLineBitmap := TBitmap.Create;
+ FScrollMode := smAuto;
+ FUndoList := TGLSMemoUndoList.Create;
+ FFirstUndoList := FUndoList;
+ FUndoList.Memo := Self;
+ FUndoLimit := 100;
+ TGLSMemoStrings(FLines).DoAdd('');
+// DESTROY
+destructor TGLSCustomMemo.Destroy;
+ FFont.Free;
+ FLines.Free;
+ FGutter.Free;
+ sbVert.Free;
+ sbHorz.Free;
+ FStyles.Free;
+ FLineBitmap.Free;
+ FFirstUndoList.Free;
+// ---------------------TGLSMemoScrollBar functions
+procedure TGLSMemoScrollBar.SetParams(Index: integer; Value: integer);
+ 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;
+//-------------------- CREATE ------------------------------
+constructor TGLSMemoScrollBar.Create(AParent: TGLSMemoAbstractScrollableObject;
+ FParent := AParent;
+ FButtonLength := 16;
+ FKind := AKind;
+ FState := sbsWait;
+//-------------------- RECT -----------------------
+function TGLSMemoScrollBar.GetRect: TRect;
+ Result := Rect(Left, Top, Left + Width, Top + Height);
+//-------------------- GET THUMB RECT -----------------------
+function TGLSMemoScrollBar.GetThumbRect: TRect;
+ TotalLen, FreeLen, ThumbLen, ThumbOffset, ThumbCoord: integer;
+ K: double;
+ if MaxPosition <= 0 then
+ Result := Rect(0, 0, 0, 0);
+ if Kind = sbVertical then
+ TotalLen := Height
+ TotalLen := Width;
+ FreeLen := TotalLen - 2 * FButtonLength;
+ K := (Total - MaxPosition) / MaxPosition;
+ if K > 0 then
+ ThumbLen := round(FreeLen * K / (1 + K));
+ if ThumbLen < 8 then
+ ThumbLen := 8;
+ if ThumbLen >= FreeLen then
+ Result := Rect(0, 0, 0, 0)
+ ThumbOffset := round((FreeLen - ThumbLen) * Position / MaxPosition);
+ ThumbCoord := FButtonLength + ThumbOffset;
+ Result := Rect(Left + 1, Top + ThumbCoord, Left + Width, Top + ThumbCoord
+ + ThumbLen)
+ Result := Rect(Left + ThumbCoord, Top + 1, Left + ThumbCoord + ThumbLen,
+ Top + Height);
+//-------------------- GET Back RECT -----------------------
+function TGLSMemoScrollBar.GetBackRect: TRect;
+ Result := Rect(Left + 1, Top, Left + Width, Top + FButtonLength)
+ Result := Rect(Left, Top + 1, Left + FButtonLength, Top + Height);
+//-------------------- GET MIDDLE RECT -----------------------
+function TGLSMemoScrollBar.GetMiddleRect: TRect;
+ bRect, fRect: TRect;
+ bRect := BackRect;
+ fRect := ForwardRect;
+ Result := Rect(Left + 1, bRect.Bottom, Left + Width, fRect.Top)
+ Result := Rect(bRect.Right, Top + 1, fRect.Left, Top + Height);
+//-------------------- GET Forward RECT -----------------------
+function TGLSMemoScrollBar.GetForwardRect: TRect;
+ Result := Rect(Left + 1, Top + Height - FButtonLength, Left + Width, Top +
+ Height)
+ Result := Rect(Left + Width - FButtonLength, Top + 1, Left + Width, Top +
+ Height);
+//-------------------- GET PAGE BACK RECT -----------------------
+function TGLSMemoScrollBar.GetPgBackRect: TRect;
+ thRect: TRect;
+ thRect := GetThumbRect;
+ if thRect.Bottom = 0 then
+ Result := Rect(Left + 1, Top + FButtonLength, Left + Width, thRect.Top - 1)
+ Result := Rect(Left + FButtonLength, Top + 1, thRect.Left - 1, Top +
+//-------------------- GET PG FORWARD RECT -----------------------
+function TGLSMemoScrollBar.GetPgForwardRect: TRect;
+ Result := Rect(Left + 1, thRect.Bottom, Left + Width, Top + Height -
+ FButtonLength)
+ Result := Rect(thRect.Right, Top + 1, Left + Width - FButtonLength, Top +
+//-------------------- PAINT TO -----------------------
+procedure TGLSMemoScrollBar.PaintTo(ACanvas: TCanvas);
+ sRect, mRect, gRect, thRect: TRect;
+ iconX, iconY, shift: integer;
+ with ACanvas do
+ Pen.Color := clSilver;
+ MoveTo(Left, Top);
+ LineTo(Left, Top + Height);
+ sRect := BackRect;
+ FillRect(sRect);
+ if State = sbsBack then
+ shift := 1;
+ Pen.Color := clGray;
+ with sRect do
+ Rectangle(Left, Top, Right, Bottom);
+ shift := 0;
+ Border(ACanvas, sRect, btFlatRaised);
+ iconX := sRect.Left + (Width - 1 - 7) div 2;
+ iconY := sRect.Top + (FButtonLength - 8) div 2;
+ Draw(iconX + shift, iconY + shift, bmScrollBarUp);
+ gRect := ForwardRect;
+ FillRect(gRect);
+ if State = sbsForward then
+ with gRect do
+ Border(ACanvas, gRect, btFlatRaised);
+ 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);
+ LineTo(Left + Width, Top);
+ iconX := sRect.Left + shift + (FButtonLength - 8) div 2;
+ iconY := sRect.Top + shift + (Height - 1 - 7) div 2;
+ Draw(iconX + shift, iconY + shift, bmScrollBarLeft);
+ 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);
+ Brush.Bitmap := bmScrollBarFill;
+ FillRect(mRect);
+ Brush.Bitmap := nil;
+ if State = sbsPageBack then
+ Brush.Color := clGray;
+ FillRect(PageBackRect);
+ if State = sbsPageForward then
+ FillRect(PageForwardRect);
+ thRect := ThumbRect;
+ FillRect(thRect);
+ Border(ACanvas, thRect, btFlatRaised);
+//-------------------- SET STATE ----------
+procedure TGLSMemoScrollBar.SetState(Value: TsbState);
+ if FState <> Value then
+ FState := Value;
+//-------------------- MOUSE DOWN ------------
+function TGLSMemoScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
+ X,
+ Y: Integer):
+ Boolean;
+ sRect, gRect, thRect, pbRect, pfRect: TRect;
+ if (Width = 0) or (Height = 0) then
+ pbRect := PageBackRect;
+ pfRect := PageForwardRect;
+ if PointInRect(Point(X, Y), sRect) then
+ State := sbsBack;
+ InvalidateRect(Parent.Handle, @sRect, True);
+ if PointInRect(Point(X, Y), gRect) then
+ State := sbsForward;
+ InvalidateRect(Parent.Handle, @gRect, True);
+ if PointInRect(Point(X, Y), pbRect) then
+ State := sbsPageBack;
+ InvalidateRect(Parent.Handle, @pbRect, True);
+ if PointInRect(Point(X, Y), pfRect) then
+ State := sbsPageForward;
+ InvalidateRect(Parent.Handle, @pfRect, True);
+ if PointInRect(Point(X, Y), thRect) then
+ State := sbsDragging;
+ FXOffset := X - thRect.Left;
+ FYOffset := Y - thRect.Top;
+//-------------------- MOUSE UP ----------
+function TGLSMemoScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
+ Y:
+ Integer):
+ case State of
+ sbsBack:
+ State := sbsWait;
+ FParent.DoScroll(Self, -1);
+ sbsForward:
+ FParent.DoScroll(Self, 1);
+ sbsPageBack:
+ FParent.DoScrollPage(Self, -1);
+ sbsPageForward:
+ FParent.DoScrollPage(Self, 1);
+ sbsDragging:
+//-------------------- MOUSE MOVE -----------
+function TGLSMemoScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer):
+ if not PointInRect(Point(X, Y), sRect) then
+ if not PointInRect(Point(X, Y), gRect) then
+ if not PointInRect(Point(X, Y), pbRect) then
+ if not PointInRect(Point(X, Y), pfRect) then
+ MoveThumbTo(X, Y);
+//-------------------- MOVE THUMB TO ------------
+function TGLSMemoScrollBar.MoveThumbTo(X, Y: Integer): integer;
+ thRect, mRect: TRect;
+ FreeLen, ThumbLen, NewPosition, NewOffset: integer;
+ mRect := MiddleRect;
+ NewOffset := 0;
+ FreeLen := 0;
+ ThumbLen := 0;
+ case Kind of
+ FreeLen := mRect.Bottom - mRect.Top;
+ ThumbLen := thRect.Bottom - thRect.Top;
+ NewOffset := Y - FYOffset - (Top + FButtonLength);
+ FreeLen := mRect.Right - mRect.Left;
+ ThumbLen := thRect.Right - thRect.Left;
+ NewOffset := X - FXOffset - (Left + FButtonLength);
+ NewPosition := round(NewOffset * MaxPosition / (FreeLen - ThumbLen));
+ Result := NewPosition - Position;
+ if NewPosition <> Position then
+ Parent.DoScroll(Self, NewPosition - Position);
+// GUTTER
+//-------------------- SET PARAMS -----------------------
+procedure TGLSMemoGutter.SetParams(Index: integer; Value: integer);
+ 0: FLeft := Value;
+ 1: FTop := Value;
+ 2: FWidth := Value;
+ 3: FHeight := Value;
+procedure TGLSMemoGutter.PaintTo(ACanvas: TCanvas);
+ LineNo, T, H: integer;
+ MoveTo(Left + Width - 1, Top);
+ LineTo(Left + Width - 1, Top + Height);
+ 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
+ T := Top;
+ H := FMemo.FCellSize.H;
+ LineNo := FMemo.FTopLine;
+ while T < Top + Height do
+ FMemo.OnGutterDraw(FMemo, ACanvas, LineNo,
+ Rect(Left, T, Left + Width - 2, T + H));
+ T := T + H;
+ Inc(LineNo);
+ if LineNo >= FMemo.Lines.Count then
+//-------------------- INVALIDATE -----------------------
+procedure TGLSMemoGutter.Invalidate;
+ gRect: TRect;
+ gRect := Rect(Left, Top, Left + Width, Top + Height);
+ InvalidateRect(FMemo.Handle, @gRect, True);
+//-------------------- GET RECT -----------------------
+function TGLSMemoGutter.GetRect: TRect;
+// ---------------------TStyleList
+procedure TStyleList.CheckRange(Index: integer);
+ if (Index < 0) or (Index >= Count) then
+ raise EListError.Create('Incorrect list item index ' + IntToStr(Index));
+//-------------------- DESTROY ---------------------------
+destructor TStyleList.Destroy;
+ Clear;
+//-------------------- CHANGE ---------------------------
+procedure TStyleList.Change(Index: integer; ATextColor, ABkCOlor: TColor;
+ AStyle: TFontStyles);
+ P: TCharStyle;
+ CheckRange(Index);
+ P := TCharStyle(Items[Index]);
+ P.TextColor := ATextColor;
+ P.BkColor := ABkColor;
+ P.Style := AStyle;
+//-------------------- ADD ---------------------------
+function TStyleList.Add(ATextColor, ABkColor: TColor; AStyle: TFontStyles):
+ Integer;
+ P := TCharStyle.Create;
+ with P do
+ TextColor := ATextColor;
+ BkColor := ABkColor;
+ Style := AStyle;
+ Result := inherited Add(P);
+//-------------------- CLEAR ---------------------------
+procedure TStyleList.Clear;
+ while Count > 0 do
+ Delete(0);
+//-------------------- DELETE ---------------------------
+procedure TStyleList.Delete(Index: Integer);
+ P.Free;
+//-------------------- GET/SET TEXT COLOR ---------------------------
+function TStyleList.GetTextColor(Index: Integer): TColor;
+ Result := TCharStyle(Items[Index]).TextColor;
+procedure TStyleList.SetTextColor(Index: Integer; Value: TColor);
+ TCharStyle(Items[Index]).TextColor := Value;
+//-------------------- GET/SET BK COLOR ---------------------------
+function TStyleList.GetBkColor(Index: Integer): TColor;
+ Result := TCharStyle(Items[Index]).BkColor;
+procedure TStyleList.SetBkColor(Index: Integer; Value: TColor);
+ TCharStyle(Items[Index]).BkColor := Value;
+//-------------------- GET/SET STYLE ---------------------------
+function TStyleList.GetStyle(Index: Integer): TFontStyles;
+ Result := TCharStyle(Items[Index]).Style;
+procedure TStyleList.SetStyle(Index: Integer; Value: TFontStyles);
+ TCharStyle(Items[Index]).Style := Value;
+// ---------------------TGLSMemoStrings
+destructor TGLSMemoStrings.Destroy;
+ P: TObject;
+ P := inherited GetObject(0);
+ inherited Delete(0);
+//-------------------- CLEAR ----------------------
+procedure TGLSMemoStrings.Clear;
+ if (Count = 1) and (Strings[0] = '') then
+//-------------------- ASSIGN ----------------------
+procedure TGLSMemoStrings.Assign(Source: TPersistent);
+ if Source is TStrings then
+ BeginUpdate;
+ // inherited Clear;
+ AddStrings(TStrings(Source));
+ EndUpdate;
+ inherited Assign(Source);
+//-------------------- ADD ----------------------
+function TGLSMemoStrings.DoAdd(const S: string): Integer;
+ Result := inherited AddObject(S, nil);
+function TGLSMemoStrings.Add(const S: string): Integer;
+ if Assigned(FMemo.Parent) then
+ Result := FMemo.AddString(S)
+ Result := DoAdd(S);
+//-------------------- OBJECT ----------------------
+function TGLSMemoStrings.AddObject(const S: string; AObject: TObject): Integer;
+ if AObject <> nil then
+ raise EInvalidOp.Create(SObjectsNotSupported);
+//-------------------- INSERT ----------------------
+procedure TGLSMemoStrings.InsertObject(Index: Integer;
+ const S: string; AObject: TObject);
+ DoInsert(Index, S);
+//-------------------- DO INSERT ----------------------
+procedure TGLSMemoStrings.DoInsert(Index: Integer; const S: string);
+ InsertItem(Index, S, nil);
+procedure TGLSMemoStrings.Insert(Index: Integer; const S: string);
+ if Assigned(FMemo) then
+ FMemo.InsertString(Index, S)
+//-------------------- DELETE ----------------------
+procedure TGLSMemoStrings.Delete(Index: Integer);
+ if (Index < 0) or (Index > Count - 1) then
+ if FDeleting or (not Assigned(FMemo)) then
+ P := inherited GetObject(Index);
+ FMemo.DeleteLine(Index, -1, -1, -1, -1, True);
+//-------------------- LOAD FROM FILE ----------------------
+procedure TGLSMemoStrings.LoadFromFile(const FileName: string);
+ with FMemo do
+ FMemo.Invalidate;
+//-------------------- SET UPDATE STATE ----------------------
+procedure TGLSMemoStrings.SetUpdateState(Updating: Boolean);
+ if Updating then
+ Inc(FLockCount)
+ else if FLockCount > 0 then
+ Dec(FLockCount);
+//-------------------- CHECK RANGE ---------------------------
+procedure TGLSMemoStrings.CheckRange(Index: integer);
+ raise EListError('Incorrect index of list item ' + IntToStr(Index));
+//-------------------- GET OBJECT ---------------------------
+function TGLSMemoStrings.GetObject(Index: Integer): TObject;
+ Result := inherited GetObject(Index);
+ if Assigned(Result) and (Result is TLineProp) then
+ Result := TLineProp(Result).FObject;
+//-------------------- PUT OBJECT ---------------------------
+procedure TGLSMemoStrings.PutObject(Index: Integer; AObject: TObject);
+ P := Objects[Index];
+ if Assigned(P) and (P is TLineProp) then
+ TLineProp(P).FObject := AObject
+ inherited PutObject(Index, AObject);
+//-------------------- GET LINE PROP ---------------------------
+function TGLSMemoStrings.GetLineProp(Index: integer): TLineProp;
+ Result := TLineProp(P);
+//-------------------- CREATE PROP --------------------------
+function TGLSMemoStrings.CreateProp(Index: integer): TLineProp;
+ Result := TLineProp.Create;
+ FStyleNo := 0;
+ FInComment := False;
+ FInBrackets := -1;
+ FValidAttrs := False;
+ FCharAttrs := '';
+ FObject := Objects[Index];
+ inherited PutObject(Index, Result);
+//-------------------- GET LINE STYLE --------------------------
+function TGLSMemoStrings.GetLineStyle(Index: integer): integer;
+ P: TLineProp;
+ P := LineProp[Index];
+ if P = nil then
+ Result := 0
+ Result := P.FStyleNo;
+//-------------------- SET LINE STYLE --------------------------
+procedure TGLSMemoStrings.SetLineStyle(Index: integer; Value: integer);
+ P := CreateProp(Index);
+ P.FStyleNo := Value;
+//-------------------- GET/SET IN COMMENT ---------------------------
+function TGLSMemoStrings.GetInComment(Index: Integer): Boolean;
+ Result := False
+ Result := P.FInComment;
+procedure TGLSMemoStrings.SetInComment(Index: Integer; Value: Boolean);
+ P.FInComment := Value;
+//-------------------- GET/SET IN BRACKETS ---------------------------
+function TGLSMemoStrings.GetInBrackets(Index: Integer): integer;
+ Result := -1
+ Result := P.FInBrackets;
+procedure TGLSMemoStrings.SetInBrackets(Index: Integer; Value: integer);
+ P.FInBrackets := Value;
+//-------------------- GET/SET VALID ATTRS ---------------------------
+function TGLSMemoStrings.GetValidAttrs(Index: Integer): Boolean;
+ Result := P.FValidAttrs;
+procedure TGLSMemoStrings.SetValidAttrs(Index: Integer; Value: Boolean);
+ P.FValidAttrs := Value;
+//-------------------- GET/SET CHAR ATTRS ---------------------------
+function TGLSMemoStrings.GetCharAttrs(Index: Integer): string;
+ Result := ''
+ Result := P.FCharAttrs;
+procedure TGLSMemoStrings.SetCharAttrs(Index: Integer; const Value: string);
+ P.FCharAttrs := Value;
+// ---------------------TGLSMemoUndo
+constructor TGLSMemoUndo.Create(ACurX0, ACurY0, ACurX, ACurY: integer; const AText:
+ FUndoCurX0 := ACurX0;
+ FUndoCurY0 := ACurY0;
+ FUndoCurX := ACurX;
+ FUndoCurY := ACurY;
+ FUndoText := AText;
+procedure TGLSMemoUndo.Undo;
+ CurY := FUndoCurY;
+ CurX := FUndoCurX;
+ PerformUndo;
+ CurY := FUndoCurY0;
+ CurX := FUndoCurX0;
+procedure TGLSMemoUndo.Redo;
+ PerformRedo;
+function TGLSMemoUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
+//---------------- TINSERT CHAR UNDO --------------------------
+procedure TGLSMemoInsCharUndo.PerformUndo;
+ CurrLine: string;
+ for i := Length(FUndoText) downto 1 do
+ CurrLine := FMemo.Lines[FMemo.CurY];
+ if ((FUndoText[i] = #13) and (FMemo.CurX = 0)) or
+ (FUndoText[i] = CurrLine[FMemo.CurX]) then
+ FMemo.BackSpace;
+procedure TGLSMemoInsCharUndo.PerformRedo;
+ for i := 1 to Length(FUndoText) do
+ if FUndoText[i] = #13 then
+ NewLine
+ InsertChar(FUndoText[i]);
+function TGLSMemoInsCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
+ if not ((NewUndo is TGLSMemoInsCharUndo) and
+ (NewUndo.UndoCurX0 = FUndoCurX) and
+ (NewUndo.UndoCurY0 = FUndoCurY)) then
+ FUndoText := FUndoText + NewUndo.FUndoText;
+ FUndoCurX := NewUndo.UndoCurX;
+ FUndoCurY := NewUndo.UndoCurY;
+//---------------- TDELETE CHAR UNDO --------------------------
+procedure TGLSMemoDelCharUndo.PerformUndo;
+ if not FIsBackspace then
+procedure TGLSMemoDelCharUndo.PerformRedo;
+ if FIsBackspace then
+ BackSpace
+function TGLSMemoDelCharUndo.Append(NewUndo: TGLSMemoUndo): Boolean;
+ if not ((NewUndo is TGLSMemoDelCharUndo) and
+ if TGLSMemoDelCharUndo(NewUndo).FIsBackspace <> FIsBackspace then
+ FUndoText := NewUndo.FUndoText + FUndoText;
+//---------------- TDELETE BUF, LINE UNDO --------------------------
+constructor TGLSMemoDelLineUndo.Create(AIndex, ACurX0, ACurY0, ACurX, ACurY:
+ integer; const AText: string);
+ inherited Create(ACurX0, ACurY0, ACurX, ACurY, AText);
+ FIndex := AIndex;
+procedure TGLSMemoDelLineUndo.PerformUndo;
+ SaveCurX: integer;
+ SaveCurX := CurX;
+ SetSelText(PChar(FUndoText + #13#10));
+ CurX := SaveCurX;
+procedure TGLSMemoDelLineUndo.PerformRedo;
+ FMemo.DeleteLine(FIndex, FUndoCurX0, FUndoCurY0, FUndoCurX, FUndoCurY, True);
+procedure TGLSMemoDeleteBufUndo.PerformUndo;
+ SetSelText(PChar(FUndoText));
+procedure TGLSMemoDeleteBufUndo.PerformRedo;
+ FSelStartX := FUndoSelStartX;
+ FSelStartY := FUndoSelStartY;
+ FSelEndX := FUndoSelEndX;
+ FSelEndY := FUndoSelEndY;
+//---------------- TPASTE UNDO --------------------------
+procedure TGLSMemoPasteUndo.PerformUndo;
+ FSelStartX := FUndoCurX0;
+ FSelStartY := FUndoCurY0;
+ FSelEndX := FUndoCurX;
+ FSelEndY := FUndoCurY;
+procedure TGLSMemoPasteUndo.PerformRedo;
+//---------------- TUNDO LIST --------------------------
+constructor TGLSMemoUndoList.Create;
+ FPos := 0;
+ FIsPerforming := False;
+ FLimit := 100;
+destructor TGLSMemoUndoList.Destroy;
+function TGLSMemoUndoList.Get(Index: Integer): TGLSMemoUndo;
+ Result := TGLSMemoUndo(inherited Get(Index));
+function TGLSMemoUndoList.Add(Item: Pointer): Integer;
+ if FIsPerforming then
+ TGLSMemoUndo(Item).Free;
+ if (Count > 0) and
+ Items[0].Append(TGLSMemoUndo(Item)) then
+ TGLSMemoUndo(Item).FMemo := Self.FMemo;
+ if FPos > 0 then
+ while FPos > 0 do
+ Dec(FPos);
+ Insert(0, Item);
+ if Count > FLimit then
+ Delete(Count - 1);
+ Memo.UndoChange;
+procedure TGLSMemoUndoList.Clear;
+ with Memo do
+ if not (csDestroying in ComponentState) then
+ UndoChange;
+procedure TGLSMemoUndoList.Delete(Index: Integer);
+ TGLSMemoUndo(Items[Index]).Free;
+procedure TGLSMemoUndoList.Undo;
+ OldAutoIndent: Boolean;
+ if FPos < Count then
+ OldAutoIndent := Memo.AutoIndent;
+ Memo.AutoIndent := False;
+ FIsPerforming := True;
+ Items[FPos].Undo;
+ Inc(FPos);
+ Memo.AutoIndent := OldAutoIndent;
+procedure TGLSMemoUndoList.Redo;
+ Items[FPos].Redo;
+procedure TGLSMemoUndoList.SetLimit(Value: integer);
+ if FLimit <> Value then
+ Value := 10;
+ if Value > 0 then
+ FLimit := Value;
+procedure TGLSSynHiMemo.Paint;
+ FIsPainting := True;
+ DelimiterStyle := FDelimiterStyle;
+ CommentStyle := FCommentStyle;
+ NumberStyle := FNumberStyle;
+ FIsPainting := False;
+// ---------------------TGLSSynHiMemo
+procedure TGLSSynHiMemo.SetStyle(Index: integer; Value: TCharStyle);
+ No: integer;
+ No := -1;
+ 0: No := FDelimiterStyleNo;
+ 1: No := FCommentStyleNo;
+ 2: No := FNumberStyleNo;
+ with Value do
+ Styles.Change(No, TextColor, BkColor, Style);
+ if not FIsPainting then
+// SYNTAX MEMO - SET WORD LIST
+procedure TGLSSynHiMemo.SetWordList(Value: TGLSMemoStringList);
+ FWordList.Assign(Value);
+procedure TGLSSynHiMemo.SetSpecialList(Value: TGLSMemoStringList);
+ FSpecialList.Assign(Value);
+procedure TGLSSynHiMemo.SetBracketList(Value: TGLSMemoStringList);
+ FBracketList.Assign(Value);
+// SYNTAX MEMO - SET CASE SENSITIVE
+procedure TGLSSynHiMemo.SetCaseSensitive(Value: Boolean);
+ LineNo: integer;
+ if Value <> FCaseSensitive then
+ FCaseSensitive := Value;
+ for LineNo := 0 to Lines.Count - 1 do
+// SYNTAX MEMO - GET TOKEN
+function TGLSSynHiMemo.GetToken(const S: string; var From: integer;
+ 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;
+ Result := (StrLComp(PChar(S) + Pos - 1, PChar(S0), Length(S0)) = 0);
+ function Equal(const s1, s2: string): Boolean;
+ if FCaseSensitive then
+ Result := s1 = s2
+ Result := AnsiLowerCase(s1) = AnsiLowerCase(s2);
+ toStart := From;
+ toEnd := From;
+ TokenType := ttOther;
+ StyleNo := 0;
+ // End of line
+ if From > Len then
+ From := -1;
+ TokenType := ttEOL;
+ // Begin of multiline comment
+ if (MultiCommentLeft <> '') and (MultiCommentRight <> '') and
+ StartsFrom(S, From, MultiCommentLeft) then
+ Result := MultiCommentLeft;
+ FInComment := True;
+ TokenType := ttComment;
+ StyleNo := FCommentStyleNo;
+ Inc(From, Length(MultiCommentLeft));
+ // Inside multiline comment
+ if FInComment then
+ toEnd := toStart;
+ while (toEnd <= Len) and (not StartsFrom(S, toEnd, MultiCommentRight)) do
+ Inc(toEnd);
+ if toEnd > Len then
+ Result := Copy(S, From, toEnd - From);
+ From := toEnd;
+ toEnd := toEnd + Length(MultiCommentRight);
+ // Inside brikets
+ if FInBrackets >= 0 then
+ Brackets := FBracketList[FInBrackets];
+ toEnd := toStart + 1;
+ while (toEnd <= Len) and (S[toEnd] <> Brackets[2]) do
+ StyleNo := integer(FBracketList.Objects[FInBrackets]);
+ if toEnd <= Len then
+ From := toEnd + 1;
+ Result := Copy(S, toStart, toEnd - toStart + 1);
+ TokenType := ttBracket;
+ // Spaces
+ while (toStart <= Len) and (S[toStart] = ' ') do
+ Inc(toStart);
+ if toStart > From then
+ Result := Copy(S, From, toStart - From);
+ From := toStart;
+ TokenType := ttSpace;
+ // Comment
+ if (FLineComment <> '') and StartsFrom(S, From, FLineComment) then
+ Result := Copy(S, From, Len);
+ From := Len + 1;
+ // Special keyword
+ Done := False;
+ for i := 0 to FSpecialList.Count - 1 do
+ LenSpec := Length(FSpecialList[i]);
+ if StrLComp(PChar(S) + toStart - 1,
+ PChar(FSpecialList[i]), LenSpec) = 0 then
+ toEnd := toStart + LenSpec - 1;
+ StyleNo := integer(FSpecialList.Objects[i]);
+ TokenType := ttSpecial;
+ Done := True;
+ // Brickets
+ if not Done then
+ for i := 0 to FBracketList.Count - 1 do
+ Brackets := FBracketList[i];
+ if S[toStart] = Brackets[1] then
+ FInBrackets := i;
+ FInBrackets := -1
+ Dec(toEnd);
+ StyleNo := integer(FBracketList.Objects[i]);
+ // Delimeters
+ if not Done and CharInSet(S[toStart], Delimiters) then
+ StyleNo := FDelimiterStyleNo;
+ TokenType := ttDelimiter;
+ // --- Integer or float type
+ if not Done and CharInSet(S[toStart], ['0'..'9', '.']) then
+ IntPart := 0;
+ WasPoint := False;
+ TokenType := ttInteger;
+ StyleNo := FNumberStyleNo;
+ while (toEnd <= Len) and CharInSet(S[toEnd], ['0'..'9', '.']) do
+ if S[toEnd] = '.' then
+ if not WasPoint then
+ WasPoint := True;
+ TokenType := ttFloat;
+ TokenType := ttWrongNumber;
+ Color := clRed;
+ else if not WasPoint then
+ IntPart := IntPart * 10 + Ord(S[toEnd]) - Ord('0');
+ IntPart := MaxInt;
+ // Select word
+ while (toEnd <= Len) and not CharInSet(S[toEnd], Delimiters) do
+ // Find in dictionary
+ for i := 0 to FWordList.Count - 1 do
+ if Equal(Result, FWordList[i]) then
+ StyleNo := integer(FWordList.Objects[i]);
+ TokenType := ttWord;
+// SYNTAX MEMO - FIND LINE ATTRS
+procedure TGLSSynHiMemo.FindLineAttrs(Sender: TObject; LineNo: integer;
+ var Attrs: string);
+ i, From, TokenLen: integer;
+ S, Token: string;
+ TokenType: TTokenType;
+ StyleNo, OldInBrackets: integer;
+ OldInComment: Boolean;
+ SetLength(Attrs, Length(S));
+ FInComment := InComment[LineNo];
+ FInBrackets := InBrackets[LineNo];
+ From := 1;
+ Token := GetToken(S, From, TokenType, StyleNo);
+ if TokenType = ttEOL then
+ TokenLen := Length(Token);
+ for i := From - TokenLen to From - 1 do
+ Attrs[i] := Char(StyleNo);
+ if LineNo < Lines.Count - 1 then
+ OldInComment := InComment[LineNo + 1];
+ OldInBrackets := InBrackets[LineNo + 1];
+ if OldInComment <> FInComment then
+ InComment[LineNo + 1] := FInComment;
+ ValidAttrs[LineNo + 1] := False;
+ if OldInBrackets <> FInBrackets then
+ InBrackets[LineNo + 1] := FInBrackets;
+// SYNTAX MEMO - ADD WORD
+procedure TGLSSynHiMemo.AddWord(StyleNo: integer; const ArrS: array of string);
+ for i := Low(ArrS) to high(ArrS) do
+ FWordList.AddObject(ArrS[i], TObject(StyleNo));
+// SYNTAX MEMO - ADD SPECIAL
+procedure TGLSSynHiMemo.AddSpecial(StyleNo: integer; const ArrS: array of string);
+ FSpecialList.AddObject(ArrS[i], TObject(StyleNo));
+// SYNTAX MEMO - ADD BRACKETS
+procedure TGLSSynHiMemo.AddBrackets(StyleNo: integer; const ArrS: array of string);
+ FBracketList.AddObject(ArrS[i], TObject(StyleNo));
+// SYNTAX MEMO - CREATE
+constructor TGLSSynHiMemo.Create(AOwner: TComponent);
+ FWordList := TGLSMemoStringList.Create;
+ FSpecialList := TGLSMemoStringList.Create;
+ FBracketList := TGLSMemoStringList.Create;
+ FDelimiterStyle := TCharStyle.Create;
+ with FDelimiterStyle do
+ TextColor := clBlue;
+ BkColor := clWhite;
+ Style := [];
+ FCommentStyle := TCharStyle.Create;
+ with FCommentStyle do
+ TextColor := clYellow;
+ BkColor := clSkyBlue;
+ Style := [fsItalic];
+ FNumberStyle := TCharStyle.Create;
+ with FNumberStyle do
+ TextColor := clNavy;
+ Style := [fsBold];
+ FDelimiterStyleNo := Styles.Add(clBlue, clWhite, []);
+ FCommentStyleNo := Styles.Add(clSilver, clWhite, [fsItalic]);
+ FNumberStyleNo := Styles.Add(clNavy, clWhite, [fsBold]);
+ OnGetLineAttrs := FindLineAttrs;
+ Delimiters := [' ', ',', ';', ':', '.', '(', ')', '{', '}', '[', ']',
+ '=', '+', '-', '*', '/', '^', '%', '<', '>',
+ '"', '''', #13, #10];
+// SYNTAX MEMO - DESTROY
+destructor TGLSSynHiMemo.Destroy;
+ FWordList.Free;
+ FSpecialList.Free;
+ FBracketList.Free;
+ FDelimiterStyle.Free;
+ FCommentStyle.Free;
+ FNumberStyle.Free;
+// ---------------------TGLSMemoStringList
+procedure TGLSMemoStringList.ReadStrings(Reader: TReader);
+ Reader.ReadListBegin;
+ while not Reader.EndOfList do
+ i := Add(Reader.ReadString);
+ Objects[i] := TObject(Reader.ReadInteger);
+ Reader.ReadListEnd;
+// STRING LIST - WRITE STRINGS
+procedure TGLSMemoStringList.WriteStrings(Writer: TWriter);
+ with Writer do
+ WriteListBegin;
+ for i := 0 to Count - 1 do
+ WriteString(Strings[i]);
+ WriteInteger(Integer(Objects[i]));
+ WriteListEnd;
+// STRING LIST - DEFINE PROPERTIES
+procedure TGLSMemoStringList.DefineProperties(Filer: TFiler);
+ Filer.DefineProperty('Strings', ReadStrings, WriteStrings, Count > 0);
+// ---------------------ScrollBar bitmaps
+procedure CreateScrollBarBitmaps;
+ i, j: integer;
+ bmScrollBarFill := TBitmap.Create;
+ with bmScrollBarFill, Canvas do
+ 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;
+ bmScrollBarUp := TBitmap.Create;
+ with bmScrollBarUp, Canvas do
+ Width := 7;
+ 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);
+ bmScrollBarDown := TBitmap.Create;
+ with bmScrollBarDown, Canvas do
+ MoveTo(0, 2);
+ LineTo(7, 2);
+ MoveTo(1, 3);
+ LineTo(6, 3);
+ MoveTo(2, 4);
+ LineTo(5, 4);
+ Pixels[3, 5] := clBlack;
+ bmScrollBarLeft := TBitmap.Create;
+ with bmScrollBarLeft, Canvas do
+ Height := 7;
+ Pixels[2, 3] := clBlack;
+ MoveTo(3, 2);
+ LineTo(3, 5);
+ MoveTo(4, 1);
+ LineTo(4, 6);
+ MoveTo(5, 0);
+ LineTo(5, 7);
+ bmScrollBarRight := TBitmap.Create;
+ with bmScrollBarRight, Canvas do
+ MoveTo(2, 0);
+ LineTo(2, 7);
+ MoveTo(3, 1);
+ LineTo(3, 6);
+ MoveTo(4, 2);
+ LineTo(4, 5);
+ Pixels[5, 3] := clBlack;
+//------------------ FREE SCROLL BAR BITMAPs -------------------
+procedure FreeScrollBarBitmaps;
+ bmScrollBarFill.Free;
+ bmScrollBarUp.Free;
+ bmScrollBarDown.Free;
+ bmScrollBarLeft.Free;
+ bmScrollBarRight.Free;
+//----------------------------------
+ RegisterClasses([TGLSSynHiMemo]);
+ CreateScrollBarBitmaps;
+ IntelliMouseInit;
+finalization
+ FreeScrollBarBitmaps;
@@ -4,7 +4,7 @@
unit GLS.ParallelRegister;
-(* Registration unit for GLScene GPU Computing package *)
+(* Registration unit for GPU Computing package *)
@@ -1,402 +1,416 @@
- An old PlugIn Manager unit. Don't know if if ever wa used...
-unit GLPlugInManager;
- Winapi.Windows,
- GLPlugInIntf;
- PPlugInEntry = ^TGLPlugInEntry;
- TGLPlugInEntry = record
- Path: TFileName;
- Handle: HINST;
- FileSize: Integer;
- FileDate: TDateTime;
- EnumResourcenames: TEnumResourceNames;
- GetServices: TGetServices;
- GetVendor: TGetVendor;
- GetDescription: TGetDescription;
- GetVersion: TGetVersion;
- TGLPlugInManager = class;
- TGLResourceManager = class(TComponent)
- procedure Notify(Sender: TGLPlugInManager; Operation: TOperation;
- Service: TPIServiceType; PlugIn: Integer); virtual; abstract;
- TGLPlugInList = class(TStringList)
- FOwner: TGLPlugInManager;
- function GetPlugInEntry(Index: Integer): PPlugInEntry;
- procedure SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
- procedure ReadPlugIns(Reader: TReader);
- procedure WritePlugIns(Writer: TWriter);
- constructor Create(AOwner: TGLPlugInManager); virtual;
- procedure ClearList;
- property Objects[Index: Integer]: PPlugInEntry read GetPlugInEntry
- write SetPlugInEntry; default;
- property Owner: TGLPlugInManager read FOwner;
- PResManagerEntry = ^TResManagerEntry;
- TResManagerEntry = record
- Manager: TGLResourceManager;
- Services: TPIServices;
- TGLPlugInManager = class(TComponent)
- FLibraryList: TGLPlugInList;
- FResManagerList: TList;
- procedure DoNotify(Operation: TOperation; Service: TPIServiceType;
- PlugIn: Integer);
- function FindResManager(AManager: TGLResourceManager): PResManagerEntry;
- function GetIndexFromFilename(FileName: String): Integer;
- function GetPlugInFromFilename(FileName: String): PPlugInEntry;
- function AddPlugIn(Path: TFileName): Integer;
- procedure EditPlugInList;
- procedure RegisterResourceManager(AManager: TGLResourceManager;
- Services: TPIServices);
- procedure RemovePlugIn(Index: Integer);
- procedure UnRegisterRessourceManager(AManager: TGLResourceManager;
- property PlugIns: TGLPlugInList read FLibraryList write FLibraryList;
-// ------------------------------------------------------------------------------
-// ----------------- TGLPlugInList ------------------------------------------------
-constructor TGLPlugInList.Create(AOwner: TGLPlugInManager);
- FOwner := AOwner;
- Sorted := False;
- Duplicates := DupAccept;
-procedure TGLPlugInList.ClearList;
- FOwner.RemovePlugIn(0);
-function TGLPlugInList.GetPlugInEntry(Index: Integer): PPlugInEntry;
- Result := PPlugInEntry( inherited Objects[Index]);
-procedure TGLPlugInList.SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
- inherited Objects[Index] := Pointer(AEntry);
-procedure TGLPlugInList.WritePlugIns(Writer: TWriter);
- I: Integer;
- Writer.WriteListBegin;
- for I := 0 to Count - 1 do
- Writer.WriteString(Objects[I].Path);
- Writer.WriteListEnd;
-procedure TGLPlugInList.ReadPlugIns(Reader: TReader);
- ClearList;
- FOwner.AddPlugIn(Reader.ReadString);
-procedure TGLPlugInList.DefineProperties(Filer: TFiler);
- Filer.DefineProperty('Paths', ReadPlugIns, WritePlugIns, Count > 0);
-// ----------------- TGLPlugInManager ---------------------------------------------
-constructor TGLPlugInManager.Create(AOwner: TComponent);
- inherited Create(AOwner);
- FLibraryList := TGLPlugInList.Create(Self);
- FResManagerList := TList.Create;
-destructor TGLPlugInManager.Destroy;
- FLibraryList.ClearList;
- FLibraryList.Free;
- for I := 0 to FResManagerList.Count - 1 do
- FreeMem(PResManagerEntry(FResManagerList[I]), SizeOf(TResManagerEntry));
- FResManagerList.Free;
- inherited Destroy;
-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
- NewPlugIn: PPlugInEntry;
- OldError: Integer;
- NewHandle: HINST;
- ServiceFunc: TGetServices;
- SearchRec: TSearchRec;
- Service: TPIServiceType;
- OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
- if Length(Path) > 0 then
- Result := GetIndexFromFilename(Path);
- // plug-in already registered?
- if Result > -1 then
- // 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
- // if address not found then the given library is not valid
- // release it from client memory
- FreeLibrary(NewHandle);
- // 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
- 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');
- 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);
- SetErrorMode(OldError);
-procedure TGLPlugInManager.DoNotify(Operation: TOperation;
- Service: TPIServiceType; PlugIn: Integer);
- 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);
-function TGLPlugInManager.FindResManager(AManager: TGLResourceManager)
- : PResManagerEntry;
- if PResManagerEntry(FResManagerList[I]).Manager = AManager then
- Result := PResManagerEntry(FResManagerList[I]);
-function TGLPlugInManager.GetIndexFromFilename(FileName: String): Integer;
- for I := 0 to FLibraryList.Count - 1 do
- if CompareText(FLibraryList[I].Path, FileName) = 0 then
-function TGLPlugInManager.GetPlugInFromFilename(FileName: String): PPlugInEntry;
- I := GetIndexFromFilename(FileName);
- if I > -1 then
- Result := FLibraryList[I]
-procedure TGLPlugInManager.RegisterResourceManager(AManager: TGLResourceManager;
- ManagerEntry: PResManagerEntry;
- ManagerEntry := FindResManager(AManager);
- if assigned(ManagerEntry) then
- ManagerEntry.Services := ManagerEntry.Services + Services
- New(ManagerEntry);
- ManagerEntry.Manager := AManager;
- ManagerEntry.Services := Services;
- FResManagerList.Add(ManagerEntry);
-procedure TGLPlugInManager.RemovePlugIn(Index: Integer);
- Entry: PPlugInEntry;
- Entry := FLibraryList.Objects[Index];
- Services := Entry.GetServices;
- // notify for all services to be deleted all registered resource managers
- DoNotify(opRemove, Service, Index);
- FreeLibrary(Entry.Handle);
- Dispose(Entry);
- FLibraryList.Delete(Index);
-procedure TGLPlugInManager.EditPlugInList;
- ///TGLPlugInManagerEditor.EditPlugIns(Self); //Circular call to edit Listbox items?
-procedure TGLPlugInManager.UnRegisterRessourceManager(AManager: TGLResourceManager;
- Index: Integer;
- ManagerEntry.Services := ManagerEntry.Services - Services;
- if ManagerEntry.Services = [] then
- Index := FResManagerList.IndexOf(ManagerEntry);
- Dispose(ManagerEntry);
- FResManagerList.Delete(Index);
+unit GLS.PlugInManager;
+(* An old PlugIn Manager unit. Yet not ever was used... *)
+ Winapi.Windows,
+ VCL.Forms;
+ 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;
+ PPlugInEntry = ^TGLPlugInEntry;
+ TGLPlugInEntry = record
+ Path: TFileName;
+ Handle: HINST;
+ FileSize: Integer;
+ FileDate: TDateTime;
+ EnumResourcenames: TEnumResourceNames;
+ GetServices: TGetServices;
+ GetVendor: TGetVendor;
+ GetDescription: TGetDescription;
+ GetVersion: TGetVersion;
+ TGLPlugInManager = class;
+ TGLResourceManager = class(TComponent)
+ procedure Notify(Sender: TGLPlugInManager; Operation: TOperation;
+ Service: TPIServiceType; PlugIn: Integer); virtual; abstract;
+ TGLPlugInList = class(TStringList)
+ FOwner: TGLPlugInManager;
+ function GetPlugInEntry(Index: Integer): PPlugInEntry;
+ procedure SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
+ procedure ReadPlugIns(Reader: TReader);
+ procedure WritePlugIns(Writer: TWriter);
+ constructor Create(AOwner: TGLPlugInManager); virtual;
+ procedure ClearList;
+ property Objects[Index: Integer]: PPlugInEntry read GetPlugInEntry
+ write SetPlugInEntry; default;
+ property Owner: TGLPlugInManager read FOwner;
+ PResManagerEntry = ^TResManagerEntry;
+ TResManagerEntry = record
+ Manager: TGLResourceManager;
+ Services: TPIServices;
+ TGLPlugInManager = class(TComponent)
+ FLibraryList: TGLPlugInList;
+ FResManagerList: TList;
+ procedure DoNotify(Operation: TOperation; Service: TPIServiceType;
+ PlugIn: Integer);
+ function FindResManager(AManager: TGLResourceManager): PResManagerEntry;
+ function GetIndexFromFilename(FileName: String): Integer;
+ function GetPlugInFromFilename(FileName: String): PPlugInEntry;
+ function AddPlugIn(Path: TFileName): Integer;
+ procedure EditPlugInList;
+ procedure RegisterResourceManager(AManager: TGLResourceManager;
+ Services: TPIServices);
+ procedure RemovePlugIn(Index: Integer);
+ procedure UnRegisterRessourceManager(AManager: TGLResourceManager;
+ property PlugIns: TGLPlugInList read FLibraryList write FLibraryList;
+// ------------------------------------------------------------------------------
+// ----------------- TGLPlugInList ------------------------------------------------
+constructor TGLPlugInList.Create(AOwner: TGLPlugInManager);
+ FOwner := AOwner;
+ Sorted := False;
+ Duplicates := DupAccept;
+procedure TGLPlugInList.ClearList;
+ FOwner.RemovePlugIn(0);
+function TGLPlugInList.GetPlugInEntry(Index: Integer): PPlugInEntry;
+ Result := PPlugInEntry( inherited Objects[Index]);
+procedure TGLPlugInList.SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
+ inherited Objects[Index] := Pointer(AEntry);
+procedure TGLPlugInList.WritePlugIns(Writer: TWriter);
+ I: Integer;
+ Writer.WriteListBegin;
+ for I := 0 to Count - 1 do
+ Writer.WriteString(Objects[I].Path);
+ Writer.WriteListEnd;
+procedure TGLPlugInList.ReadPlugIns(Reader: TReader);
+ ClearList;
+ FOwner.AddPlugIn(Reader.ReadString);
+procedure TGLPlugInList.DefineProperties(Filer: TFiler);
+ Filer.DefineProperty('Paths', ReadPlugIns, WritePlugIns, Count > 0);
+// ----------------- TGLPlugInManager ---------------------------------------------
+constructor TGLPlugInManager.Create(AOwner: TComponent);
+ FLibraryList := TGLPlugInList.Create(Self);
+ FResManagerList := TList.Create;
+destructor TGLPlugInManager.Destroy;
+ FLibraryList.ClearList;
+ FLibraryList.Free;
+ for I := 0 to FResManagerList.Count - 1 do
+ FreeMem(PResManagerEntry(FResManagerList[I]), SizeOf(TResManagerEntry));
+ FResManagerList.Free;
+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
+ NewPlugIn: PPlugInEntry;
+ OldError: Integer;
+ NewHandle: HINST;
+ ServiceFunc: TGetServices;
+ SearchRec: TSearchRec;
+ Service: TPIServiceType;
+ OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
+ if Length(Path) > 0 then
+ Result := GetIndexFromFilename(Path);
+ // plug-in already registered?
+ if Result > -1 then
+ // 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
+ // if address not found then the given library is not valid
+ // release it from client memory
+ FreeLibrary(NewHandle);
+ // 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
+ 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');
+ 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);
+ SetErrorMode(OldError);
+procedure TGLPlugInManager.DoNotify(Operation: TOperation;
+ Service: TPIServiceType; PlugIn: Integer);
+ 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);
+function TGLPlugInManager.FindResManager(AManager: TGLResourceManager)
+ : PResManagerEntry;
+ if PResManagerEntry(FResManagerList[I]).Manager = AManager then
+ Result := PResManagerEntry(FResManagerList[I]);
+function TGLPlugInManager.GetIndexFromFilename(FileName: String): Integer;
+ for I := 0 to FLibraryList.Count - 1 do
+ if CompareText(FLibraryList[I].Path, FileName) = 0 then
+function TGLPlugInManager.GetPlugInFromFilename(FileName: String): PPlugInEntry;
+ I := GetIndexFromFilename(FileName);
+ if I > -1 then
+ Result := FLibraryList[I]
+procedure TGLPlugInManager.RegisterResourceManager(AManager: TGLResourceManager;
+ ManagerEntry: PResManagerEntry;
+ ManagerEntry := FindResManager(AManager);
+ if assigned(ManagerEntry) then
+ ManagerEntry.Services := ManagerEntry.Services + Services
+ New(ManagerEntry);
+ ManagerEntry.Manager := AManager;
+ ManagerEntry.Services := Services;
+ FResManagerList.Add(ManagerEntry);
+procedure TGLPlugInManager.RemovePlugIn(Index: Integer);
+ Entry: PPlugInEntry;
+ Entry := FLibraryList.Objects[Index];
+ Services := Entry.GetServices;
+ // notify for all services to be deleted all registered resource managers
+ DoNotify(opRemove, Service, Index);
+ FreeLibrary(Entry.Handle);
+ Dispose(Entry);
+ FLibraryList.Delete(Index);
+procedure TGLPlugInManager.EditPlugInList;
+ ///TGLPlugInManagerEditor.EditPlugIns(Self); //Circular call to edit Listbox items?
+procedure TGLPlugInManager.UnRegisterRessourceManager(AManager: TGLResourceManager;
+ Index: Integer;
+ ManagerEntry.Services := ManagerEntry.Services - Services;
+ if ManagerEntry.Services = [] then
+ Index := FResManagerList.IndexOf(ManagerEntry);
+ Dispose(ManagerEntry);
+ FResManagerList.Delete(Index);
@@ -5,7 +5,7 @@
unit GLS.SceneRegister;
(*
- Registration unit for GLScene library components, property editors and
+ Registration unit for library components, property editors and
IDE experts.
*)
@@ -29,12 +29,12 @@ uses
DesignEditors,
VCLEditors,
- GLScene,
- GLStrings,
GLContext,
GLCrossPlatform,
- GLObjectManager;
+ GLObjectManager,
+ GLStrings;
TGLLibMaterialNameProperty = class(TStringProperty)
@@ -287,6 +287,7 @@ uses
FShaderUniformEditor,
FVectorEditor,
FSceneEditor,
GLAnimatedSprite,
GLAsmShader,
@@ -383,24 +384,22 @@ uses
GLTimeEventsMgr,
GLTrail,
GLTree,
- GLFileTIN,
GLUserShader,
- GLVfsPAK,
GLWin32Viewer,
GLWaterPlane,
GLWindows,
GLWindowsFont,
GLzBuffer,
- GLSMemo,
+ GLS.Memo,
- // Image file formats
+//----------------- File formats
+ GLFileVfsPAK,
FileDDSImage,
FileTGA,
- // Vector file formats
+//------------------ Vector file formats
GLFile3DS,
GLFileASE,
GLFileB3D,
@@ -423,11 +422,11 @@ uses
GLFileSTL,
GLFileVRML,
- // Sound file formats
+//----------------- Sound file formats
GLFileWAV,
GLFileMP3,
- // Raster file format
+//----------------- Raster file format
GLFileDDS,
GLFileO3TC,
GLFileHDR,
@@ -1327,14 +1326,14 @@ end;
procedure GLRegisterPropertiesInCategories;
// property types
- // TGLScreenDepth in GLWin32FullScreenViewer
+ // ScreenDepth in Win32FullScreenViewer
RegisterPropertiesInCategory(strOpenGLCategoryName,
[TypeInfo(TGLCamera), TypeInfo(TGLSceneBuffer),
TypeInfo(TGLVSyncMode), TypeInfo(TGLScreenDepth)]);
- // TGLSceneViewer
+ // SceneViewer
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLSceneViewer, ['*Render']);
- // GLScene
+ // Scene
[TypeInfo(TGLObjectsSorting), TypeInfo(TGLProgressEvent),
TypeInfo(TGLBehaviours), TypeInfo(TGLEffects),
@@ -1355,16 +1354,10 @@ begin
RegisterPropertiesInCategory(strVisualCategoryName, TGLCamera, ['DepthOfView', 'SceneScale']);
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLNonVisualViewer, ['*Render']);
- // GLObjects
+ // Objects
[TypeInfo(TGLLinesNodes), TypeInfo(TGLLineNodesAspect),
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
RegisterPropertiesInCategory(strLayoutCategoryName, TGLDummyCube, ['VisibleAtRunTime']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLDummyCube, ['CubeSize', 'VisibleAtRunTime']);
@@ -1377,7 +1370,12 @@ begin
['Antialiased', 'Division', 'Line*', 'NodeSize']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLCube, ['Cube*']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLFrustrum, ['ApexHeight', 'Base*']);
+ // SpaceText
+ RegisterPropertiesInCategory(strLayoutCategoryName, [TypeInfo(TGLTextAdjust)]);
+ RegisterPropertiesInCategory(strLocalizableCategoryName, [TypeInfo(TGLSpaceTextCharRange)]);
+ RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TGLLineSplineMode),
+ TypeInfo(TGLCapType), TypeInfo(TGLNormalSmoothing),
+ TypeInfo(TGLArrowHeadStyle), TypeInfo(TGLTextAdjust)]);
RegisterPropertiesInCategory(strVisualCategoryName, TGLSpaceText,
['AllowedDeviation', 'AspectRatio', 'Extrusion', 'Oblique', 'TextHeight']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLSphere,
@@ -1398,12 +1396,12 @@ begin
['Bottom*', 'Loops', 'Slices', 'Stacks', 'Top*']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLPolygon, ['Division']);
- // GLMultiPolygon
+ // MultiPolygon
RegisterPropertiesInCategory(strVisualCategoryName, TGLContour, ['Division']);
RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLContourNodes),
TypeInfo(TGLContours)]);
- // GLExtrusion
+ // Extrusion
RegisterPropertiesInCategory(strVisualCategoryName, TGLExtrusionSolid, ['Stacks']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLPipeNode, ['RadiusFactor']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLPipe,
@@ -1413,7 +1411,7 @@ begin
RegisterPropertiesInCategory(strVisualCategoryName, TGLRevolutionSolid,
['Division', 'Slices', 'YOffsetPerTurn']);
- // GLVectorFileObjects
+ // VectorFileObjects
[TypeInfo(TGLActorAnimationMode), TypeInfo(TGLActorAnimations),
TypeInfo(TGLMeshAutoCenterings), TypeInfo(TGLActorFrameInterpolation),
@@ -1431,11 +1429,11 @@ begin
['*Frame*', 'Interval', 'OverlaySkeleton', 'UseMeshmaterials']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLActor, ['OverlaySkeleton']);
- // GLMesh
+ // Mesh
[TypeInfo(TGLMeshMode), TypeInfo(TGLVertexMode)]);
- // GLGraph
+ // Graph
[TypeInfo(TGLHeightFieldOptions)]);
RegisterPropertiesInCategory(strVisualCategoryName,
@@ -1444,11 +1442,11 @@ begin
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLXYZGrid, ['Antialiased']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLXYZGrid, ['Antialiased', 'Line*']);
- // GLParticles
+ // Particles
RegisterPropertiesInCategory(strLayoutCategoryName, TGLParticles, ['VisibleAtRunTime']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLParticles, ['*Size', 'VisibleAtRunTime']);
- // GLSkydome
+ // Skydome
[TypeInfo(TGLSkyDomeBands), TypeInfo(TGLSkyDomeOptions), TypeInfo(TGLSkyDomeStars)]);
RegisterPropertiesInCategory(strVisualCategoryName, TGLSkyDomeBand, ['Slices', 'Stacks', '*Angle']);
@@ -1456,11 +1454,11 @@ begin
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLEarthSkyDome,
['Slices', 'Stacks', 'SunElevation', 'Turbidity']);
- // GLMirror
+ // Mirror
[TypeInfo(TGLMirrorOptions), TypeInfo(TGLBaseSceneObject)]);
- // GLParticleFX
+ // ParticleFX
RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLBlendingMode)]);
[TypeInfo(TGLBlendingMode), TypeInfo(TPFXLifeColors), TypeInfo(TSpriteColorMode)]);
@@ -1472,69 +1470,60 @@ begin
RegisterPropertiesInCategory(strVisualCategoryName, TGLPolygonPFXManager, ['NbSides']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLPointLightPFXManager, ['TexMapSize']);
- // GLTerrainRenderer
+ // TerrainRenderer
RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLHeightDataSource)]);
RegisterPropertiesInCategory(strVisualCategoryName, TGLTerrainRenderer,
['*CLOD*', 'QualityDistance', 'Tile*']);
- // GLzBuffer
+ // zBuffer
RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLMemoryViewer),
TypeInfo(TGLSceneViewer), TypeInfo(TOptimise)]);
RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TOptimise)]);
RegisterPropertiesInCategory(strVisualCategoryName, TGLZShadows,
['DepthFade', '*Shadow', 'Soft', 'Tolerance']);
- // GLHUDObjects
+ // HUDObjects
RegisterPropertiesInCategory(strLayoutCategoryName, [TypeInfo(TTextLayout)]);
RegisterPropertiesInCategory(strVisualCategoryName, [TypeInfo(TGLBitmapFont), TypeInfo(TTextLayout)]);
RegisterPropertiesInCategory(strLocalizableCategoryName,[TypeInfo(TGLBitmapFont)]);
- // GLTexture
+ // Texture
[TypeInfo(TGLMaterial), TypeInfo(TGLMaterialLibrary),
TypeInfo(TGLLibMaterials), TypeInfo(TGLTextureNeededEvent)]);
- RegisterPropertiesInCategory(strOpenGLCategoryName,
- TGLLibMaterial, ['Texture2Name']);
+ RegisterPropertiesInCategory(strOpenGLCategoryName, TGLLibMaterial, ['Texture2Name']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLLibMaterial, ['TextureOffset', 'TextureScale']);
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLMaterialLibrary, ['TexturePaths']);
- // GLCadencer
- [TypeInfo(TGLCadencer)]);
+ // Cadencer
+ RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TGLCadencer)]);
- // GLCollision
- [TypeInfo(TObjectCollisionEvent)]);
+ // Collision
+ RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TObjectCollisionEvent)]);
- // GLFireFX
+ // FireFX
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLFireFXManager,
['MaxParticles', 'NoZWrite', 'Paused', 'UseInterval']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLFireFXManager,
['Fire*', 'InitialDir', 'NoZWrite', 'Particle*', 'Paused']);
- // GLThorFX
- [TypeInfo(TCalcPointEvent)]);
+ // ThorFX
+ RegisterPropertiesInCategory(strOpenGLCategoryName, [TypeInfo(TCalcPointEvent)]);
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLThorFXManager,
['Maxpoints', 'Paused']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLThorFXManager,
['Core', 'Glow*', 'Paused', 'Target', 'Vibrate', 'Wildness']);
- // GLBitmapFont
- [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,
['Char*', '*Interval*', '*Space', 'Glyphs']);
- // GLHeightData
+ // HeightData
RegisterPropertiesInCategory(strOpenGLCategoryName, TGLBitmapHDS, ['MaxPoolSize']);
RegisterPropertiesInCategory(strVisualCategoryName, TGLBitmapHDS, ['Picture']);
@@ -1663,17 +1652,12 @@ begin
RegisterPropertyEditor(TypeInfo(TGLMaterialComponentName), TGLShaderModel5,
'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);
function GetGLSceneVersion: string;
@@ -1880,7 +1864,9 @@ begin
RegisterSceneObject(TGLFBORenderer, 'OpenGL FrameBuffer', '', HInstance);
+//------------------------------------------------------
ObjectManager.Free;
unit GLS.cgRegister;
-(* Registration unit for CG shader *)
+(* Registration unit for CG shader package *)
- Cross XML routines
unit GLSCrossXML;
+(* Cross XML routines *)
@@ -8093,3 +8093,4 @@ initialization
QueryPerformanceFrequency(vCounterFrequency);
@@ -38,7 +38,7 @@ uses
GLRenderContextInfo,
GLBaseClasses,
GLTextureFormat;
- Defines common vector types as advanced records.
-unit GLTypes;
+unit GLVectorRecTypes;
+(* Defines common vector types as advanced records *)
@@ -325,14 +325,14 @@ type
TxPolyhedron = array of TxPolygon3D;
TxPolyhedron = record
Facets: array of TxPolygon3D;
function NetLength;
function Area;
function Volume;
//--------------------------
// Mesh simple record types
@@ -775,7 +775,9 @@ begin
-{ TxVector }
+//-----------------------------
+// TxVector
constructor TxVector.Create(V: TAbstractVector);
@@ -986,7 +988,9 @@ begin
-{ TxQuatHelper }
+// TxQuatHelper
function TxQuatHelper.ToMatrix: TxMatrix;
@@ -1002,7 +1006,9 @@ begin
Result[3, 3] := Sqr(FData[0]) - Sqr(FData[1]) - Sqr(FData[2]) + Sqr(FData[3]);
-{ TxVecHelper }
+// TxVecHelper
function TxVecHelper.ToDiagMatrix: TxMatrix;
@@ -1079,7 +1085,9 @@ begin
-{ TxDim }
+// TxDim
constructor TxDim.Create(ARowCount: Integer; AColCount: Integer = 0);
@@ -1088,7 +1096,9 @@ begin
-{ TxPoint2D }
+// TxPoint2D
function TxPoint2D.Create(X, Y : Single): TxPoint2D;
@@ -1129,7 +1139,9 @@ begin
Result := Point.Distance(Center) <= Radius;
-{ TxPoint3D }
+// TxPoint3D
function TxPoint3D.Create(X, Y, Z: Single): TxPoint3D;
@@ -1169,7 +1181,9 @@ begin
Self.Z := Z;
-{ TxVector2D }
+// TxVector2D
function TxVector2D.Create(const AX, AY, AW: Single): TxVector2D;
@@ -1226,7 +1240,7 @@ begin
//---------------------------------
-{ TxVector3D }
+// TxVector3D
function TxVector3D.Create(const AX, AY, AZ, AW: Single): TxVector3D;
@@ -1287,7 +1301,7 @@ begin
-{ TxQuaternion }
+// TxQuaternion
function TxQuaternion.GetElement(Index: Byte): Extended;
@@ -1,452 +0,0 @@
- 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;
- System.Contnrs,
- GLApplicationFileIO;
- SIGN = 'PACK'; //Signature for uncompressed - raw pak.
- SIGN_COMPRESSED = 'PACZ'; //Signature for compressed pak.
- TZCompressedMode = (Good, Fast, Auto, None);
- TPakHeader = record
- Signature: array[0..3] of AnsiChar;
- DirOffset: integer;
- DirLength: integer;
- TFileSection = record
- FileName: array[0..119] of AnsiChar;
- FilePos: integer;
- FileLength: integer;
- TGLVfsPAK = class (TComponent)
- 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);
- 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;
- // 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;
-// for GLApplicationFileIO unit
-function PAKCreateFileStream(const fileName: string; mode: word): TStream;
-function PAKFileStreamExists(const fileName: string): boolean;
- ActiveVfsPAK: TGLVfsPak;
-//---------------------------------------------------------------------
- Dir: TFileSection;
-function BackToSlash(const s: string): string;
- SetLength(Result, Length(s));
- for i := 1 to Length(s) do
- if s[i] = '\' then
- Result[i] := '/'
- Result[i] := s[i];
-// GLApplicationFileIO 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));
- else begin
- if FileExists(fileName) then begin
- Result := TFileStream.Create(FileName, fmOpenReadWrite or fmShareDenyWrite);
- Result := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
- Result:=nil;
- for i:=0 to FStreamList.Count-1 do begin
- Result:=True;
- Result := FileExists(fileName);
-//--------------------------
-// TGLVfsPAK
-function TGLVfsPAK.GetStreamNumber: integer;
- Result:=FStreamList.IndexOf(FStream);
-procedure TGLVfsPAK.SetStreamNumber(i:integer);
-constructor TGLVfsPAK.Create(AOwner : TComponent);
- FPakFiles := TStringList.Create;
- FStreamList := TObjectList.Create(True);
- FFilesLists := TObjectList.Create(True);
- ActiveVfsPAK := Self;
- vAFIOCreateFileStream := PAKCreateFileStream;
- vAFIOFileStreamExists := PAKFileStreamExists;
- FCompressionLevel := None;
- FCompressed := False;
-constructor TGLVfsPAK.Create(AOwner : TComponent; const CbrMode: TZCompressedMode);
- Self.Create(AOwner);
- FCompressed := FCompressionLevel <> None;
-destructor TGLVfsPAK.Destroy;
- vAFIOCreateFileStream := nil;
- vAFIOFileStreamExists := nil;
- SetLength(FHeaderList, 0);
- FPakFiles.Free;
- // Objects are automatically freed by TObjectList
- FStreamList.Free;
- FFilesLists.Free;
- ActiveVfsPAK := nil;
-function TGLVfsPAK.GetFileCount: integer;
- Result := FHeader.DirLength div SizeOf(TFileSection);
-procedure TGLVfsPAK.MakeFileList;
- I: integer;
- FStream.Seek(FHeader.DirOffset, soFromBeginning);
- FFiles.Clear;
- for i := 0 to FileCount - 1 do
- FStream.ReadBuffer(Dir, SizeOf(TFileSection));
- FFiles.Add(string(Dir.FileName));
-procedure TGLVfsPAK.LoadFromFile(const FileName: string; Mode: word);
- l: integer;
- FFileName := FileName;
- FPakFiles.Clear;
- FPakFiles.Add(FileName);
- FFiles := TStringList.Create;
- FStream := TFileStream.Create(FileName, Mode);
- if FStream.Size = 0 then
- if FCompressed then
- FHeader.Signature := SIGN_COMPRESSED
- 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.');
- FStream.WriteBuffer(FHeader, SizeOf(TPakHeader));
- FStream.Position := 0;
- FStream.ReadBuffer(FHeader, SizeOf(TPakHeader));
- if (FHeader.Signature <> SIGN) and (FHeader.Signature <> SIGN_COMPRESSED) then
- raise Exception.Create(FileName+' - This is not PAK file');
- //Set the compression flag property.
- FCompressed := FHeader.Signature = SIGN_COMPRESSED;
- if FCompressed then begin
- if FileCount <> 0 then
- MakeFileList;
- l:=Length(FHeaderList);
- SetLength(FHeaderList, l+1);
- FHeaderList[l]:=FHeader;
- FFilesLists.Add(FFiles);
- FStreamList.Add(FStream);
-procedure TGLVfsPAK.ClearPakFiles;
- FStreamList.Clear;
- FFilesLists.Clear;
-function TGLVfsPAK.GetFile(index: integer): TStream;
- 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;
-function TGLVfsPAK.FileExists(const FileName: string): boolean;
- Result := (FFiles.IndexOf(FileName) > -1);
-function TGLVfsPAK.GetFile(const FileName: string): TStream;
- if Self.FileExists(FileName) then
- Result := GetFile(FFiles.IndexOf(FileName));
-function TGLVfsPAK.GetFileSize(index: integer): integer;
- FStream.Read(Dir, SizeOf(Dir));
- Result := Dir.FileLength;
-function TGLVfsPAK.GetFileSize(const FileName: string): integer;
- Result := GetFileSize(FFiles.IndexOf(FileName));
-{$WARNINGS OFF}
-procedure TGLVfsPAK.AddFromStream(const FileName, Path: string; F: TStream);
- Temp: TMemoryStream;
- FStream.Position := FHeader.DirOffset;
- if FHeader.DirLength > 0 then
- Temp := TMemoryStream.Create;
- Temp.CopyFrom(FStream, FHeader.DirLength);
- Temp.Position := 0;
- Dir.FilePos := FHeader.DirOffset;
- Dir.FileLength := F.Size;
- FStream.CopyFrom(F, 0);
- FHeader.DirOffset := FStream.Position;
- FStream.CopyFrom(Temp, 0);
- Temp.Free;
- StrPCopy(Dir.FileName, Path + ExtractFileName(FileName));
- FStream.WriteBuffer(Dir, SizeOf(TFileSection));
- FHeader.DirLength := FHeader.DirLength + SizeOf(TFileSection);
- FFiles.Add(Dir.FileName);
-{$WARNINGS ON}
-procedure TGLVfsPAK.AddFromFile(const FileName, Path: string);
- F: TFileStream;
- if not FileExists(FileName) then
- exit;
- F := TFileStream.Create(FileName, fmOpenRead);
- AddFromStream(FileName, Path, F);
- F.Free;
-procedure TGLVfsPAK.AddEmptyFile(const FileName, Path: string);
- F: TMemoryStream;
- F := TMemoryStream.Create;
-procedure TGLVfsPAK.RemoveFile(index: integer);
- f: TFileSection;
- FStream.Seek(Dir.FilePos + Dir.FileLength, soFromBeginning);
- Temp.CopyFrom(FStream, FStream.Size - FStream.Position);
- FStream.Position := Dir.FilePos;
- FHeader.DirOffset := FHeader.DirOffset - dir.FileLength;
- Temp.Clear;
- if i > index then
- 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));
- i := FHeader.DirOffset + SizeOf(TFileSection) * index;
- FStream.Position := i + SizeOf(TFileSection);
- if FStream.Position < FStream.Size then
- FStream.Position := i;
- FHeader.DirLength := FHeader.DirLength - SizeOf(TFileSection);
- FStream.Size := FStream.Size - dir.FileLength - SizeOf(TFileSection);
-procedure TGLVfsPAK.RemoveFile(const FileName: string);
- RemoveFile(FFiles.IndexOf(FileName));
-procedure TGLVfsPAK.Extract(index: integer; const NewName: string);
- s: TFileStream;
- if NewName = '' then
- if (index < 0) or (index >= FileCount) then
- s := TFileStream.Create(NewName, fmCreate);
- s.CopyFrom(GetFile(index), 0);
- s.Free;
-procedure TGLVfsPAK.Extract(const FileName, NewName: string);
- Extract(FFiles.IndexOf(FileName), NewName);
@@ -1,18 +1,18 @@
- OpenGL tokens
unit OpenGLTokens;
+(* OpenGL tokens *)
Winapi.Windows,
GLVectorTypes;