mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-20 05:22:34 +01:00
SynEdit, Refactor: Changed Phys/Logical Conversation (tabs, utf8)
git-svn-id: trunk@18603 -
This commit is contained in:
parent
dd08096ff5
commit
01e79b4d74
@ -68,7 +68,7 @@ begin
|
||||
Inc(Result);
|
||||
end;
|
||||
if Physical and (Result>0) then
|
||||
Result := TSynEdit(Editor).LogicalToPhysicalCol(Line, Result+1)-1;
|
||||
Result := TSynEdit(Editor).LogicalToPhysicalCol(Line, -1, Result+1)-1; // TODO, Need the real index of the line
|
||||
end else
|
||||
Result := 0;
|
||||
end;
|
||||
@ -98,7 +98,7 @@ begin
|
||||
if SpaceCount2 = SpaceCount1 then
|
||||
SpaceCount2 := 0;
|
||||
// remove visible spaces
|
||||
LogSpacePos := TSynEdit(Editor).PhysicalToLogicalCol(Line, SpaceCount2 + 1);
|
||||
LogSpacePos := TSynEdit(Editor).PhysicalToLogicalCol(Line, PhysCaret.y-1, SpaceCount2 + 1);
|
||||
CaretNewX := SpaceCount2 + 1;
|
||||
DelChars := copy(Line, LogSpacePos, PhysCaret.X - LogSpacePos);
|
||||
InsChars := ''; // TODO: if tabs were removed, maybe fill-up with spaces
|
||||
@ -132,7 +132,8 @@ begin
|
||||
sbitSpace:
|
||||
InsChars := StringOfChar(' ', SpaceCount2);
|
||||
sbitCopySpaceTab:
|
||||
InsChars := copy(Temp, 1, TSynEdit(Editor).PhysicalToLogicalCol(Temp, SpaceCount2+1)-1);
|
||||
InsChars := copy(Temp, 1, TSynEdit(Editor).PhysicalToLogicalCol(Temp,
|
||||
BackCounter, SpaceCount2+1)-1);
|
||||
sbitPositionCaret:
|
||||
if Line <> '' then
|
||||
InsChars := StringOfChar(' ', SpaceCount2)
|
||||
@ -140,7 +141,7 @@ begin
|
||||
InsChars := '';
|
||||
end;
|
||||
Result := InsChars + Line;
|
||||
CaretNewX := TSynEdit(Editor).LogicalToPhysicalCol(Result, SpaceCount2+1);
|
||||
CaretNewX := TSynEdit(Editor).LogicalToPhysicalCol(Result, PhysCaret.y - 1, SpaceCount2+1);
|
||||
end;
|
||||
|
||||
function TSynBeautifier.GetIndentForLine(Editor: TSynEditBase; const Line: string; const PhysCaret: TPoint): Integer;
|
||||
|
||||
@ -471,7 +471,6 @@ type
|
||||
function GetLineText: string;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function GetCharLen(const Line: string; CharStartPos: integer): integer;
|
||||
function AdjustPhysPosToCharacterStart(Line: integer; PhysPos: integer): integer;
|
||||
function GetLogicalCaretXY: TPoint;
|
||||
procedure SetCFDividerDrawLevel(const AValue: Integer);
|
||||
function GetCFDividerDrawLevel : Integer;
|
||||
@ -756,18 +755,13 @@ type
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
// Byte to Char
|
||||
function LogicalToPhysicalPos(const p: TPoint): TPoint;
|
||||
function LogicalToPhysicalCol(const Line: string;
|
||||
LogicalPos: integer): integer;
|
||||
function LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
||||
LogicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
function LogicalToPhysicalCol(const Line: String; Index, LogicalPos
|
||||
: integer): integer;
|
||||
// Char to Byte
|
||||
function PhysicalToLogicalPos(const p: TPoint): TPoint;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos: integer): integer;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
function PhysicalLineLength(Line: PChar; LineLen: integer;
|
||||
WithTabs: boolean): integer;
|
||||
Index, PhysicalPos: integer): integer;
|
||||
function PhysicalLineLength(Line: String; Index: integer): integer;
|
||||
function ScreenColumnToXValue(Col: integer): integer; // map screen column to screen pixel
|
||||
procedure MoveCaretToVisibleArea;
|
||||
procedure MoveCaretIgnoreEOL(const NewCaret: TPoint);
|
||||
@ -1817,22 +1811,6 @@ begin
|
||||
Result:=1;
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.AdjustPhysPosToCharacterStart(Line: integer;
|
||||
PhysPos: integer): integer;
|
||||
var
|
||||
s: string;
|
||||
BytePos: LongInt;
|
||||
begin
|
||||
Result:=PhysPos;
|
||||
if Result<1 then
|
||||
Result:=1
|
||||
else if (Line>=1) and (Line<=FTheLinesView.Count) then begin
|
||||
s:=FTheLinesView[Line-1];
|
||||
BytePos:=PhysicalToLogicalCol(s,Result);
|
||||
Result:=LogicalToPhysicalCol(s,BytePos);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.GetLogicalCaretXY: TPoint;
|
||||
begin
|
||||
Result:=PhysicalToLogicalPos(CaretXY);
|
||||
@ -3685,7 +3663,7 @@ begin
|
||||
if not (eoScrollPastEol in fOptions) then begin
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
Line:=FTheLinesView[Value.Y-1];
|
||||
nMaxX := PhysicalLineLength(PChar(Line),length(Line),true)+1;
|
||||
nMaxX := PhysicalLineLength(Line, Value.Y-1) + 1;
|
||||
{$ELSE}
|
||||
nMaxX := Length(FTheLinesView[Value.Y - 1]) + 1; //abc 2000-09-30
|
||||
{$ENDIF}
|
||||
@ -6158,12 +6136,8 @@ begin
|
||||
// join this line with the last line if possible
|
||||
if CaretY > 1 then begin
|
||||
CaretY := CaretY - 1;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
CaretX := LogicalToPhysicalCol(FTheLinesView[CaretY - 1],
|
||||
Length(FTheLinesView[CaretY - 1]) + 1);
|
||||
{$ELSE}
|
||||
CaretX := Length(Lines[CaretY - 1]) + 1;
|
||||
{$ENDIF}
|
||||
CaretX := PhysicalLineLength(FTheLinesView[CaretY - 1],
|
||||
CaretY - 1) + 1;
|
||||
FTheLinesView.Delete(CaretY);
|
||||
DoLinesDeleted(CaretY, 1);
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
@ -6194,9 +6168,9 @@ begin
|
||||
Helper := Copy(Temp, CaretX, counter);
|
||||
VDelete(Temp, CaretX, counter, drLTR);
|
||||
{$ELSE USE_UTF8BIDI_LCL}
|
||||
LogCaretXY.X:=PhysicalToLogicalCol(Temp,CaretX-counter);
|
||||
LogCaretXY.X:=PhysicalToLogicalCol(Temp, CaretY-1, CaretX-counter);
|
||||
LogCounter:=GetCharLen(Temp,LogCaretXY.X);
|
||||
CaretX := LogicalToPhysicalCol(Temp,LogCaretXY.X);
|
||||
CaretX := LogicalToPhysicalCol(Temp, CaretY-1, LogCaretXY.X);
|
||||
Helper := Copy(Temp, LogCaretXY.X, LogCounter);
|
||||
System.Delete(Temp, LogCaretXY.X, LogCounter);
|
||||
//debugln('ecDeleteLastChar delete char CaretX=',dbgs(CaretX),
|
||||
@ -6263,7 +6237,7 @@ begin
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
Counter:=GetCharLen(Temp,LogCaretXY.X);
|
||||
Helper := Copy(Temp, LogCaretXY.X, Counter);
|
||||
Caret.X := LogicalToPhysicalCol(Temp,LogCaretXY.X+Counter);
|
||||
Caret.X := LogicalToPhysicalCol(Temp, CaretY-1, LogCaretXY.X+Counter);
|
||||
Caret.Y := CaretY;
|
||||
{$IFDEF USE_UTF8BIDI_LCL}
|
||||
VDelete(Temp, LogCaretXY.X, Counter, drLTR);
|
||||
@ -6307,7 +6281,7 @@ begin
|
||||
end;
|
||||
ecDeleteWord, ecDeleteEOL:
|
||||
if not ReadOnly then begin
|
||||
Len := LogicalToPhysicalCol(LineText,Length(LineText)+1)-1;
|
||||
Len := LogicalToPhysicalCol(LineText, CaretY-1,Length(LineText)+1)-1;
|
||||
Helper := '';
|
||||
Caret := CaretXY;
|
||||
if Command = ecDeleteWord then begin
|
||||
@ -8114,17 +8088,17 @@ begin
|
||||
Dec(iLine);
|
||||
if iLine < 0 then break;
|
||||
PrevLine := FTheLinesView[iLine];
|
||||
until PhysicalLineLength(PChar(PrevLine),length(PrevLine),true) > OldCaretX - 1;
|
||||
until PhysicalLineLength(PrevLine, iLine) > OldCaretX - 1;
|
||||
|
||||
if iLine >= 0 then begin
|
||||
p := @PrevLine[PhysicalToLogicalCol(PrevLine,OldCaretX)];
|
||||
p := @PrevLine[PhysicalToLogicalCol(PrevLine, iLine, OldCaretX)];
|
||||
// scan over non-whitespaces
|
||||
while not (p^ in [#0, #9, #32]) do
|
||||
inc(p);
|
||||
// scan over whitespaces
|
||||
while (p^ in [#9, #32]) do
|
||||
inc(p);
|
||||
i := LogicalToPhysicalCol(PrevLine, p-@PrevLine[1]+1) - CaretX;
|
||||
i := LogicalToPhysicalCol(PrevLine, iLine, p-@PrevLine[1]+1) - CaretX;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -9304,28 +9278,18 @@ end;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function TCustomSynEdit.LogicalToPhysicalCol(const Line: string;
|
||||
LogicalPos: integer): integer;
|
||||
function TCustomSynEdit.LogicalToPhysicalCol(const Line: String;
|
||||
Index, LogicalPos: integer): integer;
|
||||
// LogicalPos is 1-based
|
||||
// Index 0-based LineNumber
|
||||
begin
|
||||
Result := TSynEditStrings(FTheLinesView).LogicalToPhysicalCol(PChar(Pointer(Line)),
|
||||
length(Line),LogicalPos,1,1);
|
||||
Result := TSynEditStrings(FTheLinesView).LogicalToPhysicalCol(Line, Index,
|
||||
LogicalPos);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
||||
LogicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
// Note: LogicalPos, StartBytePos, StartPhysicalPos start at 1
|
||||
function TCustomSynEdit.PhysicalLineLength(Line: String; Index: integer): integer;
|
||||
begin
|
||||
Result := TSynEditStrings(FTheLinesView).LogicalToPhysicalCol(Line, LineLen, LogicalPos,
|
||||
StartBytePos, StartPhysicalPos);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.PhysicalLineLength(Line: PChar; LineLen: integer;
|
||||
WithTabs: boolean): integer;
|
||||
begin
|
||||
if WithTabs then
|
||||
Result:=LogicalToPhysicalCol(Line,LineLen,LineLen+1,1,1)-1
|
||||
else
|
||||
Result:=UTF8Length(Line,LineLen);
|
||||
Result:=LogicalToPhysicalCol(Line, Index, length(Line)+1) - 1
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.PhysicalToLogicalPos(const p: TPoint): TPoint;
|
||||
@ -9334,16 +9298,10 @@ begin
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos: integer): integer;
|
||||
Index, PhysicalPos: integer): integer;
|
||||
begin
|
||||
Result := TSynEditStrings(FTheLinesView).PhysicalToLogicalCol(Line,PhysicalPos,1,1);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
begin
|
||||
Result := TSynEditStrings(FTheLinesView).PhysicalToLogicalCol(Line, PhysicalPos,
|
||||
StartBytePos, StartPhysicalPos);
|
||||
Result := TSynEditStrings(FTheLinesView).PhysicalToLogicalCol(Line, Index,
|
||||
PhysicalPos);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.ScreenColumnToXValue(Col : integer) : integer;
|
||||
|
||||
@ -71,41 +71,6 @@ function GetIntArray(Count: Cardinal; InitialValue: integer): PIntArray;
|
||||
|
||||
procedure InternalFillRect(dc: HDC; const rcPaint: TRect);
|
||||
|
||||
// Converting tabs to spaces: To use the function several times it's better
|
||||
// to use a function pointer that is set to the fastest conversion function.
|
||||
type
|
||||
TConvertTabsProc = function(const Line: AnsiString;
|
||||
TabWidth: integer): AnsiString;
|
||||
|
||||
function GetBestConvertTabsProc(TabWidth: integer): TConvertTabsProc;
|
||||
// This is the slowest conversion function which can handle TabWidth <> 2^n.
|
||||
function ConvertTabs(const Line: AnsiString; TabWidth: integer): AnsiString;
|
||||
|
||||
{begin} //mh 2000-10-19
|
||||
type
|
||||
TConvertTabsProcEx = function(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
TSimulateConvertTabsProcEx = function(const Line: AnsiString;
|
||||
TabWidth: integer; out HasTabs: boolean): integer;
|
||||
// returns length of converted string
|
||||
{$ENDIF}
|
||||
|
||||
function GetBestConvertTabsProcEx(TabWidth: integer): TConvertTabsProcEx;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function GetBestSimulateConvertTabsProcEx(
|
||||
TabWidth:integer): TSimulateConvertTabsProcEx;
|
||||
{$ENDIF}
|
||||
// This is the slowest conversion function which can handle TabWidth <> 2^n.
|
||||
function ConvertTabsEx(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
{end} //mh 2000-10-19
|
||||
|
||||
function CharIndex2CaretPos(Index, TabWidth: integer;
|
||||
const Line: string): integer;
|
||||
function CaretPos2CharIndex(Position, TabWidth: integer; const Line: string;
|
||||
var InsideTabChar: boolean): integer;
|
||||
|
||||
// search for the first char of set AChars in Line, starting at index Start
|
||||
function StrScanForCharInSet(const Line: string; Start: integer;
|
||||
AChars: TSynIdentChars): integer;
|
||||
@ -238,391 +203,6 @@ end;
|
||||
|
||||
{***}
|
||||
|
||||
// mh: Please don't change; no stack frame and efficient register use.
|
||||
function GetHasTabs(pLine: PChar; out CharsBefore: integer): boolean;
|
||||
begin
|
||||
CharsBefore := 0;
|
||||
if Assigned(pLine) then begin
|
||||
while (pLine^ <> #0) do begin
|
||||
if (pLine^ = #9) then break;
|
||||
Inc(CharsBefore);
|
||||
Inc(pLine);
|
||||
end;
|
||||
Result := (pLine^ = #9);
|
||||
end else
|
||||
Result := FALSE;
|
||||
end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function StringHasTabs(const Line: string; out CharsBefore: integer): boolean;
|
||||
var LineLen: integer;
|
||||
begin
|
||||
LineLen:=length(Line);
|
||||
CharsBefore := 1;
|
||||
while (CharsBefore<=LineLen) and (Line[CharsBefore]<>#9) do
|
||||
inc(CharsBefore);
|
||||
Result:=CharsBefore<=LineLen;
|
||||
dec(CharsBefore);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{begin} //mh 2000-10-19
|
||||
function ConvertTabs1Ex(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
var
|
||||
pDest: PChar;
|
||||
nBeforeTab: integer;
|
||||
begin
|
||||
Result := Line; // increment reference count only
|
||||
if GetHasTabs(pointer(Line), nBeforeTab) then begin
|
||||
HasTabs := TRUE; //mh 2000-11-08
|
||||
pDest := @Result[nBeforeTab + 1]; // this will make a copy of Line
|
||||
// We have at least one tab in the string, and the tab width is 1.
|
||||
// pDest points to the first tab char. We overwrite all tabs with spaces.
|
||||
repeat
|
||||
if (pDest^ = #9) then pDest^ := ' ';
|
||||
Inc(pDest);
|
||||
until (pDest^ = #0);
|
||||
end else
|
||||
HasTabs := FALSE;
|
||||
end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SimulateConvertTabs1Ex(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): integer;
|
||||
// TabWidth=1
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
Result:=length(Line);
|
||||
i:=1;
|
||||
while (i<=Result) and (Line[i]<>#9) do inc(i);
|
||||
HasTabs:=(i<=Result);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function ConvertTabs1(const Line: AnsiString; TabWidth: integer): AnsiString;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
begin
|
||||
Result := ConvertTabs1Ex(Line, TabWidth, HasTabs);
|
||||
end;
|
||||
|
||||
function ConvertTabs2nEx(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
var
|
||||
i, DestLen, TabCount, TabMask: integer;
|
||||
pSrc, pDest: PChar;
|
||||
begin
|
||||
Result := Line; // increment reference count only
|
||||
if GetHasTabs(pointer(Line), DestLen) then begin
|
||||
HasTabs := TRUE; //mh 2000-11-08
|
||||
pSrc := @Line[1 + DestLen];
|
||||
// We have at least one tab in the string, and the tab width equals 2^n.
|
||||
// pSrc points to the first tab char in Line. We get the number of tabs
|
||||
// and the length of the expanded string now.
|
||||
TabCount := 0;
|
||||
TabMask := (TabWidth - 1) xor $7FFFFFFF;
|
||||
repeat
|
||||
if (pSrc^ = #9) then begin
|
||||
DestLen := (DestLen + TabWidth) and TabMask;
|
||||
Inc(TabCount);
|
||||
end else
|
||||
Inc(DestLen);
|
||||
Inc(pSrc);
|
||||
until (pSrc^ = #0);
|
||||
// Set the length of the expanded string.
|
||||
SetLength(Result, DestLen);
|
||||
DestLen := 0;
|
||||
pSrc := PChar(Line);
|
||||
pDest := PChar(Result);
|
||||
// We use another TabMask here to get the difference to 2^n.
|
||||
TabMask := TabWidth - 1;
|
||||
repeat
|
||||
if (pSrc^ = #9) then begin
|
||||
i := TabWidth - (DestLen and TabMask);
|
||||
Inc(DestLen, i);
|
||||
repeat
|
||||
pDest^ := ' ';
|
||||
Inc(pDest);
|
||||
Dec(i);
|
||||
until (i = 0);
|
||||
Dec(TabCount);
|
||||
if (TabCount = 0) then begin
|
||||
repeat
|
||||
Inc(pSrc);
|
||||
pDest^ := pSrc^;
|
||||
Inc(pDest);
|
||||
until (pSrc^ = #0);
|
||||
exit;
|
||||
end;
|
||||
end else begin
|
||||
pDest^ := pSrc^;
|
||||
Inc(pDest);
|
||||
Inc(DestLen);
|
||||
end;
|
||||
Inc(pSrc);
|
||||
until (pSrc^ = #0);
|
||||
end else
|
||||
HasTabs := FALSE;
|
||||
end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SimulateConvertTabs2nEx(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): integer;
|
||||
var
|
||||
LineLen, DestLen, SrcPos, TabMask: integer;
|
||||
begin
|
||||
LineLen:=length(Line);
|
||||
if StringHasTabs(Line, DestLen) then begin
|
||||
HasTabs := TRUE;
|
||||
SrcPos:=DestLen+1;
|
||||
// We have at least one tab in the string, and the tab width equals 2^n.
|
||||
// pSrc points to the first tab char in Line. We get the number of tabs
|
||||
// and the length of the expanded string now.
|
||||
TabMask := (TabWidth - 1) xor $7FFFFFFF;
|
||||
repeat
|
||||
if (Line[SrcPos] = #9) then
|
||||
DestLen := (DestLen + TabWidth) and TabMask
|
||||
else
|
||||
Inc(DestLen);
|
||||
Inc(SrcPos);
|
||||
until (SrcPos>LineLen);
|
||||
Result:=DestLen;
|
||||
end else begin
|
||||
Result := LineLen;
|
||||
HasTabs := FALSE;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function ConvertTabs2n(const Line: AnsiString; TabWidth: integer): AnsiString;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
begin
|
||||
Result := ConvertTabs2nEx(Line, TabWidth, HasTabs);
|
||||
end;
|
||||
|
||||
function ConvertTabsEx(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
var
|
||||
i, DestLen, TabCount: integer;
|
||||
pSrc, pDest: PChar;
|
||||
begin
|
||||
Result := Line; // increment reference count only
|
||||
if GetHasTabs(pointer(Line), DestLen) then begin
|
||||
HasTabs := TRUE; //mh 2000-11-08
|
||||
pSrc := @Line[1 + DestLen];
|
||||
// We have at least one tab in the string, and the tab width is greater
|
||||
// than 1. pSrc points to the first tab char in Line. We get the number
|
||||
// of tabs and the length of the expanded string now.
|
||||
TabCount := 0;
|
||||
repeat
|
||||
if (pSrc^ = #9) then begin
|
||||
DestLen := DestLen + TabWidth - DestLen mod TabWidth;
|
||||
Inc(TabCount);
|
||||
end else
|
||||
Inc(DestLen);
|
||||
Inc(pSrc);
|
||||
until (pSrc^ = #0);
|
||||
// Set the length of the expanded string.
|
||||
SetLength(Result, DestLen);
|
||||
DestLen := 0;
|
||||
pSrc := PChar(Line);
|
||||
pDest := PChar(Result);
|
||||
repeat
|
||||
if (pSrc^ = #9) then begin
|
||||
i := TabWidth - (DestLen mod TabWidth);
|
||||
Inc(DestLen, i);
|
||||
repeat
|
||||
pDest^ := ' ';
|
||||
Inc(pDest);
|
||||
Dec(i);
|
||||
until (i = 0);
|
||||
Dec(TabCount);
|
||||
if (TabCount = 0) then begin
|
||||
repeat
|
||||
Inc(pSrc);
|
||||
pDest^ := pSrc^;
|
||||
Inc(pDest);
|
||||
until (pSrc^ = #0);
|
||||
exit;
|
||||
end;
|
||||
end else begin
|
||||
pDest^ := pSrc^;
|
||||
Inc(pDest);
|
||||
Inc(DestLen);
|
||||
end;
|
||||
Inc(pSrc);
|
||||
until (pSrc^ = #0);
|
||||
end else
|
||||
HasTabs := FALSE;
|
||||
end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SimulateConvertTabsEx(const Line: AnsiString; TabWidth: integer;
|
||||
out HasTabs: boolean): integer;
|
||||
var
|
||||
LineLen, DestLen, SrcPos: integer;
|
||||
begin
|
||||
LineLen:=length(Line);
|
||||
if StringHasTabs(Line, DestLen) then begin
|
||||
HasTabs := TRUE;
|
||||
SrcPos := DestLen+1;
|
||||
// We have at least one tab in the string, and the tab width is greater
|
||||
// than 1. pSrc points to the first tab char in Line. We get the number
|
||||
// of tabs and the length of the expanded string now.
|
||||
repeat
|
||||
if (Line[SrcPos] = #9) then
|
||||
DestLen := DestLen + TabWidth - DestLen mod TabWidth
|
||||
else
|
||||
Inc(DestLen);
|
||||
Inc(SrcPos);
|
||||
until (SrcPos > LineLen);
|
||||
Result:=DestLen;
|
||||
end else begin
|
||||
Result:=LineLen;
|
||||
HasTabs := FALSE;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function ConvertTabs(const Line: AnsiString; TabWidth: integer): AnsiString;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
begin
|
||||
Result := ConvertTabsEx(Line, TabWidth, HasTabs);
|
||||
end;
|
||||
|
||||
function IsPowerOfTwo(TabWidth: integer): boolean;
|
||||
var
|
||||
nW: integer;
|
||||
begin
|
||||
nW := 2;
|
||||
repeat
|
||||
if (nW >= TabWidth) then break;
|
||||
Inc(nW, nW);
|
||||
until (nW >= $10000); // we don't want 64 kByte spaces...
|
||||
Result := (nW = TabWidth);
|
||||
end;
|
||||
|
||||
function GetBestConvertTabsProc(TabWidth: integer): TConvertTabsProc;
|
||||
begin
|
||||
if (TabWidth < 2) then Result := TConvertTabsProc(@ConvertTabs1)
|
||||
else if IsPowerOfTwo(TabWidth) then
|
||||
Result := TConvertTabsProc(@ConvertTabs2n)
|
||||
else
|
||||
Result := TConvertTabsProc(@ConvertTabs);
|
||||
end;
|
||||
|
||||
function GetBestConvertTabsProcEx(TabWidth: integer): TConvertTabsProcEx;
|
||||
begin
|
||||
if (TabWidth < 2) then
|
||||
Result := TConvertTabsProcEx(@ConvertTabs1Ex)
|
||||
else if IsPowerOfTwo(TabWidth) then
|
||||
Result := TConvertTabsProcEx(@ConvertTabs2nEx)
|
||||
else
|
||||
Result := TConvertTabsProcEx(@ConvertTabsEx);
|
||||
end;
|
||||
{end} //mh 2000-10-19
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function GetBestSimulateConvertTabsProcEx(
|
||||
TabWidth:integer): TSimulateConvertTabsProcEx;
|
||||
begin
|
||||
if (TabWidth < 2) then Result :=
|
||||
TSimulateConvertTabsProcEx(@SimulateConvertTabs1Ex)
|
||||
else if IsPowerOfTwo(TabWidth) then
|
||||
Result := TSimulateConvertTabsProcEx(@SimulateConvertTabs2nEx)
|
||||
else
|
||||
Result := TSimulateConvertTabsProcEx(@SimulateConvertTabsEx);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{***}
|
||||
|
||||
function CharIndex2CaretPos(Index, TabWidth: integer;
|
||||
const Line: string): integer;
|
||||
var
|
||||
iChar: integer;
|
||||
pNext: PChar;
|
||||
begin
|
||||
// possible sanity check here: Index := Max(Index, Length(Line));
|
||||
if Index > 1 then begin
|
||||
if (TabWidth <= 1) or not GetHasTabs(pointer(Line), iChar) then
|
||||
Result := Index
|
||||
else begin
|
||||
if iChar + 1 >= Index then
|
||||
Result := Index
|
||||
else begin
|
||||
// iChar is number of chars before first #9
|
||||
Result := iChar;
|
||||
// Index is *not* zero-based
|
||||
Inc(iChar);
|
||||
Dec(Index, iChar);
|
||||
pNext := @Line[iChar];
|
||||
while Index > 0 do begin
|
||||
case pNext^ of
|
||||
#0: break;
|
||||
#9: begin
|
||||
// Result is still zero-based
|
||||
Inc(Result, TabWidth);
|
||||
Dec(Result, Result mod TabWidth);
|
||||
end;
|
||||
else Inc(Result);
|
||||
end;
|
||||
Dec(Index);
|
||||
Inc(pNext);
|
||||
end;
|
||||
// done with zero-based computation
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
Result := 1;
|
||||
end;
|
||||
|
||||
function CaretPos2CharIndex(Position, TabWidth: integer; const Line: string;
|
||||
var InsideTabChar: boolean): integer;
|
||||
var
|
||||
iPos: integer;
|
||||
pNext: PChar;
|
||||
begin
|
||||
InsideTabChar := FALSE;
|
||||
if Position > 1 then begin
|
||||
if (TabWidth <= 1) or not GetHasTabs(pointer(Line), iPos) then
|
||||
Result := Position
|
||||
else begin
|
||||
if iPos + 1 >= Position then
|
||||
Result := Position
|
||||
else begin
|
||||
// iPos is number of chars before first #9
|
||||
Result := iPos + 1;
|
||||
pNext := @Line[Result];
|
||||
// for easier computation go zero-based (mod-operation)
|
||||
Dec(Position);
|
||||
while iPos < Position do begin
|
||||
case pNext^ of
|
||||
#0: break;
|
||||
#9: begin
|
||||
Inc(iPos, TabWidth);
|
||||
Dec(iPos, iPos mod TabWidth);
|
||||
if iPos > Position then begin
|
||||
InsideTabChar := TRUE;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
else Inc(iPos);
|
||||
end;
|
||||
Inc(Result);
|
||||
Inc(pNext);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
Result := Position;
|
||||
end;
|
||||
|
||||
function StrScanForCharInSet(const Line: string; Start: integer;
|
||||
AChars: TSynIdentChars): integer;
|
||||
var
|
||||
|
||||
@ -644,7 +644,8 @@ var
|
||||
else begin
|
||||
TempString := FLines[FCaret.LinePos - 1];
|
||||
Len := Length(TempString);
|
||||
LogicalInsertPos := FLines.PhysicalToLogicalCol(TempString,InsertPos);
|
||||
LogicalInsertPos := FLines.PhysicalToLogicalCol(TempString,
|
||||
FCaret.LinePos - 1, InsertPos);
|
||||
if Len < LogicalInsertPos
|
||||
then begin
|
||||
TempString :=
|
||||
|
||||
@ -35,6 +35,8 @@ type
|
||||
Index, Count: Integer) of object;
|
||||
TSynEditNotifyReason = (senrLineCount, senrLineChange);
|
||||
|
||||
TPhysicalCharWidths = Array of Shortint;
|
||||
|
||||
{ TSynEditStrings }
|
||||
|
||||
TSynEditStrings = class(TStrings)
|
||||
@ -50,7 +52,6 @@ type
|
||||
function GetExpandedString(Index: integer): string; virtual; abstract;
|
||||
function GetLengthOfLongestLine: integer; virtual; abstract;
|
||||
procedure SetTextStr(const Value: string); override;
|
||||
|
||||
public
|
||||
constructor Create;
|
||||
procedure DeleteLines(Index, NumLines: integer); virtual; abstract;
|
||||
@ -66,20 +67,16 @@ type
|
||||
procedure RemoveChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); virtual; abstract;
|
||||
public
|
||||
function GetPhysicalCharWidths(Index: Integer): TPhysicalCharWidths;
|
||||
function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; virtual; abstract;
|
||||
// Byte to Char
|
||||
function LogicalToPhysicalPos(const p: TPoint): TPoint;
|
||||
function LogicalToPhysicalCol(const Line: string;
|
||||
LogicalPos: integer): integer;
|
||||
function LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
||||
LogicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; virtual;
|
||||
function LogicalToPhysicalCol(const Line: String;
|
||||
Index, LogicalPos: integer): integer; virtual;
|
||||
// Char to Byte
|
||||
function PhysicalToLogicalPos(const p: TPoint): TPoint;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos: integer): integer;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; virtual;
|
||||
Index, PhysicalPos: integer): integer;
|
||||
public
|
||||
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
@ -134,6 +131,9 @@ type
|
||||
AHandler: TStringListLineCountEvent); override;
|
||||
procedure RemoveChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); override;
|
||||
|
||||
function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; override;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
@ -149,6 +149,11 @@ begin
|
||||
IsUtf8 := True;
|
||||
end;
|
||||
|
||||
function TSynEditStrings.GetPhysicalCharWidths(Index: Integer): TPhysicalCharWidths;
|
||||
begin
|
||||
Result := GetPhysicalCharWidths(Strings[Index], Index);
|
||||
end;
|
||||
|
||||
function TSynEditStrings.GetIsUtf8 : Boolean;
|
||||
begin
|
||||
Result := FIsUtf8;
|
||||
@ -197,81 +202,57 @@ function TSynEditStrings.LogicalToPhysicalPos(const p : TPoint) : TPoint;
|
||||
begin
|
||||
Result := p;
|
||||
if Result.Y - 1 < Count then
|
||||
Result.X:=LogicalToPhysicalCol(self[Result.Y - 1],Result.X);
|
||||
Result.X:=LogicalToPhysicalCol(self[Result.Y - 1], Result.Y, Result.X);
|
||||
end;
|
||||
|
||||
function TSynEditStrings.LogicalToPhysicalCol(const Line : string; LogicalPos : integer) : integer;
|
||||
begin
|
||||
Result := LogicalToPhysicalCol(PChar(Pointer(Line)),length(Line),LogicalPos,1,1);
|
||||
end;
|
||||
|
||||
function TSynEditStrings.LogicalToPhysicalCol(Line : PChar; LineLen : integer; LogicalPos, StartBytePos, StartPhysicalPos : integer) : integer;
|
||||
function TSynEditStrings.LogicalToPhysicalCol(const Line : String;
|
||||
Index, LogicalPos: integer) : integer;
|
||||
var
|
||||
BytePos, ByteLen: integer;
|
||||
ScreenPos: integer;
|
||||
i, ByteLen: integer;
|
||||
CharWidths: TPhysicalCharWidths;
|
||||
begin
|
||||
ByteLen := LineLen;
|
||||
// map UTF8
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos:= StartBytePos;
|
||||
while BytePos<LogicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@Line[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(ScreenPos,LogicalPos-BytePos);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if (BytePos>LogicalPos) and (ScreenPos>StartPhysicalPos) then
|
||||
dec(ScreenPos);
|
||||
Result := ScreenPos;
|
||||
CharWidths := GetPhysicalCharWidths(Line, Index);
|
||||
ByteLen := length(Line);
|
||||
dec(LogicalPos);
|
||||
|
||||
if LogicalPos > ByteLen then begin
|
||||
Result := 1 + LogicalPos - ByteLen;
|
||||
LogicalPos := ByteLen;
|
||||
end
|
||||
else
|
||||
Result := 1;
|
||||
|
||||
for i := 0 to LogicalPos - 1 do
|
||||
Result := Result + CharWidths[i];
|
||||
end;
|
||||
|
||||
function TSynEditStrings.PhysicalToLogicalPos(const p : TPoint) : TPoint;
|
||||
begin
|
||||
Result := p;
|
||||
if (Result.Y>=1) and (Result.Y <= Count) then
|
||||
Result.X:=PhysicalToLogicalCol(self[Result.Y - 1],Result.X,1,1);
|
||||
Result.X:=PhysicalToLogicalCol(self[Result.Y - 1], Result.Y - 1, Result.X);
|
||||
end;
|
||||
|
||||
function TSynEditStrings.PhysicalToLogicalCol(const Line : string; PhysicalPos : integer) : integer;
|
||||
begin
|
||||
Result:=PhysicalToLogicalCol(Line,PhysicalPos,1,1);
|
||||
end;
|
||||
|
||||
function TSynEditStrings.PhysicalToLogicalCol(const Line : string; PhysicalPos, StartBytePos, StartPhysicalPos : integer) : integer;
|
||||
function TSynEditStrings.PhysicalToLogicalCol(const Line : string;
|
||||
Index, PhysicalPos : integer) : integer;
|
||||
var
|
||||
BytePos, ByteLen: integer;
|
||||
ScreenPos: integer;
|
||||
PLine: PChar;
|
||||
CharWidths: TPhysicalCharWidths;
|
||||
begin
|
||||
CharWidths := GetPhysicalCharWidths(Line, Index);
|
||||
ByteLen := Length(Line);
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos := StartBytePos;
|
||||
PLine := PChar(Line);
|
||||
// map utf
|
||||
while ScreenPos < PhysicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@PLine[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(BytePos,PhysicalPos-ScreenPos);
|
||||
break;
|
||||
end;
|
||||
ScreenPos := 1;
|
||||
BytePos := 0;
|
||||
|
||||
while BytePos < ByteLen do begin
|
||||
if ScreenPos + CharWidths[BytePos] > PhysicalPos then
|
||||
exit(BytePos+1);
|
||||
ScreenPos := ScreenPos + CharWidths[BytePos];
|
||||
inc(BytePos);
|
||||
end;
|
||||
if (ScreenPos>PhysicalPos) and (BytePos>1) and (BytePos-2<ByteLen)
|
||||
and (PLine[BytePos-2]=#9) then
|
||||
dec(BytePos);
|
||||
Result := BytePos;
|
||||
|
||||
Result := BytePos + 1 + PhysicalPos - ScreenPos;
|
||||
end;
|
||||
|
||||
{ TSynEditStringsLinked }
|
||||
@ -415,6 +396,11 @@ begin
|
||||
fSynStrings.PutObject(Index, AObject);
|
||||
end;
|
||||
|
||||
function TSynEditStringsLinked.GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths;
|
||||
begin
|
||||
Result := fSynStrings.GetPhysicalCharWidths(Line, Index);
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.SetUpdateState(Updating: Boolean);
|
||||
begin
|
||||
if Updating then
|
||||
|
||||
@ -200,6 +200,7 @@ type
|
||||
AHandler: TStringListLineCountEvent); override;
|
||||
procedure RemoveChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); override;
|
||||
function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; override;
|
||||
public
|
||||
property DosFileFormat: boolean read fDosFileFormat write fDosFileFormat;
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
@ -707,6 +708,29 @@ begin
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
// Maps the Physical Width (ScreenCells) to each character
|
||||
// Multibyte Chars have thw width on the first byte, and a 0 Width for all other bytes
|
||||
function TSynEditStringList.GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths;
|
||||
var
|
||||
i, j: Integer;
|
||||
begin
|
||||
SetLength(Result, Length(Line));
|
||||
i := 0;
|
||||
j := 0;
|
||||
while i < length(Line) do begin
|
||||
if j > 0 then begin
|
||||
Result[i] := 0;
|
||||
dec(j);
|
||||
end else begin
|
||||
Result[i] := 1;
|
||||
if IsUtf8 then
|
||||
j := UTF8CharacterLength(@Line[i+1]) - 1;
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
{end} //mh 2000-10-19
|
||||
|
||||
function TSynEditStringList.GetObject(Index: integer): TObject;
|
||||
|
||||
@ -41,8 +41,6 @@ type
|
||||
TSynEditStringTabExpander = class(TSynEditStringsLinked)
|
||||
private
|
||||
FTabWidth: integer;
|
||||
FConvertTabsProc: TConvertTabsProcEx;
|
||||
FSimulateConvertTabsProc: TSimulateConvertTabsProcEx;
|
||||
FIndexOfLongestLine: Integer;
|
||||
function GetLengthOfLine(Index: Integer): integer;
|
||||
procedure SetLengthOfLine(Index: Integer; const AValue: integer);
|
||||
@ -53,6 +51,7 @@ TSynEditStringTabExpander = class(TSynEditStringsLinked)
|
||||
function GetTabWidth : integer;
|
||||
procedure SetTabWidth(const AValue : integer);
|
||||
function GetExpandedString(Index: integer): string; override;
|
||||
function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; override;
|
||||
function GetLengthOfLongestLine: integer; override;
|
||||
property LengthOfLine[Index: Integer]: integer
|
||||
read GetLengthOfLine write SetLengthOfLine;
|
||||
@ -61,14 +60,6 @@ TSynEditStringTabExpander = class(TSynEditStringsLinked)
|
||||
destructor Destroy; override;
|
||||
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
|
||||
// TODO: maybe use inherited for utf8?
|
||||
function LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
||||
LogicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; override;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; override;
|
||||
public
|
||||
property TabWidth: integer read GetTabWidth write SetTabWidth;
|
||||
end;
|
||||
@ -76,6 +67,18 @@ TSynEditStringTabExpander = class(TSynEditStringsLinked)
|
||||
|
||||
implementation
|
||||
|
||||
function GetHasTabs(pLine: PChar): boolean;
|
||||
begin
|
||||
if Assigned(pLine) then begin
|
||||
while (pLine^ <> #0) do begin
|
||||
if (pLine^ = #9) then break;
|
||||
Inc(pLine);
|
||||
end;
|
||||
Result := (pLine^ = #9);
|
||||
end else
|
||||
Result := FALSE;
|
||||
end;
|
||||
|
||||
{ TSynEditStringTabExpander }
|
||||
|
||||
constructor TSynEditStringTabExpander.Create(ASynStringSource: TSynEditStrings);
|
||||
@ -117,8 +120,6 @@ begin
|
||||
if FTabWidth = AValue then exit;
|
||||
|
||||
FTabWidth := AValue;
|
||||
FConvertTabsProc := GetBestConvertTabsProcEx(fTabWidth);
|
||||
FSimulateConvertTabsProc := GetBestSimulateConvertTabsProcEx(fTabWidth);
|
||||
FIndexOfLongestLine := -1;
|
||||
for i := 0 to Count - 1 do
|
||||
if not(LengthOfLine[i] >= NoTabLengthOffset) then
|
||||
@ -136,33 +137,54 @@ end;
|
||||
|
||||
function TSynEditStringTabExpander.ExpandedString(Index: integer): string;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
Line: String;
|
||||
CharWidths: TPhysicalCharWidths;
|
||||
i, j, l: Integer;
|
||||
begin
|
||||
if fSynStrings[Index] = '' then begin
|
||||
Result := '';
|
||||
LengthOfLine[Index] := 0 + NoTabLengthOffset;
|
||||
Line := fSynStrings[Index];
|
||||
if (Line = '') or (not GetHasTabs(PChar(Line))) then begin
|
||||
Result := Line;
|
||||
LengthOfLine[Index] := length(Result) + NoTabLengthOffset;
|
||||
end else begin
|
||||
Result := fConvertTabsProc(fSynStrings[Index], fTabWidth, HasTabs);
|
||||
if HasTabs then
|
||||
LengthOfLine[Index] := length(Result)
|
||||
else
|
||||
LengthOfLine[Index] := length(Result) + NoTabLengthOffset;
|
||||
CharWidths := GetPhysicalCharWidths(Line, Index);
|
||||
l := 0;
|
||||
for i := 0 to length(CharWidths)-1 do
|
||||
l := l + CharWidths[i];
|
||||
SetLength(Result, l);
|
||||
|
||||
l := 1;
|
||||
for i := 1 to length(CharWidths) do begin
|
||||
if Line[i] <> #9 then begin
|
||||
Result[l] := Line[i];
|
||||
inc(l);
|
||||
end else begin
|
||||
for j := 1 to CharWidths[i-1] do begin
|
||||
Result[l] := ' ';
|
||||
inc(l);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
LengthOfLine[Index] := length(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.ExpandedStringLength(Index: integer): Integer;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
Line: String;
|
||||
CharWidths: TPhysicalCharWidths;
|
||||
i, j, l: Integer;
|
||||
begin
|
||||
if fSynStrings[Index] = '' then begin
|
||||
Line := fSynStrings[Index];
|
||||
if (Line = '') or (not GetHasTabs(PChar(Line))) then begin
|
||||
Result := 0;
|
||||
LengthOfLine[Index] := 0 + NoTabLengthOffset;
|
||||
LengthOfLine[Index] := Length(Line) + NoTabLengthOffset;
|
||||
end else begin
|
||||
Result := fSimulateConvertTabsProc(fSynStrings[Index], fTabWidth, HasTabs);
|
||||
if HasTabs then
|
||||
LengthOfLine[Index] := Result
|
||||
else
|
||||
LengthOfLine[Index] := Result + NoTabLengthOffset;
|
||||
CharWidths := GetPhysicalCharWidths(Line, Index);
|
||||
Result := 0;
|
||||
for i := 0 to length(CharWidths)-1 do
|
||||
Result := Result + CharWidths[i];
|
||||
|
||||
LengthOfLine[Index] := Result;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -177,6 +199,21 @@ begin
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.GetPhysicalCharWidths(const Line: String;
|
||||
Index: Integer): TPhysicalCharWidths;
|
||||
var
|
||||
i, p: Integer;
|
||||
begin
|
||||
Result := inherited GetPhysicalCharWidths(Line, Index);
|
||||
p := 0;
|
||||
for i := 0 to length(Line) -1 do begin
|
||||
if Result[i] = 0 then continue;
|
||||
if Line[i+1] = #9 then
|
||||
Result[i] := FTabWidth - p mod FTabWidth;
|
||||
p := p + Result[i];
|
||||
end
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.GetLengthOfLongestLine: integer;
|
||||
var
|
||||
i, j, MaxLen: integer;
|
||||
@ -204,74 +241,5 @@ begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.LogicalToPhysicalCol(Line: PChar;
|
||||
LineLen: integer; LogicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
var
|
||||
BytePos, ByteLen: integer;
|
||||
ScreenPos: integer;
|
||||
begin
|
||||
ByteLen := LineLen;
|
||||
// map UTF8 and Tab chars
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos:= StartBytePos;
|
||||
while BytePos<LogicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
if Line[BytePos-1] = #9 then begin
|
||||
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@Line[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end;
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(ScreenPos,LogicalPos-BytePos);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if (BytePos>LogicalPos) and (ScreenPos>StartPhysicalPos) then
|
||||
dec(ScreenPos);
|
||||
Result := ScreenPos;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
var
|
||||
BytePos, ByteLen: integer;
|
||||
ScreenPos: integer;
|
||||
PLine: PChar;
|
||||
begin
|
||||
ByteLen := Length(Line);
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos := StartBytePos;
|
||||
PLine := PChar(Line);
|
||||
// map utf and tab chars
|
||||
while ScreenPos < PhysicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
if (PLine[BytePos-1] <> #9) then begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@PLine[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
||||
inc(BytePos);
|
||||
end;
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(BytePos,PhysicalPos-ScreenPos);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if (ScreenPos>PhysicalPos) and (BytePos>1) and (BytePos-2<ByteLen)
|
||||
and (PLine[BytePos-2]=#9) then
|
||||
dec(BytePos);
|
||||
Result := BytePos;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
@ -109,7 +109,7 @@ begin
|
||||
and ((IndentLen>length(s)) or (s[IndentLen] in [#9,' '])) do
|
||||
inc(IndentLen);
|
||||
end;
|
||||
IndentLen:=AEditor.LogicalToPhysicalCol(s,IndentLen);// consider tabs
|
||||
IndentLen:=AEditor.LogicalToPhysicalCol(s, p.y - 1, IndentLen);// consider tabs
|
||||
dec(IndentLen);
|
||||
end;
|
||||
p := AEditor.BlockBegin;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user