TMaskEdit: change internal datstructure, remove no longer needed functions.

- better code readability (IMHO).
- lifts the current restriction on the number of tMaskedTye enums we can have.

git-svn-id: trunk@64757 -
This commit is contained in:
bart 2021-03-06 18:49:05 +00:00
parent 86d7ce6416
commit 07895b46b1

View File

@ -87,7 +87,7 @@ const
type type
{ Type for mask (internal) } { Type for mask (internal) }
tMaskedType = (Char_Start, tMaskedType = (Char_IsLiteral,
Char_Number, Char_Number,
Char_NumberFixed, Char_NumberFixed,
Char_NumberPlusMin, Char_NumberPlusMin,
@ -119,11 +119,15 @@ type
Char_HexFixedUpCase, //Lazarus extension, not supported by Delphi Char_HexFixedUpCase, //Lazarus extension, not supported by Delphi
Char_HexFixedDownCase, //Lazarus extension, not supported by Delphi Char_HexFixedDownCase, //Lazarus extension, not supported by Delphi
Char_Binary, //Lazarus extension, not supported by Delphi Char_Binary, //Lazarus extension, not supported by Delphi
Char_BinaryFixed, //Lazarus extension, not supported by Delphi Char_BinaryFixed); //Lazarus extension, not supported by Delphi
Char_Stop); {currently we have 31 enums, I think we cannot add more BB}
TInternalMask = array[1..255] of TUtf8Char; TIntMaskRec = record
MaskType: TMaskedType;
Literal: TUtf8Char;
end;
TInternalMask = array[1..255] of TIntMaskRec;
TMaskeditTrimType = (metTrimLeft, metTrimRight); TMaskeditTrimType = (metTrimLeft, metTrimRight);
{ Exception class } { Exception class }
@ -200,7 +204,8 @@ const
FInRealSetTextWhileMasked: Boolean; FInRealSetTextWhileMasked: Boolean;
procedure ClearInternalMask(out AMask: TInternalMask; out ALengthIndicator: Integer); procedure ClearInternalMask(out AMask: TInternalMask; out ALengthIndicator: Integer);
procedure AddToMask(Value: TUtf8Char); procedure AddToMask(ALiteral: TUtf8Char);
procedure AddToMask(AMaskType: TMaskedType);
function GetModified: Boolean; function GetModified: Boolean;
procedure SetMask(Value : String); procedure SetMask(Value : String);
function GetIsMasked : Boolean; function GetIsMasked : Boolean;
@ -216,10 +221,7 @@ const
function HasSelection: Boolean; function HasSelection: Boolean;
function HasExtSelection: Boolean; function HasExtSelection: Boolean;
Function CharToMask(UCh : TUtf8Char) : tMaskedType; Function IsLiteral(Index: Integer): Boolean;
Function MaskToChar(Value : tMaskedType) : Char;
Function IsMaskChar(Ch : TUtf8Char) : Boolean;
Function IsLiteral(Ch: TUtf8Char): Boolean;
function TextIsValid(const Value: String): Boolean; function TextIsValid(const Value: String): Boolean;
function CharMatchesMask(const Ch: TUtf8Char; const Position: Integer): Boolean; function CharMatchesMask(const Ch: TUtf8Char; const Position: Integer): Boolean;
function ClearChar(Position : Integer) : TUtf8Char; function ClearChar(Position : Integer) : TUtf8Char;
@ -367,6 +369,7 @@ const
cMask_AlphaNum, cMask_AlphaNumFixed, cMask_AlphaNum, cMask_AlphaNum, cMask_AlphaNumFixed, cMask_AlphaNumFixed, cMask_AlphaNum, cMask_AlphaNumFixed, cMask_AlphaNum, cMask_AlphaNum, cMask_AlphaNumFixed, cMask_AlphaNumFixed,
cMask_AllChars, cMask_AllCharsFixed, cMask_AllChars, cMask_AllChars, cMask_AllCharsFixed, cMask_AllCharsFixed, cMask_AllChars, cMask_AllCharsFixed, cMask_AllChars, cMask_AllChars, cMask_AllCharsFixed, cMask_AllCharsFixed,
cMask_HourSeparator, cMask_DateSeparator, #0); cMask_HourSeparator, cMask_DateSeparator, #0);
{$endif} {$endif}
const const
@ -374,6 +377,13 @@ const
Comma = ','; Comma = ',';
//Utf8 helper functions //Utf8 helper functions
function StringToHex(S: String): String;
var
i: Integer;
begin
Result := '';
for i := 1 to length(S) do Result := Result + '$' + IntToHex(Ord(S[i]),2);
end;
function GetCodePoint(const S: String; const Index: PtrInt): TUTF8Char; function GetCodePoint(const S: String; const Index: PtrInt): TUTF8Char;
//equivalent for Result := S[Index], but for Utf8 encoded strings //equivalent for Result := S[Index], but for Utf8 encoded strings
@ -392,13 +402,6 @@ begin
Result := Res; Result := Res;
end; end;
function StringToHex(S: String): String;
var
i: Integer;
begin
Result := '';
for i := 1 to length(S) do Result := Result + '$' + IntToHex(Ord(S[i]),2);
end;
procedure SetCodePoint(var S: String; const Index: PtrInt; CodePoint: TUTF8Char); procedure SetCodePoint(var S: String; const Index: PtrInt; CodePoint: TUTF8Char);
//equivalent for S[Index] := CodePoint, but for Utf8 encoded strings //equivalent for S[Index] := CodePoint, but for Utf8 encoded strings
@ -515,10 +518,18 @@ begin
{$POP} {$POP}
end; end;
procedure TCustomMaskEdit.AddToMask(Value: TUtf8Char); procedure TCustomMaskEdit.AddToMask(ALiteral: TUtf8Char);
begin begin
Inc(FMaskLength); Inc(FMaskLength);
FMask[FMaskLength] := Value; FMask[FMaskLength].Literal := ALiteral;
FMask[FMaskLength].MaskType := Char_IsLiteral;
end;
procedure TCustomMaskEdit.AddToMask(AMaskType: TMaskedType);
begin
Inc(FMaskLength);
FMask[FMaskLength].Literal := EmptyStr;
FMask[FMaskLength].MaskType := AMaskType;
end; end;
function TCustomMaskEdit.GetModified: Boolean; function TCustomMaskEdit.GetModified: Boolean;
@ -609,111 +620,111 @@ begin
cMask_Letter: begin cMask_Letter: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_LetterUpCase)) AddToMask(Char_LetterUpCase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_LetterDownCase)) AddToMask(Char_LetterDownCase)
else else
AddToMask(MaskToChar(Char_Letter)) AddToMask(Char_Letter)
end; end;
cMask_LetterFixed: begin cMask_LetterFixed: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_LetterFixedUpCase)) AddToMask(Char_LetterFixedUpCase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_LetterFixedDownCase)) AddToMask(Char_LetterFixedDownCase)
else else
AddToMask(MaskToChar(Char_LetterFixed)) AddToMask(Char_LetterFixed)
end; end;
cMask_AlphaNum: begin cMask_AlphaNum: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_AlphaNumUpcase)) AddToMask(Char_AlphaNumUpcase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_AlphaNumDownCase)) AddToMask(Char_AlphaNumDownCase)
else else
AddToMask(MaskToChar(Char_AlphaNum)) AddToMask(Char_AlphaNum)
end; end;
cMask_AlphaNumFixed: begin cMask_AlphaNumFixed: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_AlphaNumFixedUpcase)) AddToMask(Char_AlphaNumFixedUpcase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_AlphaNumFixedDownCase)) AddToMask(Char_AlphaNumFixedDownCase)
else else
AddToMask(MaskToChar(Char_AlphaNumFixed)) AddToMask(Char_AlphaNumFixed)
end; end;
cMask_AllChars: begin cMask_AllChars: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_AllUpCase)) AddToMask(Char_AllUpCase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_AllDownCase)) AddToMask(Char_AllDownCase)
else else
AddToMask(MaskToChar(Char_All)) AddToMask(Char_All)
end; end;
cMask_AllCharsFixed: begin cMask_AllCharsFixed: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_AllFixedUpCase)) AddToMask(Char_AllFixedUpCase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_AllFixedDownCase)) AddToMask(Char_AllFixedDownCase)
else else
AddToMask(MaskToChar(Char_AllFixed)) AddToMask(Char_AllFixed)
end; end;
cMask_Number: AddToMask(MaskToChar(Char_Number)); cMask_Number: AddToMask(Char_Number);
cMask_NumberFixed: AddToMask(MaskToChar(Char_NumberFixed)); cMask_NumberFixed: AddToMask(Char_NumberFixed);
cMask_NumberPlusMin: AddToMask(MaskToChar(Char_NumberPlusMin)); cMask_NumberPlusMin: AddToMask(Char_NumberPlusMin);
cMask_HourSeparator: AddToMask(MaskToChar(Char_HourSeparator)); cMask_HourSeparator: AddToMask(Char_HourSeparator);
cMask_DateSeparator: AddToMask(MaskToChar(Char_DateSeparator)); cMask_DateSeparator: AddToMask(Char_DateSeparator);
cMask_Hex: begin cMask_Hex: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_HexUpCase)) AddToMask(Char_HexUpCase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_HexDownCase)) AddToMask(Char_HexDownCase)
else else
AddToMask(MaskToChar(Char_Hex)) AddToMask(Char_Hex)
end; end;
cMask_HexFixed: begin cMask_HexFixed: begin
if InUp if InUp
then then
AddToMask(MaskToChar(Char_HexFixedUpCase)) AddToMask(Char_HexFixedUpCase)
else else
if InDown if InDown
then then
AddToMask(MaskToChar(Char_HexFixedDownCase)) AddToMask(Char_HexFixedDownCase)
else else
AddToMask(MaskToChar(Char_HexFixed)) AddToMask(Char_HexFixed)
end; end;
cMask_Binary: AddToMask(MaskToChar(Char_Binary)); cMask_Binary: AddToMask(Char_Binary);
cMask_BinaryFixed: AddToMask(MaskToChar(Char_BinaryFixed)); cMask_BinaryFixed: AddToMask(Char_BinaryFixed);
cMask_NoLeadingBlanks: cMask_NoLeadingBlanks:
begin begin
@ -730,7 +741,7 @@ begin
end; end;
FFirstFreePos := 1; FFirstFreePos := 1;
//Determine first position where text can be entered (needed for DeleteChars() //Determine first position where text can be entered (needed for DeleteChars()
while (FFirstFreePos <= FMaskLength) and IsLiteral(FMask[FFirstFreePos]) do Inc(FFirstFreePos); while (FFirstFreePos <= FMaskLength) and IsLiteral(FFirstFreePos) do Inc(FFirstFreePos);
if (FMaskLength > 0) then if (FMaskLength > 0) then
begin begin
SetCharCase(ecNormal); SetCharCase(ecNormal);
@ -763,8 +774,7 @@ Var
I : Integer; I : Integer;
OldValue: TUtf8Char; OldValue: TUtf8Char;
Begin Begin
if (Value <> FSpaceChar) And if (Value <> FSpaceChar) (* and ((Not IsMaskChar(Value)) {or (CharToMask(Value) = Char_Space)}) *) then
((Not IsMaskChar(Value)) {or (CharToMask(Value) = Char_Space)}) then
begin begin
OldValue := FSpaceChar; OldValue := FSpaceChar;
FSpaceChar := Value; FSpaceChar := Value;
@ -773,9 +783,9 @@ Begin
S := inherited RealGetText; S := inherited RealGetText;
for I := 1 to Utf8Length(S) do for I := 1 to Utf8Length(S) do
begin begin
if (GetCodePoint(S,i) = OldValue) and (not IsLiteral(FMask[i])) then SetCodePoint(S,i,FSpaceChar); if (GetCodePoint(S,i) = OldValue) and (not IsLiteral(i)) then SetCodePoint(S,i,FSpaceChar);
//also update FTextOnEnter to reflect new SpaceChar! //also update FTextOnEnter to reflect new SpaceChar!
if (GetCodePoint(FTextOnEnter,i) = OldValue) and (not IsLiteral(FMask[i])) then SetCodePoint(FTextOnEnter,i,FSpaceChar); if (GetCodePoint(FTextOnEnter,i) = OldValue) and (not IsLiteral(i)) then SetCodePoint(FTextOnEnter,i,FSpaceChar);
end; end;
//FCurrentText := S; //FCurrentText := S;
RealSetTextWhileMasked(S); RealSetTextWhileMasked(S);
@ -807,11 +817,11 @@ procedure TCustomMaskEdit.SelectNextChar;
begin begin
if (FCursorPos + 1) > FMaskLength then Exit; if (FCursorPos + 1) > FMaskLength then Exit;
Inc(FCursorPos); Inc(FCursorPos);
While (FCursorPos + 1 < FMaskLength) and (IsLiteral(FMask[FCursorPos + 1])) do While (FCursorPos + 1 < FMaskLength) and (IsLiteral(FCursorPos + 1)) do
begin begin
Inc(FCursorPos); Inc(FCursorPos);
end; end;
if IsLiteral(FMask[FCursorPos + 1]) then Inc(FCursorPos); if IsLiteral(FCursorPos + 1) then Inc(FCursorPos);
SetCursorPos; SetCursorPos;
end; end;
@ -826,11 +836,11 @@ begin
if (FCursorPos = 0) and (AStop - AStart <= 1) then Exit; if (FCursorPos = 0) and (AStop - AStart <= 1) then Exit;
P := FCursorPos; P := FCursorPos;
Dec(FCursorPos); Dec(FCursorPos);
While (FCursorPos > 0) and IsLiteral(FMask[FCursorPos + 1]) do While (FCursorPos > 0) and IsLiteral(FCursorPos + 1) do
begin begin
Dec(FCursorPos); Dec(FCursorPos);
end; end;
if (FCursorPos = 0) and (P <> 0) and IsLiteral(FMask[FCursorPos + 1]) then FCursorPos := P; if (FCursorPos = 0) and (P <> 0) and IsLiteral(FCursorPos + 1) then FCursorPos := P;
SetCursorPos; SetCursorPos;
end; end;
@ -865,7 +875,7 @@ procedure TCustomMaskEdit.JumpToNextDot(Dot: Char);
Result := 0; Result := 0;
for i := Start to FMaskLength do for i := Start to FMaskLength do
begin begin
if (FMask[i] = Sub) then if (FMask[i].MaskType = Char_IsLiteral) and (FMask[i].Literal = Sub) then
begin begin
Result := i; Result := i;
exit; exit;
@ -895,7 +905,7 @@ begin
//When mask has both period and comma only the first occurence is jumpable //When mask has both period and comma only the first occurence is jumpable
if P2 < P then HasNextDot := False; if P2 < P then HasNextDot := False;
end; end;
CanJump := HasNextDot and (P < FMaskLength) and (not IsLiteral(FMask[P+1])); CanJump := HasNextDot and (P < FMaskLength) and (not IsLiteral(P+1));
if CanJump then if CanJump then
begin begin
FCursorPos := P; FCursorPos := P;
@ -932,40 +942,10 @@ begin
end; end;
// Transform a single char in a MaskType //Return if the index passed contains a literal in FMask (so it cannot be altered)
function TCustomMaskEdit.CharToMask(UCh: TUtf8Char): tMaskedType; function TCustomMaskEdit.IsLiteral(Index: Integer): Boolean;
var
Ch: Char;
Begin
Result := Char_Start;
if (Length(UCh) <> 1) then exit;
Ch := UCh[1];
if (Ord(Ch) > Ord(Char_Start)) and
(Ord(Ch) < Ord(Char_Stop) )
then
Result := tMaskedType(Ord(Ch));
End;
// Trasform a single MaskType into a char
function TCustomMaskEdit.MaskToChar(Value: tMaskedType): Char;
Begin
Result := Char(Ord(Value));
End;
// Return if the char passed is a valid MaskType char
function TCustomMaskEdit.IsMaskChar(Ch: TUtf8Char): Boolean;
Begin
Result := (CharToMask(Ch) <> Char_Start);
End;
//Return if the char passed is a literal (so it cannot be altered)
function TCustomMaskEdit.IsLiteral(Ch: TUtf8Char): Boolean;
begin begin
Result := (not IsMaskChar(Ch)) or Result := (FMask[Index].MaskType in [Char_IsLiteral, Char_HourSeparator, Char_DateSeparator]);
(IsMaskChar(Ch) and (CharToMask(Ch) in [Char_HourSeparator, Char_DateSeparator{, Char_Space}]))
end; end;
@ -995,7 +975,7 @@ var
begin begin
Result := False; Result := False;
if (Position < 1) or (Position > FMaskLength) then Exit; if (Position < 1) or (Position > FMaskLength) then Exit;
Current := CharToMask(FMask[Position]); Current := FMask[Position].MaskType;
case Current Of case Current Of
Char_Number : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'9',#32]); Char_Number : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'9',#32]);
Char_NumberFixed : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'9']); Char_NumberFixed : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'9']);
@ -1029,10 +1009,10 @@ begin
Char_HexFixedDownCase : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'9','a'..'f']); Char_HexFixedDownCase : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'9','a'..'f']);
Char_Binary : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'1',#32]); Char_Binary : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'1',#32]);
Char_BinaryFixed : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'1']); Char_BinaryFixed : OK := (Length(Ch) = 1) and (Ch[1] In ['0'..'1']);
else//it's a literal
begin Char_IsLiteral : OK := (Ch = FMask[Position].Literal);
OK := (Ch = FMask[Position]); otherwise
end; Raise EDBEditError.CreateFmt('MaskEdit Internal Error.'^m' Found unexpected MaskType at index %d with ordinal value %d',[Position, Integer(Current)]);
end;//case end;//case
//DebugLn('Position = ',DbgS(Position),' Current = ',MaskCharToChar[Current],' Ch = "',Ch,'" Ok = ',DbgS(Ok)); //DebugLn('Position = ',DbgS(Position),' Current = ',MaskCharToChar[Current],' Ch = "',Ch,'" Ok = ',DbgS(Ok));
Result := Ok; Result := Ok;
@ -1185,7 +1165,7 @@ begin
//Restore all MaskLiterals, or we will potentially leave the control //Restore all MaskLiterals, or we will potentially leave the control
//in an unrecoverable state, eventually crashing the app //in an unrecoverable state, eventually crashing the app
for i := 1 to Utf8Length(S) do for i := 1 to Utf8Length(S) do
if IsLiteral(FMask[i]) then SetCodePoint(S,i,ClearChar(i)); if IsLiteral(i) then SetCodePoint(S,i,ClearChar(i));
//Pad resulting string with ClearChar if text is too short //Pad resulting string with ClearChar if text is too short
{$if fpc_fullversion >= 30202} {$if fpc_fullversion >= 30202}
while Utf8Length(S) < FMaskLength do S := S + ClearChar(Utf8Length(S)+1); while Utf8Length(S) < FMaskLength do S := S + ClearChar(Utf8Length(S)+1);
@ -1211,9 +1191,8 @@ end;
// Clear (virtually) a single Utf8 char in position Position // Clear (virtually) a single Utf8 char in position Position
function TCustomMaskEdit.ClearChar(Position : Integer) : TUtf8Char; function TCustomMaskEdit.ClearChar(Position : Integer) : TUtf8Char;
begin begin
Result := FMask[Position];
//For Delphi compatibilty, only literals remain, all others will be blanked //For Delphi compatibilty, only literals remain, all others will be blanked
case CharToMask(FMask[Position]) Of case FMask[Position].MaskType Of
Char_Number, Char_Number,
Char_NumberFixed, Char_NumberFixed,
Char_NumberPlusMin, Char_NumberPlusMin,
@ -1244,13 +1223,14 @@ begin
Char_Binary, Char_Binary,
Char_BinaryFixed : Result := FSpaceChar; Char_BinaryFixed : Result := FSpaceChar;
{Char_Space : Result := #32; //FSpaceChar?; //not Delphi compatible, see notes above} {Char_Space : Result := #32; //FSpaceChar?; //not Delphi compatible, see notes above}
Char_HourSeparator : Result := DefaultFormatSettings.TimeSeparator; Char_HourSeparator : Result := DefaultFormatSettings.TimeSeparator;
Char_DateSeparator : Result := DefaultFormatSettings.DateSeparator; Char_DateSeparator : Result := DefaultFormatSettings.DateSeparator;
Char_IsLiteral : Result := FMask[Position].Literal;
otherwise
raise EDBEditError.CreateFmt('MaskEdit Internal Error.'^m' Found unexpected MaskType at index %d with ordinal value %d',[Position, Integer(FMask[Position].MaskType)]);
end; end;
end; end;
//Insert a single Utf8 char at the current position of the cursor //Insert a single Utf8 char at the current position of the cursor
procedure TCustomMaskEdit.InsertChar(Ch : TUtf8Char); procedure TCustomMaskEdit.InsertChar(Ch : TUtf8Char);
Var Var
@ -1284,7 +1264,7 @@ function TCustomMaskEdit.CanInsertChar(Position: Integer; var Ch: TUtf8Char;
Var Var
Current : tMaskedType; Current : tMaskedType;
Begin Begin
Current := CharToMask(FMask[Position]); Current := FMask[Position].MaskType;
Result := False; Result := False;
// If in UpCase convert the input char // If in UpCase convert the input char
@ -1345,7 +1325,7 @@ Begin
Char_HexFixedDownCase : Result := (Length(Ch) = 1) and (Ch[1] In ['0'..'9','a'..'f']); Char_HexFixedDownCase : Result := (Length(Ch) = 1) and (Ch[1] In ['0'..'9','a'..'f']);
Char_Binary, Char_Binary,
Char_BinaryFixed : Result := (Length(Ch) = 1) and (Ch[1] In ['0'..'1']); Char_BinaryFixed : Result := (Length(Ch) = 1) and (Ch[1] In ['0'..'1']);
Char_IsLiteral : Result := False;
end; end;
//while typing a space is not allowed in these cases, whilst pasting Delphi allows it nevertheless //while typing a space is not allowed in these cases, whilst pasting Delphi allows it nevertheless
if not Result and IsPasting and (Ch = #32) and if not Result and IsPasting and (Ch = #32) and
@ -1379,7 +1359,7 @@ begin
if HasSelection then if HasSelection then
begin begin
DeleteSelected; DeleteSelected;
if IsLiteral(FMask[FCursorPos]) then if IsLiteral(FCursorPos) then
SelectNextChar; SelectNextChar;
end end
else else
@ -1399,7 +1379,7 @@ begin
if HasExtSelection then if HasExtSelection then
begin begin
DeleteSelected; DeleteSelected;
if IsLiteral(FMask[FCursorPos]) then if IsLiteral(FCursorPos) then
SelectNextChar; SelectNextChar;
end end
else else
@ -1456,10 +1436,10 @@ function TCustomMaskEdit.ApplyMaskToText(Value: TCaption): TCaption;
Result := False; Result := False;
for i := StartAt to FMaskLength do for i := StartAt to FMaskLength do
begin begin
if IsLiteral(FMask[i]) then if IsLiteral(i) then
begin begin
FoundAt := i; FoundAt := i;
ALiteral := ClearChar(i); ALiteral := FMask[i].Literal; // ClearChar(i);
Result := True; Result := True;
Exit; Exit;
end; end;
@ -1595,7 +1575,7 @@ begin
j := 1; j := 1;
for i := 1 to FMaskLength do for i := 1 to FMaskLength do
begin begin
if not IsLiteral(FMask[i]) then if not IsLiteral(i) then
begin begin
if (GetCodePoint(Value,j) = #32) then SetCodePoint(S,i,FSpaceChar) else SetCodePoint(S,i, GetCodePoint(Value,j)); if (GetCodePoint(Value,j) = #32) then SetCodePoint(S,i,FSpaceChar) else SetCodePoint(S,i, GetCodePoint(Value,j));
Inc(j); Inc(j);
@ -1609,7 +1589,7 @@ begin
j := Utf8Length(Value); j := Utf8Length(Value);
for i := FMaskLength downto 1 do for i := FMaskLength downto 1 do
begin begin
if not IsLiteral(FMask[i]) then if not IsLiteral(i) then
begin begin
if (GetCodePoint(Value,j) = #32) then SetCodePoint(S,i,FSpaceChar) else SetCodePoint(S,i, GetCodePoint(Value,j)); if (GetCodePoint(Value,j) = #32) then SetCodePoint(S,i,FSpaceChar) else SetCodePoint(S,i, GetCodePoint(Value,j));
Dec(j); Dec(j);
@ -1645,7 +1625,7 @@ Begin
//FSpaceChar can be used as a literal in the mask, so put it back //FSpaceChar can be used as a literal in the mask, so put it back
for i := 1 to FMaskLength do for i := 1 to FMaskLength do
begin begin
if IsLiteral(FMask[i]) and (FMask[i] = FSpaceChar) then if IsLiteral(i) and (FMask[i].Literal = FSpaceChar) then
begin begin
SetCodePoint(S, i, FSpaceChar); SetCodePoint(S, i, FSpaceChar);
end; end;
@ -1654,7 +1634,7 @@ Begin
begin begin
for i := 1 to FMaskLength do for i := 1 to FMaskLength do
begin begin
if IsLiteral(FMask[i]) then SetCodePoint(S, i, #1); //We know this char can never be in Text, so this is safe if IsLiteral(i) then SetCodePoint(S, i, #1); //We know this char can never be in Text, so this is safe
end; end;
S := StringReplace(S, #1, '', [rfReplaceAll]); S := StringReplace(S, #1, '', [rfReplaceAll]);
//Trimming only occurs if FMaskSave = False //Trimming only occurs if FMaskSave = False
@ -1679,7 +1659,7 @@ Begin
//FSpaceChar can be used as a literal in the mask, so put it back //FSpaceChar can be used as a literal in the mask, so put it back
for i := 1 to FMaskLength do for i := 1 to FMaskLength do
begin begin
if IsLiteral(FMask[i]) and (FMask[i] = FSpaceChar) then if IsLiteral(i) and (FMask[i].Literal = FSpaceChar) then
begin begin
SetCodePoint(Result, i, FSpaceChar); SetCodePoint(Result, i, FSpaceChar);
end; end;
@ -1846,7 +1826,7 @@ begin
end end
else else
begin begin
if ((FCursorPos = 0) and (IsLiteral(FMask[1]))) then if ((FCursorPos = 0) and (IsLiteral(1))) then
//On entering select first editable char //On entering select first editable char
SelectNextChar SelectNextChar
else else
@ -2037,6 +2017,12 @@ begin
Key := 0; Key := 0;
Exit; Exit;
end; end;
if (Key = VK_A) and (Shift = [ssModifier]) then
begin
SelectAll;
Key := 0;
Exit;
end;
end; end;
@ -2049,7 +2035,7 @@ begin
end; end;
FCursorPos := GetSelStart; FCursorPos := GetSelStart;
//If the cursor is on a MaskLiteral then go to the next writable position if a key is pressed (Delphi compatibility) //If the cursor is on a MaskLiteral then go to the next writable position if a key is pressed (Delphi compatibility)
if IsLiteral(FMask[FCursorPos + 1]) then if IsLiteral(FCursorPos + 1) then
begin begin
SelectNextChar; SelectNextChar;
Key := EmptyStr; Key := EmptyStr;
@ -2155,7 +2141,7 @@ begin
while (P <= FMaskLength) and (i <= Utf8Length(ClipText)) do while (P <= FMaskLength) and (i <= Utf8Length(ClipText)) do
begin begin
//Skip any literal //Skip any literal
while (P < FMaskLength) and (IsLiteral(FMask[P])) do Inc(P); while (P < FMaskLength) and (IsLiteral(P)) do Inc(P);
//debugln('TCustomMaskEdit.PasteFromClipBoard C: P = ',DbgS(p)); //debugln('TCustomMaskEdit.PasteFromClipBoard C: P = ',DbgS(p));
//Skip any char in ClipText that cannot be inserted at current position //Skip any char in ClipText that cannot be inserted at current position
CP := GetCodePoint(ClipText,i); CP := GetCodePoint(ClipText,i);