We have to upgrade to XE2 (from Delphi6).
I collected many informations about this, but one of them isn't clear for me.
We are using String - what is AnsiString in XE.
As I know we must replace all (P)Ansi[String/Char] in our libraries to avoid the side effects of Unicode converts, and to we can compile our projects.
It is ok, but we are also using TStringList, and I don't found any TAnsiStringList class to change it simply... ;-)
What do you know about this? Can this cause problems too? Or this class have an option to preserve the strings?
(Ok, it seems to be 3 questions, but it is one only)
The program / OS language is hungarian, the charset is WIN-1250, what have some strange characters, like Ő, and Ű...
Thanks for your every information, link, etc.
1) 1st of all - WHY should u use AnsiStringList, rather than converting all your project to unicode-aware TStringList ? That should have certain detailed reasons, to suggest viable alternatives.
Unicode is a superset of windows-1250, windows-1251 and such.
Normally all you locale-specific string would be just losslessly converted to Unicode. IT is the opposite, Unicode to AnsiString, convertion that may loose data.
Explicit or implicit (like AnsiChar reduction in "if char-var in char-set")
You may have type-unsafe API like in DLLs, where compiler cannot check if you pass PChar or PAnsiChar, but you anyway should not pass objects liek TStrings into DLLs, there are BPLs for that.
So you probably just do not need TAnsiStringList
2) you can take TJclAnsiStringList from Jedi Code Library
3) You can use XE2 stock TList<AnsiString> type
Related
I'm working with a large codebase that is using a mix of ANSI characters and Unicode characters. Currently, there are like 13 home-rolled string classes in the project along with many home-rolled string manipulation functions (not sure why someone needed to write convert_to_upper that uses toupper).
I would like to standardize our string handling and from my past work with MFC, I really think using CAtlString is the best solution.
Ignoring the "I hate Microsoft" reasons, why would you suggest not using it and what alternative would you suggest?
One of the reasons I like CAtlSting is the easy handling of string conversion.
CAtlString myString;
myString = "Hello from ANSI";
myString = L"Hello from Unicode";
CAtlStringA ansiString("ANSI");
CAtlStringW unicodeString(ansiString); //Automatic translation to wide string
This kind of flexibility means we don't have to worry about what the string is. You just use the object.
Thanks
i found on internet some source for crypt string and i saw that on delphi 7 the string is crypted and decrypted well, and when i try to do the same things with delphi xe2,xe3,xe4,xe5 the encryption end decryption fail with this error "invalid buffer size for decryption"
i'm using aes.pas and eiaes.pas from here: http://code.google.com/p/jalphi-lib/source/browse/trunk/codemyth/delphi/dontuseit/?r=7
i think that the problem is the enconding of string.
Is it possible to solve this problem?
The AES library you provided the link to has not been updated to support the fact that "String" in later versions of Delphi (Delphi 2009 onward) is now a UnicodeString where each character is a WideChar.
You have 4 options:
Contact the library author and ask if a Unicode version is
planned/available
Attempt to modify the library to support Unicode yourself (or find
someone who can/will help do this)
Find an alternative encryption library that already supports Unicode
Ensure that you only use ANSI Strings with the library.
This last option may not be viable for you but if it is then you will still need to modify the AES library, but you will not need to do any code changes.
The problem is that "String" and "Char" in the later versions of Delphi are "Wide" types (2 bytes per 'character'). This difference is almost certainly causing problems with code in the AES library that assumes only ONE byte per character.
You can make these assumptions valid by making sure that the AES code is working with ANSI Strings.
If you choose to do this, then I would suggest that you introduce two new types:
type
AESString = ANSIString;
AESChar = ANSIChar;
PAESChar = ^AESChar;
You will then need to go through the AES library code replacing any reference to "String" with "AESString", "Char" with "AESChar" and "PChar" with "PAESChar".
This should then make AES an ANSI String library and it will still be usable in Delphi 7 (i.e. pre-Delphi 2009) if that's important for you.
If you then find in the future that you do need to fully support Unicode strings and then need to properly fix the AES library code itself, you can do this and then simply change the AESString and AESChar types to:
type
AESString = String;
AESChar = Char;
If this is then compiled with a non-Unicode version of Delphi, the library will automatically revert back to ANSI String ("String" == ANSIString pre-D2009), so your Unicode changes will need to take this into account if you need to support both Unicode and non-Unicode versions of Delphi. You do need to be careful, but this is not difficult.
If I had a file called raw_text.txt, is there a way I could iterate through each bit?
I see the following but am confused on how to use it:
http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/File-Manipulation.html
— procedure: file-attributes/mode-string attributes
The mode string of the file, a newly allocated string showing the file's mode bits. Under unix, this string is in unix format. Under Windows, this string shows the standard “DOS” attributes in their usual format.
EDIT: I am using mit-scheme
It's implementation-specific. On the Racket side of things, there are a few libraries:
http://planet.racket-lang.org/display.ss?package=bitsyntax.plt&owner=tonyg
http://planet.racket-lang.org/display.ss?package=bit-io.plt&owner=soegaard
You can probably use something like the binary-parse library as well: http://okmij.org/ftp/Scheme/binary-io.html, as long as your implementation of Scheme can support it.
Under MIT Scheme, you can use the bit-string functions.
I haven't actually tried to do anything with this, but I think you're looking for this section of the mit-scheme docs: Input/Output. Specifically the file ports and input procedures sections.
I didn't see anything specifically about reading the binary bits, but if it's character bytes you want, it looks like there are procedures for that. Maybe you want to do something like this?
(call-with-input-file "raw_text.txt" <procedure>)
or
(call-with-binary-file "raw_text.txt" <procedure>)
Where <procedure> will take the file port and use the input procedures to read things from that file.
Just out of curiosity, what are you trying to do?
EDIT: It appears that someone did a write up on this here.
I am coding a plugin for autodesk 3dsmax and they recommend to use the _T(x) macro for every string literal to make it work with unicode as well. I am using the stl string class a lot in this code. So do I have to rewrite the code: string("foo") to: string(_T("foo")) ? Actually the stl string class doesnt have a constructor for wchars, so it doesnt make sense, does it?
Thx
Look at the definition of "T" macro - it expands to "L" in "Unicode" builds or nothing in "non-Unicode" builds. If you want to keep using the string calss and follow the recommendation for your plugin, your best bet is to use something like tstring which would follow the same rules.
But the truth is - all this "T" business made a lot of sense 10 years ago - all modern Windows versions are Unicode-only and you can just use wstring.
You could create an own string class say xstring and use the _T for constants and then internally, depending on unicode or not switch to string or wstring. either that or instantiate xstring<yourchartype>
I'm using Delphi 2007 and I wonder how the following problem can be solved:
I have to translate AComp.Caption for example, but the string that I want to assign to the caption, often depends on some data (for example a date or a number, that gets Formatted). Therefore I have to save the data and the string in a new variable for every translation, which is really annoying.
What I want to do is something like that:
// will add the string and data to an internal list of Translator
// and will then return a DynamicString, which represents the translated value
AComp.Caption := T.NewTranslatedString("Hello %s, do you like cheese?", User)
(Note that AComp.Caption ("Hello %s..") can be changed in different methods)
When switching to another language, you would call T.TranslateAgain() and the value of all strings will be translated and, if data given, formatted again.
Is this possible or do you know another way for solving the given problem?
Thanks in advance
Additional question:
Are strings normal objects, that I can subclass and add dynamic behaviour that changes the string itself in special cases?
Delphi strings are not objects, you can't add behaviours to them. You would need to develop your own class.
The Windows way to localize applications is to get advantage of resources, that can be changed (and loading redirected) without changes to the code (no need to call special functions or add new components), and without run-time calls but to load the resource. The only disadvantage of resources is they cannot be changed easily by the end user. The Delphi 2007 standard localization tools use this approach.
Anyway there are some libraries like dxGetText (which is a port of the GNU gettext library) or TsiLang, for example that use a more "intrusive" approach, requiring changes to your code or adding components. In exchange they can simplify end-user localization.
Before developing your own localization library, I would check if one of the existing ones fits youe needs.
Note: Be aware that Delphi localization tool has significant issues that weren't fixed until XE (which I didn't test yet). See for example QC #79449. Unluckily the fix was never backported to earlier releases.
You can use Delphi's own translator tool. It is able to extract strings and resourcestrings from your source code and form DFM files, and gives you a graphical user interface to translate them to any language. It then creates a resource DLL for each language. The DLL containing the translated strings and DFM data. You should deploy this translation DLL with your project to the destination machine.
In your case, your strings are divided into two groups; fixed strings which do not need any further processing, and parametrized strings which need some additional data to be formatted properly. For the fixed strings, you can just type in the translation into translator tool. For parametrized strings, save each one as a resourcestring and use the resourcestring for formatting them. For example:
resourcestring
strDoYouLikeCheese = 'Hello %s, do you like cheese?';
...
AComp.Caption := Format(strDoYouLikeCheese,[User]);
Now you can use the translator tool or any resource editor to translate the resourcestring into your desired language without the need for changing your source code or recompiling it.
What you want to do is to localize your application. Delphi has support for this, based around the resourcestring keyword. However, I've never done any localization myself so I recommend that you do some websearch for this topic or perhaps wait for the other experts here to supply more detailed help!
You could use a dictionary to keep track of the string mappings, something like this
TTranslator = class
private
FMappings : TDictionary <String, String>;
public
function Translate (const SrcStr : String) : String;
procedure SetMapping (const SrcStr, DestStr : String);
end;
function TTranslator.Translate (const SrcStr : String) : String;
begin
if not FMappings.TryGetValue (SrcStr, Result) then
Result := SrcStr;
end;
procedure TTranslator.SetMapping (const SrcStr, DestStr : String);
begin
FMappings.AddOrSetValue (SrcStr, DestStr);
end;
Translating would then be simply several calls to SetMappings. This gives you a lot of flexiblity. Anyway, you might consider using the built-in localization support or even third-party solutions.
EDIT: Just saw that you are using Delphi 2007, so you don't have TDictionary available. The idea should remain valid, just use any dictionary implementation or a list-based approach.
And to answer the other part of your question: no, strings are not normal object (actually they are not objects at all). They are special in various ways (memory management, copy-on-write behaviour) and it is not possible to subclass them. But that's not what you want anyway if I understood the question correctly.