I have a problem with reading a String Gadget in Storm-Wizard:
How can I read this String Gadget?
A String schould be writen which is in StringGadget,
but this is not the case.
What Funktion do I have to call?
Can no one really halp me?
Tschau Thomas
If you want I send You the Source.
Thomas Lichtenstern (g...@rz.fh-augsburg.de) wrote about Again, read String-Gadget:
> Hallo,
> I have a problem with reading a String Gadget in Storm-Wizard:
> How can I read this String Gadget?
> A String schould be writen which is in StringGadget,
> but this is not the case.
> What Funktion do I have to call?
/*
DESCRIPTION
Read string from string gadget from window
PARAMETERS
win Window to which the gadget was added
gad String gadget to read string from
buf Buffer to copy the data to
bufsize size of the buffer (excluding null byte, i.e. the
buffer must be one byte larger)
RETURN
None
NOTES
UNTESTED
*/
void ReadStrGad(struct Window *win,struct Gadget *strgad,char *buf,
long bufsize)
{
USHORT pos;
pos=RemoveGadget(win,strgad); // Only access gadgets that are
// removed from the list
strncpy(buf,(char *)((struct StringInfo*)
strgad->SpecialInfo)->Buffer,bufsize);
buf[bufsize]=0; // In case all bytes were needed,
// strncpy doesn't add a null byte
AddGadget(win,strgad,pos); // Re-insert gadget. In this case
// case, a refresh isn't necessary
}
Greetings
--
Christian Wasner (CRISI/PHANTASM)
Christia...@hamburg.netsurf.de
Q: How do I get the X11 sources ?
A: Post DPaint2 into comp.sys.amiga.misc.
> pos=RemoveGadget(win,strgad); // Only access gadgets that are
> // removed from the list
> strncpy(buf,(char *)((struct StringInfo*)
> strgad->SpecialInfo)->Buffer,bufsize);
> buf[bufsize]=0; // In case all bytes were needed,
> // strncpy doesn't add a null byte
> AddGadget(win,strgad,pos); // Re-insert gadget. In this case
This seems like an overkill. Use a macro like this:
#define GetGadString(g) (((struct StringInfo *)g->SpecialInfo)->Buffer)
You don't need to detach the gadget first.
--
\\\\\\ Petter Nilsen - IRC: Mitchman - mailto:pet...@thule.no |\
>>>>>>============================================================| >
////// THOR Team Coordinator - http://www.thule.no/~pettern/ |/
Failsafe pickup: A women asks, "Excuse me, do you have the time?" You: "Do you
have the energy?"
>> pos=RemoveGadget(win,strgad); // Only access gadgets that are
>> // removed from the list
>> strncpy(buf,(char *)((struct StringInfo*)
>> strgad->SpecialInfo)->Buffer,bufsize);
>> buf[bufsize]=0; // In case all bytes were needed,
>> // strncpy doesn't add a null byte
>> AddGadget(win,strgad,pos); // Re-insert gadget. In this case
> This seems like an overkill. Use a macro like this:
Overkill ??? any decent CPU could execute the above code a hundred
thousand times per second at least.
> #define GetGadString(g) (((struct StringInfo *)g->SpecialInfo)->Buffer)
> You don't need to detach the gadget first.
Oops, I mixed that. But when changing the buffer you have to ;-)
However, it's not a good idea to access the buffer directly all the
time. You really should copy the contents or otherwise the string may
change at some inopportune moment.
In article <1344.7053...@hamburg.netsurf.de>,
christia...@hamburg.netsurf.de (Christian Wasner) wrote:
>> #define GetGadString(g) (((struct StringInfo *)g->SpecialInfo)->Buffer)
>> You don't need to detach the gadget first.
> Oops, I mixed that. But when changing the buffer you have to ;-)
Changing the buffer should be done using the system supported method, namely
SetGadgetAttrs (or GT_SetGadgetAttrs on a gadtools gadget).
> However, it's not a good idea to access the buffer directly all the
> time. You really should copy the contents or otherwise the string may
> change at some inopportune moment.
Uh, like where and when? If your program is the only on accessing and using
this string gadget, there's absolutely no need to copy the string (and what
would that accomplish anyway?).
--
\\\\\\ Petter Nilsen - IRC: Mitchman - mailto:pet...@thule.no |\
>>>>>>============================================================| >
////// THOR Team Coordinator - http://www.thule.no/~pettern/ |/
Tennis is irrelevant. - Bjorn Borg
>>> #define GetGadString(g) (((struct StringInfo *)g->SpecialInfo)->Buffer)
>>> You don't need to detach the gadget first.
>> Oops, I mixed that. But when changing the buffer you have to ;-)
> Changing the buffer should be done using the system supported method, namely
> SetGadgetAttrs (or GT_SetGadgetAttrs on a gadtools gadget).
Even though it simplifies matters, it's not required to use
gadtools.library for this.
>> However, it's not a good idea to access the buffer directly all the
>> time. You really should copy the contents or otherwise the string may
>> change at some inopportune moment.
> Uh, like where and when? If your program is the only on accessing and using
Probably since the birth of intuition.
> this string gadget, there's absolutely no need to copy the string (and what
> would that accomplish anyway?).
Of course it is. It's probably intuition's input handler that copies
the keyboard input into the buffer and maintains the undo buffer and
all the private entries of the StringInfo structure of the string
gadget currently being active. Or do you think the data magically
warps into the buffer, using a time paradoxn ? ;-)
>> this string gadget, there's absolutely no need to copy the string (and what
>> would that accomplish anyway?).
> Of course it is. It's probably intuition's input handler that copies
> the keyboard input into the buffer and maintains the undo buffer and
> all the private entries of the StringInfo structure of the string
> gadget currently being active. Or do you think the data magically
> warps into the buffer, using a time paradoxn ? ;-)
uh. The pointer will be valid when you read and act on it, no matter what
intuition does, since it's obviously not doing it at the same time you're
accessing the pointer and USING it in a program. Unless the program is
multithreaded, ofcourse.
--
\\\\\\ Petter Nilsen - IRC: Mitchman - mailto:pet...@thule.no |\
>>>>>>============================================================| >
////// THOR Team Coordinator - http://www.thule.no/~pettern/ |/
Nothing is so smiple that it can't get screwed up.
No. If the gadget is still attached to the window and active then the
user can change the text in it at the same time as your program is
looking at it. IE. the pointer is still valid, but the data it is
pointing to may change at any moment. For example: a simple
capitalisation:
char *buffer = stringGad->buffer;
char letter = *buffer;
letter |= 'A'-'a';
*buffer = letter;
The character in the buffer may change after you read it out (line 2)
and before you put it back (line 4). Result: nasty experience for the
user. Ok, you could operate directly on the buffer in this case, but
not always. At the extreme intuition could change the location of the
buffer on you (I don't think it ever does, but I'm not sure it promises
it won't, either), so that:
char *buffer = stringGad->buffer;
*buffer |= 'A'-'a';
Could be writing to the wrong buffer.
So, if you want to use the buffer of a string gadget without being
_very_ careful it is best to remove or at least disable it first.
Regards,
--
Steve Hodge
s...@cs.waikato.ac.nz
Computer Science Dept, University of Waikato,
Hamilton, New Zealand
>>> this string gadget, there's absolutely no need to copy the string (and
>>> what would that accomplish anyway?).
>> Of course it is. It's probably intuition's input handler that copies
>> the keyboard input into the buffer and maintains the undo buffer and
>> all the private entries of the StringInfo structure of the string
>> gadget currently being active. Or do you think the data magically
>> warps into the buffer, using a time paradoxn ? ;-)
> uh. The pointer will be valid when you read and act on it, no matter what
> intuition does, since it's obviously not doing it at the same time you're
> accessing the pointer and USING it in a program. Unless the program is
> multithreaded, ofcourse.
But accessing and using it isn't an atomic operation, i.e. it can be
suspended at any time by an interrupt, like the one that runs the
input handler chain. The input handler isn't a task, but even if it
would be, there is no security that you program isn't interrupted at
some inopportune moment in order to give the CPU to some other task,
like the hypotheticel input handler task.
In contrast to the RKRMs saying that it's always safe (to which I
unfortunately agreed in some prior posting), I doubt that accessing
the contents of a string gadget being added to some gadget list won't
cause any problems, even if you copy it elsewhere. Only removing it
from the list, using the appropriate intuition function, will prevent
such problems.
Hi Christian!
Christian Wasner <christia...@hamburg.netsurf.de> writes:
>But accessing and using it isn't an atomic operation, i.e. it can be
>suspended at any time by an interrupt, like the one that runs the
>input handler chain. The input handler isn't a task, but even if it
>would be, there is no security that you program isn't interrupted at
>some inopportune moment in order to give the CPU to some other task,
>like the hypotheticel input handler task.
Only a tiny correction to the statement above: The input handler isn't
a task of its own, but called by the input.device as a subroutine which
IS a task.
Hence, looking at FindTask(NULL) in an input handler will result in the
input.device task structure. Strictly speaking the input handler mechanism
uses an interrupt structure without beeing an interrupt. (-;
(The input device is interrupt driven, i.e. collects messages from interrupts.
But it does not call the input device handlers in an interrupt context!)
>In contrast to the RKRMs saying that it's always safe (to which I
>unfortunately agreed in some prior posting), I doubt that accessing
>the contents of a string gadget being added to some gadget list won't
>cause any problems, even if you copy it elsewhere. Only removing it
>from the list, using the appropriate intuition function, will prevent
>such problems.
Hm.... yes. But intuition won't remove or re-allocate your string gadget
buffer in any way. What could happen is that the string you read from the
buffer is
simply non-sense because your task gets suspended between the copy operation
(remember, the input handler is CALLED by the input.device task which runs
at priority 20 - it isn't an interrupt in this sense. A Forbid() Permit()
pair is good enough to stop this).
I would call this a minor problem... what could happen
if the result is an invalid string? You have to check the user's input any-
ways (for example for legal file names...). The only real trouble is that
the NUL termination of the string might get lost temporarily, so allocate a
slightly larger buffer that what is really needed for the gadget and fill it
with zeros...
Greetings,
Thomas
______________don't_cut_here,_it_could_damage_your_terminal____________________
_______ _____ _____
/ / / / / / / EMAIL: th...@einstein.math.tu-berlin.de
/ /____/ / / /____/
/ / / / / / \ http://www.math.tu-berlin.de/~thor/thor/index.html
/ / / /____/ / /
_______________________________________________________________________________
> Christian Wasner <christia...@hamburg.netsurf.de> writes:
> Only a tiny correction to the statement above: The input handler isn't
> a task of its own, but called by the input.device as a subroutine which
> IS a task.
Yes, you're right here. That's why that task has priority 20 which
means that it most certainly WILL get the CPU when it gets some work
to do. As I said, effects will stay the same.
>>In contrast to the RKRMs saying that it's always safe (to which I
>>unfortunately agreed in some prior posting), I doubt that accessing
>>the contents of a string gadget being added to some gadget list won't
>>cause any problems, even if you copy it elsewhere. Only removing it
>>from the list, using the appropriate intuition function, will prevent
>>such problems.
> Hm.... yes. But intuition won't remove or re-allocate your string gadget
> buffer in any way. What could happen is that the string you read from the
> buffer is
> simply non-sense because your task gets suspended between the copy operation
> (remember, the input handler is CALLED by the input.device task which runs
> at priority 20 - it isn't an interrupt in this sense. A Forbid() Permit()
> pair is good enough to stop this).
If you can solve a problem without using Forbid()/Permit(), you should
do so. There is no difference with respect to programming
efforts between calling Forbid/Permit or RemoveGadget/AddGadget. But
Forbid/Permit IMHO is the least desirable method because it not only
prevents the input handler from doing its work, but all other tasks,
too. Since the matter is about gadgets (which means that the relevant
part of the program waits for intuition events 99% of the time anyway)
there is no reason not to remove the gadget, copy the buffer and add
it again.
> I would call this a minor problem... what could happen
> if the result is an invalid string? You have to check the user's input any-
> ways (for example for legal file names...). The only real trouble is that
If there is nothing to check (e.g. if you have a "Enter your
favourite letters" string gadget :-)), you may not get what you want. And,
referring to your file name example, what would happen if an invalid
string is copied ? Perhaps a requester like "Cannot open file
surkzg" will confuse the user.
> the NUL termination of the string might get lost temporarily, so allocate a
> slightly larger buffer that what is really needed for the gadget and fill it
> with zeros...
Strings should always be null-terminated if you ensure that the last
byte of StringInfo->Buffer is set to zero before adding the gadget...
assuming that input.device doesn't abuse the space after the actual
string end for something else.