27
27
If you do not delete the provisions above, a recipient may use your version
28
28
of this file under either the MPL or the GPL.
30
$Id: synedittextbuffer.pp 36227 2012-03-22 18:28:03Z martin $
30
$Id: synedittextbuffer.pp 39835 2013-01-12 10:47:23Z martin $
32
32
You may retrieve the latest version of this file at the SynEdit home page,
33
33
located at http://SynEdit.SourceForge.net
181
181
function GetRange(Index: Pointer): TSynManagedStorageMem; override;
182
182
procedure PutRange(Index: Pointer; const ARange: TSynManagedStorageMem); override;
183
183
function Get(Index: integer): string; override;
184
function GetCapacity: integer;
185
{$IFDEF SYN_COMPILER_3_UP} override; {$ENDIF} //mh 2000-10-18
184
function GetCapacity: integer; override;
186
185
function GetCount: integer; override;
187
186
procedure SetCount(const AValue: Integer);
188
187
function GetObject(Index: integer): TObject; override;
189
188
procedure Put(Index: integer; const S: string); override;
190
189
procedure PutObject(Index: integer; AObject: TObject); override;
191
procedure SetCapacity(NewCapacity: integer);
192
{$IFDEF SYN_COMPILER_3_UP} override; {$ENDIF} //mh 2000-10-18
190
procedure SetCapacity(NewCapacity: integer); override;
193
191
procedure SetUpdateState(Updating: Boolean; Sender: TObject); override;
195
193
procedure UndoEditLinesDelete(LogY, ACount: Integer);
196
194
procedure IncreaseTextChangeStamp;
197
195
procedure DoGetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer; PWidths: PPhysicalCharWidth); override;
196
function LogicPosIsCombining(const AChar: PChar): Boolean; inline;
199
198
function GetDisplayView: TLazSynDisplayView; override;
236
235
property Modified: Boolean read FModified write SetModified;
237
// Char bounds // 1 based (1 is the 1st char in the line)
238
function LogicPosAddChars(const ALine: String; ALogicalPos, ACount: integer;
239
AFlags: LPosFlags = []): Integer; override;
240
function LogicPosIsAtChar(const ALine: String; ALogicalPos: integer;
241
AFlags: LPosFlags = []): Boolean; override;
242
function LogicPosAdjustToChar(const ALine: String; ALogicalPos: integer;
243
AFlags: LPosFlags = []): Integer; override;
238
244
property UndoList: TSynEditUndoList read GetUndoList write fUndoList;
239
245
property RedoList: TSynEditUndoList read GetRedoList write fRedoList;
240
246
procedure EditInsert(LogX, LogY: Integer; AText: String); override;
241
247
function EditDelete(LogX, LogY, ByteLen: Integer): String; override;
248
function EditReplace(LogX, LogY, ByteLen: Integer; AText: String): String; override;
242
249
procedure EditLineBreak(LogX, LogY: Integer); override;
243
250
procedure EditLineJoin(LogY: Integer; FillText: String = ''); override;
244
251
procedure EditLinesInsert(LogY, ACount: Integer; AText: String = ''); override;
551
550
FAttachedSynEditList := TFPList.Create;
552
551
FUndoList := TSynEditUndoList.Create;
553
fUndoList.OnAddedUndo := {$IFDEF FPC}@{$ENDIF}UndoRedoAdded;
552
fUndoList.OnAddedUndo := @UndoRedoAdded;
554
553
FRedoList := TSynEditUndoList.Create;
555
fRedoList.OnAddedUndo := {$IFDEF FPC}@{$ENDIF}UndoRedoAdded;
554
fRedoList.OnAddedUndo := @UndoRedoAdded;
556
555
FIsUndoing := False;
557
556
FIsRedoing := False;
558
557
FModified := False;
834
832
for i := 0 to LineLen-1 do begin
837
j := UTF8CharacterLength(Line);
839
if LogicPosIsCombining(Line) then
844
// if ((Line+1)^ in [#$80..#$FF]) and (i>0)
845
// then PWidths^ := 0 // Combining Diacritical Marks (belongs to previos char) 0300-036F
846
// else PWidths^ := 1;
848
// if ((Line+1)^ in [#$00..#$AF]) and (i>0)
849
// then PWidths^ := 0 // Combining Diacritical Marks
850
// else PWidths^ := 1;
852
// if (((Line+1)^ = #$B7) and ((Line+2)^ in [#$80..#$BF])) and (i>0)
853
// then PWidths^ := 0 // Combining Diacritical Marks Supplement 1DC0-1DFF
854
// else PWidths^ := 1;
856
// if (((Line+1)^ = #$83) and ((Line+2)^ in [#$90..#$FF])) and (i>0)
857
// then PWidths^ := 0 // Combining Diacritical Marks for Symbols 20D0-20FF
858
// else PWidths^ := 1;
860
// if (((Line+1)^ = #$B8) and ((Line+2)^ in [#$A0..#$AF])) and (i>0)
861
// then PWidths^ := 0 // Combining half Marks FE20-FE2F
862
// else PWidths^ := 1;
847
//for i := 0 to LineLen-1 do begin
848
// if j = 0 then begin
849
// j := UTF8CharacterLength(Line);
851
// ( ( (Line^ = #$CC) and ((Line+1)^ in [#$80..#$FF]) ) or
852
// ( (Line^ = #$CD) and ((Line+1)^ in [#$00..#$AF]) ) )
854
// PWidths^ := 0 // Combining Diacritical Marks
872
function TSynEditStringList.LogicPosIsCombining(const AChar: PChar): Boolean;
875
( (AChar[0] = #$CC) ) or // Combining Diacritical Marks (belongs to previos char) 0300-036F
876
( (AChar[0] = #$CD) and (AChar[1] in [#$80..#$AF]) ) or // Combining Diacritical Marks
877
( (AChar[0] = #$D8) and (AChar[1] in [#$90..#$9A]) ) or // Arabic 0610 (d890)..061A (d89a)
878
( (AChar[0] = #$D9) and (AChar[1] in [#$8b..#$9f, #$B0]) ) or // Arabic 064B (d98b)..065F (d99f) // 0670 (d9b0)
879
( (AChar[0] = #$DB) and (AChar[1] in [#$96..#$9C, #$9F..#$A4, #$A7..#$A8, #$AA..#$AD]) ) or // Arabic 06D6 (db96).. .. ..06EA (dbaa)
880
( (AChar[0] = #$E0) and (AChar[1] = #$A3) and (AChar[2] in [#$A4..#$BE]) ) or // Arabic 08E4 (e0a3a4) ..08FE (e0a3be)
881
( (AChar[0] = #$E1) and (AChar[1] = #$B7) ) or // Combining Diacritical Marks Supplement 1DC0-1DFF
882
( (AChar[0] = #$E2) and (AChar[1] = #$83) and (AChar[2] in [#$90..#$FF]) ) or // Combining Diacritical Marks for Symbols 20D0-20FF
883
( (AChar[0] = #$EF) and (AChar[1] = #$B8) and (AChar[2] in [#$A0..#$AF]) ) // Combining half Marks FE20-FE2F
866
887
function TSynEditStringList.GetDisplayView: TLazSynDisplayView;
1068
function TSynEditStringList.LogicPosAddChars(const ALine: String; ALogicalPos,
1069
ACount: integer; AFlags: LPosFlags): Integer;
1073
// UTF8 handing of chars
1074
Result := ALogicalPos;
1076
if ACount > 0 then begin;
1077
while (Result < l) and (ACount > 0) do begin
1079
if (ALine[Result] in [#0..#127, #192..#255]) and
1080
( (lpStopAtCodePoint in AFlags) or (not LogicPosIsCombining(@ALine[Result])) )
1084
if lpAllowPastEOL in AFlags then
1085
Result := Result + ACount;
1087
if (Result <= l) then
1088
while (Result > 1) and
1089
( (not(ALine[Result] in [#0..#127, #192..#255])) or
1090
( (not(lpStopAtCodePoint in AFlags)) and LogicPosIsCombining(@ALine[Result]) )
1095
while (Result > 1) and (ACount < 0) do begin
1097
if (Result > l) or (Result = 1) or
1098
( (ALine[Result] in [#0..#127, #192..#255]) and
1099
( (lpStopAtCodePoint in AFlags) or (not LogicPosIsCombining(@ALine[Result])) )
1107
function TSynEditStringList.LogicPosIsAtChar(const ALine: String; ALogicalPos: integer;
1108
AFlags: LPosFlags): Boolean;
1110
// UTF8 handing of chars
1111
Result := (lpAllowPastEol in AFlags) and (ALogicalPos >= 1);
1112
if (ALogicalPos < 1) or (ALogicalPos > length(ALine)) then exit;
1113
Result := ALine[ALogicalPos] in [#0..#127, #192..#255];
1116
Result := (ALogicalPos = 1) or
1117
(lpStopAtCodePoint in AFlags) or
1118
(not LogicPosIsCombining(@ALine[ALogicalPos]));
1121
function TSynEditStringList.LogicPosAdjustToChar(const ALine: String; ALogicalPos: integer;
1122
AFlags: LPosFlags): Integer;
1124
// UTF8 handing of chars
1125
Result := ALogicalPos;
1126
if (ALogicalPos < 1) or (ALogicalPos > length(ALine)) then exit;
1128
if lpAdjustToNext in AFlags then begin
1129
while (Result <= length(ALine)) and
1130
( (not(ALine[Result] in [#0..#127, #192..#255])) or
1132
(not(lpStopAtCodePoint in AFlags)) and LogicPosIsCombining(@ALine[Result])
1139
if (not (lpAllowPastEol in AFlags)) and (Result > length(ALine)) then
1140
Result := length(ALine); // + 1
1141
if (Result > length(ALine)) then exit;
1143
while (Result > 1) and
1144
( (not(ALine[Result] in [#0..#127, #192..#255])) or
1145
( (not(lpStopAtCodePoint in AFlags)) and LogicPosIsCombining(@ALine[Result]) )
1047
1151
procedure TSynEditStringList.MarkModified(AFirst, ALast: Integer);
1049
1153
Index: Integer;
1051
1155
for Index := AFirst - 1 to ALast - 1 do
1052
if (Index >= 0) and (Index < Count) then
1156
if (Index >= 0) or (Index < Count) then
1053
1157
Flags[Index] := Flags[Index] + [sfModified] - [sfSaved];
1127
1231
LogX := Length(s) + 1;
1129
1233
Strings[LogY - 1] := copy(s,1, LogX - 1) + AText + copy(s, LogX, length(s));
1130
CurUndoList.AddChange(TSynEditUndoTxtInsert.Create(LogX, LogY, Length(AText)));
1235
CurUndoList.AddChange(TSynEditUndoTxtInsert.Create(LogX, LogY, Length(AText)));
1131
1236
MarkModified(LogY, LogY);
1132
1237
SendNotification(senrEditAction, self, LogY, 0, LogX, length(AText), AText);
1133
1238
DecIsInEditAction;
1245
if ByteLen <= 0 then
1140
1247
IncIsInEditAction;
1141
1248
s := Strings[LogY - 1];
1142
1249
if LogX - 1 > Length(s) then
1144
1251
Result := copy(s, LogX, ByteLen);
1145
1252
Strings[LogY - 1] := copy(s,1, LogX - 1) + copy(s, LogX + ByteLen, length(s));
1146
CurUndoList.AddChange(TSynEditUndoTxtDelete.Create(LogX, LogY, Result));
1147
MarkModified(LogY, LogY);
1148
SendNotification(senrEditAction, self, LogY, 0, LogX, -ByteLen, '');
1253
if Result <> '' then
1254
CurUndoList.AddChange(TSynEditUndoTxtDelete.Create(LogX, LogY, Result));
1255
MarkModified(LogY, LogY);
1256
SendNotification(senrEditAction, self, LogY, 0, LogX, -ByteLen, '');
1260
function TSynEditStringList.EditReplace(LogX, LogY, ByteLen: Integer; AText: String): String;
1266
if ByteLen <= 0 then
1268
s := Strings[LogY - 1];
1269
if LogX - 1 > Length(s) then begin
1270
AText := StringOfChar(' ', LogX - 1 - Length(s)) + AText;
1271
LogX := Length(s) + 1;
1274
if LogX - 1 + ByteLen > Length(s) then
1275
ByteLen := Length(s) - (LogX-1);
1276
Result := copy(s, LogX, ByteLen);
1278
SetLength(s2, Length(s) - ByteLen + Length(AText));
1280
system.Move(s[1], s2[1], LogX-1);
1282
system.Move(AText[1], s2[LogX], Length(AText));
1283
if Length(s)-(LogX-1)-ByteLen > 0 then
1284
system.Move(s[LogX+ByteLen], s2[LogX+Length(AText)], Length(s)-(LogX-1)-ByteLen);
1285
Strings[LogY - 1] := s2;
1286
//Strings[LogY - 1] := copy(s,1, LogX - 1) + AText + copy(s, LogX + ByteLen, length(s));
1288
if Result <> '' then
1289
CurUndoList.AddChange(TSynEditUndoTxtDelete.Create(LogX, LogY, Result));
1291
CurUndoList.AddChange(TSynEditUndoTxtInsert.Create(LogX, LogY, Length(AText)));
1293
MarkModified(LogY, LogY);
1294
SendNotification(senrEditAction, self, LogY, 0, LogX, -ByteLen, '');
1295
SendNotification(senrEditAction, self, LogY, 0, LogX, length(AText), AText);
1149
1296
DecIsInEditAction;