Archive: string functions


string functions
Hello

I'm new to NSIS, it looked fine at first sight but when I tried to make installer what I wanted I hit some problems:
1) Using variables is big pain, using strings manipulation is HUGE pain. I don't get how modern installer can lack any decent number of functions for such basic task. Handling Path/reg keys require complicated function in current script using StrCpy/StrCmp/IntOp. For example in my installer have to read key from file which stores installed path of application. But it isn't stored in right-to-use format I need to manipulate (cut path add some text). I've done it but when I want to display it using Static in confirmation window, it "eats" backshlashes. :-\ So is there easy way of manipulating paths in current NSIS ?
2) In general my installer will be template for game maps installers of other people so such user will customize name and similar things in script (stored as constants), but how to add files the easy way (not editing script and making line for every single file). Is there any file list generator or can I use external (of script) file-list file (:)) ?


1) The strings commands are easy to use if you follow the documentation. Probably there is already are suitable function written for you:

http://nsis.sourceforge.net/archive/...11&instances=0

2) Using an extenal header file is even better. The users will only have to modify that file with defines. You can also use defines for filenames or add all files in a folder using *.* or /r.


I know these function are the only help, but I would still opt for something easier as string manipulation is used very often and seeking and adding long function for every simple string task is a little too much work.
Also docs are not so informative, I had to dig quite a bit to find out how to concatenate strings. I found it finally in some example in the internet. The same goes for InstallOptions and custom pages in general.


You can do everything with the current string commands. Sometimes you will have to use multiple commands, but that's the basic of all programming languages. There are hundreds of things you can do with strings, it's impossible to add a command for every possibility.

The whole point of having function is that becomes easy to do the same thing multiple times. If you think the functions they make your script less easy to read, put them in a header file.

If we would add a command for all things that can also be done using the scripting language, NSIS would become huge.

We are always working on improvements of the documentation, but it takes a lot of time. If you think it can be improved, why not help yourself?


Well I don't want to create any argument but people can still write in assembler so what for do we need NSIS then? I was talking about usability and making things easier, which should be the goal of every computer app and epecially NSIS for installation tasks. I'm not saying that you should mirror STL or some other lib but few basic things.
As for me writitng docs - I was saying that one (in this case me) can't learn much from than - how could I write docs knowing little about subject, that's the problem.


So which things do you think that can be added to make string manipulation easier?

The problem is that it's easy to complain about documentation, but if nobody wants to help improving them (after they have learned NSIS) we don't get any further.


String functions like:
* finding index of char/substr in string
* finding first occurence char from subset in string starting from index.
* replacing char/substring in string
* conversion to/from C-style strings (for easier using strings in Windows functions).
* concatenating string (in current system name of veriable is joined with following text, which can make trouble in some cases) OR append-to-text function.

First three should have reverse-index versions. If this is too big to add maybe it could be made as plugin with "extra string functions".


Concatenating strings can be done with StrCpy, like

StrCpy $MYSTRING "sometext $MYSTRING1 $MYSTRING2"

The are currently functions for all these search & replace actions. I see no reason to integrate them, it will only make the installer larger (functions only take a few bytes, adding it in native code to the exehead takes much more space).

You could write a plug-in with string functions, but it will still be larger than functions, and it will do exactly the same.


i would add these typical c++ string-commands:
String.SubString
StringReplace
String.LastDelimiter
String.Length
String.Pos

i think, those are the most used, an important commands (after the included StrCpy and StrCmp).


Most of these things can be done using the current commands (StrLen etc.). For the others you can use a function.

If someone wants to make a plug-in or header file with string manipulation functions, I will include it in the distribution.


hmm, yes, i already thougt at a plugin for those commands, or even a collection of macros doing this in a header-file at the include-dir.
maybe an include-file would be easier ...

ah, i forgot that StrLen already exists :)


It would be nice if someone could put all useful string functions together in a nice header file with some documentation.


Do you want the typical <string.h> functions?


Not all, but a few, the most handy during setup functions, like those I mentioned. I don't think they would take more than 1-2KB of code.

Originally posted by Joost Verburg
Concatenating strings can be done with StrCpy, like

StrCpy $MYSTRING "sometext $MYSTRING1 $MYSTRING2"
What if I want to insert variable into word, like "$APPNAMEreadme.txt", will it work correctly if I will have variables $APPNAME, $APPNAMER, $APPNAMEREAD ?

PS. How to display path text from string char in Label control of dialog window? I have to convert it to C-style string; creating such function in current script would be quite painful.

Originally posted by KHysiek
PS. How to display path text from string char in Label control of dialog window? I have to convert it to C-style string; creating such function in current script would be quite painful.
This may help you: http://nsis.sourceforge.net/archive/...ances=0,11,122

Putting all of the codes in one file, ready to include, like the <string.h> C++ file and thousands of others inside the C++, is the unique solution for that, I think, like Joost said.

If everyone wants, I can make an integrated file for that, but you have to aid sometimes because I don't know the C++ files and codes! (I think I have at least the C++ files, but I don't know how to use them)


It would be nice to have all of the string functions in one place. I often forget which header file I have strstr in or which one has strreplace. It would be great to include string.nsh and have all those functions right there (and probably something I should have been doing on my own anyway.).


yes, that would be really nice.
but i think, if someone collects all this functions, it will be better to convert them to macros. macros are much easier to include in the code, than functions, which require some 'pushing'.


Must agree, better than plugin, a Nsis Header (NSH) will be a solution. I'm making a plugin, (3.40 KB) and 3 functions to include; I think will be better to make Nsis header files rather to embed the DLL.... :)


I'll do this way: (example)

${StrTok} $0 "My text" " "

It will combine:

Defines - easy the call of commands.
Macros - easy the call of command parameters.
Functions - don't occupy much space in compiled installer.


Great, if you can finish it soon it can be included in NSIS 2.


Wow, that was unexpected...

In the case of StrTok, I don't know if I have to put the result in a variable, several ones, or use several times the same command to return results for each string before and after separators...


Something to bear in mind if you plan on bundling all these functions in a single header: all of them will be included in the installer whether used or not, and the compiler will throw up warnings about them.


I thought they'd only be included if you specifically say:
!include "strings.nsh"

'Doh Sorry, didn't think about it very hard before I posted. :D


He means that all functions in a header file will be included when including the file.

This problem can be solved by using macros which is already what deguix wants to do.


EDIT: I think that this should be not included in the NSIS 2, because putting this without much work in it (the first version) will be complainted for everyone, that something could be better.

You remember the old NSIS Update? It was just included after some NSIS versions, because needed to be changed?...


Ok, I have the beta... It has these functions now:

Function - Command "Parameters":

Search in String Function - ${StrStr} "ResultVar" "StrToSearchIn" "StrToBeSearched"
StrTok Function - ${StrTok} "ResultVar" "ResultVar2" "StrToTokenizing" "Separators"
Copy to Clipboard Function - ${StrClbSet} "String"
Copy from Clipboard Function - ${StrClbGet} "ResultVar"

Use a first command out of Sections and Functions to insert its function in your installer script.

I made changes in two functions:

StrTok Function - now is based in StrStr, more simpler I think, but the results didn't change.

Copy from Clipboard Function - the function name was "CopyToClipboard", changed it to "CopyFromClipboard".

(I think someone should put the Modern UI startup message in the compilation as my style, because is more clear.)

(The documentation doesn't say about "/*" (start) and "*/" (end) for comments.)

Example Script:


Name Test
OutFile Test.exe

!include "StringFunctions.nsh"

${StrStr}

Section

${StrStr} $0 "this is a long ass string" "ass"

SectionEnd


Put this file in the NSIS Include Dir.

Yes, you can also use C-style comments. I'll add it to the manual.


Version 0.02, now just lacks the documentation and more tests...

This file includes basic how to use, commands, and comments about functions included and not included.

If you have any complaint about functions included or not included, please tell me now or I will finish the final version first... :cool:


So, what about functions I've mentioned earlier ? :)


* finding index of char/substr in string
Maybe a change to StrStr to do that, so I have to work a little bit...

* finding first occurence char from subset in string starting from index.
You can do this using StrCpy to customize where it will start and use StrStr Function.

* replacing char/substring in string
Use StrReplace Function.

* conversion to/from C-style strings (for easier using strings in Windows functions).
Hmmmm... maybe using System plugin or Math plugin. I will try to search.

* concatenating string (in current system name of veriable is joined with following text, which can make trouble in some cases) OR append-to-text function.
One command resume it all: StrCpy.

PS. How to display path text from string char in Label control of dialog window? I have to convert it to C-style string; creating such function in current script would be quite painful.
Use NSISToIO inside header file. (I don't know if this is right if you want to do that in a normal dialog from Windows or something)

conversion to/from C-style strings (for easier using strings in Windows functions).
NSIS uses C-style strings. What do you mean by this?

Any estimate to when 1.00 will be ready?


Hehehe, I bought a new game and I and my brother couldn't stop to play it until now... but it is nearly done. 6:00 AM of tomorrow is done, or more soon if it is possible... (sharing pc problems, you know)


Version 1.00 done. Included the header file and manual.

Changes:

- Added documentation.
- Renamed header file to "StrFunc.nsh".
- Added 1 function, StrLoc.
- Modified StrStrAdv, removed some lines.
- Fixed StrTok, 2 simple numbers made it loop everytime.
- Fixed some small issues in the header file.


Thanks.

I tried to write an example file for the header file but stumbled upon a few problems. The example file, including the described problems is attached.

StrLoc doesn't seem to function when the string it searches for is larger than the string it searches in. I found this because I got confused of the readme which states the usage line is:

${StrLoc} ResultVar String StrToSearchIn Direction

On first look it looks like I'm supposed to put the string that I want searched in StringToSearchIn, but it's the other way around. How about SearchIn SearchFor?

According to my understanding, the next line should return "abc", but it doesn't:

${StrStrAdv} $0 "abcabcabc" "abc" "<" ">" "0" "1"

It returns an empty string. If I search for the second occurrence of "abc" in "abcabcabc", starting from the right position, it should find the second set of "abc", but it doesn't.

StrSort doesn't seem to want to search for more than one char (line 136). It also has a problem if you want to search for "error" (line 139).

And last but not least, StrTok gets stuck in an endless loop if the token number is 0.


Version 1.01, all bugs you said are fixed:

- Fixed Documentation about StrSort and StrTok.
- Fixed StrTok default value for the string part. Now it's "L".
- Fixed StrStrAdv fixed wrong search when had a combination of same substrings one after another in a string.
- Fixed StrLoc, when a string isn't found, don't return any value at all.

Read the manual for see more details.


StrLoc and StrSort are still not working right. The documentation of StrSort got mixed up. It's talking about StringToSearch but there is no such parameter on the usage line. Example attached.


Fixed StrLoc, removed StrSort and added to CVS.


Oh right, as you wish...


Archive: string functions


But I did another version, adding my new AdvStrSort, and fixing spelling errors in the documentation:

New in 1.02 - 02/07/04:
-----------------------

- Fixed Documentation about StrLoc. "Direction" is really
"OffsetDirection".
- Added my new AdvStrSort, and removed the old one.
I tested the new function all night until now, and it's working.

Kichik, don't dispair. Use the same example you're using just adding the new qualities of AdvStrSort (called inside as StrSort). Nothing was changed in other functions.

Example of use - StrSort:

${StrSort} $0 "This is just an example" " just" "" "ple" "0" "0"

$0 = "This is an exam"

;"This is just an example" is the String
;" just" is the CenterStr
;"" is the LeftStr
;"ple" is the RightStr
;Display LeftStr and RightStr FALSE
;Display CenterStr FALSE

Are you sure you want to keep the old version of the readme and not use my changes?

This StrSort call fails:

${StrSort} $0 "This is just an example" "j" "" "" "1" "0"
StrCmp $0 "This is ust an example" 0 strsorterror


Yep. Because the last "0" says that will not include the CenterStr.

I did your changes in my documentation. Only if had any more changes you did in other functions but StrLoc...

You can do any changes to it, I can't go to Internet 9:00AM to 10:00PM (but sometimes I can with a little help...).


But it does include CenterStr, that's the problem.

The zip you've attached doesn't include a single change I made to the readme.


Fixed and included your changes in the readme.


Thanks, uploaded.


Ahhhh... This time it is right... Thanks for all Kichik.


thanks deguix and Kichik, I've been using these string functions with the new build and they work great! Thank you for your hard work.


Using Str functions in the uninstaller
Hi everyone !

First of all, congratulation to the NSIS dev team : I've used NSIS two years ago to build an installer for my university project, it worked great for my needs..

When I started using it again a few months ago, I couldn't believe how nicer it became! I'm glad the version 2.0 has been released, keep up gooooood work :up: !


Now here is my question.

@deguix: no doubt your string functions header is useful, but is there an easy way to use these functions in the uninstaller ? Euh, maybe I missed something ?


Thanks :)

evilO/Olive


sure.
use it in the same way like in the installer.
just in an "un.xyz" section, or in the "Uninstaller"-section, or any related function.


Err, well, I've already tried before to post in this thread, but obviously the compiler complains about the functions not starting with "un."...

Apparently it's not possible to use them in the uninstaller without having to modify the (neatly designed) header.

Am I wrong ? :confused:

evilO/Olive


I'll fix that and another bug tomorrow.

To everyone know, the reason I'm slow in responses and fixes is that I have 2 school tests tomorrow(school time: 8:00 AM to 2:15 PM), I have 2 school projects to do, I share the computer with 3 more persons, my internet time is limited 5AM to 7AM, sometimes I use at 10PM, and rarely I can use another times.

So please, BE PATIENT.

Just that for now...


Deguix : don't worry, there is no hurry .. I could'nt provide fixes and answers with half of your amount of work :p

So ... good luck for your exams :)

evilO/Olive


Just ignore my last message...

1.03 - 02/12/2004

- Added commands support for uninstall sections and functions.
- Fixed variables switch in "StrLoc" and "StrTok" after using these.
Read the manual first to use commands supported for uninstall section, nothing changed with install supported commands.

The file:

Hi Deguix ! Thanks a lot for your fix, but, err, I hate to say that but I still have troubles... :(

1) I Have tried the sample provided in the doc (2.2 How To Use Commands In Uninstall Sections and Functions) :
it does work using either ${StrStr} or ${UnStrStr}, but doesn't work if I use both :weird: :

!insertmacro: macro "FUNCTION_STRING_StrStr" requires 0 parameter(s), passed 3!

2) There is a "mistake" for the function StrTok, the second macro used to call the function is :
!macro FUNCTION_STRING_StrTok_Call
instead of
!macro FUNCTION_STRING_UnStrTok_Call


evilO/Olive


Euh, sorry but I think I've just found two other "mistakes" in the following macros:

1) in "FUNCTION_STRING_StrStrAdv":

; ...
!ifdef FUNCTION_STRING_UninstSupport
!undef UnStrStrAdv
!define UnStrStrAdv "!insertmacro FUNCTION_STRING_UnStrStrAdv_Call"
Function un.AdvancedStrStr
!else
!undef StrStrAdv
!define StrStrAdv "!insertmacro FUNCTION_STRING_StrStrAdv_Call"
Function AdvancedStrStr
!endif

Function AdvancedStrStr ; <-- should be removed
; ...

2) Same for "FUNCTION_STRING_StrLowerCase"


Thanks :)

evilO/Olive


ammm.... And I forgot to say: "I didn't test this feature", so can have a lot of mistakes in there... but anyways, thanks evilO. Same version 1.03.


Well, Deguix, it seems that I still can't get your example to work... :confused:

There is apparently no way to use both functions in the same script. I mean, ${StrStr} AND ${UnStrStr} for instance. I've attached the output if that can help.

Well, I'm sorry to be such a pain :(

evilO/Olive

PS: Have a good week-end :)


Ohhh, now I remember, is a define to indentify if a function inserter command has been called more than one time... When I define it before calling the inserter macro, it skips the code. EDIT: When you call the ${StrStr} and ${UnStrStr} is like calling it two times (so you can use after ${UnStrFunc} the same ${StrStr} that will be the same thing as ${UnStrStr}).

I'll publish the fix when I exit from school (I'm there now) and when I have the first opportunity to connect to internet in home.


The fix is here (I think), test it. Same version number 1.03.

(from those tests I mention before, all of them were 100 or above (from bonus questions))


Hi Deguix !

Thanks for the quickness of your answers, I'm sorry I couldn't test your fix earlier but I was away 'til this morning..

Well, everything seems to work fine as far as I have tested... :) I'm glad you got this header file working, these functions will really help (plus I'm creating a header file as well and now I know how to design it efficiently :p).

Thanks a lot for your efforts :up: !!



evilO/Olive

PS: about your tests I've no idea whether a mark above 100 is good or not (but I assume it is otherwise you wouldn't have written it :D ), as in France the range is from 0 to 20 ...


Version 1.03 has been uploaded to CVS.


Maybe in future it can be more than just a header file of string functions...

[About Tests:]

In Brazil the range is from 0 to 10, or are letters P (10), S+ (7.5), S (5), S- (2.5), and NS (0) or are letters PS (10), S+ (7.5), S (5), S- (2.5), and I (0) (maybe it has more).

In U.S.A. the range is from 0 to 100 which results in the letters A+(97-100) A(93-97) A-(90-93) B+(87-90) B(83-87) B-(80-83) C+(77-80) C(73-77) C-(70-73) D+(67-70) D(63-67) D-(60-63) F(0-60) E(didn't complete the course objectives).

Maybe this is interesting:

In Sao Paulo city, because have a lot of people, and so the schools are crowded, there has a law that you can pass grades 1-7 with the worst score. I don't remember when they launched that law (1997 or 98), but I know when you do that, you go to "summer school", and they pass you to the next grade after.


Hi Deguix !

Maybe in future it can be more than just a header file of string functions...
What do you mean ? you intend to make a plugin with these functions ? Don't you think the header file is enough ?
BTW I rewrote and reorganized all my header files using your 'design' (defines-macros-functions), now it's easier with less code and it's working perfectly :up: !


About the tests:
Ok I understand better now, although I find it strange to have letters AND numbers for the tests marks, especially if the range is just from 0 to 10.. Well, I'm used to have only numbers that's why :D
So you achieved more than 100 !!! felicitações ! What would that make ? A++ :p !?

About San Paulo City (it IS interesting): can't they keep up with the construction of new schools or is it that the city council don't want to ? I mean, the problem has to be serious if they have to make a law: what about the "credibility" of the educational system if anyone can pass :weird: !?

Anyway have a nice week-end :)

evilO/Olive

What do you mean ? you intend to make a plugin with these functions ? Don't you think the header file is enough ?
I meant: more header files of other function types...

About the tests:

What would that make ? A++ !?
Is the same A+.

About San Paulo City (it IS interesting): can't they keep up with the construction of new schools or is it that the city council don't want to ? I mean, the problem has to be serious if they have to make a law: what about the "credibility" of the educational system if anyone can pass !?
When the economy continues not good enough, they cut education, culture... results-> the children learn from parents how to disrespect the other... results-> violence, robbery.... There your home is your prision; who should be in prision is on the streets...

About the credibility, they don't really care, is too difficult to get a new job...

Hello Deguix !

Which functions types would you like to create headers for ? IMHO the string header was the most important. As I told you I have created some with the functions I needed the most, but I doubt many people would need all that stuff.

Is the same A+
It was only a (bad) joke :D


About the schools:

I didn't understand in the first place that it was an economical reason.. Unfortunately it seems to be the same all over the world:
In France as well, since the elections of 2001 they accelerated the reduction of credits for education, research, culture, health, unemployment benefits, retirement benefits (now we have to work longer to get less money at the end), ... :mad:
And the country's money (our money !!) is going to the police, to the army, to taxes exemption for rich people... Just happiness really... :rolleyes:

And in top of that they decided to build 30 new prisons, half of which will be specially 'designed' for youngsters.. They changed the law and now you can go in prison being 16 years old, and 'disciplinary actions' can be taken starting from 13 years old... MAD !! Really I get desperate about mankind..

Well, I think I'll stop complaining for today, and get myself a nice cold beer :)

Version 1.04:

- Added my new StrCase, removed StrLower and StrUpper.
- Organized by name commands inside header and readme files.

StrCase converts strings to Lower Case and Upper Case + the new Title Case and Sentence Case (readme's example):

- Lower Case (this is just an example. however this can be useful.)
- Upper Case (THIS IS JUST AN EXAMPLE. HOWEVER THIS CAN BE USEFUL.)
- Title Case (This Is Just An Example. However This Can Be Useful.)
- Sentence Case (This is just an example. However this can be useful.)
Default is "Setence Case". (I didn't include "Invert Case" by NSIS scripting limitations, I have to use System plugin to implement it)

(If you noticed, StrCase now appears as the first command due to its name)

The next target for changes probably is "Number to String Converter Function" which has bugs now.

The file:

Version 1.05:

- Added new StrNumToStr. Supported languages are English and Portuguese (Brazil).
- Fixed a bug with StrCase, Title Case wasn't working as should be.
- Fixed a bug with StrStrAdv, previous fix created another bug, string not returned correctly when using backwards search with "DisplayStrToSearch" as "0".

New Function StrNumToStr:

Converts Numbers to Strings. Main Features:

- Multilanguage support. (English and Portuguese (Brazil))
- Supports numbers up to 18 digits.
- Virtually, the number digits limit is unlimited (doesn't use Int64), I'm just lazy to add support for numbers bigger than quadrillion...

(as it uses just two languages now, has to be included any of the languages supported by the command in your script)

Anyone can contribute or talk about StrNumToStr translations.

Please test it so I can be certain about its quality.

The file:


Will someone put this version 1.05 inside NSIS package? It has something wrong or is too much updated in a small amount of time?


Testing...
Hi Deguix :)

I wanted to do some translations for this new function, and I played a bit with it.. I just have a few questions:

1) For "1789" I have the result "Seventeen hundred and eighty-nine", shouldn't it be "one thousand seven hundred and eighty-nine" ?

I have noticed it as in french it should be "mille sept-cent quatre-vingt-neuf", except if you're talking about a date, in which case both can be used.
For instance:
"la Revolution francaise a eu lieu en dix-sept cent quatre-vingt-neuf"
("The french revolution took place in seventeen hundred and eighty-nine")


2) Another point:

- If I set "100-900_DIFFERENT" to 1, I have:
123123 "Cent vingt-trois mille cent vingt-trois" -> correct

223223 "vingt-trois mille vingt-trois" -> NOT correct, should be "deux cent vingt-trois mille deux cent vingt-trois"

- If I set "100-900_DIFFERENT" to 0, I have:

123123 "un cent vingt-trois mille un cent vingt-trois" -> NOT correct (errors in red)

223223 "Deux cent vingt-trois mille deux cent vingt-trois" -> correct


3) Could you explain these:

11-19_EQUAL
100-900_DIFFERENT
11-99_HUNDRED

Thanks

evilO/Olive


I made some changes to it, added a new LangString for your case, and changed the names of other LangStrings to easier to understand... Test it. Same version. (thanks for trying to translate it, so I can make changes depending how the numbers from other languages are).

1) You can set the translation option "1100-9900_ARE_HUNDRED" to 0, so will output right as you need.

2) I added an option to support this, see the new LangStrings inside StrFunc.nsh.

3) I made changes to make things more clear, see the new LangStrings inside StrFunc.nsh.


Hi Deguix :) !

Ok I tested the modifications:

1) Ok, this works fine now, thanks :up:

2) Still does not work: maybe another flag has to be added for that.

In french, if the figure of the hundreds or the thousands is 1, we do *not* write it. Therefore, 123 should give "cent vingt-trois" and not "un cent vingt-trois"

If this figure is > 1, then we do write it. 223 is written "Deux cent vingt-trois"

Same for the thousands:
1123 should give "Mille cent vingt-trois" and
2123 should give "Deux mille cent vingt-trois"


evilO/Olive

PS: BTW I just had a few compilation problems and had to make changes to
!define FUNCTION_STRING_UninstSupport
...

1) I have replaced:

!define StrNumToStr `!insertmacro FUNCTION_STRING_StrNumToStr`
by:

!define UnStrNumToStr `!insertmacro FUNCTION_STRING_StrNumToStr`


2) Added:

!define UnStrCase `!insertmacro FUNCTION_STRING_StrCase`

and removed:

!define UnStrUpperCase `!insertmacro FUNCTION_STRING_StrUpperCase`

!define UnStrLowerCase `!insertmacro FUNCTION_STRING_StrLowerCase`




I think that's all for now :)


1) Set "1**_DIFFERENT_SUFIX" LangString to 1 and set "100D" as "hundred (in your language)".

"100" and "100D" have to be the same because Portuguese has a little thing different... (100 = "cem", 101 -> 199 = "cento")

2) I fixed these bugs you said now. Test it.

Oh, thanks for the support, I don't know other languages than English and Portuguese (Brazil) so I don't know what to add besides what I did know.

EDIT: Ops! Thousands are different too! I have to work on it later, this file above doesn't have it. (Oh man, Portuguese has it too, how did I forget that!)


Hi Deguix !

Finally, the forums are back :D ! Well, anyway we release some software at the moment and I won't be able to test the functions for a few days.. :(

Also because writting numbers is more complicated that it looks, at least in french (I had to get a whole web page about writting numbers in french from 1484 to nowadays, with all the variations...).

But don't worry I'll test it ASAP :)

Oh, just two little things :

1) In the macro FUNCTION_STRING_UninstSupport, this define is still there:

!define StrNumToStr `!insertmacro FUNCTION_STRING_StrNumToStr`

and should be replaced by

!define UnStrNumToStr `!insertmacro FUNCTION_STRING_StrNumToStr`


2) I've found a (little) bug in the function StrCase :

If you decide to use $R5 to store the function's return value, the return value is appended to the variable's initial value. Just an initialisation problem.

Here is the code to reproduce the bug:

!includeStrFunc.nsh

${StrCase}

Name"Example1"
OutFile"example1.exe"
InstallDir$PROGRAMFILESExample1
Pageinstfiles

Section
""
StrCpy$R5"blabla"
StrCpy$0"string"
${StrCase}$R5"$0""UpperCase"
MessageBoxMB_OK"Res:$R5";<--atthispointtheresultis"blablaSTRING"
SectionEnd

evilO/Olive

Ahhh... how the old times were good, I had the entire day to test all things I submitted (the computer was too worse you couldn't really play on it). Now with a new computer, the time was shrunken and my brother is liking it because he can now access the internet about everytime, and play his favourite games...

But I'll try to make a file to test this file before launching a new version to test if it works.

Is it really hard to learn how to use French numbers or you're just saying you're not French?


Hi Deguix

Yeah I've seen a few posts about your brother who monopolizes the computer... Erf, the "old times" ... Well, I recall on a 0x86 we could already play at "Double Dragon" or "Xenon 2", but
you're brother probably doesn't know about these :p

Oh, and I'm french :D... But there a a different rules, especially for big numbers (what they call "short scale" and "long scale"), some variations. So I would like to take some time to make sure the function behave correctly, and to make proper translations...

Have a nice week-end ! :)

evilO/Olive


Version 1.06:

- Added instructions for StrNumToStr translation.
- Fixed lots of bugs from faulty basic header file structure relating to StrNumToStr command.
- Fixed the bug where the old string was attached to string returned by StrCase when $R5 variable was used.

I've a new file for testing, which provides all the essential verification system for the header file.

It isn't included with the package because it's just for developer's use now. :(

Fixed bugs all bugs, including the ones you said and ones we didn't discover before. Bugs already fixed will never appear anymore.

And I added a new LangString for StrNumToStr, 1***_DIFFERENT_PREFIX which enables thousands to be w/o the number on the left.

Test drive it now!


Hi deguix !

Well, I'm really sorry about the delay but as I told you we had
some piece of software to release, deadlines, etc. :(
I really had no time, I'm glad it's over for now... :)


So I have tested the function, and my conclusion is that it's definitely complicated to create such a function with the support of several languages... :D


Correct strings are in green, "errors" are in red.


1) About the hundreds and the thousands without the prefix:

It's working perfectly :up:


2) About the numbers from 21 to 69:

The separator changes, it's a special case for 21, 31, 41, 51, 61.
Another flag might have to be added (!!)

- If I set "Sep*0-*9" to " et ", I get this:

20 -> vingt
21 -> vingt et un
22 -> vingt et deux
23 -> vingt et trois

- If I set "Sep*0-*9" to "-", I get this:

20 -> vingt
21 -> vingt-un
22 -> vingt-deux
23 -> vingt-trois

- And it should be:

20 -> vingt
21 -> vingt et un
22 -> vingtt-deux
23 -> vingtt-trois
...



3) About the numbers from 70 to 79:

Instead of having the figure of the tens for "seventy" + 1, 2, 3 ..,
we use the figure of the tens for "sixty": + 11, 12, 13, ...

- I get:

70 -> soixante-dix (60-10)
71 -> soixante-dix et un (60-10 et 1)
72 -> soixante-dix et deux (60-10 et 2)
73 -> soixante-dix et trois (60-10 et 3)

- Instead of:

70 -> soixante-dix (60-10)
71 -> soixante et onze (60 et 11)
72 -> soixante-douze (60-12)
73 -> soixante-treize (60-13)
...



4) Same for the numbers from 90 to 99:

Instead of having the figure of the tens for "ninety" + 1, 2, 3 ..,
we use the figure of the tens for "eighty": + 11, 12, 13, ...

- I get:

90 -> quatre-vingt-dix (4-20-10)
91 -> quatre-vingt-dix et un (4-20-10 et 1)
92 -> quatre-vingt-dix et deux (4-20-10 et 2)
93 -> quatre-vingt-dix et trois (4-20-10 et 3)
...

- Instead of

90 -> quatre-vingt-dix (4-20-10)
91 -> quatre-vingt-onze (4-20-11)
92 -> quatre-vingt-douze (4-20-12)
93 -> quatre-vingt-treize (4-20-13)
...

Now it starts to get complicated...



5) For the numbers from 80 to 89:

5a: Here we use the figure of the tens for "eighty" + 1, 2, 3 ..
5b: it's the same separator for all the numbers
5c: there is a special rule for the plural, as for the hundreds (see point 6)

Therefore we should have:

80 -> quatre-vingts (4-20)
81 -> quatre-vingt-un (4-20-1)
82 -> quatre-vingt-deux (4-20-2)
83 -> quatre-vingt-trois (4-20-3)
...



6) For the hundreds:

The word "cent" (hundred) does vary when there is a digit that multiplies it just before,
and when it's not followed by a cardinal number.

6a: if there are no digits after the hundreds

For instance:
100 -> cent
200 -> deux cents (2 * 100)
300 -> trois cents (3 * 100)
400 -> quatre cents (4 * 100)
...

BUT:
1100 -> mille cent (1000 + 100, does NOT multiply)


6b: if there are digits after the hundreds

201 -> deux cent un
202 -> deux cent deux
203 -> deux cent trois
...
200 000 -> deux cent mille

BUT:
200 000 000 -> deux cents millions
200 000 000 000 -> deux cents milliards
...

As millions, milliards and so on are not "cardinal number" but "names".

Exactly the same rule applies for the word "vingt" in "quatre-vingts".

81 -> quatre-vingt-un
82 -> quatre-vingt-deux
83 -> quatre-vingt-trois
...
80 000 -> quatre-vingt mille

BUT:
80 000 000 -> quatre-vingts millions
80 000 000 000 -> quatre-vingts milliards



Ok I think that's all for now. I just hope that it was clear, don't hesitate to ask if you've got any question.. :)



evilO/Olive


What is that? Oh man, this will be more complicated than I ever imagined... OK, it won't be done so fast...


How about a version without that function for now?


Archive: string functions


As you wish, removed all info about this function for now, until I get it done (won't be so soon :():


Hi Deguix !

I'm sorry to have discouraged you, I just wanted to help... :(
But, as I told you in a previous post, it's quite complicated to write
numbers in french (I think you have noticed :D).
And I tried to make it as simple and structured as possible...

Well, it's not an easy job, I understand you don't want to program that now.
Just let me know when something is done if you want me to do some tests.. :)

evilO/Olive


I don't want to do that now because I working on several projects for some other programs. Just to prevent "overload". :D But when everything is clear I'll work again on it.


I just uploaded the new version of StrFunc.nsh test. Is to replace the older one (which doesn't compile now). It tests all commands when installing and uninstalling.


So which one is it going to be for 2.01?


1) The last zip file.

2) This last file which is the test of StrFunc (as you or Joost requested in PM, replacing the example coming with NSIS which has problems).

3) The updated documentation below. I fixed only the mention of StrNumToStr on the Comments about functions included and not included, Version History and Functions Credits. Same version.


String Functions Header File 1.07
As kichik slowed so much the release of NSIS 2.01 (see previous posts) I could have some time off to do the new String Functions Header File. Give a look on these changes below:

1.07 - 09/16/2004

- StrStrAdv and StrCase have their functions remodeled with LogicLib.
Functions have a lesser chance to have bugs.
- Added case-sensitive comparation option for StrStrAdv.
- StrCase now uses System.dll which makes case convertions effective with
all latin letters (i.e. ê).
- StrClbSet and StrClbGet removed, added StrClb.
- Made compact the most usual operations inside the header file. File size
reduced.
- Added "!verbose" to header file -> faster compilation and header file
output organized (code borrowed from LogicLib.nsh).

Kichik, as you plan to release NSIS 2.01 (for real this time) you can put the StrFunc test example on NSIS for now (just to update). Then afterwards, I'll create a better example like the one from Word Functions Header File (but better, hehe :) what am I planning now?)

Thank you dselkirk and eccles for LogicLib. That tool made everything easier for me this version...

This file below contains:

- StrFunc.nsh (header)
- StrFunc.txt (manual)
- StrFunc.nsi (example)


  • The example fails on StrClb
  • If you're already using System.dll, why not use IsCharAlpha or even GetStringType instead of lots of comprasions?
  • You don't have to make two copies of the code, you can assume the LogicLib is present. It is installed a line after StrFunc.nsh in makensis.nsi

Updated documentation because I forgot to remove a feature from ${StrCase}. (not again):(

The example fails on StrClb
This was not expected by me, where did you find the failure?

If you're already using System.dll, why not use IsCharAlpha or even GetStringType instead of lots of comprasions?
Maybe you should give me "IsCharAlpha" code, because I couldn't get it to work at any costs.

You don't have to make two copies of the code, you can assume the LogicLib is present. It is installed a line after StrFunc.nsh in makensis.nsi
The real thing is that the LogicLib version is (probably) the same as the converted to normal one. Commenting one of them makes no difference. If you want me to do so I can comment the LogicLib one and just include the original in the distribution.

The failure is in Examples\StrFunc.nsi.

IsCharAlpha needs a char. For this, you can treat the string a struct of some bytes and get the first byte.

If I were you, I'd prefer keeping the LogicLib code. It's simpler. Why keep two versions? It's more work.


The failure is in Examples\StrFunc.nsi.
But where in the file? I tested and everything passed...

IsCharAlpha needs a char. For this, you can treat the string a struct of some bytes and get the first byte.
I'm not getting this code to work for days. And I already tried that without any luck.

If I were you, I'd prefer keeping the LogicLib code. It's simpler. Why keep two versions? It's more work.
Ok, at least you know how difficult is to create one... I just wanted to keep the original because it doesn't require LogicLib, but if you think so, I'll fix that at night.

With the files you've attached, it fails in the uninstaller. I haven't gotten into it to see which line exactly.


I attached the example again. It's still working for me normally.

(I should add another thing to the documentation about the "${UnStrFunc}" which was removed)


I managed to solve it by passing OpenClipboard the window handle (was giving errors about the thread not having an open clipboard associated with it) and by locking and unlocking the handle returned by GetClipboardData (like in the MSDN example).


I managed to solve it by passing OpenClipboard the window handle (was giving errors about the thread not having an open clipboard associated with it) and by locking and unlocking the handle returned by GetClipboardData (like in the MSDN example).
The code I used was mostly copied (only with added comments and united options) from the separated old ${StrClbSet} and ${StrClbGet}. The older versions didn't have the window handle set.

If you are getting errors now, you never tested those before (I think). Can you test if the older StrFunc.nsh version ${StrClbSet} and ${StrClbGet} have this problem?

Posted version requiring LogicLib.nsh to be included before including StrFunc.nsh. But there is still the problems about "IsCharAlpha" API and "${StrClb}" with that issue you said. Maybe is better you to fix the issues above as I don't know how to fix them :(...


The original example had just one test. The new example has many and it usually doesn't fail in the first one. If I add more tests to the original example, it fails too.

Here's an example for IsCharAlpha:

StrCpy $0 "testing... testing... 1 2 3"

System::Call "*(&t${NSIS_MAX_STRLEN} r0) i .r1"
StrCpy $2 $1
loop:
System::Call "*$2(&i1 .r4)"
StrCmp $4 0 done
System::Call "user32::IsCharAlpha(i r4) i .r4"
StrCmp $4 0 0 +3
DetailPrint "$4 - not alpha"
Goto +2
DetailPrint "$4 - alpha"
IntOp $2 $2 + 1
Goto loop
done:
System::Free $1

I'm going to fix tomorrow morning or night (depending if I have time). But what did you do to result in that code so fast? I think only you and brainsucker (and some other people) knows how to do everything with System plugin.


Ok, I've done what you told me. However maybe you should give the code of ${StrClb} that worked with you so I can implement it to the header file. I can't do anything else because on my computer the old example (first published 1.07 example) runs perfectly.

I re-added "<>" (switch) case for ${StrCase} because of the code you gave me on your last post.


It would be nicer if you include LogicLib.nsh yourself and not ask the user to do it. There will be no errors if it's included more than once.

You forgot to System::Free call for the allocated buffers in StrCase.

StrClb changes are really simple. Lock and unlock what you get from GetClipboardData and pass $HWNDPARENT and not 0 to OpenClipboard.


StrClb changes are really simple. Lock and unlock what you get from GetClipboardData and pass $HWNDPARENT and not 0 to OpenClipboard.
I'm not totally experienced on System plugin (as I implicitly said with "IsCharAlpha"). I think this discussion could be shortned by just posting a simple code like that one you posted for "IsCharAlpha" (as you said it's simple for you and that you done it already).

If I would do the code, then probably in the future I would need to fix something on this code as it could not continue to work on your computer... Sorry if I'm so dumb to understand it completely. ;)

Thanks kichik for including your changes to StrFunc.nsh on NSIS 2.01. Everything is working perfectly.


New version of StrFunc. The biggest change: all functions from StrFunc are now on LogicLib coding, and comments added on most parts of functions. Second biggest change: StrSort has been changed and can break old scripts. See its documentation. List of changes:

1.08 - 10/12/2004

- Converted all the functions to LogicLib.
- StrSort: Totally remade and it can break old scripts. See documentation for details.
- Added defines: StrFunc_List, *_List and *_TypeList.
- Fixed StrStrAdv: Variables $R0-$R3 couldn't be used on scripts before calling.
- StrRep: Cut down some variables.
- Arranged correctly the order of StrSort on the documentation.


Hi Deguix :)

I know I haven't been on the forum for a while, I just had tons of work to do (and still no Internet connection at home..).
But I was keeping an eye on your String functions header.. I downloaded the last version... Really nice job :up: !

Well, I just had 2 problems using the new functions header file (but I didn't test all the functions):
- I had to fix all the "StrTok" calls in my scripts as you decreased the starting index for the "ResultPart" (and to re-test and validate everything :()
- You forgot a "Push $R0 / Pop $R0" in the function "StrTok", the content of $R0 is lost when the function exits

That's all for now.. bye :)


evilO/Olive


You forgot a "Push $R0 / Pop $R0" in the function "StrTok", the content of $R0 is lost when the function exits
It's even worse than I thought, $9 contents are lost also. Thanks for the information.

So what goes into 2.02?


I didn't even start to work on it. I totally forgot about NSIS 2.02. As there are only small fixes requested this should be completed tomorrow evening or even sooner.


Hi Deguix :)

Hum I noticed some other small problems with the new version of StrFunc.nsh while I was doing some further testing:


------- StrCase:
An instruction is missing at the beginning of the function (Exch), the contents of $0 and $1 are swapped when the function exits


------- StrClb:
- I couldn't manage to swap strings using "<>", so I modified the function, but you'll probably find a better fix :D

One thing I didn't understand:
For the operation "<", after the call to "GetClipboardData" there is the handle in $2
For the operation "<>", after the call to "GetClipboardData" there is the string in $2
Why?

- There is a typo in the function's comments:

$0 = Action (input)
$1 = String (input)

should be

$0 = String (input)
$1 = Action (input)

------- StrRep:
An instruction is missing at the end of the function (Pop $R3), the content of $R3 is lost


------- StrSort:
There is a parameter missing in the doc's example


------- StrStrAdv:
The example in the doc is slightly wrong:

${StrStrAdv}$0"ThisISreallyjustanexample""IS"">"">""1""0""1"

returns "IS really just an example" (and not "really just an example" as stated in the doc)

To get the string "really just an example", the example should be
${StrStrAdv}$0"ThisISreallyjustanexample""IS"">"">""0""0""1"


Hum I think that's all I found..
Have a nice day :)


evilO/Olive

OK, I expected those functions to have bugs, but I didn't think they contained so many of them.

I can see that those are mainly from stack, so I should add to the StrFunc.nsi StrCpy's for each variable, and see if they are swaped when they shouldn't be.


Well they didn't contain that much bugs since you rewrote a lot of the code.. :) Moreover, the functions *do* work, as you said it's mainly stack problems..
Well, I spoted them because I had strange behaviors in my installers all of a sudden..

I can see that those are mainly from stack, so I should add to the StrFunc.nsi StrCpy's for each variable, and see if they are swaped when they shouldn't be.
Hum I used a user-defined variable and the "dumpstate" plugin to check the content of the variables, you could do that in a shortened version of StrFunc.nsi to test..

Ah, and have you an answer for my question about "GetClipboardData" ?

Thanks, bye ! :)

evilO/Olive

PS: sorry I should have attached the 'nsh' file in the previous post..

IRON JUSTICE
*removed*


Well they didn't contain that much bugs since you rewrote a lot of the code...
For me one bug is enough to make me fix it, so I say one is a lot.

Hum I used a user-defined variable and the "dumpstate" plugin to check the content of the variables, you could do that in a shortened version of StrFunc.nsi to test..
I'm going to do that because that way it is automatic. This means (about) never this bug will appear again when scripting.

About the documentation, as it is not done automatically, it will probably have typos.

Ah, and have you an answer for my question about "GetClipboardData" ?
Not yet, I have to share the computer with 3 more people so my time is restricted.

(next time attach .nsh files as they are, don't use the extention .txt at the end)

String Functions Header File 1.09
I fixed those bugs and some others from other topics posts:

1.09 - 10/22/2004

- Fixed stack problems involving: StrCase, StrRep, StrSort, StrTok.
- Fixed StrClb: When "Action" = "<>", handle was wrongly outputed as text.
- Fixed StrSort, StrStrAdv documentation examples.
- Fixed StrIOToNSIS, StrLoc, StrNSISToIO, StrRep, StrStr: sometimes didn't find "StrToSearch" at all.


For me one bug is enough to make me fix it, so I say one is a lot
Well from that point of view of course..
I'm going to do that because that way it is automatic
Ok I didn't understand exactly what you intended to do in the first place..
About the documentation, as it is not done automatically, it will probably have typos
Hum yes just another typo: for the example of "StrSort" I think that
${StrSort}$0"Thisisjustanexample""just""""ple""0""0""0"

should be
${StrSort}$0"Thisisjustanexample""""just""ple""0""0""0"

next time attach .nsh files as they are, don't use the extention .txt at the end
Oops I wasn't awake this day, I missed "nsh" in the valid file extensions.. :D

Bye :) !

evilO/Olive

This alternative version has a more compressed code on the header file than this current version. A drawback is the slower speed of compilation for the user. (That's why it's alternative from the current version).

It shows how to make the use of "!system" compile time instruction to bypass the limitation of inclusion of macros inside macros by using the inclusion of external files. (macros can include macros from other files only)

The resulted executable will have the exact size as using the default one.

I'm sad that this approach didn't make my code smaller w/ a decent speed. :(


Hi,
i have this problem to solve,
I want to remove the very last "\" from a string
example : "C:\abcd\abcd\"
I want to convert this string to "C:\abcd\abcd"

I tried to use

StrLoc $0 "C:\abcd\abcd\" "\" "<"

but $0 = 11 instead of 1
so StrLoc counts the location from the end of string but doesnt start the search from the end of the String so it still gives the first "\" found. Is there any way to solve my problem?

Thanks


StrCpy $0 `C:\abcd\abcd\` 1 -1
StrCmp $0 `\` 0 +2
StrCpy $0 $0 -1

Stu