Page 1 of 1
WritePreferenceString() with string contains line feed
Posted: Thu Mar 05, 2015 3:48 pm
by uwekel
Hi,
if you use the WritePreferencesString() function with a string containing a line feed, the structure of the settings file will be damaged. Also the original value will not be restored, because it is cut-off at the position of the first line feed.
I propose to encode the line feeds with a special character and automatically decode them again when using the ReadPreferenceString().
Regards
Uwe
Re: WritePreferenceString() with string contains line feed
Posted: Thu Mar 05, 2015 4:50 pm
by Michael Vogel
+1
Another, tiny thing with preference files which could be optimized (for Mr.Monk and me) - please remove the first empty line on the top of a preference file (which uses the #PB_Preference_GroupSeparator flag).
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 12:39 am
by Dude
Preference strings are meant to be single-line only, by the very definition of the INI file format.
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 6:33 am
by Michael Vogel
Dude wrote:Preference strings are meant to be single-line only, by the very definition of the INI file format.
So if more mean the same thing, PB may support this meaning, too. Than it would be nice if only such strings would be written. So if PB handles this, it would be standardized and creates preference files which are compatible with other systems.
Otherwise there are some tons of possibilities to deal with it:
- special tricks could be used to convert the strings when writing/reading: "line 1"+x0D+"line 2" or "line 1\nline 2"
- strings are cutted at the position of the first illegal character: "line 1"
- the readpreferencestring function will get more intelligence (good luck)
- and so on.
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 7:56 am
by Danilo
Dude wrote:Preference strings are meant to be single-line only, by the very definition of the INI file format.
I think so, too.
Anyway, some simple ReplaceString will do, if somebody really requires this functionality.
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 8:51 am
by uwekel
I think there is nothing bad if the restored string is exactly the same as the stored one. I came across it, when saving and restoring the input of an editor gadget. It could be more simple if the preferences function would take it into account. And linefeeds are not the same on all systems, so you have to take care of it, too.
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 10:52 am
by Little John
uwekel wrote:I think there is nothing bad if the restored string is exactly the same as the stored one.
That's a very general statement, and it's true.
However, as Dude wrote, this file format is not designed for storing line feeds.
If in the future INI or PREFS files would exist with line feeds as part of the data, those files could not be read correctly by existing programs. Such a situation is undesirable and would cause unnecessary confusion.
uwekel wrote: I came across it, when saving and restoring the input of an editor gadget.
For this purpose, you can use other file formats that are also supported by PureBasic, for instance XML.
Maybe JSON also allows to store line feeds, I don't know.
You can also design an own file format, e.g.
[ASectionName]
Some text
with line breaks
[AnotherSectionName]
More text ...
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 12:34 pm
by uwekel
Little John wrote:For this purpose, you can use other file formats that are also supported by PureBasic, for instance XML.
I prefer to put this setting together with all other settings to the preferences file. Temporarily, i encode it this way:
Code: Select all
ReplaceString(ReplaceString(MyStringWithLinefeed$, #CR$, "#CR$"), #LF$, "#LF$")
But it is not 100% error proof

Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 12:59 pm
by Michael Vogel
Just one (quick and dirty) non-standard approach to handle LF and CR (coded it for ascii, only few adjustments have to be done for unicode).
But...
... it's proprietary, so only usable within your own solutions
... you can't use Chr(1) and Chr(2) anymore (who cares, Chr(0) can't be used either)
Code: Select all
Procedure Mem(*mem1,*mem2,lines=5)
Protected i,j
Protected b1,b2
Protected s.s
While i<lines
s=RSet(Hex(i<<4),4,"0")+" "
For j=0 To 15
b1=PeekB(*mem1+i<<4+j)&$FF
b2=PeekB(*mem2+i<<4+j)&$FF
s+RSet(Hex(b1),2,"0")
If b1=b2
s+" "
Else
s+"!"
EndIf
Next j
s+" | "
For j=0 To 15
c=PeekB(*mem1+i<<4+j)
If c>=' ' And c<='z'
s+Chr(c)
Else
s+"."
EndIf
Next j
Debug s
i+1
Wend
Debug ":"
EndProcedure
Procedure.s AngryBird(s.s,mode)
#Q=#DOUBLEQUOTE$
#NewLF=1
#NewCR=2
Protected c,n
n=Len(s)
While n
n-1
c=PeekC(@s+n)
Select c
Case #LF
If mode : PokeC(@s+n,#NewLF) : EndIf
Case #CR
If mode : PokeC(@s+n,#NewCR) : EndIf
Case #NewLF
If mode=0 : PokeC(@s+n,#LF) : EndIf
Case #NewCR
If mode=0 : PokeC(@s+n,#CR) : EndIf
EndSelect
Wend
If mode
If PeekC(@s)<>'"' : s=#Q+s+#Q : EndIf
Else
If PeekC(@s)='"' : s=Mid(s,2,Len(s)-2) : EndIf
EndIf
ProcedureReturn s
EndProcedure
sonderbar.s
For i=3 To 255
sonderbar+RSet(Str(i%100),2,"0")+Chr(i)+" "
Next i
CreatePreferences("sonderbar.ini")
WritePreferenceString("standard",#Q+sonderbar+#Q)
WritePreferenceString("modified",AngryBird(sonderbar,#True))
ClosePreferences()
OpenPreferences("sonderbar.ini")
seltsam.s=ReadPreferenceString("standard","")
wundersam.s=AngryBird(ReadPreferenceString("modified",""),#False)
ClosePreferences()
Mem(@sonderbar,@seltsam)
If sonderbar=seltsam
Debug "ok"
EndIf
Mem(@sonderbar,@wundersam)
If sonderbar=wundersam
Debug "ok"
EndIf
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 9:20 pm
by Danilo
uwekel wrote:Temporarily, i encode it this way:
Code: Select all
ReplaceString(ReplaceString(MyStringWithLinefeed$, #CR$, "#CR$"), #LF$, "#LF$")
You may want to cover #CRLF$ as well. It is one line break on some electronic typewriters.
Your current solution would probably make 2 line breaks out of one #CRLF$.
Re: WritePreferenceString() with string contains line feed
Posted: Fri Mar 06, 2015 9:35 pm
by uwekel
I now changed the code a bit, and use Chr(1) and Chr(2) as Michael proposed.
Encoding:
Code: Select all
ReplaceString(MyStringWithLinefeeds$, #LF$, Chr(1), #PB_String_InPlace)
ReplaceString(MyStringWithLinefeeds$, #CR$, Chr(2), #PB_String_InPlace)
Decoding:
Code: Select all
ReplaceString(MyStringWithLinefeeds$, Chr(1), #LF$, #PB_String_InPlace)
ReplaceString(MyStringWithLinefeeds$, Chr(2), #CR$, #PB_String_InPlace)
In most cases, Chr(1) and Chr(2) won't be typed into an editor gadget.
Btw, #PB_String_Inplace is really cool!