[comp.sys.mac.programmer] What's wrong with this ModalDialog filterproc?

sirkm@ssyx.ucsc.edu (Greg Anderson) (12/27/89)

I wrote a filterproc for ModalDialog that allows the user to cut, copy
and paste to fields in a modal dialog box by pressing command-c, command-x
and command-v, respectively.  The filterproc works great--cutting and
pasting work as expected.  However, if the user presses <Return>,
ModalDialog no longer returns with itemHit = 1.

IM I-416 says:

"A function result of TRUE tells ModalDialog to return immediately
rather than handle the event; in this case, the filterProc function
sets itemHit to the item number that ModalDialog should return."

I thought that's what I did, but it doesn't work.  When the user
presses <Return> or <Enter> the filterProc beeps (note the inclusion
of a Sysbeep() in the filterProc), but the <Return> is added to
the active textedit field rather than causing modaldialog to exit
with itemHit = 1.

I'm using the MPW C.  Here's the filterProc:

/*----------------------------------------------------------------------
|  This filter, when passed to ModalDialog, will allow the user to
|  cut, copy and paste by pressing command-X, command-C or command-V,
|  respectively.
----------------------------------------------------------------------*/
pascal int cutPasteFilter( DialogPtr dlog, EventRecord *theEvent, int *itemHit )
{
	char		key;
	
	/*
	 *  We only wish to filter keyDown events.
	 */
	if( theEvent->what == keyDown )
	{
		key = theEvent->message & charCodeMask;
		/*
		 *  Is the command key down?
		 */
		if( theEvent->modifiers & cmdKey )
		{
			switch( key )
			{
			case 'x':
				ZeroScrap();
				DlgCut( dlog );
				if( TEToScrap() != noErr )
					SysBeep(0);
				break;
						
			case 'c':
				ZeroScrap();
				DlgCopy( dlog );
				if( TEToScrap() != noErr )
					SysBeep(0);
				break;
						
			case 'v':
				if( TEFromScrap() == noErr )
					DlgPaste( dlog );
				else
					SysBeep(0);
				break;
			}
			theEvent->what = nullEvent;
			return(false);
		}
		else if( (key == 13) || (key == 3) )
		{
			SysBeep(0);
			*itemHit = 1;
			return(true);
		}
	}
	return(false);
}

  ___\    /___               Greg Anderson              ___\    /___ 
  \   \  /   /         Social Sciences Computing        \   \  /   /
   \  /\/\  /    University of California, Santa Cruz    \  /\/\  /
    \/    \/              sirkm@ssyx.ucsc.edu             \/    \/

beard@ux1.lbl.gov (Patrick C Beard) (12/28/89)

In article <10125@saturn.ucsc.edu> sirkm@ssyx.ucsc.edu (Greg Anderson) writes:
>I wrote a filterproc for ModalDialog that allows the user to cut, copy
>and paste to fields in a modal dialog box by pressing command-c, command-x
>and command-v, respectively.  The filterproc works great--cutting and
>pasting work as expected.  However, if the user presses <Return>,
>ModalDialog no longer returns with itemHit = 1.
...
>pascal int cutPasteFilter( DialogPtr dlog, EventRecord *theEvent, int *itemHit )
        ^^^                                                        ^^^
Boom.  You've been burned by MPW C.  MPW C's "int" is really a "long".  i.e.
32 bits.  When writing routines that will be called from the toolbox, pascal
integers map to C "short"s.

So, the fix is:

pascal short
cutPasteFilter(DialogPtr dlg, EventRecord *evt, short *itemHit) { ... }

Hope that helps.

-------------------------------------------------------------------------------
-  Patrick Beard, Macintosh Programmer                        (beard@lbl.gov) -
-  Berkeley Systems, Inc.  ".......<dead air>.......Good day!" - Paul Harvey  -
-------------------------------------------------------------------------------

tim@hoptoad.uucp (Tim Maroney) (12/28/89)

In article <10125@saturn.ucsc.edu> sirkm@ssyx.ucsc.edu (Greg Anderson) writes:
>I wrote a filterproc for ModalDialog that allows the user to cut, copy
>and paste to fields in a modal dialog box by pressing command-c, command-x
>and command-v, respectively.  The filterproc works great--cutting and
>pasting work as expected.  However, if the user presses <Return>,
>ModalDialog no longer returns with itemHit = 1.
>
>I'm using the MPW C.  Here's the filterProc:
>
>pascal int cutPasteFilter(DialogPtr dlog, EventRecord *theEvent, int *itemHit)

ints are four bytes in MPW C.  INTEGERs are two bytes in Mac Pascals.
When the type INTEGER occurs in Inside Macintosh, you need to translate
it as "short", not as "int"; and leave Boolean as Boolean (it's defined
in types.h).  This should solve your problem.  Change your declaration to:

pascal Boolean
cutPasteFilter(DialogPtr dlog, EventRecord *theEvent, short *itemHit)

>		if( theEvent->modifiers & cmdKey )
>		{
>			switch( key )
>			{
>			case 'x':
>				ZeroScrap();
>				DlgCut( dlog );
>				if( TEToScrap() != noErr )
>					SysBeep(0);
>				break;
>						
>			case 'c':

And so on.  You have an internationalization problem here.  These codes
are surely not the same under all langauges.  I assume this is in an
application, so the best way to handle the equivalencies is using your
own Edit menu.  Call MenuKey to translate the character into a menu
command; then do this edit processing if the menu id is the id of your
edit menu, and switch on the menu item number rather than on the
character typed.

(If you didn't have an edit menu handy in the menu bar -- for instance,
in a DA running under an application with an unknown edit menu id --
then you would have to keep a STR# resource to keep track of the
appropriate shortcuts for editing.)
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"He goes on about the wailing and gnashing of teeth.  It comes in one
 verse after another, and it is quite manifest to the reader that there
 is a certain pleasure in contemplating the wailing and gnashing of
 teeth, or else it would not occur so often."
	-- Bertrand Russell, "Why I Am Not a Christian"

sirkm@ssyx.ucsc.edu (Greg Anderson) (12/28/89)

In article <9418@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>And so on.  You have an internationalization problem here.  These codes
>are surely not the same under all langauges.

IM I-53 and I-343 (and other places) state that Z, X, C and V _must_
be used for undo, cut, copy and paste.  However, I suppose that this
isn't possible to use these keys in non-roman systems, so you do have
a point.  I've never seen it addressed before, though.

>(If you didn't have an edit menu handy in the menu bar -- for instance,
>in a DA running under an application with an unknown edit menu id --

Unfortunately, this program is a DA.  However, isn't the Edit menu always
the third menu on the menu bar, and the order of the items always Undo,
blank line, cut, copy, paste, clear by convention?  You can get a copy
of the menu list with GetMenuBar, but paging through IM, I am at a loss
as to how one might use this information to step through the menu list
and examine what is there.  All I need to know is the ID of the third menu!
(Frustration.)

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
And if I cannot obtain this information, then how, praytell, can my DA
flash the EDIT menu when the user selects undo, cut, copy or paste?
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

>then you would have to keep a STR# resource to keep track of the
>appropriate shortcuts for editing.)

This seems like a poor solution to a problem that should have a simple
answer--namely, finding the ID of any arbitrary menu.

Arg.

So, has anyone else out there done anything like this with a DA?
 
>Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

  ___\    /___               Greg Anderson              ___\    /___ 
  \   \  /   /         Social Sciences Computing        \   \  /   /
   \  /\/\  /    University of California, Santa Cruz    \  /\/\  /
    \/    \/              sirkm@ssyx.ucsc.edu             \/    \/

tim@hoptoad.uucp (Tim Maroney) (12/29/89)

In article <10135@saturn.ucsc.edu> sirkm@ssyx.ucsc.edu (Greg Anderson) writes:
>In article <9418@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>>And so on.  You have an internationalization problem here.  These codes
>>are surely not the same under all langauges.
>
>IM I-53 and I-343 (and other places) state that Z, X, C and V _must_
>be used for undo, cut, copy and paste.  However, I suppose that this
>isn't possible to use these keys in non-roman systems, so you do have
>a point.  I've never seen it addressed before, though.

Inside Mac volume 1 was written long before the Mac OS was ported to any
non-Roman systems....

>>(If you didn't have an edit menu handy in the menu bar -- for instance,
>>in a DA running under an application with an unknown edit menu id --
>
>Unfortunately, this program is a DA.  However, isn't the Edit menu always
>the third menu on the menu bar, and the order of the items always Undo,
>blank line, cut, copy, paste, clear by convention?

Yes, but just go through any public software repositories (say a BBS or
the BMUG archives) and you'll see these rules violated again and
again.  They shouldn't be violated, but you can't be sure that they
won't be; you are a desk accessory that might be running under any
harebrained program that the user acres to run.

>You can get a copy
>of the menu list with GetMenuBar, but paging through IM, I am at a loss
>as to how one might use this information to step through the menu list
>and examine what is there.  All I need to know is the ID of the third menu!
>(Frustration.)

No, sorry, maybe in a better world than this one.  If you do need to know
this sometime, the information is on IM I-346.  The MenuList is a variable
sized relocatable array.

>!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
>And if I cannot obtain this information, then how, praytell, can my DA
>flash the EDIT menu when the user selects undo, cut, copy or paste?
>!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

MenuKey does that for you.

>>then you would have to keep a STR# resource to keep track of the
>>appropriate shortcuts for editing.)
>
>This seems like a poor solution to a problem that should have a simple
>answer--namely, finding the ID of any arbitrary menu.

Programming is full of poor solutions that are also the only solutions.

>Arg.

Indeed.

>So, has anyone else out there done anything like this with a DA?

DA windows should be modeless in almost all cases, so I haven't.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

If you vote for clowns, you have no right to complain that only clowns
make it to the ballot.

ts@cup.portal.com (Tim W Smith) (12/30/89)

I had a similar problem in Think C ( I don't use MPW ).  My filters
would handle the events they cared about OK, but they would not
return what I expected.

The problem was with the declaration.  My function was declared "pascal
int" rather than "pascal boolean".  Try chaning that "int" in your
declaration to "boolean" ( or "Boolean" or whatever typdef MPW uses... )
and see if that helps.

						Tim Smith