[mac] Foundation.cfString -> Foundation.nsString to let autoreleasepool to release these strings automatically

This commit is contained in:
Alexey Pegov
2011-09-28 15:41:43 +04:00
parent 13d3f5e373
commit b95ae38eeb
8 changed files with 58 additions and 47 deletions
@@ -149,8 +149,9 @@ public class MacOSApplicationProvider implements ApplicationComponent {
Foundation.registerObjcClassPair(checkForUpdatesClass);
ID checkForUpdates = Foundation.invoke("NSCheckForUpdates", "alloc");
Foundation.invoke(checkForUpdates, Foundation.createSelector("initWithTitle:action:keyEquivalent:"), Foundation.cfString("Check for Updates..."),
Foundation.createSelector("checkForUpdates"), Foundation.cfString(""));
Foundation.invoke(checkForUpdates, Foundation.createSelector("initWithTitle:action:keyEquivalent:"),
Foundation.nsString("Check for Updates..."),
Foundation.createSelector("checkForUpdates"), Foundation.nsString(""));
Foundation.invoke(checkForUpdates, Foundation.createSelector("setTarget:"), checkForUpdates);
Foundation.invoke(appMenu, Foundation.createSelector("insertItem:atIndex:"), checkForUpdates, 1);
@@ -53,10 +53,10 @@ public class MacRestarter {
final long processId = Foundation.invoke(app, Foundation.createSelector("processIdentifier")).longValue();
final ID args = Foundation.invoke(Foundation.getClass("NSArray"), Foundation.createSelector("arrayWithObjects:"),
new Object[]{Foundation.cfString(appPath), Foundation.cfString(String.valueOf(processId))});
new Object[]{Foundation.nsString(appPath), Foundation.nsString(String.valueOf(processId))});
Foundation.invoke(Foundation.getClass("NSTask"), Foundation.createSelector("launchedTaskWithLaunchPath:arguments:"),
Foundation.cfString(relaunchPath), args);
Foundation.nsString(relaunchPath), args);
}
}
}
@@ -26,7 +26,6 @@ import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.foundation.MacUtil;
import com.sun.jna.Callback;
import com.sun.jna.Pointer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -130,7 +129,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
public void callback(ID self, String selector, ID toSelect) {
final ID chooser = invoke("NSOpenPanel", "openPanel");
invoke(chooser, "setPrompt:", Foundation.cfString("Choose"));
invoke(chooser, "setPrompt:", Foundation.nsString("Choose"));
invoke(chooser, "setCanChooseFiles:", myChooserDescriptor.isChooseFiles());
invoke(chooser, "setCanChooseDirectories:", myChooserDescriptor.isChooseFolders());
invoke(chooser, "setAllowsMultipleSelection:", myChooserDescriptor.isChooseMultiple());
@@ -152,8 +151,8 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
invoke(chooser, "setDelegate:", self);
Object directory = null;
Object file = null;
ID directory = null;
ID file = null;
final String toSelectPath = toSelect == null || toSelect.intValue() == 0 ? null : Foundation.toStringViaUTF8(toSelect);
final VirtualFile toSelectFile = toSelectPath == null ? null : LocalFileSystem.getInstance().findFileByPath(toSelectPath);
if (toSelectFile != null) {
@@ -161,8 +160,8 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
directory = toSelect;
}
else {
directory = Foundation.cfString(toSelectFile.getParent().getPath());
file = Foundation.cfString(toSelectFile.getName());
directory = Foundation.nsString(toSelectFile.getParent().getPath());
file = Foundation.nsString(toSelectFile.getName());
}
}
@@ -181,6 +180,14 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
if (focusedWindow != null) {
invoke(chooser, "beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo:",
directory, file, null, focusedWindow, self, Foundation.createSelector("openPanelDidEnd:returnCode:contextInfo:"), null);
if (directory != null) {
Foundation.cfRelease(directory);
}
if (file != null) {
Foundation.cfRelease(file);
}
}
}
}
@@ -265,7 +272,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
try {
final ID delegate = invoke(Foundation.getClass("NSOpenPanelDelegate_"), "new");
final Pointer select = toSelect == null ? null : Foundation.cfString(toSelect.getPath());
final ID select = toSelect == null ? null : Foundation.nsString(toSelect.getPath());
Foundation.cfRetain(delegate);
invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("showOpenPanel:"), select, false);
@@ -281,7 +288,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
try {
final ID delegate = invoke(Foundation.getClass("NSOpenPanelDelegate_"), "new");
final Pointer select = toSelect == null ? null : Foundation.cfString(toSelect.getPath());
final ID select = toSelect == null ? null : Foundation.nsString(toSelect.getPath());
Foundation.cfRetain(delegate);
invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("showOpenPanel:"), select, false);
@@ -177,18 +177,18 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable {
ID delegate = invoke(invoke("IdeaNSWindowDelegate" + v, "alloc"), "init");
invoke(notificationCenter, "addObserver:selector:name:object:", delegate,
Foundation.createSelector("windowDidEnterFullScreen:"),
Foundation.cfString("NSWindowDidEnterFullScreenNotification"), window);
Foundation.nsString("NSWindowDidEnterFullScreenNotification"), window);
//invoke(notificationCenter, "addObserver:selector:name:object:", delegate,
// Foundation.createSelector("windowDidExitFullScreen:"),
// Foundation.cfString("NSWindowDidExitFullScreenNotification"), window);
// Foundation.nsString("NSWindowDidExitFullScreenNotification"), window);
} else {
// toggle toolbar
String className = "IdeaToolbar" + v;
final ID ownToolbar = Foundation.registerObjcClass(Foundation.getClass("NSToolbar"), className);
Foundation.registerObjcClassPair(ownToolbar);
ID toolbar = invoke(invoke(className, "alloc"), "initWithIdentifier:", Foundation.cfString(className));
ID toolbar = invoke(invoke(className, "alloc"), "initWithIdentifier:", Foundation.nsString(className));
Foundation.cfRetain(toolbar);
invoke(toolbar, "setVisible:", 0); // hide native toolbar by default
@@ -158,7 +158,7 @@ public class MacMessagesImpl extends MacMessages {
// it is impossible to override ESCAPE key behavior -> key should be named "Cancel" to be bound to ESC
//if (!alternateExist) {
//invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:", 1), "setKeyEquivalent:", cfString("\\e"));
//invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:", 1), "setKeyEquivalent:", nsString("\\e"));
//}
String doNotAsk = toStringViaUTF8(doNotAskText);
@@ -263,19 +263,21 @@ public class MacMessagesImpl extends MacMessages {
final ID buttonsArray = invoke("NSMutableArray", "array");
for (String s : buttons) {
invoke(buttonsArray, "addObject:", cfString(UIUtil.removeMnemonic(s)));
ID s1 = nsString(UIUtil.removeMnemonic(s));
invoke(buttonsArray, "addObject:", s);
cfRelease(s1);
}
ID paramsArray = invoke("NSArray", "arrayWithObjects:", cfString(title),
ID paramsArray = invoke("NSArray", "arrayWithObjects:", nsString(title),
// replace % -> %% to avoid formatted parameters (causes SIGTERM)
cfString(StringUtil.stripHtml(message, true).replace("%", "%%")),
focusedWindow, cfString(fakeTitle), cfString(errorStyle ? "error" : "-1"),
cfString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden()
nsString(StringUtil.stripHtml(message, true).replace("%", "%%")),
focusedWindow, nsString(fakeTitle), nsString(errorStyle ? "error" : "-1"),
nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden()
// TODO: state=!doNotAsk.shouldBeShown()
? "-1"
: doNotAskDialogOption.getDoNotShowMessage()),
cfString(Integer.toString(defaultOptionIndex)),
cfString(Integer.toString(focusedOptionIndex)), buttonsArray, null);
nsString(Integer.toString(defaultOptionIndex)),
nsString(Integer.toString(focusedOptionIndex)), buttonsArray, null);
IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false);
@@ -427,13 +429,13 @@ public class MacMessagesImpl extends MacMessages {
fakeTitle = String.format("MacSheetDialog-%d", delegate.intValue());
ID paramsArray = invoke("NSArray", "arrayWithObjects:", cfString(title), cfString(UIUtil.removeMnemonic(defaultText)),
cfString(otherText == null ? "-1" : UIUtil.removeMnemonic(otherText)),
cfString(alternateText == null ? "-1" : UIUtil.removeMnemonic(alternateText)),
ID paramsArray = invoke("NSArray", "arrayWithObjects:", nsString(title), nsString(UIUtil.removeMnemonic(defaultText)),
nsString(otherText == null ? "-1" : UIUtil.removeMnemonic(otherText)),
nsString(alternateText == null ? "-1" : UIUtil.removeMnemonic(alternateText)),
// replace % -> %% to avoid formatted parameters (causes SIGTERM)
cfString(StringUtil.stripHtml(message, true).replace("%", "%%")),
focusedWindow, cfString(fakeTitle), cfString(errorStyle ? "error" : "-1"),
cfString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden()
nsString(StringUtil.stripHtml(message, true).replace("%", "%%")),
focusedWindow, nsString(fakeTitle), nsString(errorStyle ? "error" : "-1"),
nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden()
// TODO: state=!doNotAsk.shouldBeShown()
? "-1"
: doNotAskDialogOption.getDoNotShowMessage()), null);
@@ -55,7 +55,7 @@ public class Growl {
new Object[]{myProductName, applicationIcon, defaultNotifications, allNotifications});
final ID center = invoke("NSDistributedNotificationCenter", "defaultCenter");
final Object notificationName = Foundation.cfString(GROWL_APPLICATION_REGISTRATION_NOTIFICATION);
final Object notificationName = Foundation.nsString(GROWL_APPLICATION_REGISTRATION_NOTIFICATION);
invoke(center, "postNotificationName:object:userInfo:deliverImmediately:", notificationName, null, userDict, true);
invoke(autoReleasePool, "release");
}
@@ -66,7 +66,7 @@ public class Growl {
GROWL_NOTIFICATION_NAME, GROWL_NOTIFICATION_TITLE, GROWL_NOTIFICATION_DESCRIPTION, GROWL_APP_NAME},
new Object[]{notification, title, description, myProductName});
final ID center = invoke("NSDistributedNotificationCenter", "defaultCenter");
final Object notificationName = Foundation.cfString(GROWL_NOTIFICATION);
final Object notificationName = Foundation.nsString(GROWL_NOTIFICATION);
invoke(center, "postNotificationName:object:userInfo:deliverImmediately:", notificationName, null, dict, true);
invoke(autoReleasePool, "release");
@@ -104,7 +104,7 @@ public class Growl {
if (o instanceof Pointer || o instanceof ID) {
return o;
} else if (o instanceof String) {
return Foundation.cfString((String) o);
return Foundation.nsString((String)o);
} else {
throw new IllegalArgumentException("Unsupported type! " + o.getClass());
}
@@ -128,7 +128,7 @@ public class Foundation {
public static boolean isPackageAtPath(@NotNull final String path) {
final ID workspace = invoke("NSWorkspace", "sharedWorkspace");
final ID result = invoke(workspace, createSelector("isFilePackageAtPath:"), cfString(path));
final ID result = invoke(workspace, createSelector("isFilePackageAtPath:"), nsString(path));
return result.intValue() == 1;
}
@@ -138,18 +138,17 @@ public class Foundation {
return isPackageAtPath(file.getPath());
}
/**
* Return a CFString as an ID, toll-free bridged to NSString.
* <p/>
* Note that the returned string must be freed with {@link #cfRelease(ID)}.
*/
public static Pointer cfString(String s) {
public static ID nsString(String s) {
// Use a byte[] rather than letting jna do the String -> char* marshalling itself.
// Turns out about 10% quicker for long strings.
try {
if (s.length() == 0) {
return invoke("NSString", "string");
}
byte[] utf16Bytes = s.getBytes("UTF-16LE");
return myFoundationLibrary.CFStringCreateWithBytes(null, utf16Bytes, utf16Bytes.length, FoundationLibrary.kCFStringEncodingUTF16LE,
(byte)0); /* kTextEncodingUnicodeDefault + kUnicodeUTF16LEFormat */
return invoke(invoke("NSString", "alloc"), "initWithBytes:length:encoding:", utf16Bytes, utf16Bytes.length,
myFoundationLibrary.CFStringConvertEncodingToNSStringEncoding(FoundationLibrary.kCFStringEncodingUTF16LE));
}
catch (UnsupportedEncodingException x) {
throw new RuntimeException(x);
@@ -179,7 +178,7 @@ public class Foundation {
public static long getEncodingCode(@Nullable String encodingName) {
if (StringUtil.isEmptyOrSpaces(encodingName)) return -1;
Pointer converted = cfString(encodingName);
ID converted = nsString(encodingName);
int cfEncoding = myFoundationLibrary.CFStringConvertIANACharSetNameToEncoding(converted);
if (cfEncoding == FoundationLibrary.kCFStringEncodingInvalidId) return -1;
@@ -190,8 +189,10 @@ public class Foundation {
myFoundationLibrary.CFRetain(id);
}
public static void cfRelease(ID id) {
myFoundationLibrary.CFRelease(id);
public static void cfRelease(ID... id) {
for (ID id1 : id) {
myFoundationLibrary.CFRelease(id1);
}
}
public static boolean isMainThread() {
@@ -223,7 +224,7 @@ public class Foundation {
final ID ideaRunnable = getClass("IdeaRunnable");
final ID runnableObject = invoke(invoke(ideaRunnable, "alloc"), "init");
invoke(runnableObject, "performSelectorOnMainThread:withObject:waitUntilDone:", createSelector("run:"),
cfString(String.valueOf(ourCurrentRunnableCount)), Boolean.valueOf(waitUntilDone));
nsString(String.valueOf(ourCurrentRunnableCount)), Boolean.valueOf(waitUntilDone));
invoke(runnableObject, "release");
}
@@ -30,14 +30,14 @@ public interface FoundationLibrary extends Library {
ID objc_allocateClassPair(ID supercls, String name, int extraBytes);
void objc_registerClassPair(ID cls);
Pointer CFStringCreateWithBytes(Pointer allocator, byte[] bytes, int byteCount, int encoding, byte isExternalRepresentation);
ID CFStringCreateWithBytes(Pointer allocator, byte[] bytes, int byteCount, int encoding, byte isExternalRepresentation);
byte CFStringGetCString(ID theString, byte[] buffer, int bufferSize, int encoding);
int CFStringGetLength(ID theString);
int CFStringConvertNSStringEncodingToEncoding(long nsEncoding);
ID CFStringConvertEncodingToIANACharSetName(int cfEncoding);
int CFStringConvertIANACharSetNameToEncoding(Pointer encodingName);
int CFStringConvertIANACharSetNameToEncoding(ID encodingName);
long CFStringConvertEncodingToNSStringEncoding(int cfEncoding);
void CFRetain(ID cfTypeRef);