Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Cactus Dan

macrumors member
Original poster
Aug 8, 2010
30
0
Howdy,

I've created a C callable function to open the NSOpenPanel and convert the selected file name and path to a character array that's passed to the function:
Code:
//Create open panel dialog
int callFileOpenDialog(int type, char **fName)
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	NSOpenPanel *open = [NSOpenPanel openPanel];
	NSString *pathName;
	
	[open setResolvesAliases: true]; //Enable alias resolving
	[open setAllowsMultipleSelection: false]; //Disable multiple selection
	
	switch(type)
	{
		case FILE_SELECTION:
			[open setCanChooseDirectories: false]; //Disable folder selection
			[open setCanChooseFiles: true]; //Enable file selection
			break;
		case DIR_SELECTION:
			[open setCanChooseDirectories: true]; //Enable folder selection
			[open setCanChooseFiles: false]; //Disable file selection
			break;
	}
	
	//Display open panel
	int result = [open runModal];
	if(result == NSOKButton)
	{
		switch(type)
		{
			case FILE_SELECTION:
				pathName = [open filename];
				break;
			case DIR_SELECTION:
				pathName = [open directory];
				break;
		}
		
		*fName = (char *)malloc(strlen([pathName UTF8String]));
		strcpy(*fName, [pathName UTF8String]);

		[pool release];
		return 1;
	}
	
	[pool release];
	return 0;
}

... which works fine except that the main window loses it's focus after the NSOpenPanel is closed.

Is there a way to get a pointer to the window that's in focus at the beginning of the above function, and then return the focus to that window at the end of the function?

I've been searching, but don't really know what I'm looking for, so my search parameters are probably wrong.

Adios,
Cactus Dan
 
The focused window is called the key window in Cocoa. You can get the current key window with code like this (untested):
Code:
NSWindow *keyWindow = [NSApp keyWindow];

After the NSOpenPanel runs, you can restore the key window with code like this (also untested):
Code:
[keyWindow makeKeyWindow];
 
Howdy,

Thanks! That seems to work fine. ;)

Edit:
One more question: would you put that inside or outside the NSAutoreleasePool calls?

Adios,
Cactus Dan
 
Code:
	//Display open panel
	int result = [open runModal];
	if(result == NSOKButton)
	{
		switch(type)
		{
			case FILE_SELECTION:
				pathName = [open filename];
				break;
			case DIR_SELECTION:
				pathName = [open directory];
				break;
		}
		
[COLOR="Red"]		*fName = (char *)malloc(strlen([pathName UTF8String]));
		strcpy(*fName, [pathName UTF8String]);
[/COLOR]
		[pool release];
		return 1;
	}
	
	[pool release];
	return 0;
}

The red-hilited code is wrong. You're not accounting for the NUL byte at the end of the C-string.

I don't know if that's the cause of the problem you described, but the consequences of this bug can be grave.
 
So, what is the correct way?

The correct way is to account for all the bytes. That means counting all the bytes. Since a C string is always marked by a single terminating NUL byte, how do you think you should account for that byte?

Suppose strlen() returns 54. What count should you pass to malloc()?

Suppost strlen() returns 182. What count should you pass to malloc()?
 
As long as we're talking about the "correct way", I think using fileSystemRepresentation is better than UTF8String
 
Howdy,
As long as we're talking about the "correct way", I think using fileSystemRepresentation is better than UTF8String
That looks like it's Cocoa specific, so that won't work. Thanks anyway.

Edit:
Oh wait, I just looked that up and it says it returns a const char*. Maybe I'll investigate this further.

Adios,
Cactus Dan
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.