Whilst using ProWesS inSBasic is generally not very difficult, curiously
enough, one must pay a little bit more attention to what one does with
strings, if they are used as parameters for the PWxxxx keywords. (This
short explanation does not concern the PW function
nor the other keywords which don't start with 'PW', where strings are
handled normally). Some of the tags or types passed to the keywords use
string parameters: for example, the text in an item object. Unless you
adhere to the rules explained below, there can be a slight problem. But
first, a little history lesson is in order:
History
The potential problem here stems from the question: how long is a piece of
string? This happens to be not only a bad pun, but also the true reason
things get so involved here. It was originally foreseen that ProWesS would
be programmed in 'C'. To a large extent, ProWesS itself is programmed in
'C'. The 'C' language uses a certain way to determine how long a string is:
it starts at the start of the string (it knows where that is), and then
strings along (groan) until it finds a \0, i.e. a CHR$(0). It then knows
where the end of the string is, and so it can determine how long the string
itself is.
As you may know, the QL uses another way of handling strings: the characters of the string are preceded by two bytes, which contain the length of the string. So, there is no CHR$(0) at the end, and the same string "Isn't computing great" looks, in memory, as follows: in normal QL mode:
Of course, these two ways of doing things are incompatible... This means
that you, the programmer, must make sure that your strings always end with
a CHR$(0): if you pass a string variable (such as a$), make sure that a$
contains a CHR$(0) at the end: a$=a$&CHR$(0)
. Likewise for
arrays: if you pass (part of) an array, this must end with CHR$(0):
The strings you pass to ProWesS are not always copied to a safe place, since ProWesS in many cases thinks (just like most 'C' programs) that if you pass it a string, then you should damn well keep the string until it has finished. This means that you cannot pass a direct string , or the result of a string function, to any of the PWxxxx keywords, you must always pass a string variable (with the CHR$(0) at the end).
Moreover, this string variable must not be a LOCal variable, since these are thrown away when you quit the function/procedure where they were declared (unless you are sure that the object won't need the string any more when you quit the function/procedure, e.g. if you remove the object before leaving the function/procedure.)
Fortunately enough, there are one or two exceptions: Some of the tags
allow a string parameter with 'COPY', which means that ProWesS does copy
the string to a safe place. In these cases you can pass a direct string.
These tags generally contain the word 'COPY' at the end, so they are easy
to recognise. This is also mentioned in the manual where Types and Tags are detailed.
The rules for passing strings
In short, here are the rules for passing strings:
a$&CHR$(0)
but always write:
a$=a$&CHR$(0)
and then pass a$.
Finally, one small bonus: whenever you can pass a direct string (or string
function), there is no need to append a CHR$(0) at the end, this will be
done automatically.
Arrays
In the 'C' interface, some tags allow you to pass string arrays (for
example MENU_ADD_ARRAY)
. It has been attempted to keep this
functionality, so that you can also pass SBasic arrays to the corresponding
SBasic keyword. This is no problem, if you keep the following in mind:
DIM
a$(10,20)
).
DIM a$(2,20) a$(0)="Element one"&CHR$(0) a$(1)="Element two"&CHR$(0) a$(2)="Element three"&CHR$(0) (...) xobj=PWcreate(...PW('MENU_ADD_ARRAY'),3,DIMN(a$,2)+2,a$,...)or a more generic example:
DIM a$(x,y) a$(0)="Element one"&CHR$(0) a$(1)="Element two"&CHR$(0) a$(2)="Element three"&CHR$(0) (...) a$(x)="Element x"&CHR$(0) (...) length=DIMN(a$,2)+2 length=length + (length && 1) xobj=PWcreate(...PW('MENU_ADD_ARRAY'),x+1,length,a$,...)The
length=length + (length && 1)
part of this program makes
sure that 1 is added to length if length is uneven: (x && 1) returns 1 if x
is uneven, and 0 if it is even.