diff options
-rw-r--r-- | examples/gui/fontselect/fontselect.lpi | 7 | ||||
-rw-r--r-- | examples/gui/fontselect/fontselect.lpr | 6 | ||||
-rw-r--r-- | examples/gui/fontselect/strconstants.pas | 14 | ||||
-rw-r--r-- | src/corelib/gdi/fpgfx_package.lpk | 6 | ||||
-rw-r--r-- | src/corelib/gdi/fpgfx_package.pas | 2 | ||||
-rw-r--r-- | src/corelib/gfx_pofiles.pas | 35 | ||||
-rw-r--r-- | src/corelib/gfx_stringhashlist.pas | 332 | ||||
-rw-r--r-- | src/corelib/lang_afrikaans.inc | 40 | ||||
-rw-r--r-- | src/corelib/lang_english.inc | 6 | ||||
-rw-r--r-- | src/corelib/lang_french.inc | 3 | ||||
-rw-r--r-- | src/corelib/lang_german.inc | 3 | ||||
-rw-r--r-- | src/corelib/lang_italian.inc | 3 | ||||
-rw-r--r-- | src/corelib/lang_portuguese.inc | 3 | ||||
-rw-r--r-- | src/corelib/lang_russian.inc | 3 | ||||
-rw-r--r-- | src/corelib/x11/fpgfx_package.lpk | 6 | ||||
-rw-r--r-- | src/corelib/x11/fpgfx_package.pas | 3 |
16 files changed, 438 insertions, 34 deletions
diff --git a/examples/gui/fontselect/fontselect.lpi b/examples/gui/fontselect/fontselect.lpi index d97b57fa..9e24bba9 100644 --- a/examples/gui/fontselect/fontselect.lpi +++ b/examples/gui/fontselect/fontselect.lpi @@ -32,12 +32,17 @@ <MinVersion Minor="5" Valid="True"/> </Item1> </RequiredPackages> - <Units Count="1"> + <Units Count="2"> <Unit0> <Filename Value="fontselect.lpr"/> <IsPartOfProject Value="True"/> <UnitName Value="fontselect"/> </Unit0> + <Unit1> + <Filename Value="strconstants.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="strconstants"/> + </Unit1> </Units> </ProjectOptions> <CompilerOptions> diff --git a/examples/gui/fontselect/fontselect.lpr b/examples/gui/fontselect/fontselect.lpr index 0c2187b5..ce5e301a 100644 --- a/examples/gui/fontselect/fontselect.lpr +++ b/examples/gui/fontselect/fontselect.lpr @@ -14,7 +14,8 @@ uses gui_listbox, gui_edit, gui_label, - gfx_constants; + gfx_constants, + strconstants; type @@ -31,6 +32,7 @@ type public constructor Create(AOwner: TComponent); override; end; + { TMainForm } @@ -63,7 +65,7 @@ end; constructor TMainForm.Create(AOwner: TComponent); begin inherited Create(AOwner); - WindowTitle := 'Font selection test'; + WindowTitle := rsTitle; SetPosition(100, 100, 500, 400); btnSelectFont := CreateButton(self, 10, 10, 110, rsSelectAFont, @btnSelectFontClick); diff --git a/examples/gui/fontselect/strconstants.pas b/examples/gui/fontselect/strconstants.pas new file mode 100644 index 00000000..15151839 --- /dev/null +++ b/examples/gui/fontselect/strconstants.pas @@ -0,0 +1,14 @@ +unit strconstants; + +{$mode objfpc}{$H+} + +interface + +resourcestring + rsTitle = 'Font selection test'; + + +implementation + +end. + diff --git a/src/corelib/gdi/fpgfx_package.lpk b/src/corelib/gdi/fpgfx_package.lpk index afac8510..c3807141 100644 --- a/src/corelib/gdi/fpgfx_package.lpk +++ b/src/corelib/gdi/fpgfx_package.lpk @@ -26,7 +26,7 @@ <License Value="Modified LGPL "/> <Version Minor="6" Release="1"/> - <Files Count="18"> + <Files Count="19"> <Item1> <Filename Value="..\gfxbase.pas"/> <UnitName Value="gfxbase"/> @@ -99,6 +99,10 @@ <Filename Value="..\gfx_translations.pas"/> <UnitName Value="gfx_translations"/> </Item18> + <Item19> + <Filename Value="..\gfx_stringhashlist.pas"/> + <UnitName Value="gfx_stringhashlist"/> + </Item19> </Files> <RequiredPkgs Count="1"> <Item1> diff --git a/src/corelib/gdi/fpgfx_package.pas b/src/corelib/gdi/fpgfx_package.pas index 0753d2ee..8751d325 100644 --- a/src/corelib/gdi/fpgfx_package.pas +++ b/src/corelib/gdi/fpgfx_package.pas @@ -10,7 +10,7 @@ uses gfxbase, fpgfx, gfx_gdi, gfx_stdimages, gfx_imgfmt_bmp, gfx_widget, gfx_UTF8utils, gfx_extinterpolation, gfx_cmdlineparams, gfx_utils, gfx_popupwindow, gfx_impl, gfx_command_intf, gfx_wuline, gfx_imagelist, - gfx_constants, gfx_pofiles, gfx_translations; + gfx_constants, gfx_pofiles, gfx_translations, gfx_stringhashlist; implementation diff --git a/src/corelib/gfx_pofiles.pas b/src/corelib/gfx_pofiles.pas index 67c5d74f..85e6004e 100644 --- a/src/corelib/gfx_pofiles.pas +++ b/src/corelib/gfx_pofiles.pas @@ -34,12 +34,15 @@ unit gfx_pofiles; {$mode objfpc}{$H+}{$INLINE ON} +{.$Define DEBUG} + interface uses Classes, SysUtils, - Contnrs; + Contnrs, + gfx_stringhashlist; type TPOFileItem = class(TObject) @@ -54,8 +57,8 @@ type TPOFile = class(TObject) protected FItems: TFPList; // list of TPOFileItem - FIdentifierToItem: TFPObjectHashTable; - FOriginalToItem: TFPObjectHashTable; + FIdentifierToItem: TStringHashList; + FOriginalToItem: TStringHashList; public constructor Create(const AFilename: string); constructor Create(AStream: TStream); @@ -261,8 +264,8 @@ var begin inherited Create; FItems := TFPList.Create; - FIdentifierToItem := TFPObjectHashTable.Create(False); - FOriginalToItem := TFPObjectHashTable.Create(False); + FIdentifierToItem := TStringHashList.Create(False); + FOriginalToItem := TStringHashList.Create(True); Size := AStream.Size - AStream.Position; if Size <= 0 then @@ -341,6 +344,9 @@ procedure TPOFile.Add(const Identifier, OriginalValue, TranslatedValue: string); var Item: TPOFileItem; begin + {$IFDEF DEBUG} + writeln('TPOFile.Add: ' + Identifier + ' | ' + OriginalValue + ' | ' + TranslatedValue); + {$ENDIF} if (TranslatedValue = '') then Exit; //==> Item := TPOFileItem.Create(Identifier, OriginalValue, TranslatedValue); @@ -352,10 +358,20 @@ end; function TPOFile.Translate(const Identifier, OriginalValue: string): string; var Item: TPOFileItem; + s: string; begin - Item := TPOFileItem(FIdentifierToItem.Items[Identifier]); + s := StringReplace(Identifier, '.', ':', []); + {$IFDEF DEBUG} + writeln('TPOFile.Translate: ' + s + '(' + Identifier + ') | ' + OriginalValue); + {$ENDIF} + Item := TPOFileItem(FIdentifierToItem.Data[s]); if Item = nil then - Item := TPOFileItem(FOriginalToItem.Items[OriginalValue]); + begin + {$IFDEF DEBUG} + writeln(' identifier lookup failed, trying original value'); + {$ENDIF} + Item := TPOFileItem(FOriginalToItem.Data[OriginalValue]); + end; if Item <> nil then begin Result := Item.Translation; @@ -363,7 +379,12 @@ begin raise Exception.Create('TPOFile.Translate Inconsistency'); end else + begin + {$IFDEF DEBUG} + writeln(' OriginalValue lookup failed, defaulting to original value'); + {$ENDIF} Result := OriginalValue; + end; end; { TPOFileItem } diff --git a/src/corelib/gfx_stringhashlist.pas b/src/corelib/gfx_stringhashlist.pas new file mode 100644 index 00000000..1c5d2724 --- /dev/null +++ b/src/corelib/gfx_stringhashlist.pas @@ -0,0 +1,332 @@ +{ + ***************************************************************************** + * * + * This file is part of the Lazarus Component Library (LCL) * + * * + * See the file COPYING.modifiedLGPL, included in this distribution, * + * for details about the copyright. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * * + ***************************************************************************** + + Thanks to Markus Waldenburg. + + Ported this unit to fpGUI by Graeme Geldenhuys. + TStringHashList is supposed to be faster than FPC's TFPObjectHashTable. This + unit is used in gfx_pofile unit. + +} +unit gfx_stringhashlist; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, gfx_constants; + +type + PStringHashItem = ^TStringHashItem; + TStringHashItem = record + HashValue: Cardinal; + Key: String; + Data: Pointer; + end; + + PStringHashItemList = ^PStringHashItem; + + TStringHashList = class(TObject) + private + FList: PStringHashItemList; + FCount: Integer; + fCaseSensitive: Boolean; + function CompareString(const Value1, Value2: String): Boolean; + function CompareValue(const Value1, Value2: Cardinal): Integer; + function GetData(const S: String): Pointer; + procedure SetCaseSensitive(const Value: Boolean); + procedure Delete(Index: Integer); + procedure SetData(const S: String; const AValue: Pointer); + protected + function HashOf(const Key: string): Cardinal; + procedure Insert(Index: Integer; Item: PStringHashItem); + public + constructor Create(CaseSensitivity: boolean); + destructor Destroy; override; + function Add(const S: String): Integer; + function Add(const S: String; ItemData: Pointer): Integer; + procedure Clear; + function Find(const S: String): Integer; + function Remove(const S: String): Integer; + property CaseSensitive: Boolean read fCaseSensitive write SetCaseSensitive; + property Count: Integer read FCount; + property Data[const S: String]: Pointer read GetData write SetData; default; + property List: PStringHashItemList read FList; + end; + + +implementation + +var + UpperCaseChars: array[char] of char; + +{ TStringHashList } + +function TStringHashList.Add(const S: String): Integer; +begin + Result:=Add(S,nil); +end; + +function TStringHashList.Add(const S: String; ItemData: Pointer): Integer; +var + Item: PStringHashItem; + First, Last, I: Integer; + Val: Cardinal; + Larger: boolean; +begin + New(Item); + Val:= HashOf(S); + Item^.HashValue := Val; + Item^.Key := S; + Item^.Data := ItemData; + if FCount > 0 then + begin + First:=0; + Last:= FCount-1; + Larger:=False; + while First<=Last do + begin + I:=(First+Last)shr 1; + Case CompareValue(Val, fList[I]^.HashValue)<=0 of + True: + begin + Last:=I-1; + Larger:=False; + end; + False: + begin + First:=I+1; + Larger:=True; + end; + end; + end; + Case Larger of + True: Result:=I+1; + False: Result:=I; + end; + end else + Result:=0; + Insert(Result,Item); +end; + +procedure TStringHashList.Clear; +var + I: Integer; +begin + if fCount = 0 then exit; + for I:= 0 to fCount -1 do + Dispose(fList[I]); + if FList<>nil then begin + FreeMem(FList); + FList:=nil; + end; + fCount:= 0; +end; + +function TStringHashList.CompareString(const Value1, Value2: String): Boolean; +var + I, Len: Integer; + P1,P2: PChar; +begin + Result:= False; + P1:= PChar(Value1); + Len:= Length(Value1); + P2:= PChar(Value2); + if Len = Length(Value2) then + begin + Result:= True; + case fCaseSensitive of + True: + for I:= Len -1 downto 0 do + if P1[I] <> P2[I] then begin + Result:= False; + break; + end; + False: + for I:= Len -1 downto 0 do + if UpperCaseChars[P1[I]] <> UpperCaseChars[P2[I]] then begin + Result:= False; + break; + end; + end; + end; +end; + +function TStringHashList.CompareValue(const Value1, Value2: Cardinal): Integer; +begin + Result:= 0; + if Value1 > Value2 then + Result:= 1 + else if Value1 < Value2 then + Result:= -1; +end; + +function TStringHashList.GetData(const S: String): Pointer; +var i: integer; +begin + i:=Find(S); + if i>=0 then + Result:=FList[i]^.Data + else + Result:=nil; +end; + +procedure TStringHashList.Delete(Index: Integer); +begin + if (Index >= 0) and (Index < FCount) then + begin + dec(FCount); + if Index < FCount then + System.Move(FList[Index + 1], FList[Index], + (FCount - Index) * SizeOf(PStringHashItem)); + end; +end; + +procedure TStringHashList.SetData(const S: String; const AValue: Pointer); +var i: integer; +begin + i:=Find(S); + if i>=0 then + FList[i]^.Data:=AValue + else + Add(S,AValue); +end; + +destructor TStringHashList.Destroy; +begin + Clear; + inherited Destroy; +end; + +function TStringHashList.Find(const S: String): Integer; +var + Value: Integer; + First, Last, Temp, I: Integer; +begin + Value:= HashOf(s); + Result:= -1; + First:= 0; + Last:= Count -1; + while First <= Last do + begin + Temp:= (First + Last) div 2; + case CompareValue(Value, FList[Temp]^.HashValue) of + 1: First:= Temp +1; + 0: + begin + Result:= Temp; + if CompareString(S, FList[Temp]^.Key) then + exit + else + break; + end; + -1: Last:= Temp-1; + end; + end; + if Result <> -1 then + begin + Result:= -1; + First:= Temp -1; + if First > 0 then + while CompareValue(Value, FList[First]^.HashValue) = 0 do + dec(First); + inc(First); + Last:= Temp +1; + if Last < Count -1 then + while CompareValue(Value, FList[Last]^.HashValue) = 0 do + inc(Last); + dec(Last); + for I:= First to Last do + if CompareString(S, FList[I]^.Key) then + begin + Result:= I; + Exit; + end; + end; +end; + +function TStringHashList.HashOf(const Key: string): Cardinal; +var + P: PChar; + I, Len: Integer; +begin + P:= PChar(Key); + Len:= Length(Key); + Result := Len; + // use the last 30 characters to compute the hash + case fCaseSensitive of + True: + for I:= Len -1 downto 0 do + inc(Result, cardinal(ord(P[I])) shl I); + False: + for I:= Len -1 downto 0 do + inc(Result, cardinal(ord(UpperCaseChars[P[I]])) shl I); + end; +end; + +procedure TStringHashList.Insert(Index: Integer; Item: PStringHashItem); +begin + ReallocMem(FList, (fCount +1) * SizeOf(PStringHashItem)); + if Index > fCount then Index:= fCount; + if Index < 0 then Index:= 0; + if Index < FCount then + System.Move(FList[Index], FList[Index + 1], + (FCount - Index) * SizeOf(PStringHashItem)); + FList[Index] := Item; + Inc(FCount); +end; + +constructor TStringHashList.Create(CaseSensitivity: boolean); +begin + fCaseSensitive:=CaseSensitivity; + inherited Create; +end; + +function TStringHashList.Remove(const S: String): Integer; +begin + Result:= Find(S); + if Result > -1 then + begin + Dispose(fList[Result]); + Delete(Result); + end; +end; + +procedure TStringHashList.SetCaseSensitive(const Value: Boolean); +begin + if fCaseSensitive <> Value then + begin + if Count > 0 then + begin + raise EListError.Create(rsListMustBeEmpty); + exit; + end; + fCaseSensitive := Value; + end; +end; + +//------------------------------------------------------------------------------ +procedure InternalInit; +var c: char; +begin + for c:=Low(char) to High(char) do begin + UpperCaseChars[c]:=upcase(c); + end; +end; + +initialization + InternalInit; + +end. diff --git a/src/corelib/lang_afrikaans.inc b/src/corelib/lang_afrikaans.inc index d00420fc..fe7d3a1f 100644 --- a/src/corelib/lang_afrikaans.inc +++ b/src/corelib/lang_afrikaans.inc @@ -7,25 +7,25 @@ rsLanguage = 'Afrikaans'; rsOK = 'Goed'; rsCancel = 'Kanselleer'; rsHelp = 'Hulp'; -rsOpen = 'Maak oop'; +rsOpen = 'Open'; rsSave = 'Stoor'; -rsCreate = 'Create'; +rsCreate = 'Skep'; rsChange = 'Verander'; rsFind = 'Vind'; rsSearch = 'Soek'; rsReplace = 'Vervang'; -rsConfirm = 'Confirm'; +rsConfirm = 'Bevestig'; rsAll = 'Alles'; -rsSelect = 'Select'; +rsSelect = 'Kies'; rsYes = 'Ja'; rsNo = 'Nee'; -rsAbort = 'Abort'; +rsAbort = 'Staak'; rsRetry = 'Probeer weer'; rsIgnore = 'Ignoreer'; rsClose = 'Sluit'; -rsInsert = 'Insert'; +rsInsert = 'Invoeg'; rsEdit = 'Redigeer'; -rsDelete = 'Delete'; +rsDelete = 'Skrap'; rsExit = 'Staak'; rsYesToAll = 'Ja vir Alles'; rsNoToAll = 'Nee vir Alles'; @@ -35,7 +35,7 @@ rsNoToAll = 'Nee vir Alles'; rsError = 'Fout'; rsCriticalError = 'Kritiese Fout'; rsInformation = 'Informasie'; -rsConfirmation = 'Confirm'; +rsConfirmation = 'Bevestiging'; rsWarning = 'Waarskuwing'; rsMessage = 'Boodskap'; @@ -45,34 +45,36 @@ rsAllFiles = 'Alle Lers'; // CreateDir Dialog -rsCreateDirectory = 'Create directory'; -rsEnterNewDirectory = 'Enter new directory name'; -rsCannotCreateDir = 'Cannot create directory'; +rsCreateDirectory = 'Skep ''n lêergids'; +rsEnterNewDirectory = 'Gee ''n nuwe lêergids naam'; +rsCannotCreateDir = 'Kan nie die lêergids skep nie'; // Font Dialog -rsSelectAFont = 'Select a font'; +rsSelectAFont = 'Kies ''n lettertipe'; rsName = 'Naam'; -rsCollection = 'Collection'; +rsCollection = 'Versameling'; rsSize = 'Groote'; rsStyle = 'Steil'; -rsItalic = 'Italic'; -rsBold = 'Bold'; +rsItalic = 'Kursief'; +rsBold = 'Vetdruk'; rsUnderScore = 'Onderstreep'; -rsExampleText = 'Example Text'; +rsExampleText = 'Teks Voorbeeld'; // Open Dialog rsOpenAFile = 'Maak ''n ler op'; rsFileName = 'Ler naam'; rsFileType = 'Tipe Ler'; -rsDrive = 'Drive'; +rsDrive = 'Dryf'; rsFiles = 'Lers'; -rsDirectories = 'Directories'; -rsShowHidden = 'Show hidden files'; +rsDirectories = 'Lêergidse'; +rsShowHidden = 'Wys verseekte lêers'; // Save Dialog rsSaveAFile = 'Stoor ''n ler'; +// Error messages +rsListMustBeEmpty = 'Lys moet leeg wees'; diff --git a/src/corelib/lang_english.inc b/src/corelib/lang_english.inc index dcbc1836..291f66fd 100644 --- a/src/corelib/lang_english.inc +++ b/src/corelib/lang_english.inc @@ -35,7 +35,7 @@ rsNoToAll = 'No to All'; rsError = 'Error'; rsCriticalError = 'Critical Error'; rsInformation = 'Information'; -rsConfirmation = 'Confirm'; +rsConfirmation = 'Confirmation'; rsWarning = 'Warning'; rsMessage = 'Message'; @@ -75,4 +75,8 @@ rsShowHidden = 'Show hidden files'; // Save Dialog rsSaveAFile = 'Save file as'; +// Error messages +rsListMustBeEmpty = 'List must be empty'; + + diff --git a/src/corelib/lang_french.inc b/src/corelib/lang_french.inc index a265e61d..dd1945f5 100644 --- a/src/corelib/lang_french.inc +++ b/src/corelib/lang_french.inc @@ -76,3 +76,6 @@ rsShowHidden = 'Montrer les fichiers cachés'; rsSaveAFile = 'Sauver sous'; +// Error messages +rsListMustBeEmpty = 'Liste doit être vide'; + diff --git a/src/corelib/lang_german.inc b/src/corelib/lang_german.inc index 6a9c4e59..6bc34d97 100644 --- a/src/corelib/lang_german.inc +++ b/src/corelib/lang_german.inc @@ -76,3 +76,6 @@ rsShowHidden = 'Show hidden files'; rsSaveAFile = 'Datei speichern'; +// Error messages +rsListMustBeEmpty = 'Liste müssen leer sein'; + diff --git a/src/corelib/lang_italian.inc b/src/corelib/lang_italian.inc index aeadb65c..bb3fb809 100644 --- a/src/corelib/lang_italian.inc +++ b/src/corelib/lang_italian.inc @@ -76,3 +76,6 @@ rsShowHidden = 'Mostra files nascosti'; rsSaveAFile = 'Salva con nome'; +// Error messages +rsListMustBeEmpty = 'Elenco deve essere vuoto'; + diff --git a/src/corelib/lang_portuguese.inc b/src/corelib/lang_portuguese.inc index 3d3751da..07cc50cd 100644 --- a/src/corelib/lang_portuguese.inc +++ b/src/corelib/lang_portuguese.inc @@ -77,3 +77,6 @@ rsShowHidden = 'Mostrar arquivos ocultos'; rsSaveAFile = 'Salvar arquivo como'; +// Error messages +rsListMustBeEmpty = 'Lista deve estar vazio'; + diff --git a/src/corelib/lang_russian.inc b/src/corelib/lang_russian.inc index e03513ed..e2e2ecf8 100644 --- a/src/corelib/lang_russian.inc +++ b/src/corelib/lang_russian.inc @@ -76,3 +76,6 @@ rsShowHidden = 'Показывать скрытые файлы'; rsSaveAFile = 'Сохранить файл как'; +// Error messages +rsListMustBeEmpty = 'Список должен быть пустым'; + diff --git a/src/corelib/x11/fpgfx_package.lpk b/src/corelib/x11/fpgfx_package.lpk index f2a3d477..786dd522 100644 --- a/src/corelib/x11/fpgfx_package.lpk +++ b/src/corelib/x11/fpgfx_package.lpk @@ -24,7 +24,7 @@ <License Value="Modified LGPL "/> <Version Minor="6" Release="1"/> - <Files Count="20"> + <Files Count="21"> <Item1> <Filename Value="x11_xft.pas"/> <UnitName Value="x11_xft"/> @@ -105,6 +105,10 @@ <Filename Value="../gfx_translations.pas"/> <UnitName Value="gfx_translations"/> </Item20> + <Item21> + <Filename Value="../gfx_stringhashlist.pas"/> + <UnitName Value="gfx_stringhashlist"/> + </Item21> </Files> <LazDoc Paths="../../../docs/xml/corelib/;../../../docs/xml/corelib/x11/;../../../docs/xml/corelib/gdi/"/> <RequiredPkgs Count="1"> diff --git a/src/corelib/x11/fpgfx_package.pas b/src/corelib/x11/fpgfx_package.pas index d1484532..d7813dee 100644 --- a/src/corelib/x11/fpgfx_package.pas +++ b/src/corelib/x11/fpgfx_package.pas @@ -10,7 +10,8 @@ uses x11_xft, x11_keyconv, gfxbase, gfx_x11, fpgfx, gfx_stdimages, gfx_imgfmt_bmp, gfx_widget, gfx_UTF8utils, gfx_extinterpolation, gfx_cmdlineparams, gfx_utils, gfx_popupwindow, gfx_impl, gfx_command_intf, gfx_wuline, - gfx_imagelist, gfx_constants, gfx_pofiles, gfx_translations; + gfx_imagelist, gfx_constants, gfx_pofiles, gfx_translations, + gfx_stringhashlist; implementation |