[comp.sys.mac] Need help in THINK C

parnes@eniac.seas.upenn.edu (Gary Parnes) (10/23/89)

I've started programming on my Mac, finally.  BTW, thanks to all of you
who pointed me toward the Programmer's Primer... it really helped.

I have a problem...  How do you copy a string from a dialog EditText item
into a character array?  I want to copy it to a new memory location so I can
take it apart and do unspeakable things to it, etc.  But, every time I try
locking down the handle and copying the string using strcpy, the computer
locks.  Even the onboard debugger doesn't offer any useful error messages.

Anyone know what to do?
						Gary

/=============================================================================\
| "You're obviously misinformed... everything  |  Gary Parnes		      |
|  EAST of the San Andreas Fault is going to   |  Computer Science Engineer   |
|  fall into the ATLANTIC Ocean."              |  University of Pennsylvania  |
|   *** parnes@eniac.seas.upenn.edu ***        |  *NOT* Penn State, Dammit!   |
\=============================================================================/

rsilverman@eagle.wesleyan.edu (10/24/89)

In article <15790@netnews.upenn.edu>, parnes@eniac.seas.upenn.edu (Gary Parnes) writes:

> I have a problem...  How do you copy a string from a dialog EditText item
> into a character array?  I want to copy it to a new memory location so I can
> take it apart and do unspeakable things to it, etc.  But, every time I try
> locking down the handle and copying the string using strcpy, the computer
> locks.  Even the onboard debugger doesn't offer any useful error messages.

Gary,
	You have to be careful with dialogs; the items are not always stored as
you think they might be.  It's best to use the routines provided for accessing
them.  In this case, the problem is probably this: the text for all text items
in a dialog is kept in one big TextEdit record, managed by the Dialog Manager.
Use the GetIText (I think that's it) routine to retrieve the text from an item.
Remember, it will return it as a Pascal string, so you'll have to add the NUL
yourself.  It's not suprising that it's locking up on you: the text your
copying, even if it's the right part, will not have a NUL at the end, so strcpy 
will happily keep copying for quite a while, overwriting all sorts of stuff --
including your code, perhaps? -- at the destination.

Ah, for a protected-mode operating system...

					good luck,

                                                Richard Silverman

arpa:	rsilverman@eagle.wesleyan.edu           Systems Engineer
bitnet:	rsilverman@wesleyan.bitnet              AM Computer Products
CIS:	[72727,453]                             Southington, CT 06489

oster@dewey.soe.berkeley.edu (David Phillip Oster) (10/24/89)

Here is how you retrieve the text from an edittext item in a dialog.
Remember to do this _before_ you DisposDialog() the dialog.

First, define a helper routine
/* GetDIHandle - return handle value of dialog item
 */
Handle GetDIHandle(i)short i;{
  short theType;
  Handle theHandle;
  Rect theRect;

  GetDItem(thePort, i, &theType, &theHandle, &theRect);
  return theHandle;
}

Then, you can fetch it like this:
Str255	s;

SetPort(myDialog);
GetIText(GetDIHandle(ITEM), s);

paf@nada.kth.se (Patrik F{ltstr|m) (10/24/89)

In article <2393@eagle.wesleyan.edu> rsilverman@eagle.wesleyan.edu writes:
>Remember, it will return it as a Pascal string, so you'll have to add the NUL
>yourself.  It's not suprising that it's locking up on you: the text your
>copying, even if it's the right part, will not have a NUL at the end, so strcpy 
>will happily keep copying for quite a while, overwriting all sorts of stuff --
>including your code, perhaps? -- at the destination.

Use the function
char *CtoPstr(char *s); /* Page 121 in Thinc C 4.0 manual */

>Ah, for a protected-mode operating system...

Will that be in 8.0?

>                                                Richard Silverman
	Patrik F{ltstr|m <paf@nada.kth.se>

)) (10/24/89)

In article <2393@eagle.wesleyan.edu> rsilverman@eagle.wesleyan.edu writes:

>Ah, for a protected-mode operating system...

Seconded ! Still noone has sent me pointers to (on-line) info on
the PMMU, so that I may hack an INIT (crude & ugly 8) that may,
eventually, provide this in one way or another...

Hack on,
						h+@nada.kth.se
-- 
Mooo.

rcfische@polyslo.CalPoly.EDU (Raymond C. Fischer) (10/25/89)

In article <2154@draken.nada.kth.se> d88-jwa@nada.kth.se (Jon W{tte) writes:
>In article <2393@eagle.wesleyan.edu> rsilverman@eagle.wesleyan.edu writes:
>>Ah, for a protected-mode operating system...
>
>Seconded ! Still noone has sent me pointers to (on-line) info on
>the PMMU, so that I may hack an INIT (crude & ugly 8) that may,
>eventually, provide this in one way or another...

In this particular case, a protected mode OS wouldn't have helped much.
The program would still have died, memory would still be overwritten,
and the program would have died at the same time as without protection.

When strcpy is used to copy a pascal string to a local variable, what 
usually gets trashed is the return address.  Thus the program dies when
the routine tries to return to a bad address.  Now, some of you may be
thinking "Why not protect the stack?".  This isn't feasable because ...

1) The MMU's smallest page size is 256 bytes (on a 256 byte boundary).
2) Each entry in the page table uses 4 bytes (for 256 byte pages, 1 in
   every 64 bytes is used for the page table).
3) Even if you could do this, enabling/disabling protection after each
   routine would slow things down somewhat.

Protection is nice, no argument from me, it's just not as simple and not
the cure-all some people think it is.  True, it keeps programs from taking
the whole Mac with them, but this is useful only under Multifinder.  And
crashes on my Mac (that haven't been my fault) are very rare.

What would be nice is if Apple did virtual memory the correct way.  Rather
than use it to expand the memory space for Multifinder, it should be
used to have multiple virtual Macs, each with its own memory space.  But
there I go, second guessing the people who know much more about the
problem.

Additional info on the MMU and memory protection can be found in ...
"MC68030 Enhanced 32-Bit Microprocessor User's Manual" published by
Motorola.

Ray Fischer
rcfische@polyslo.calpoly.edu

t-jacobs@cs.utah.edu (Tony Jacobs) (10/25/89)

I'm starting to see TOO many posts that ought to be in comp.sys.mac.programming

Please, the reason for multiple groups is to cut down the traffic and spread
it around.

Tony Jacobs * Center for Engineering Design * U of U * t-jacobs@ced.utah.edu

garym@telesoft.com (Gary Morris @nova) (10/25/89)

In article <2393@eagle.wesleyan.edu>, rsilverman@eagle.wesleyan.edu writes:
> In article <15790@netnews.upenn.edu>, parnes@eniac.seas.upenn.edu
>    (Gary Parnes) writes:
> > I have a problem...  How do you copy a string from a dialog EditText item
> > into a character array?  
> 
> ...In this case, the problem is probably this: the text for all text items
> in a dialog is kept in one big TextEdit record, managed by the Dialog
> Manager.  Use the GetIText (I think that's it) routine to retrieve the text
> from an item.  Remember, it will return it as a Pascal string, so you'll
> have to add the NUL yourself. 

Not only do you need to add a NUL (0) at the end, you must skip over the
length byte at the beginning of Pascal strings.  If you have a Pascal string
Pstr, you can pass it to a C routine, like so:

	Pstr[ Pstr[0] ] = (char) 0;	/* add the NUL on the end */

	strcpy( DestStr, &Pstr[1] );	/* copy string with first character */

Or if you don't want to modify the source string by adding a NUL on the end
you can use strncpy and specify the length to copy:

	strncpy( DestStr, &Pstr[1], (int) Pstr[0] );

Or with Think C you can use the supplied routine "PtoCstr" to convert a 
string from Pascal format to C format.

Disclaimer: I haven't actually tried these examples and I'm new to using C
on the Mac (I prefer TeleSoft Ada).  If these examples don't work I will
repair or replace them or refund your purchase price at my option.

--GaryM
-- 
Gary Morris      {uunet,ucsd}!telesoft!garym       TeleSoft
N6FRT            garym@telesoft.com                San Diego, CA, USA
ASEL             garym@nynashamn.telelogic.se      +1 619 457-2700
"If something is worth doing, it's worth doing right."

)) (10/25/89)

In article <573@telesoft.com> garym@telesoft.com (Gary Morris @nova) writes:

>Not only do you need to add a NUL (0) at the end, you must skip over the
>length byte at the beginning of Pascal strings.  If you have a Pascal string
>Pstr, you can pass it to a C routine, like so:

>	Pstr[ Pstr[0] ] = (char) 0;	/* add the NUL on the end */

>	strcpy( DestStr, &Pstr[1] );	/* copy string with first character */

Of course this is completelky, utterly wrong. It zaps the last character
in the string to a 0 ! WHat you want is

Pstr[ Pstr[0] +1] = (char) 0;

This has the additional disadvantage of requiring the pascal string to
have a length < 255 characters, as you will otherwise overwrite something
else.

>Or if you don't want to modify the source string by adding a NUL on the end
>you can use strncpy and specify the length to copy:

>	strncpy( DestStr, &Pstr[1], (int) Pstr[0] );

You'd want to add a null at the end, too, so define the following
macro:

#define p_str_to_c(_p_, _c_) \
strncpy(_c_, &((_p_)[1]), (int) (_p_)[0]); \
(_c_)[(_p_)[0]] = 0;

>Or with Think C you can use the supplied routine "PtoCstr" to convert a 
>string from Pascal format to C format.

>Disclaimer: I haven't actually tried these examples and I'm new to using C
>on the Mac (I prefer TeleSoft Ada).  If these examples don't work I will

As indeed they don't. Yo, the group's called comp.sys.mac.programmer,
not comp.sys.mac.programming, and therefore your post got to comp.sys.mac.
Follow-ups redirtected to comp.sys.mac.programmer

h+@nada.kth.se == h+@proxxi.se

-- 
Bango. To the BatMobile! -Let's go!