- add more UTF8 string functions (Delete, Insert, LoweCase, UpperCase)
  - revert gtk SelStart, SelLength changes - they are and will return position in Characters
  - fix combobox completion code

git-svn-id: trunk@16478 -
This commit is contained in:
paul 2008-09-08 03:41:32 +00:00
parent 5f4857e470
commit 8ae1d62bbe
3 changed files with 78 additions and 60 deletions

View File

@ -483,7 +483,7 @@ end;
procedure TCustomComboBox.KeyUp(var Key: Word; Shift: TShiftState);
var
iSelStart: Integer; // byte position
iSelStart: Integer; // char position
sCompleteText, sPrefixText, sResultText: string;
begin
inherited KeyUp(Key, Shift);
@ -510,10 +510,10 @@ begin
iSelStart := SelStart;//Capture original cursor position
//DebugLn(['TCustomComboBox.UTF8KeyPress SelStart=',SelStart,' Text=',Text]);
//End of line completion
if ((iSelStart < Length(Text))
and (cbactEndOfLineComplete in FAutoCompleteText)) then
if ((iSelStart < UTF8Length(Text)) and
(cbactEndOfLineComplete in FAutoCompleteText)) then
Exit;
sPrefixText := LeftStr(Text, iSelStart);
sPrefixText := UTF8Copy(Text, 1, iSelStart);
sCompleteText := GetCompleteText(Text, iSelStart,
(cbactSearchCaseSensitive in FAutoCompleteText),
(cbactSearchAscending in FAutoCompleteText), Items);
@ -524,12 +524,12 @@ begin
if ((cbactEndOfLineComplete in FAutoCompleteText) and
(cbactRetainPrefixCase in FAutoCompleteText)) then
begin//Retain Prefix Character cases
Delete(sResultText, 1, iSelStart);
Insert(sPrefixText, sResultText, 1);
UTF8Delete(sResultText, 1, iSelStart);
UTF8Insert(sPrefixText, sResultText, 1);
end;
Text := sResultText;
SelStart := iSelStart;
SelLength := Length(Text);
SelLength := UTF8Length(Text);
end;
end;
end;
@ -539,8 +539,8 @@ procedure TCustomComboBox.KeyPress(var Key: char);
begin
//Convert character cases if FCharCase is not ecNormalCase
case FCharCase of
ecLowerCase: Key := lowerCase(Key);
ecUpperCase: Key := upCase(Key);
ecLowerCase: Key := lowerCase(Key);
ecUpperCase: Key := upCase(Key);
end;
inherited KeyPress(Key);
end;
@ -549,8 +549,8 @@ procedure TCustomComboBox.UTF8KeyPress(var UTF8Key: TUTF8Char);
begin
//Convert character cases if FCharCase is not ecNormalCase
case FCharCase of
ecLowerCase: UTF8Key := AnsiLowerCase(UTF8Key);
ecUpperCase: UTF8Key := AnsiUpperCase(UTF8Key);
ecLowerCase: UTF8Key := AnsiLowerCase(UTF8Key);
ecUpperCase: UTF8Key := AnsiUpperCase(UTF8Key);
end;
inherited UTF8KeyPress(UTF8Key);
end;

View File

@ -1224,14 +1224,10 @@ begin
// if the combo is an editable ...
Entry := GetComboBoxEntry(WidgetInfo^.CoreWidget);
if Entry<>nil then begin
// Note: gtk begins at 0, LCL at 1
if gtk_editable_get_selection_bounds(PGtkEditable(Entry), @AStart, @AEnd) = gtk_true then
Result := Min(AStart,AEnd)
if gtk_editable_get_selection_bounds(PGtkEditable(Entry), @AStart, @AEnd) = False then
Result := gtk_editable_get_position(PGtkEditable(Entry))
else
Result := gtk_editable_get_position(PGtkEditable(Entry));
//DebugLn(['TGtk2WSCustomComboBox.GetSelStart CharStart=',Result]);
Result:=UTF8CharToByteIndex(gtk_entry_get_text(Entry),High(integer),Result+1)-1;
//DebugLn(['TGtk2WSCustomComboBox.GetSelStart ',dbgsName(ACustomComboBox),' AText=',gtk_entry_get_text(Entry),' Result=',Result]);
Result := Min(AStart, AEnd);
end;
end;
@ -1241,7 +1237,6 @@ var
WidgetInfo: PWidgetInfo;
Entry: PGtkEntry;
AStart, AEnd: gint;
AText: Pgchar;
begin
Result := 0;
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
@ -1249,16 +1244,9 @@ begin
// if the combo is an editable ...
Entry := GetComboBoxEntry(WidgetInfo^.CoreWidget);
if Entry<>nil then begin
if gtk_editable_get_selection_bounds(PGtkEditable(Entry), @AStart, @AEnd) = gtk_true then
begin
MakeMinMax(AStart,AEnd);
AText:=gtk_editable_get_chars(PGtkEditable(Entry),AStart,AEnd);
Result:=UTF8Length(AText,(AEnd-AStart)*4);
g_free(AText);
end
else
Result := 0;
DebugLn(['TGtk2WSCustomComboBox.GetSelLength ',dbgsName(ACustomComboBox),' AText=',gtk_entry_get_text(Entry),' Result=',Result]);
if gtk_editable_get_selection_bounds(PGtkEditable(Entry), @AStart, @AEnd) = False then
Exit(gtk_editable_get_position(PGtkEditable(Entry)));
Result := ABS(AStart - AEnd);
end;
end;
@ -1325,16 +1313,13 @@ class procedure TGtk2WSCustomComboBox.SetSelStart(
var
WidgetInfo: PWidgetInfo;
Entry: PGtkEntry;
AText: Pgchar;
begin
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
Entry := GetComboBoxEntry(WidgetInfo^.CoreWidget);
if Entry<>nil then begin
//gtk_entry_select_region(Entry, NewStart, NewStart);
AText:=gtk_entry_get_text(Entry);
//DebugLn(['TGtk2WSCustomComboBox.SetSelStart ',dbgsName(ACustomComboBox),' AText=',AText,' NewStart=',NewStart,' UTF8Start=',UTF8Length(AText,NewStart-1)]);
gtk_editable_set_position(PGtkEditable(Entry), UTF8Length(AText,NewStart));
gtk_editable_set_position(PGtkEditable(Entry), NewStart);
end;
end;
@ -1343,27 +1328,14 @@ class procedure TGtk2WSCustomComboBox.SetSelLength(
var
WidgetInfo: PWidgetInfo;
Entry: PGtkEntry;
AStart, AEnd: gint;// starts at 0
ByteStart: LongInt;// starts at 0
AText: Pgchar;
NewCharLength: LongInt;
Start: Integer;
begin
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
Entry := GetComboBoxEntry(WidgetInfo^.CoreWidget);
if Entry<>nil then begin
if gtk_editable_get_selection_bounds(PGtkEditable(Entry), @AStart, @AEnd) = gtk_true then
MakeMinMax(AStart,AEnd)
else
AStart := gtk_editable_get_position(PGtkEditable(Entry));
AText:=gtk_entry_get_text(Entry);
NewCharLength:=NewLength;
if (NewCharLength>0) and (AText<>nil) then begin
ByteStart:=UTF8CharToByteIndex(AText,High(integer),AStart+1)-1;
NewCharLength:=UTF8Length(@AText[ByteStart],NewLength);
end;
//DebugLn(['TGtk2WSCustomComboBox.SetSelLength ',dbgsName(ACustomComboBox),' AText=',AText,' CharStart=',AStart,' ByteStart=',ByteStart,' NewLength=',NewLength,' NewCharLength=',NewCharLength]);
gtk_editable_select_region(PGtkEditable(Entry), AStart, AStart + NewCharLength);
Start := GetSelStart(ACustomComboBox);
gtk_editable_select_region(PGtkEditable(Entry), Start, Start + NewLength);
end;
end;

View File

@ -302,6 +302,10 @@ function UTF8CharacterStrictLength(P: PChar): integer;
function UTF8CStringToUTF8String(SourceStart: PChar; SourceLen: SizeInt) : string;
function UTF8Pos(const SearchForText, SearchInText: string): integer;
function UTF8Copy(const s: string; StartCharIndex, CharCount: integer): string;
procedure UTF8Delete(var s: String; StartCharIndex, CharCount: integer);
procedure UTF8Insert(const source: String; var s: string; StartCharIndex: integer);
function UTF8LowerCase(const s: String): String;
function UTF8UpperCase(const s: String): String;
function FindInvalidUTF8Character(p: PChar; Count: integer;
StopOnNonASCII: Boolean = false): integer;
procedure AssignUTF8ListToAnsi(UTF8List, AnsiList: TStrings);
@ -533,11 +537,13 @@ function GetCompleteText(sText: string; iSelStart: Integer;
function IsSamePrefix(sCompareText, sPrefix: string; iStart: Integer;
var ResultText: string): Boolean;
var sTempText: string;
var
sTempText: string;
begin
Result := False;
sTempText := LeftStr(sCompareText, iStart);
if not bCaseSensitive then sTempText := UpperCase(sTempText);
sTempText := UTF8Copy(sCompareText, 1, iStart);
if not bCaseSensitive then
sTempText := UTF8UpperCase(sTempText);
if (sTempText = sPrefix) then
begin
ResultText := sCompareText;
@ -545,25 +551,28 @@ function GetCompleteText(sText: string; iSelStart: Integer;
end;
end;
var i: Integer;
sPrefixText: string;
var
i: Integer;
sPrefixText: string;
begin
//DebugLn(['GetCompleteText sText=',sText,' iSelStart=',iSelStart,' bCaseSensitive=',bCaseSensitive,' bSearchAscending=',bSearchAscending,' slTextList.Count=',slTextList.Count]);
Result := sText;//Default to return original text if no identical text are found
if (sText = '') then Exit;//Everything is compatible with nothing, Exit.
if (iSelStart = 0) then Exit;//Cursor at beginning
if (slTextList.Count = 0) then Exit;//No text list to search for idtenticals, Exit.
sPrefixText := LeftStr(sText, iSelStart);//Get text from beginning to cursor position.
sPrefixText := UTF8Copy(sText, 1, iSelStart);//Get text from beginning to cursor position.
if not bCaseSensitive then
sPrefixText := UpperCase(sPrefixText);
sPrefixText := UTF8UpperCase(sPrefixText);
if bSearchAscending then
begin
for i:=0 to slTextList.Count-1 do
if IsSamePrefix(slTextList[i], sPrefixText, iSelStart, Result) then Break;
for i := 0 to slTextList.Count - 1 do
if IsSamePrefix(slTextList[i], sPrefixText, iSelStart, Result) then
break;
end else
begin
for i:=slTextList.Count-1 downto 0 do
if IsSamePrefix(slTextList[i], sPrefixText, iSelStart, Result) then Break;
for i := slTextList.Count - 1 downto 0 do
if IsSamePrefix(slTextList[i], sPrefixText, iSelStart, Result) then
break;
end;
end;
@ -2684,6 +2693,43 @@ begin
end;
end;
procedure UTF8Delete(var s: String; StartCharIndex, CharCount: integer);
var
StartBytePos: PChar;
EndBytePos: PChar;
MaxBytes: PtrInt;
begin
StartBytePos:=UTF8CharStart(PChar(s),length(s),StartCharIndex-1);
if StartBytePos <> nil then
begin
MaxBytes:=PtrInt(PChar(s)+length(s)-StartBytePos);
EndBytePos:=UTF8CharStart(StartBytePos,MaxBytes,CharCount);
if EndBytePos=nil then
Delete(s,StartBytePos-PChar(s)+1,MaxBytes)
else
Delete(s,StartBytePos-PChar(s)+1,EndBytePos-StartBytePos);
end;
end;
procedure UTF8Insert(const source: String; var s: string; StartCharIndex: integer);
var
StartBytePos: PChar;
begin
StartBytePos:=UTF8CharStart(PChar(s),length(s),StartCharIndex-1);
if StartBytePos <> nil then
Insert(source, s, StartBytePos-PChar(s)+1);
end;
function UTF8LowerCase(const s: String): String;
begin
Result := UTF8Encode(WideLowerCase(UTF8Decode(s)));
end;
function UTF8UpperCase(const s: String): String;
begin
Result := UTF8Encode(WideUpperCase(UTF8Decode(s)));
end;
function FindInvalidUTF8Character(p: PChar; Count: integer;
StopOnNonASCII: Boolean): integer;
// return -1 if ok