Merge remote-tracking branch 'origin/master' appcode/140.2053 clion/140.2044 clion/140.2052 dbe/140.2046 phpstorm/140.2048 pycharm/140.2050 rubymine/140.2051 webstorm/140.2045 webstorm/19
authorVladimir.Orlov <Vladimir.Orlov@jetbrains.com>
Fri, 30 Jan 2015 04:15:41 +0000 (07:15 +0300)
committerVladimir.Orlov <Vladimir.Orlov@jetbrains.com>
Fri, 30 Jan 2015 04:15:41 +0000 (07:15 +0300)
21 files changed:
bin/WinLauncher/WinLauncher.exe
bin/WinLauncher/WinLauncher64.exe
bin/scripts/unix/idea.sh
bin/scripts/win/idea.bat
build/conf/mac/Contents/Info.plist
build/conf/mac/Contents/MacOS/idea
build/conf/mac/Contents/MacOS/idea_appLauncher [deleted file]
build/lib/launcher-generator.jar
build/scripts/utils.gant
native/MacLauncher/Launcher.m
native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj
native/MacLauncher/PropertyFileReader.h [deleted file]
native/MacLauncher/PropertyFileReader.m [deleted file]
native/WinLauncher/WinLauncher/WinLauncher.cpp
native/WinLauncher/WinLauncher/WinLauncher.rc
native/WinLauncher/WinLauncher/resource.h
native/WinLauncher/WinLauncher/stdafx.h
platform/util/src/com/intellij/openapi/application/PathManager.java
python/edu/build/pycharm_edu_build.gant
tools/launcher-generator/src/com/pme/exe/res/vi/StringTable.java
tools/launcher-generator/src/com/pme/launcher/LauncherGeneratorMain.java

index 749a855aaa0e1b2c82ebdc104f39b94ac2de3216..d34a21c0a83def1da2bf20bad39a03824d2fed6c 100644 (file)
Binary files a/bin/WinLauncher/WinLauncher.exe and b/bin/WinLauncher/WinLauncher.exe differ
index e0855845243ee57f4689ba12b9c1953b45e12e54..6fcb99307b94eccc92ed6baba59e0a2594b41e09 100644 (file)
Binary files a/bin/WinLauncher/WinLauncher64.exe and b/bin/WinLauncher/WinLauncher64.exe differ
index 602c363458b657ca4dca03a1258458614eb2fb34..2e4a6a8710e549ff1a9e45f6c038a0fdec8e9906 100755 (executable)
@@ -133,16 +133,42 @@ if [ -z "$MAIN_CLASS_NAME" ]; then
   MAIN_CLASS_NAME="com.intellij.idea.Main"
 fi
 
-VM_OPTIONS_FILE="$@@product_uc@@_VM_OPTIONS"
-if [ -z "$VM_OPTIONS_FILE" ]; then
-  VM_OPTIONS_FILE="$IDE_BIN_HOME/@@vm_options@@$BITS.vmoptions"
+VM_OPTIONS_FILES_0=$IDE_BIN_HOME/@@vm_options@@$BITS.vmoptions
+VM_OPTIONS_FILES_1=$HOME/.@@system_selector@@/@@vm_options@@$BITS.vmoptions
+VM_OPTIONS_FILES_2=$@@product_uc@@_VM_OPTIONS
+
+VM_OPTIONS=""
+VM_OPTIONS_FILES_USED=""
+
+if [ -r "$VM_OPTIONS_FILES_0" ]; then
+  VM_OPTIONS_DATA=`"$CAT" "$VM_OPTIONS_FILES_0" | "$GREP" -v "^#.*" | "$TR" '\n' ' '`
+  VM_OPTIONS="$VM_OPTIONS $VM_OPTIONS_DATA"
+  if [ -n "$VM_OPTIONS_FILES_USED" ]; then
+    VM_OPTIONS_FILES_USED="$VM_OPTIONS_FILES_USED,"
+  fi
+  VM_OPTIONS_FILES_USED="$VM_OPTIONS_FILES_USED$VM_OPTIONS_FILES_0"
 fi
 
-if [ -r "$VM_OPTIONS_FILE" ]; then
-  VM_OPTIONS=`"$CAT" "$VM_OPTIONS_FILE" | "$GREP" -v "^#.*" | "$TR" '\n' ' '`
-  VM_OPTIONS="$VM_OPTIONS -Djb.vmOptionsFile=\"$VM_OPTIONS_FILE\""
+if [ -r "$VM_OPTIONS_FILES_1" ]; then
+  VM_OPTIONS_DATA=`"$CAT" "$VM_OPTIONS_FILES_1" | "$GREP" -v "^#.*" | "$TR" '\n' ' '`
+  VM_OPTIONS="$VM_OPTIONS $VM_OPTIONS_DATA"
+  if [ -n "$VM_OPTIONS_FILES_USED" ]; then
+    VM_OPTIONS_FILES_USED="$VM_OPTIONS_FILES_USED,"
+  fi
+  VM_OPTIONS_FILES_USED="$VM_OPTIONS_FILES_USED$VM_OPTIONS_FILES_1"
 fi
 
+if [ -r "$VM_OPTIONS_FILES_2" ]; then
+  VM_OPTIONS_DATA=`"$CAT" "$VM_OPTIONS_FILES_2" | "$GREP" -v "^#.*" | "$TR" '\n' ' '`
+  VM_OPTIONS="$VM_OPTIONS $VM_OPTIONS_DATA"
+  if [ -n "$VM_OPTIONS_FILES_USED" ]; then
+    VM_OPTIONS_FILES_USED="$VM_OPTIONS_FILES_USED,"
+  fi
+  VM_OPTIONS_FILES_USED="$VM_OPTIONS_FILES_USED$VM_OPTIONS_FILES_2"
+fi
+
+VM_OPTIONS="$VM_OPTIONS -Djb.vmOptionsFile=\"$VM_OPTIONS_FILES_USED\""
+
 IS_EAP="@@isEap@@"
 if [ "$IS_EAP" = "true" ]; then
   OS_NAME=`echo $OS_TYPE | "$TR" '[:upper:]' '[:lower:]'`
@@ -154,13 +180,13 @@ fi
 
 COMMON_JVM_ARGS="-XX:ErrorFile=$HOME/java_error_in_@@product_uc@@_%p.log \"-Xbootclasspath/a:$IDE_HOME/lib/boot.jar\" -Didea.paths.selector=@@system_selector@@ $IDE_PROPERTIES_PROPERTY"
 IDE_JVM_ARGS="@@ide_jvm_args@@"
+ALL_JVM_ARGS="$VM_OPTIONS $COMMON_JVM_ARGS $IDE_JVM_ARGS $AGENT $REQUIRED_JVM_ARGS"
 
 @@class_path@@
 if [ -n "$@@product_uc@@_CLASSPATH" ]; then
   CLASSPATH="$CLASSPATH:$@@product_uc@@_CLASSPATH"
 fi
-
-ALL_JVM_ARGS="-cp $CLASSPATH $VM_OPTIONS $COMMON_JVM_ARGS $IDE_JVM_ARGS $AGENT $REQUIRED_JVM_ARGS"
+export CLASSPATH
 
 LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH"
 export LD_LIBRARY_PATH
index 1e21c069cefbb0c739c910da21e7a0f1a3ddad3d..a63ddb75c6f3eaf931971d0b120ed61194bfa82c 100644 (file)
@@ -41,8 +41,12 @@ IF NOT "%@@product_uc@@_PROPERTIES%" == "" SET IDE_PROPERTIES_PROPERTY="-Didea.p
 :: ---------------------------------------------------------------------
 :: Collect JVM options and properties.
 :: ---------------------------------------------------------------------
-SET VM_OPTIONS_FILE=%@@product_uc@@_VM_OPTIONS%
-IF "%VM_OPTIONS_FILE%" == "" SET VM_OPTIONS_FILE=%IDE_BIN_DIR%\@@vm_options@@.vmoptions
+
+SET USER_VM_OPTIONS_FILE=%USERPROFILE%\.@@system_selector@@\@@vm_options@@.vmoptions
+SET VM_OPTIONS_FILE=%IDE_BIN_DIR%\@@vm_options@@.vmoptions
+IF EXIST %USER_VM_OPTIONS_FILE% SET VM_OPTIONS_FILE=%USER_VM_OPTIONS_FILE%
+IF NOT "%@@product_uc@@_VM_OPTIONS%" == "" SET VM_OPTIONS_FILE=%@@product_uc@@_VM_OPTIONS%
+
 SET ACC=
 FOR /F "usebackq delims=" %%i IN ("%VM_OPTIONS_FILE%") DO CALL "%IDE_BIN_DIR%\append.bat" "%%i"
 IF EXIST "%VM_OPTIONS_FILE%" SET ACC=%ACC% -Djb.vmOptionsFile="%VM_OPTIONS_FILE%"
index d13854c5f77afa7a6ad69532e87aa8ab580d4e27..31cb058c7bf065f4366ee03a3d15286b908133cb 100644 (file)
@@ -68,7 +68,7 @@
       <string>@@class_path@@</string>
 
       <key>JVMVersion</key>
-      <string>1.6*</string>
+      <string>1.6*,1.7+</string>
 
       <key>MainClass</key>
       <string>com.intellij.idea.Main</string>
index 4ead2aba15c1ea83059785cf775ebaf555fa66b4..50bc99369097b269596932c3e41db98bda0031ca 100755 (executable)
Binary files a/build/conf/mac/Contents/MacOS/idea and b/build/conf/mac/Contents/MacOS/idea differ
diff --git a/build/conf/mac/Contents/MacOS/idea_appLauncher b/build/conf/mac/Contents/MacOS/idea_appLauncher
deleted file mode 100755 (executable)
index 228b1f8..0000000
Binary files a/build/conf/mac/Contents/MacOS/idea_appLauncher and /dev/null differ
index 19951b9300c8f1746797c034d2784b9620ce6bc5..7a1574d1017629115dbb80cb9ed1106cc78edda7 100644 (file)
Binary files a/build/lib/launcher-generator.jar and b/build/lib/launcher-generator.jar differ
index 5b80441beb322246274906a1d01711d466c7ecbe..eb2386e9e3a64ff05aa44c9c47de0b3f9c180ee3 100644 (file)
@@ -367,7 +367,7 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args ->
 
   Map properties = readIdeaProperties(args)
 
-  def coreKeys = ["idea.platform.prefix", "idea.paths.selector"]
+  def coreKeys = ["idea.platform.prefix", "idea.paths.selector", "idea.executable"]
 
   String coreProperties = submapToXml(properties, coreKeys);
 
@@ -383,7 +383,7 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args ->
   if (isEap() && !args.mac_no_yjp) {
     ideaVmOptions += " ${yjpOptions(args.system_selector)}"
   }
-  new File("$path/bin/idea.vmoptions").text = ideaVmOptions
+  new File("$path/bin/${executable}.vmoptions").text = ideaVmOptions
 
   String classPath = classPathLibs.collect {"\$APP_PACKAGE/Contents/lib/${it}" }.join(":")
 
@@ -686,6 +686,7 @@ private Map readIdeaProperties(Map args) {
                            "JVMVersion": "1.6*",
                            "com.apple.mrj.application.live-resize": "false",
                            "idea.paths.selector": args.system_selector,
+                           "idea.executable": args.executable,
                            "java.endorsed.dirs": "",
                            "idea.smooth.progress": "false",
                            "apple.laf.useScreenMenuBar": "true",
index 7ccae0bec4471a7248f6acdfaf96b538a6ec8ef8..71ce04a75cb0c85d4d99e6d48c590696d945b8d8 100644 (file)
@@ -7,7 +7,6 @@
 
 #import "Launcher.h"
 #import "VMOptionsReader.h"
-#import "PropertyFileReader.h"
 #import "utils.h"
 #import <dlfcn.h>
 @class NSAlert;
@@ -163,34 +162,12 @@ void appendJvmBundlesAt(NSString *path, NSMutableArray *sink) {
 
 NSArray *allVms() {
     NSMutableArray *jvmBundlePaths = [NSMutableArray array];
-
-    // search java info in user's idea.properties
-    NSDictionary *inConfig = [PropertyFileReader readFile:getPropertiesFilePath()];
-    NSString* userJavaVersion = [inConfig objectForKey:@"JVMVersion"];
-    if (userJavaVersion != nil) JVMVersion = userJavaVersion;
-    NSString *required = requiredJvmVersion();
-
-    NSString *explicit = [[[NSProcessInfo processInfo] environment] objectForKey:@"IDEA_JDK"];
-
-    if (explicit != nil) {
-        // check if IDEA_JDK value corresponds  with JVMVersion from Info.plist
-        NSLog(@"value of IDEA_JDK: %@", explicit);
-        NSBundle *jdkBundle = [NSBundle bundleWithPath:explicit];
-        
-        if (jdkBundle != nil && required != NULL) {
-            if (satisfies(jvmVersion(jdkBundle), required)) {
-                appendBundle(explicit, jvmBundlePaths);
-                debugLog(@"User VM:");
-                debugLog([jdkBundle bundlePath]);
-            }
-        }
-    }
     if (! jvmBundlePaths.count > 0 ) {
         NSBundle *bundle = [NSBundle mainBundle];
         NSString *appDir = [bundle.bundlePath stringByAppendingPathComponent:@"Contents"];
 
         appendJvmBundlesAt([appDir stringByAppendingPathComponent:@"/jre"], jvmBundlePaths);
-        if ((jvmBundlePaths.count > 0) && (satisfies(jvmVersion(jvmBundlePaths[jvmBundlePaths.count-1]), required))) return jvmBundlePaths;
+        if (jvmBundlePaths.count > 0) return jvmBundlePaths;
 
         appendJvmBundlesAt([NSHomeDirectory() stringByAppendingPathComponent:@"Library/Java/JavaVirtualMachines"], jvmBundlePaths);
         appendJvmBundlesAt(@"/Library/Java/JavaVirtualMachines", jvmBundlePaths);
@@ -206,8 +183,8 @@ NSString *jvmVersion(NSBundle *bundle) {
     return javaVersion;
 }
 
-NSString *requiredJvmVersion() {
-    return (JVMVersion != NULL) ? JVMVersion : [[NSBundle mainBundle].infoDictionary valueForKey:@"JVMVersion" inDictionary: JVMOptions defaultObject:@"1.7*"];
+NSString *requiredJvmVersions() {
+    return [[NSBundle mainBundle].infoDictionary valueForKey:@"JVMVersion" inDictionary: JVMOptions defaultObject:@"1.7*"];
 }
 
 BOOL satisfies(NSString *vmVersion, NSString *requiredVersion) {
@@ -232,6 +209,21 @@ NSComparisonResult compareVMVersions(id vm1, id vm2, void *context) {
 }
 
 NSBundle *findMatchingVm() {
+    // The name of the environment variable.
+    NSString *variable = [[getExecutable() uppercaseString] stringByAppendingString:@"_JDK"];
+    // The explicitly set JDK to use.
+    NSString *explicit = [[[NSProcessInfo processInfo] environment] objectForKey:variable];
+    NSLog(@"Value of %@: %@", variable, explicit);
+    if (explicit != nil) {
+        NSBundle *jdkBundle = [NSBundle bundleWithPath:explicit];
+        if (jdkBundle != nil && ![jvmVersion(jdkBundle) isEqualToString:@"0"]) {
+            // If the user chooses a VM, use it even if it doesn't satisfy Info.pList
+            debugLog(@"User VM:");
+            debugLog([jdkBundle bundlePath]);
+            return jdkBundle;
+        }
+    }
+
     NSArray *vmBundles = [allVms() sortedArrayUsingFunction:compareVMVersions context:NULL];
 
     if (isDebugEnabled()) {
@@ -241,19 +233,22 @@ NSBundle *findMatchingVm() {
         }
     }
 
-    NSString *required = requiredJvmVersion();
-    debugLog([NSString stringWithFormat:@"Required VM: %@", required]);
+    NSString *requiredList = requiredJvmVersions();
+    debugLog([NSString stringWithFormat:@"Required VMs: %@", requiredList]);
 
-    if (required != nil && required != NULL) {
-      for (NSBundle *vm in vmBundles) {
-        if (satisfies(jvmVersion(vm), required)) {
-            debugLog(@"Chosen VM:");
-            debugLog([vm bundlePath]);
-            return vm;
+    if (requiredList != nil && requiredList != NULL) {
+        NSArray *array = [requiredList componentsSeparatedByString:@","];
+        for (NSString* required in array) {
+            for (NSBundle *vm in vmBundles) {
+                if (satisfies(jvmVersion(vm), required)) {
+                    debugLog(@"Chosen VM:");
+                    debugLog([vm bundlePath]);
+                    return vm;
+                }
+            }
         }
-      }
     } else {
-        NSLog(@"Info.plist is corrupted, Absent JVMOptios key.");
+        NSLog(@"Info.plist is corrupted, Absent JVMOptions key.");
         exit(-1);
     }
     NSLog(@"No matching VM found.");
@@ -287,30 +282,33 @@ CFBundleRef NSBundle2CFBundle(NSBundle *bundle) {
         NSLog(@"Info.plist is corrupted, Absent ClassPath key.");
         exit(-1);
     }
-        
-  return classpathOption;
-}
 
+    return classpathOption;
+}
 
-NSString *getSelector() {
+NSString *getJVMProperty(NSString *property) {
     NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:JVMOptions];
     NSDictionary *properties = [jvmInfo dictionaryForKey:@"Properties"];
     if (properties != nil) {
-        return [properties objectForKey:@"idea.paths.selector"];
+        return [properties objectForKey:property];
     }
     return nil;
 }
 
-NSString *getPreferencesFolderPath() {
-    return [NSString stringWithFormat:@"%@/Library/Preferences/%@", NSHomeDirectory(), getSelector()];
+NSString *getSelector() {
+    return getJVMProperty(@"idea.paths.selector");
 }
 
-NSString *getPropertiesFilePath() {
-    return [getPreferencesFolderPath() stringByAppendingString:@"/idea.properties"];
+NSString *getExecutable() {
+    return getJVMProperty(@"idea.executable");
 }
 
-NSString *getDefaultPropertiesFilePath() {
-    return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/bin/idea.properties"];
+NSString *getBundleName() {
+    return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+}
+
+NSString *getPreferencesFolderPath() {
+    return [NSString stringWithFormat:@"%@/Library/Preferences/%@", NSHomeDirectory(), getSelector()];
 }
 
 // NSString *getDefaultVMOptionsFilePath() {
@@ -329,22 +327,48 @@ NSString *getDefaultFilePath(NSString *fileName) {
     return fullFileName;
 }
 
+NSString *getApplicationVMOptionsPath() {
+    return getDefaultFilePath([NSString stringWithFormat:@"/bin/%@.vmoptions", getExecutable()]);
+}
 
-NSString *getVMOptionsFilePath() {
-    return [getPreferencesFolderPath() stringByAppendingString:@"/idea.vmoptions"];
+NSString *getUserVMOptionsPath() {
+    return [NSString stringWithFormat:@"%@/%@.vmoptions", getPreferencesFolderPath(), getExecutable()];
+}
+
+NSString *getOverrideVMOptionsPath() {
+    NSString *variable = [[getExecutable() uppercaseString] stringByAppendingString:@"_VM_OPTIONS"];
+    NSString *value = [[[NSProcessInfo processInfo] environment] objectForKey:variable];
+    NSLog(@"Value of %@ is %@", variable, value);
+    return value == nil ? @"" : value;
 }
 
 NSArray *parseVMOptions() {
-    NSArray *inConfig=[VMOptionsReader readFile:getVMOptionsFilePath()];
-    if (inConfig) return inConfig;
-    //return [VMOptionsReader readFile:getDefaultVMOptionsFilePath()];
-    return [VMOptionsReader readFile:getDefaultFilePath(@"/bin/idea.vmoptions")];
+    NSArray *files = @[getApplicationVMOptionsPath(),
+                       getUserVMOptionsPath(),
+                       getOverrideVMOptionsPath()];
+
+    NSMutableArray *options = [NSMutableArray array];
+    NSMutableArray *used = [NSMutableArray array];
+
+    for (NSString *file in files) {
+        NSLog(@"Processing VMOptions file at %@", file);
+        NSArray *contents = [VMOptionsReader readFile:file];
+        if (contents != nil) {
+            NSLog(@"Done");
+            [used addObject:file];
+            [options addObjectsFromArray:contents];
+        } else {
+            NSLog(@"No content found");
+        }
+    }
+    [options addObject:[NSString stringWithFormat:@"-Djb.vmOptionsFile=%@", [used componentsJoinedByString:@","]]];
+
+    return options;
 }
 
-NSDictionary *parseProperties() {
-    NSDictionary *inConfig = [PropertyFileReader readFile:getPropertiesFilePath()];
-    if (inConfig) return inConfig;
-    return [PropertyFileReader readFile:getDefaultPropertiesFilePath()];
+NSString *getOverridePropertiesPath() {
+    NSString *variable = [[getExecutable() uppercaseString] stringByAppendingString:@"_PROPERTIES"];
+    return [[[NSProcessInfo processInfo] environment] objectForKey:variable];
 }
 
 - (void)fillArgs:(NSMutableArray *)args_array fromProperties:(NSDictionary *)properties {
@@ -364,10 +388,14 @@ NSDictionary *parseProperties() {
     [args_array addObject:classpathOption];
 
     [args_array addObjectsFromArray:[[jvmInfo objectForKey:@"VMOptions"] componentsSeparatedByString:@" "]];
-    [args_array addObjectsFromArray:parseVMOptions()];    
+    [args_array addObjectsFromArray:parseVMOptions()];
+
+    NSString *properties = getOverridePropertiesPath();
+    if (properties != nil) {
+        [args_array addObject:[NSString stringWithFormat:@"-Didea.properties.file=%@", properties]];
+    }
 
     [self fillArgs:args_array fromProperties:[jvmInfo dictionaryForKey:@"Properties"]];
-    [self fillArgs:args_array fromProperties:parseProperties()];
 
     JavaVMInitArgs args;
     args.version = JNI_VERSION_1_6;
@@ -427,12 +455,33 @@ BOOL validationJavaVersion(){
     return true;
 }
 
+- (void)alert:(NSArray *)values {
+    NSAlert *alert = [[[NSAlert alloc] init] autorelease];
+    [alert setMessageText:[values objectAtIndex:0]];
+    [alert setInformativeText:[values objectAtIndex:1]];
+
+    if ([values count] > 2) {
+        NSTextView *accessory = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0 , 300 , 15)];
+        [accessory setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString: [values objectAtIndex:2]];
+        [str addAttribute: NSLinkAttributeName value: [values objectAtIndex:2] range: NSMakeRange(0, str.length)];
+        [accessory insertText:str];
+        [accessory setEditable:NO];
+        [accessory setDrawsBackground:NO];
+        [alert setAccessoryView:accessory];
+    }
+
+    [alert runModal];
+}
+
 - (void)launch {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
     if (vm == nil) {
-        NSString *old_launcher = [self expandMacros:@"$APP_PACKAGE/Contents/MacOS/idea_appLauncher"];
-        execv([old_launcher fileSystemRepresentation], self->argv);
+        NSString *title = @"Java not found";
+        NSString *message = [getBundleName() stringByAppendingString:@" was unable to find a valid JVM. Please download it from:"];
+        NSString *link = @"http://support.apple.com/kb/DL1572";
+        [self performSelectorOnMainThread:@selector(alert:) withObject:@[title, message, link] waitUntilDone:true];
 
         NSLog(@"Cannot find matching VM, aborting");
         exit(-1);
@@ -478,7 +527,7 @@ BOOL validationJavaVersion(){
 
     jint create_vm_rc = create_vm(&jvm, &env, &args);
     if (create_vm_rc != JNI_OK || jvm == NULL) {
-        NSLog(@"JNI_CreateJavaVM (%@) failed: %d", vm.bundlePath, create_vm_rc);
+        NSLog(@"JNI_CreateJavaVM (%@) failed: %ld", vm.bundlePath, create_vm_rc);
         exit(-1);
     }
 
index ad3262c6f77d7c2af7d88b75d1a15ff5a56bd8cb..3aead1c25806fb669abdd909f1320e37d6725538 100644 (file)
@@ -7,7 +7,6 @@
        objects = {
 
 /* Begin PBXBuildFile section */
-               1A5645DB6F789D018FF4A4AF /* PropertyFileReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */; };
                1A564BCFE66693BF0B2DD4A9 /* VMOptionsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */; };
                1A564C27F0BA05F900F34907 /* utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A564EEF77B93DBD7FD23161 /* utils.m */; };
                50E17738155444B900E97451 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50E17737155444B900E97451 /* Cocoa.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-               1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PropertyFileReader.m; sourceTree = "<group>"; };
                1A564A1031F4C91C464C1B75 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
                1A564D7CEEAA02F14A6D4F20 /* VMOptionsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMOptionsReader.h; sourceTree = "<group>"; };
                1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VMOptionsReader.m; sourceTree = "<group>"; };
                1A564EEF77B93DBD7FD23161 /* utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = utils.m; sourceTree = "<group>"; };
-               1A564F6D5833A0B9CE6E2839 /* PropertyFileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyFileReader.h; sourceTree = "<group>"; };
                50E17735155444B900E97451 /* Launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Launcher.app; sourceTree = BUILT_PRODUCTS_DIR; };
                50E17737155444B900E97451 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
                50E1773F155444B900E97451 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -54,8 +51,6 @@
                                50E1773F155444B900E97451 /* Info.plist */,
                                C0B58A123544A15DA59B13CB /* Products */,
                                C0B58A123544A15DA59B13D6 /* Frameworks */,
-                               1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */,
-                               1A564F6D5833A0B9CE6E2839 /* PropertyFileReader.h */,
                                1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */,
                                1A564D7CEEAA02F14A6D4F20 /* VMOptionsReader.h */,
                                1A564A1031F4C91C464C1B75 /* utils.h */,
                        files = (
                                C0B58A123544A15DA59B13E4 /* main.m in Sources */,
                                C0B58A123544A15DA59B13E5 /* Launcher.m in Sources */,
-                               1A5645DB6F789D018FF4A4AF /* PropertyFileReader.m in Sources */,
                                1A564BCFE66693BF0B2DD4A9 /* VMOptionsReader.m in Sources */,
                                1A564C27F0BA05F900F34907 /* utils.m in Sources */,
                        );
diff --git a/native/MacLauncher/PropertyFileReader.h b/native/MacLauncher/PropertyFileReader.h
deleted file mode 100644 (file)
index 44e46a9..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// Created by max on 11/6/12.
-//
-// To change the template use AppCode | Preferences | File Templates.
-//
-
-
-#import <Foundation/Foundation.h>
-
-
-@interface PropertyFileReader : NSObject
-+ (NSDictionary *)readFile:(NSString *)path;
-@end
\ No newline at end of file
diff --git a/native/MacLauncher/PropertyFileReader.m b/native/MacLauncher/PropertyFileReader.m
deleted file mode 100644 (file)
index 43b0682..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Created by max on 11/6/12.
-//
-// To change the template use AppCode | Preferences | File Templates.
-//
-
-
-#import "PropertyFileReader.h"
-#import "utils.h"
-
-
-@implementation PropertyFileReader {
-}
-
-+ (void)parseProperty:(NSString *)string to:(NSMutableDictionary *)to {
-    NSRange delimiter = [string rangeOfString:@"="];
-    if (delimiter.length > 0 && delimiter.location + 1 <= string.length) {
-        NSString *key = [string substringToIndex:delimiter.location];
-        NSString *value=[string substringFromIndex:delimiter.location + 1];
-        [to setObject:value forKey:key];
-    }
-}
-
-+ (NSDictionary *)readFile:(NSString *)path {
-    NSMutableDictionary *answer = [NSMutableDictionary dictionary];
-
-    NSString *contents = readFile(path);
-
-    if (contents) {
-        NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
-        for (NSString *line in lines) {
-            NSString *trimmedLine = trim(line);
-            if ([trimmedLine length] > 0) {
-                if ([trimmedLine characterAtIndex:0] != '#') {
-                    [self parseProperty:trimmedLine to:answer];
-                }
-            }
-        }
-
-        return answer;
-    }
-
-    return nil;
-}
-
-@end
\ No newline at end of file
index 681cb46ae6aa578c0170d0e219c17eb5c9b3859d..c9457e292365df800be6f1caeee891fc4d37c9eb 100644 (file)
@@ -19,8 +19,8 @@
 
 typedef JNIIMPORT jint(JNICALL *JNI_createJavaVM)(JavaVM **pvm, JNIEnv **env, void *args);
 
-HINSTANCE hInst;                                                               // current instance
-char jvmPath[_MAX_PATH];
+HINSTANCE hInst; // Current instance.
+char jvmPath[_MAX_PATH] = "";
 JavaVMOption* vmOptions = NULL;
 int vmOptionCount = 0;
 bool bServerJVM = false;
@@ -37,617 +37,702 @@ const int FILE_MAPPING_SIZE = 16000;
 
 #ifdef _M_X64
 bool need64BitJRE = true;
+#define BITS_STR "64-bit"
 #else
 bool need64BitJRE = false;
+#define BITS_STR "32-bit"
 #endif
 
+std::string EncodeWideACP(const std::wstring &str)
+{
+  int cbANSI = WideCharToMultiByte(CP_ACP, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
+  char* ansiBuf = new char[cbANSI];
+  WideCharToMultiByte(CP_ACP, 0, str.c_str(), str.size(), ansiBuf, cbANSI, NULL, NULL);
+  std::string result(ansiBuf, cbANSI);
+  delete[] ansiBuf;
+  return result;
+}
+
 std::string LoadStdString(int id)
 {
-       wchar_t *buf = NULL;
-       int len = LoadStringW(hInst, id, reinterpret_cast<LPWSTR>(&buf), 0);
-       if (len)
-       {
-               int cbANSI = WideCharToMultiByte(CP_ACP, 0, buf, len, NULL, 0, NULL, NULL);
-               char* ansiBuf = new char[cbANSI];
-               WideCharToMultiByte(CP_ACP, 0, buf, len, ansiBuf, cbANSI, NULL, NULL);
-               std::string result(ansiBuf, cbANSI);
-               delete[] ansiBuf;
-               return result;
-       }
-       return std::string();
+  wchar_t *buf = NULL;
+  int len = LoadStringW(hInst, id, reinterpret_cast<LPWSTR>(&buf), 0);
+  return len ? EncodeWideACP(std::wstring(buf, len)) : "";
 }
 
 bool FileExists(const std::string& path)
 {
-       return GetFileAttributesA(path.c_str()) != INVALID_FILE_ATTRIBUTES;
+  return GetFileAttributesA(path.c_str()) != INVALID_FILE_ATTRIBUTES;
 }
 
 bool IsValidJRE(const char* path)
 {
-       std::string dllPath(path);
-       if (dllPath[dllPath.size() - 1] != '\\')
-       {
-               dllPath += "\\";
-       }
-       return FileExists(dllPath + "bin\\server\\jvm.dll") || FileExists(dllPath + "bin\\client\\jvm.dll");
+  std::string dllPath(path);
+  if (dllPath[dllPath.size() - 1] != '\\')
+  {
+    dllPath += "\\";
+  }
+  return FileExists(dllPath + "bin\\server\\jvm.dll") || FileExists(dllPath + "bin\\client\\jvm.dll");
 }
 
 bool Is64BitJRE(const char* path)
 {
-       std::string cfgPath(path);
-       cfgPath += "\\lib\\amd64\\jvm.cfg";
-       return FileExists(cfgPath);
+  std::string cfgPath(path);
+  cfgPath += "\\lib\\amd64\\jvm.cfg";
+  return FileExists(cfgPath);
 }
 
 bool FindValidJVM(const char* path)
 {
-       if (IsValidJRE(path))
-       {
-               strcpy_s(jvmPath, _MAX_PATH - 1, path);
-               return true;
-       }
-       char jrePath[_MAX_PATH];
-       strcpy_s(jrePath, path);
-       if (jrePath[strlen(jrePath) - 1] != '\\')
-       {
-               strcat_s(jrePath, "\\");
-       }
-       strcat_s(jrePath, _MAX_PATH - 1, "jre");
-       if (IsValidJRE(jrePath))
-       {
-               strcpy_s(jvmPath, jrePath);
-               return true;
-       }
-       return false;
+  if (IsValidJRE(path))
+  {
+    strcpy_s(jvmPath, _MAX_PATH - 1, path);
+    return true;
+  }
+  char jrePath[_MAX_PATH];
+  strcpy_s(jrePath, path);
+  if (jrePath[strlen(jrePath) - 1] != '\\')
+  {
+    strcat_s(jrePath, "\\");
+  }
+  strcat_s(jrePath, _MAX_PATH - 1, "jre");
+  if (IsValidJRE(jrePath))
+  {
+    strcpy_s(jvmPath, jrePath);
+    return true;
+  }
+  return false;
 }
 
 std::string GetAdjacentDir(const char* suffix)
 {
-       char libDir[_MAX_PATH];
-       GetModuleFileNameA(NULL, libDir, _MAX_PATH - 1);
-       char* lastSlash = strrchr(libDir, '\\');
-       if (!lastSlash) return "";
-       *lastSlash = '\0';
-       lastSlash = strrchr(libDir, '\\');
-       if (!lastSlash) return "";
-       strcpy(lastSlash + 1, suffix);
-       strcat_s(libDir, "\\");
-       return std::string(libDir);
+  char libDir[_MAX_PATH];
+  GetModuleFileNameA(NULL, libDir, _MAX_PATH - 1);
+  char* lastSlash = strrchr(libDir, '\\');
+  if (!lastSlash) return "";
+  *lastSlash = '\0';
+  lastSlash = strrchr(libDir, '\\');
+  if (!lastSlash) return "";
+  strcpy(lastSlash + 1, suffix);
+  strcat_s(libDir, "\\");
+  return std::string(libDir);
 }
 
 bool FindJVMInEnvVar(const char* envVarName, bool& result)
 {
-       char envVarValue[_MAX_PATH];
-       if (GetEnvironmentVariableA(envVarName, envVarValue, _MAX_PATH - 1))
-       {
-               if (FindValidJVM(envVarValue))
-               {
-                       if (Is64BitJRE(jvmPath) != need64BitJRE) return false;
-                       result = true;
-               }
-               else
-               {
-                       char buf[_MAX_PATH];
-                       sprintf_s(buf, "The environment variable %s (with the value of %s) does not point to a valid JVM installation.",
-                               envVarName, envVarValue);
-                       MessageBoxA(NULL, buf, "Error Launching IntelliJ Platform", MB_OK);
-                       result = false;
-               }
-               return true;
-       }
-       return false;
+  char envVarValue[_MAX_PATH];
+  if (GetEnvironmentVariableA(envVarName, envVarValue, _MAX_PATH - 1))
+  {
+    if (FindValidJVM(envVarValue))
+    {
+      if (Is64BitJRE(jvmPath) != need64BitJRE) return false;
+      result = true;
+    }
+    else
+    {
+      char buf[_MAX_PATH];
+      sprintf_s(buf, "The environment variable %s (with the value of %s) does not point to a valid JVM installation.",
+        envVarName, envVarValue);
+      std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+      MessageBoxA(NULL, buf, error.c_str(), MB_OK);
+      result = false;
+    }
+    return true;
+  }
+  return false;
 }
 
 bool FindJVMInRegistryKey(const char* key, bool wow64_32)
 {
-       HKEY hKey;
-       int flags = KEY_READ;
-       if (wow64_32) flags |= KEY_WOW64_32KEY;
-       if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) != ERROR_SUCCESS) return false;
-       char javaHome[_MAX_PATH];
-       DWORD javaHomeSize = _MAX_PATH - 1;
-       bool success = false;
-       if (RegQueryValueExA(hKey, "JavaHome", NULL, NULL, (LPBYTE)javaHome, &javaHomeSize) == ERROR_SUCCESS)
-       {
-               success = FindValidJVM(javaHome);
-       }
-       RegCloseKey(hKey);
-       return success;
+  HKEY hKey;
+  int flags = KEY_READ;
+  if (wow64_32) flags |= KEY_WOW64_32KEY;
+  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) != ERROR_SUCCESS) return false;
+  char javaHome[_MAX_PATH];
+  DWORD javaHomeSize = _MAX_PATH - 1;
+  bool success = false;
+  if (RegQueryValueExA(hKey, "JavaHome", NULL, NULL, (LPBYTE)javaHome, &javaHomeSize) == ERROR_SUCCESS)
+  {
+    success = FindValidJVM(javaHome);
+  }
+  RegCloseKey(hKey);
+  return success;
 }
 
 bool FindJVMInRegistryWithVersion(const char* version, bool wow64_32)
 {
-       const char* keyName = LoadStdString(IDS_JDK_ONLY) == std::string("true")
-               ? "Java Development Kit"
-               : "Java Runtime Environment";
+  const char* keyName = LoadStdString(IDS_JDK_ONLY) == std::string("true")
+    ? "Java Development Kit"
+    : "Java Runtime Environment";
 
-       char buf[_MAX_PATH];
-       sprintf_s(buf, "Software\\JavaSoft\\%s\\%s", keyName, version);
-       return FindJVMInRegistryKey(buf, wow64_32);
+  char buf[_MAX_PATH];
+  sprintf_s(buf, "Software\\JavaSoft\\%s\\%s", keyName, version);
+  return FindJVMInRegistryKey(buf, wow64_32);
 }
 
 bool FindJVMInRegistry()
 {
 #ifndef _M_X64
-        if (FindJVMInRegistryWithVersion("1.8", true))
-               return true;
-       if (FindJVMInRegistryWithVersion("1.7", true))
-               return true;
-       if (FindJVMInRegistryWithVersion("1.6", true))
-               return true;
+  if (FindJVMInRegistryWithVersion("1.8", true))
+    return true;
+  if (FindJVMInRegistryWithVersion("1.7", true))
+    return true;
+  if (FindJVMInRegistryWithVersion("1.6", true))
+    return true;
 #endif
 
-        if (FindJVMInRegistryWithVersion("1.8", false))
-                return true;
-       if (FindJVMInRegistryWithVersion("1.7", false))
-               return true;
-       if (FindJVMInRegistryWithVersion("1.6", false))
-               return true;
-       return false;
+  if (FindJVMInRegistryWithVersion("1.8", false))
+    return true;
+  if (FindJVMInRegistryWithVersion("1.7", false))
+    return true;
+  if (FindJVMInRegistryWithVersion("1.6", false))
+    return true;
+  return false;
 }
 
-bool LocateJVM()
-{
-       bool result;
-       if (FindJVMInEnvVar(LoadStdString(IDS_JDK_ENV_VAR).c_str(), result))
-       {
-               return result;
-       }
+// The following code is taken from http://msdn.microsoft.com/en-us/library/ms684139(v=vs.85).aspx
+// and provides a backwards compatible way to check if this application is a 32-bit process running
+// on a 64-bit OS
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+LPFN_ISWOW64PROCESS fnIsWow64Process;
 
+BOOL IsWow64()
+{
+  BOOL bIsWow64 = FALSE;
 
-        std::vector<std::string> jrePaths;
-        if(need64BitJRE) jrePaths.push_back(GetAdjacentDir("jre64"));
-        jrePaths.push_back(GetAdjacentDir("jre"));
-        for(std::vector<std::string>::iterator it = jrePaths.begin(); it != jrePaths.end(); ++it) {
-          if (FindValidJVM((*it).c_str()) && Is64BitJRE(jvmPath) == need64BitJRE)
-          {
-                  return true;
-          }
-        }
+  //IsWow64Process is not available on all supported versions of Windows.
+  //Use GetModuleHandle to get a handle to the DLL that contains the function
+  //and GetProcAddress to get a pointer to the function if available.
 
-       if (FindJVMInRegistry())
-       {
-               return true;
-       }
+  fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
+      GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
 
-       if (FindJVMInEnvVar("JAVA_HOME", result))
-       {
-               return result;
-       }
+  if (NULL != fnIsWow64Process)
+  {
+    fnIsWow64Process(GetCurrentProcess(), &bIsWow64);
+  }
+  return bIsWow64;
+}
 
-       MessageBoxA(NULL, "No JVM installation found. Please reinstall the product or install a JDK.", "Error Launching IntelliJ Platform", MB_OK);
-       return false;
+bool LocateJVM()
+{
+  bool result;
+  if (FindJVMInEnvVar(LoadStdString(IDS_JDK_ENV_VAR).c_str(), result))
+  {
+    return result;
+  }
+
+  std::vector<std::string> jrePaths;
+  if(need64BitJRE) jrePaths.push_back(GetAdjacentDir("jre64"));
+  jrePaths.push_back(GetAdjacentDir("jre"));
+  for(std::vector<std::string>::iterator it = jrePaths.begin(); it != jrePaths.end(); ++it) {
+    if (FindValidJVM((*it).c_str()) && Is64BitJRE(jvmPath) == need64BitJRE)
+    {
+      return true;
+    }
+  }
+
+  if (FindJVMInRegistry())
+  {
+    return true;
+  }
+
+  if (FindJVMInEnvVar("JAVA_HOME", result))
+  {
+    return result;
+  }
+
+  std::string jvmError;
+  jvmError = "No JVM installation found. Please install a " BITS_STR " JDK.\n"
+    "If you already have a JDK installed, define a JAVA_HOME variable in\n"
+    "Computer > System Properties > System Settings > Environment Variables.";
+
+  if (IsWow64())
+  {
+    // If WoW64, this means we are running a 32-bit program on 64-bit Windows. This may explain
+    // why we couldn't locate the JVM.
+    jvmError += "\n\nNOTE: We have detected that you are running a 64-bit version of the "
+        "Windows operating system but are running the 32-bit executable. This "
+        "can prevent you from finding a 64-bit installation of Java. Consider running "
+        "the 64-bit version instead, if this is the problem you're encountering.";
+  }
+
+  std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+  MessageBoxA(NULL, jvmError.c_str(),  error.c_str(), MB_OK);
+  return false;
 }
 
 void TrimLine(char* line)
 {
-       char *p = line + strlen(line) - 1;
-       if (p >= line && *p == '\n')
-       {
-               *p-- = '\0';
-       }
-       while (p >= line && (*p == ' ' || *p == '\t'))
-       {
-               *p-- = '\0';
-       }
+  char *p = line + strlen(line) - 1;
+  if (p >= line && *p == '\n')
+  {
+    *p-- = '\0';
+  }
+  while (p >= line && (*p == ' ' || *p == '\t'))
+  {
+    *p-- = '\0';
+  }
 }
 
 bool LoadVMOptionsFile(const TCHAR* path, std::vector<std::string>& vmOptionLines)
 {
-       FILE *f = _tfopen(path, _T("rt"));
-       if (!f) return false;
+  FILE *f = _tfopen(path, _T("rt"));
+  if (!f) return false;
 
-       char line[_MAX_PATH];
-       while (fgets(line, _MAX_PATH - 1, f))
-       {
-               TrimLine(line);
-               if (line[0] == '#') continue;
-               if (strcmp(line, "-server") == 0)
-               {
-                       bServerJVM = true;
-               }
-               else if (strlen(line) > 0)
-               {
-                       vmOptionLines.push_back(line);
-               }
-       }
-       fclose(f);
+  char line[_MAX_PATH];
+  while (fgets(line, _MAX_PATH, f))
+  {
+    TrimLine(line);
+    if (line[0] == '#') continue;
+    if (strcmp(line, "-server") == 0)
+    {
+      bServerJVM = true;
+    }
+    else if (strlen(line) > 0)
+    {
+      vmOptionLines.push_back(line);
+    }
+  }
+  fclose(f);
 
-       return true;
+  return true;
 }
 
 std::string FindToolsJar()
 {
-       std::string toolsJarPath = jvmPath;
-       size_t lastSlash = toolsJarPath.rfind('\\');
-       if (lastSlash != std::string::npos)
-       {
-               toolsJarPath = toolsJarPath.substr(0, lastSlash + 1) + "lib\\tools.jar";
-               if (FileExists(toolsJarPath))
-               {
-                       return toolsJarPath;
-               }
-       }
-       return "";
+  std::string toolsJarPath = jvmPath;
+  size_t lastSlash = toolsJarPath.rfind('\\');
+  if (lastSlash != std::string::npos)
+  {
+    toolsJarPath = toolsJarPath.substr(0, lastSlash + 1) + "lib\\tools.jar";
+    if (FileExists(toolsJarPath))
+    {
+      return toolsJarPath;
+    }
+  }
+  return "";
 }
 
 std::string CollectLibJars(const std::string& jarList)
 {
-       std::string libDir = GetAdjacentDir("lib");
-       if (libDir.size() == 0 || !FileExists(libDir))
-       {
-               return "";
-       }
-
-       std::string result;
-       int pos = 0;
-       while (pos < jarList.size())
-       {
-               int delimiterPos = jarList.find(';', pos);
-               if (delimiterPos == std::string::npos)
-               {
-                       delimiterPos = jarList.size();
-               }
-               if (result.size() > 0)
-               {
-                       result += ";";
-               }
-               result += libDir;
-               result += jarList.substr(pos, delimiterPos - pos);
-               pos = delimiterPos + 1;
-       }
-       return result;
+  std::string libDir = GetAdjacentDir("lib");
+  if (libDir.size() == 0 || !FileExists(libDir))
+  {
+    return "";
+  }
+
+  std::string result;
+  int pos = 0;
+  while (pos < jarList.size())
+  {
+    int delimiterPos = jarList.find(';', pos);
+    if (delimiterPos == std::string::npos)
+    {
+      delimiterPos = jarList.size();
+    }
+    if (result.size() > 0)
+    {
+      result += ";";
+    }
+    result += libDir;
+    result += jarList.substr(pos, delimiterPos - pos);
+    pos = delimiterPos + 1;
+  }
+  return result;
 }
 
 std::string BuildClassPath()
 {
-       std::string classpathLibs = LoadStdString(IDS_CLASSPATH_LIBS);
-       std::string result = CollectLibJars(classpathLibs);
+  std::string classpathLibs = LoadStdString(IDS_CLASSPATH_LIBS);
+  std::string result = CollectLibJars(classpathLibs);
 
-       std::string toolsJar = FindToolsJar();
-       if (toolsJar.size() > 0)
-       {
-               result += ";";
-               result += toolsJar;
-       }
+  std::string toolsJar = FindToolsJar();
+  if (toolsJar.size() > 0)
+  {
+    result += ";";
+    result += toolsJar;
+  }
 
-       return result;
+  return result;
 }
 
 bool AddClassPathOptions(std::vector<std::string>& vmOptionLines)
 {
-       std::string classPath = BuildClassPath();
-       if (classPath.size() == 0) return false;
-       vmOptionLines.push_back(std::string("-Djava.class.path=") + classPath);
+  std::string classPath = BuildClassPath();
+  if (classPath.size() == 0) return false;
+  vmOptionLines.push_back(std::string("-Djava.class.path=") + classPath);
 
-       std::string bootClassPathLibs = LoadStdString(IDS_BOOTCLASSPATH_LIBS);
-       std::string bootClassPath = CollectLibJars(bootClassPathLibs);
-       if (bootClassPath.size() > 0)
-       {
-               vmOptionLines.push_back(std::string("-Xbootclasspath/a:") + bootClassPath);
-       }
+  std::string bootClassPathLibs = LoadStdString(IDS_BOOTCLASSPATH_LIBS);
+  std::string bootClassPath = CollectLibJars(bootClassPathLibs);
+  if (bootClassPath.size() > 0)
+  {
+    vmOptionLines.push_back(std::string("-Xbootclasspath/a:") + bootClassPath);
+  }
 
-       return true;
+  return true;
 }
 
 void AddPredefinedVMOptions(std::vector<std::string>& vmOptionLines)
 {
-       std::string vmOptions = LoadStdString(IDS_VM_OPTIONS);
-       while (vmOptions.size() > 0)
-       {
-               int pos = vmOptions.find(' ');
-               if (pos == std::string::npos) pos = vmOptions.size();
-               vmOptionLines.push_back(vmOptions.substr(0, pos));
-               while (pos < vmOptions.size() && vmOptions[pos] == ' ') pos++;
-               vmOptions = vmOptions.substr(pos);
-       }
+  std::string vmOptions = LoadStdString(IDS_VM_OPTIONS);
+  while (vmOptions.size() > 0)
+  {
+    int pos = vmOptions.find(' ');
+    if (pos == std::string::npos) pos = vmOptions.size();
+    vmOptionLines.push_back(vmOptions.substr(0, pos));
+    while (pos < vmOptions.size() && vmOptions[pos] == ' ') pos++;
+    vmOptions = vmOptions.substr(pos);
+  }
 
-       char ideaProperties[_MAX_PATH];
-       if (GetEnvironmentVariableA("IDEA_PROPERTIES", ideaProperties, _MAX_PATH - 1))
-       {
-               vmOptionLines.push_back(std::string("-Didea.properties.file=") + ideaProperties);
-       }
+  char propertiesFile[_MAX_PATH];
+  if (GetEnvironmentVariableA(LoadStdString(IDS_PROPS_ENV_VAR).c_str(), propertiesFile, _MAX_PATH))
+  {
+    vmOptionLines.push_back(std::string("-Didea.properties.file=") + propertiesFile);
+  }
 }
 
 bool LoadVMOptions()
 {
-       TCHAR optionsFileName[_MAX_PATH];
-       if (LoadString(hInst, IDS_VM_OPTIONS_PATH, optionsFileName, _MAX_PATH - 1))
-       {
-               TCHAR fullOptionsFileName[_MAX_PATH];
-               ExpandEnvironmentStrings(optionsFileName, fullOptionsFileName, _MAX_PATH - 1);
-
-               if (GetFileAttributes(fullOptionsFileName) == INVALID_FILE_ATTRIBUTES)
-               {
-                       GetModuleFileName(NULL, fullOptionsFileName, _MAX_PATH - 1);
-                       _tcscat_s(fullOptionsFileName, _T(".vmoptions"));
-               }
-
-               std::vector<std::string> vmOptionLines;
-               if (LoadVMOptionsFile(fullOptionsFileName, vmOptionLines))
-               {
-                       if (!AddClassPathOptions(vmOptionLines)) return false;
-                       AddPredefinedVMOptions(vmOptionLines);
-
-                       vmOptionCount = vmOptionLines.size();
-                       vmOptions = (JavaVMOption*)malloc(vmOptionCount * sizeof(JavaVMOption));
-                       for (int i = 0; i < vmOptionLines.size(); i++)
-                       {
-                               vmOptions[i].optionString = _strdup(vmOptionLines[i].c_str());
-                               vmOptions[i].extraInfo = 0;
-                       }
-
-                       return true;
-               }
-       }
-       MessageBox(NULL, _T("Cannot find VM options file"), _T("Error launching IntelliJ Platform"), MB_OK);
-       return false;
+  TCHAR buffer[_MAX_PATH];
+  TCHAR copy[_MAX_PATH];
+
+  std::vector<std::wstring> files;
+
+  GetModuleFileName(NULL, buffer, _MAX_PATH);
+  std::wstring module(buffer);
+
+  files.push_back(module + L".vmoptions");
+
+
+  if (LoadString(hInst, IDS_VM_OPTIONS_PATH, buffer, _MAX_PATH))
+  {
+    ExpandEnvironmentStrings(buffer, copy, _MAX_PATH - 1);
+    std::wstring selector(copy);
+    files.push_back(selector + module.substr(module.find_last_of('\\')) + L".vmoptions");
+  }
+
+  if (LoadString(hInst, IDS_VM_OPTIONS_ENV_VAR, buffer, _MAX_PATH))
+  {
+    if (GetEnvironmentVariableW(buffer, copy, _MAX_PATH)) {
+    ExpandEnvironmentStrings(copy, buffer, _MAX_PATH);
+    files.push_back(std::wstring(buffer));
+    }
+  }
+
+  if (files.size() == 0) {
+    std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+    MessageBoxA(NULL, "Cannot find VM options file", error.c_str(), MB_OK);
+    return false;
+  }
+
+  std::wstring used;
+  std::vector<std::string> vmOptionLines;
+  for (int i = 0; i < files.size(); i++)
+  {
+    if (GetFileAttributes(files[i].c_str()) != INVALID_FILE_ATTRIBUTES)
+    {
+      if (LoadVMOptionsFile(files[i].c_str(), vmOptionLines))
+      {
+        used += (used.size() ? L"," : L"") + files[i];
+      }
+    }
+  }
+
+  vmOptionLines.push_back(std::string("-Djb.vmOptions=") + EncodeWideACP(used));
+
+  if (!AddClassPathOptions(vmOptionLines)) return false;
+  AddPredefinedVMOptions(vmOptionLines);
+
+  vmOptionCount = vmOptionLines.size();
+  vmOptions = (JavaVMOption*)malloc(vmOptionCount * sizeof(JavaVMOption));
+  for (int i = 0; i < vmOptionLines.size(); i++)
+  {
+    vmOptions[i].optionString = _strdup(vmOptionLines[i].c_str());
+    vmOptions[i].extraInfo = 0;
+  }
+
+  return true;
 }
 
 bool LoadJVMLibrary()
 {
-       std::string dllName(jvmPath);
-       std::string binDir = dllName + "\\bin";
-       std::string serverDllName = binDir + "\\server\\jvm.dll";
-       std::string clientDllName = binDir + "\\client\\jvm.dll";
-       if ((bServerJVM && FileExists(serverDllName)) || !FileExists(clientDllName))
-       {
-               dllName = serverDllName;
-       }
-       else
-       {
-               dllName = clientDllName;
-       }
-
-       SetCurrentDirectoryA(binDir.c_str());   // ensure that we can find msvcr100.dll which is located in jre/bin directory
-       hJVM = LoadLibraryA(dllName.c_str());
-       if (hJVM)
-       {
-               pCreateJavaVM = (JNI_createJavaVM)GetProcAddress(hJVM, "JNI_CreateJavaVM");
-       }
-       if (!pCreateJavaVM)
-       {
-               char buf[_MAX_PATH];
-               sprintf(buf, "Failed to load JVM DLL %s", dllName.c_str());
-               MessageBoxA(NULL, buf, "Error Launching IntelliJ Platform", MB_OK);
-               return false;
-       }
-       return true;
+  std::string dllName(jvmPath);
+  std::string binDir = dllName + "\\bin";
+  std::string serverDllName = binDir + "\\server\\jvm.dll";
+  std::string clientDllName = binDir + "\\client\\jvm.dll";
+  if ((bServerJVM && FileExists(serverDllName)) || !FileExists(clientDllName))
+  {
+    dllName = serverDllName;
+  }
+  else
+  {
+    dllName = clientDllName;
+  }
+
+  // ensure we can find msvcr100.dll which is located in jre/bin directory; jvm.dll depends on it.
+  SetCurrentDirectoryA(binDir.c_str());
+  hJVM = LoadLibraryA(dllName.c_str());
+  if (hJVM)
+  {
+    pCreateJavaVM = (JNI_createJavaVM) GetProcAddress(hJVM, "JNI_CreateJavaVM");
+  }
+  if (!pCreateJavaVM)
+  {
+    std::string jvmError = "Failed to load JVM DLL ";
+    jvmError += dllName.c_str();
+    jvmError += "\n"
+        "If you already have a " BITS_STR " JDK installed, define a JAVA_HOME variable in "
+        "Computer > System Properties > System Settings > Environment Variables.";
+    std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+    MessageBoxA(NULL, jvmError.c_str(), error.c_str(), MB_OK);
+    return false;
+  }
+  return true;
 }
 
 bool CreateJVM()
 {
-       JavaVMInitArgs initArgs;
-       initArgs.version = JNI_VERSION_1_2;
-       initArgs.options = vmOptions;
-       initArgs.nOptions = vmOptionCount;
-       initArgs.ignoreUnrecognized = JNI_FALSE;
+  JavaVMInitArgs initArgs;
+  initArgs.version = JNI_VERSION_1_2;
+  initArgs.options = vmOptions;
+  initArgs.nOptions = vmOptionCount;
+  initArgs.ignoreUnrecognized = JNI_FALSE;
+
+  int result = pCreateJavaVM(&jvm, &env, &initArgs);
 
-       int result = pCreateJavaVM(&jvm, &env, &initArgs);
+  for (int i = 0; i < vmOptionCount; i++)
+  {
+    free(vmOptions[i].optionString);
+  }
+  free(vmOptions);
+  vmOptions = NULL;
 
-       for (int i = 0; i < vmOptionCount; i++)
-       {
-               free(vmOptions[i].optionString);
-       }
-       free(vmOptions);
-       vmOptions = NULL;
+  if (result != JNI_OK)
+  {
+    std::stringstream buf;
 
-       if (result != JNI_OK)
-       {
-               TCHAR buf[_MAX_PATH];
-               _stprintf_s(buf, _T("Failed to create JVM: error code %d"), result);
-               MessageBox(NULL, buf, _T("Error launching IntelliJ Platform"), MB_OK);
-       }
+    buf << "Failed to create JVM: error code " << result << ".\n";
+    buf << "JVM Path: " << jvmPath << "\n";
+    buf << "If you already have a " BITS_STR " JDK installed, define a JAVA_HOME variable in ";
+        "Computer > System Properties > System Settings > Environment Variables.";
+    std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+    MessageBoxA(NULL, buf.str().c_str(), error.c_str(), MB_OK);
+  }
 
-       return result == JNI_OK;
+  return result == JNI_OK;
 }
 
 jobjectArray PrepareCommandLine()
 {
-       int numArgs;
-       LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &numArgs);
-       jclass stringClass = env->FindClass("java/lang/String");
-       jobjectArray args = env->NewObjectArray(numArgs - 1, stringClass, NULL);
-       for (int i = 1; i < numArgs; i++)
-       {
-               const wchar_t* arg = argv[i];
-               env->SetObjectArrayElement(args, i - 1, env->NewString((const jchar *)arg, wcslen(argv[i])));
-       }
-       return args;
+  int numArgs;
+  LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &numArgs);
+  jclass stringClass = env->FindClass("java/lang/String");
+  jobjectArray args = env->NewObjectArray(numArgs - 1, stringClass, NULL);
+  for (int i = 1; i < numArgs; i++)
+  {
+    const wchar_t* arg = argv[i];
+    env->SetObjectArrayElement(args, i - 1, env->NewString((const jchar *)arg, wcslen(argv[i])));
+  }
+  return args;
 }
 
 bool RunMainClass()
 {
-       std::string mainClassName = LoadStdString(IDS_MAIN_CLASS);
-       jclass mainClass = env->FindClass(mainClassName.c_str());
-       if (!mainClass)
-       {
-               char buf[_MAX_PATH];
-               sprintf_s(buf, "Could not find main class %s", mainClassName.c_str());
-               MessageBoxA(NULL, buf, "Error Launching IntelliJ Platform", MB_OK);
-               return false;
-       }
-
-       jmethodID mainMethod = env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
-       if (!mainMethod)
-       {
-               MessageBoxA(NULL, "Could not find main method", "Error Launching IntelliJ Platform", MB_OK);
-               return false;
-       }
-
-       jobjectArray args = PrepareCommandLine();
-       env->CallStaticVoidMethod(mainClass, mainMethod, args);
-       jthrowable exc = env->ExceptionOccurred();
-       if (exc)
-       {
-               MessageBox(NULL, _T("Error invoking main method"), _T("Error launching IntelliJ Platform"), MB_OK);
-       }
-
-       return true;
+  std::string mainClassName = LoadStdString(IDS_MAIN_CLASS);
+  jclass mainClass = env->FindClass(mainClassName.c_str());
+  if (!mainClass)
+  {
+    char buf[_MAX_PATH + 256];
+    sprintf_s(buf, "Could not find main class %s", mainClassName.c_str());
+    std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+    MessageBoxA(NULL, buf, error.c_str(), MB_OK);
+    return false;
+  }
+
+  jmethodID mainMethod = env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
+  if (!mainMethod)
+  {
+    std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+    MessageBoxA(NULL, "Could not find main method", error.c_str(), MB_OK);
+    return false;
+  }
+
+  jobjectArray args = PrepareCommandLine();
+  env->CallStaticVoidMethod(mainClass, mainMethod, args);
+  jthrowable exc = env->ExceptionOccurred();
+  if (exc)
+  {
+    std::string error = LoadStdString(IDS_ERROR_LAUNCHING_APP);
+    MessageBoxA(NULL, "Error invoking main method", error.c_str(), MB_OK);
+  }
+
+  return true;
 }
 
 void CallCommandLineProcessor(const std::wstring& curDir, const std::wstring& args)
 {
-       JNIEnv *env;
-       JavaVMAttachArgs attachArgs;
-       attachArgs.version = JNI_VERSION_1_2;
-       attachArgs.name = "WinLauncher external command processing thread";
-       attachArgs.group = NULL;
-       jvm->AttachCurrentThread((void**)&env, &attachArgs);
-
-       std::string processorClassName = LoadStdString(IDS_COMMAND_LINE_PROCESSOR_CLASS);
-       jclass processorClass = env->FindClass(processorClassName.c_str());
-       if (processorClass)
-       {
-               jmethodID processMethodID = env->GetStaticMethodID(processorClass, "processWindowsLauncherCommandLine", "(Ljava/lang/String;Ljava/lang/String;)V");
-               if (processMethodID)
-               {
-                       jstring jCurDir = env->NewString((const jchar *)curDir.c_str(), curDir.size());
-                       jstring jArgs = env->NewString((const jchar *)args.c_str(), args.size());
-                       env->CallStaticVoidMethod(processorClass, processMethodID, jCurDir, jArgs);
-                       jthrowable exc = env->ExceptionOccurred();
-                       if (exc)
-                       {
-                               MessageBox(NULL, _T("Error sending command line to existing instance"), _T("Error"), MB_OK);
-                       }
-               }
-       }
-
-       jvm->DetachCurrentThread();
+  JNIEnv *env;
+  JavaVMAttachArgs attachArgs;
+  attachArgs.version = JNI_VERSION_1_2;
+  attachArgs.name = "WinLauncher external command processing thread";
+  attachArgs.group = NULL;
+  jvm->AttachCurrentThread((void**)&env, &attachArgs);
+
+  std::string processorClassName = LoadStdString(IDS_COMMAND_LINE_PROCESSOR_CLASS);
+  jclass processorClass = env->FindClass(processorClassName.c_str());
+  if (processorClass)
+  {
+    jmethodID processMethodID = env->GetStaticMethodID(processorClass, "processWindowsLauncherCommandLine", "(Ljava/lang/String;Ljava/lang/String;)V");
+    if (processMethodID)
+    {
+      jstring jCurDir = env->NewString((const jchar *)curDir.c_str(), curDir.size());
+      jstring jArgs = env->NewString((const jchar *)args.c_str(), args.size());
+      env->CallStaticVoidMethod(processorClass, processMethodID, jCurDir, jArgs);
+      jthrowable exc = env->ExceptionOccurred();
+      if (exc)
+      {
+        MessageBox(NULL, _T("Error sending command line to existing instance"), _T("Error"), MB_OK);
+      }
+    }
+  }
+
+  jvm->DetachCurrentThread();
 }
 
 DWORD WINAPI SingleInstanceThread(LPVOID args)
 {
-       while (true)
-       {
-               WaitForSingleObject(hEvent, INFINITE);
-               if (terminating) break;
+  while (true)
+  {
+    WaitForSingleObject(hEvent, INFINITE);
+    if (terminating) break;
 
-               wchar_t *view = static_cast<wchar_t *>(MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
-               if (!view) continue;
-               std::wstring command(view);
-               int pos = command.find('\n');
-               if (pos >= 0)
-               {
-                       std::wstring curDir = command.substr(0, pos);
-                       std::wstring args = command.substr(pos + 1);
+    wchar_t *view = static_cast<wchar_t *>(MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
+    if (!view) continue;
+    std::wstring command(view);
+    int pos = command.find('\n');
+    if (pos >= 0)
+    {
+      std::wstring curDir = command.substr(0, pos);
+      std::wstring args = command.substr(pos + 1);
 
-                       CallCommandLineProcessor(curDir, args);
-               }
+      CallCommandLineProcessor(curDir, args);
+    }
 
-               UnmapViewOfFile(view);
-       }
-       return 0;
+    UnmapViewOfFile(view);
+  }
+  return 0;
 }
 
 void SendCommandLineToFirstInstance()
 {
-       wchar_t curDir[_MAX_PATH];
-       GetCurrentDirectoryW(_MAX_PATH - 1, curDir);
-       std::wstring command(curDir);
-       command += _T("\n");
-       command += GetCommandLineW();
+  wchar_t curDir[_MAX_PATH];
+  GetCurrentDirectoryW(_MAX_PATH - 1, curDir);
+  std::wstring command(curDir);
+  command += _T("\n");
+  command += GetCommandLineW();
 
-       void *view = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
-       if (view)
-       {
-               memcpy(view, command.c_str(), (command.size() + 1) * sizeof(wchar_t));
-               UnmapViewOfFile(view);
-       }
-       SetEvent(hEvent);
+  void *view = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+  if (view)
+  {
+    memcpy(view, command.c_str(), (command.size() + 1) * sizeof(wchar_t));
+    UnmapViewOfFile(view);
+  }
+  SetEvent(hEvent);
 }
 
 bool CheckSingleInstance()
 {
-       char moduleFileName[_MAX_PATH];
-       GetModuleFileNameA(NULL, moduleFileName, _MAX_PATH - 1);
-       for (char *p = moduleFileName; *p; p++)
-       {
-               if (*p == ':' || *p == '\\') *p = '_';
-       }
-       std::string mappingName = std::string("IntelliJLauncherMapping.") + moduleFileName;
-       std::string eventName = std::string("IntelliJLauncherEvent.") + moduleFileName;
-
-       hEvent = CreateEventA(NULL, FALSE, FALSE, eventName.c_str());
-
-       hFileMapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, mappingName.c_str());
-       if (!hFileMapping)
-       {
-               hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, FILE_MAPPING_SIZE,
-                       mappingName.c_str());
-               return true;
-       }
-       else
-       {
-               SendCommandLineToFirstInstance();
-               CloseHandle(hFileMapping);
-               CloseHandle(hEvent);
-               return false;
-       }
+  char moduleFileName[_MAX_PATH];
+  GetModuleFileNameA(NULL, moduleFileName, _MAX_PATH - 1);
+  for (char *p = moduleFileName; *p; p++)
+  {
+    if (*p == ':' || *p == '\\') *p = '_';
+  }
+  std::string mappingName = std::string("IntelliJLauncherMapping.") + moduleFileName;
+  std::string eventName = std::string("IntelliJLauncherEvent.") + moduleFileName;
+
+  hEvent = CreateEventA(NULL, FALSE, FALSE, eventName.c_str());
+
+  hFileMapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, mappingName.c_str());
+  if (!hFileMapping)
+  {
+    hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, FILE_MAPPING_SIZE,
+      mappingName.c_str());
+    return true;
+  }
+  else
+  {
+    SendCommandLineToFirstInstance();
+    CloseHandle(hFileMapping);
+    CloseHandle(hEvent);
+    return false;
+  }
 }
 
 void DrawSplashImage(HWND hWnd)
 {
-       HBITMAP hSplashBitmap = (HBITMAP)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-       PAINTSTRUCT ps;
-       HDC hDC = BeginPaint(hWnd, &ps);
-       HDC hMemDC = CreateCompatibleDC(hDC);
-       HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hSplashBitmap);
-       BITMAP splashBitmap;
-       GetObject(hSplashBitmap, sizeof(splashBitmap), &splashBitmap);
-       BitBlt(hDC, 0, 0, splashBitmap.bmWidth, splashBitmap.bmHeight, hMemDC, 0, 0, SRCCOPY);
-       SelectObject(hMemDC, hOldBmp);
-       DeleteDC(hMemDC);
-       EndPaint(hWnd, &ps);
+  HBITMAP hSplashBitmap = (HBITMAP)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+  PAINTSTRUCT ps;
+  HDC hDC = BeginPaint(hWnd, &ps);
+  HDC hMemDC = CreateCompatibleDC(hDC);
+  HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hSplashBitmap);
+  BITMAP splashBitmap;
+  GetObject(hSplashBitmap, sizeof(splashBitmap), &splashBitmap);
+  BitBlt(hDC, 0, 0, splashBitmap.bmWidth, splashBitmap.bmHeight, hMemDC, 0, 0, SRCCOPY);
+  SelectObject(hMemDC, hOldBmp);
+  DeleteDC(hMemDC);
+  EndPaint(hWnd, &ps);
 }
 
 LRESULT CALLBACK SplashScreenWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-       switch (uMsg)
-       {
-       case WM_PAINT:
-               DrawSplashImage(hWnd);
-               break;
-       }
-       return DefWindowProc(hWnd, uMsg, wParam, lParam);
+  switch (uMsg)
+  {
+  case WM_PAINT:
+    DrawSplashImage(hWnd);
+    break;
+  }
+  return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 
 const TCHAR splashClassName[] = _T("IntelliJLauncherSplash");
 
 void RegisterSplashScreenWndClass()
 {
-       WNDCLASSEX wcx;
-       wcx.cbSize = sizeof(wcx);
-       wcx.style = 0;
-       wcx.lpfnWndProc = SplashScreenWndProc;
-       wcx.cbClsExtra = 0;
-       wcx.cbWndExtra = 0;
-       wcx.hInstance = hInst;
-       wcx.hIcon = 0;
-       wcx.hCursor = LoadCursor(NULL, IDC_WAIT);
-       wcx.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
-       wcx.lpszMenuName = 0;
-       wcx.lpszClassName = splashClassName;
-       wcx.hIconSm = 0;
+  WNDCLASSEX wcx;
+  wcx.cbSize = sizeof(wcx);
+  wcx.style = 0;
+  wcx.lpfnWndProc = SplashScreenWndProc;
+  wcx.cbClsExtra = 0;
+  wcx.cbWndExtra = 0;
+  wcx.hInstance = hInst;
+  wcx.hIcon = 0;
+  wcx.hCursor = LoadCursor(NULL, IDC_WAIT);
+  wcx.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
+  wcx.lpszMenuName = 0;
+  wcx.lpszClassName = splashClassName;
+  wcx.hIconSm = 0;
 
-       RegisterClassEx(&wcx);
+  RegisterClassEx(&wcx);
 }
 
 HWND ShowSplashScreenWindow(HBITMAP hSplashBitmap)
 {
-       RECT workArea;
-       SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
-       BITMAP splashBitmap;
-       GetObject(hSplashBitmap, sizeof(splashBitmap), &splashBitmap);
-       int x = workArea.left + ((workArea.right - workArea.left) - splashBitmap.bmWidth) / 2;
-       int y = workArea.top + ((workArea.bottom - workArea.top) - splashBitmap.bmHeight) / 2;
+  RECT workArea;
+  SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
+  BITMAP splashBitmap;
+  GetObject(hSplashBitmap, sizeof(splashBitmap), &splashBitmap);
+  int x = workArea.left + ((workArea.right - workArea.left) - splashBitmap.bmWidth) / 2;
+  int y = workArea.top + ((workArea.bottom - workArea.top) - splashBitmap.bmHeight) / 2;
 
-       HWND splashWindow = CreateWindowEx(WS_EX_TOOLWINDOW, splashClassName, splashClassName, WS_POPUP,
-               x, y, splashBitmap.bmWidth, splashBitmap.bmHeight, NULL, NULL, NULL, NULL);
-       SetWindowLongPtr(splashWindow, GWLP_USERDATA, (LONG_PTR)hSplashBitmap);
-       ShowWindow(splashWindow, SW_SHOW);
-       UpdateWindow(splashWindow);
-       return splashWindow;
+  HWND splashWindow = CreateWindowEx(WS_EX_TOOLWINDOW, splashClassName, splashClassName, WS_POPUP,
+    x, y, splashBitmap.bmWidth, splashBitmap.bmHeight, NULL, NULL, NULL, NULL);
+  SetWindowLongPtr(splashWindow, GWLP_USERDATA, (LONG_PTR)hSplashBitmap);
+  ShowWindow(splashWindow, SW_SHOW);
+  UpdateWindow(splashWindow);
+  return splashWindow;
 }
 
 DWORD parentProcId;
@@ -655,122 +740,122 @@ HANDLE parentProcHandle;
 
 BOOL IsParentProcessRunning(HANDLE hProcess)
 {
-       if (hProcess == NULL) return FALSE;
-       DWORD ret = WaitForSingleObject(hProcess, 0);
-       return ret == WAIT_TIMEOUT;
+  if (hProcess == NULL) return FALSE;
+  DWORD ret = WaitForSingleObject(hProcess, 0);
+  return ret == WAIT_TIMEOUT;
 }
 
 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
 {
-       DWORD procId = 0;
-       GetWindowThreadProcessId(hWnd, &procId);
-       if (parentProcId == procId)
-       {
-               WINDOWINFO wi;
-               wi.cbSize = sizeof(WINDOWINFO);
-               GetWindowInfo(hWnd, &wi);
-               if ((wi.dwStyle & WS_VISIBLE) != 0)
-               {
-                       HWND *phNewWindow = (HWND *)lParam;
-                       *phNewWindow = hWnd;
-                       return FALSE;
-               }
-       }
-       return TRUE;
+  DWORD procId = 0;
+  GetWindowThreadProcessId(hWnd, &procId);
+  if (parentProcId == procId)
+  {
+    WINDOWINFO wi;
+    wi.cbSize = sizeof(WINDOWINFO);
+    GetWindowInfo(hWnd, &wi);
+    if ((wi.dwStyle & WS_VISIBLE) != 0)
+    {
+      HWND *phNewWindow = (HWND *)lParam;
+      *phNewWindow = hWnd;
+      return FALSE;
+    }
+  }
+  return TRUE;
 }
 
 DWORD WINAPI SplashScreen(HBITMAP hSplashBitmap)
 {
-       RegisterSplashScreenWndClass();
-       HWND splashWindow = ShowSplashScreenWindow(hSplashBitmap);
-       MSG msg;
-       while (true)
-       {
-               while (PeekMessage(&msg, splashWindow, 0, 0, PM_REMOVE))
-               {
-                       TranslateMessage(&msg);
-                       DispatchMessage(&msg);
-               }
-               Sleep(50);
-               HWND hNewWindow = NULL;
-               EnumWindows(EnumWindowsProc, (LPARAM)&hNewWindow);
-               if (hNewWindow)
-               {
-                       BringWindowToTop(hNewWindow);
-                       Sleep(100);
-                       DeleteObject(hSplashBitmap);
-                       DestroyWindow(splashWindow);
-                       break;
-               }
-               if (!IsParentProcessRunning(parentProcHandle)) break;
-       }
-       return 0;
+  RegisterSplashScreenWndClass();
+  HWND splashWindow = ShowSplashScreenWindow(hSplashBitmap);
+  MSG msg;
+  while (true)
+  {
+    while (PeekMessage(&msg, splashWindow, 0, 0, PM_REMOVE))
+    {
+      TranslateMessage(&msg);
+      DispatchMessage(&msg);
+    }
+    Sleep(50);
+    HWND hNewWindow = NULL;
+    EnumWindows(EnumWindowsProc, (LPARAM)&hNewWindow);
+    if (hNewWindow)
+    {
+      BringWindowToTop(hNewWindow);
+      Sleep(100);
+      DeleteObject(hSplashBitmap);
+      DestroyWindow(splashWindow);
+      break;
+    }
+    if (!IsParentProcessRunning(parentProcHandle)) break;
+  }
+  return 0;
 }
 
 void StartSplashProcess()
 {
-       TCHAR ownPath[_MAX_PATH];
-       TCHAR params[_MAX_PATH];
+  TCHAR ownPath[_MAX_PATH];
+  TCHAR params[_MAX_PATH];
 
-       PROCESS_INFORMATION splashProcessInformation;
-       STARTUPINFO startupInfo;
-       memset(&splashProcessInformation, 0, sizeof(splashProcessInformation));
-       memset(&startupInfo, 0, sizeof(startupInfo));
-       startupInfo.cb = sizeof(startupInfo);
-       startupInfo.dwFlags = STARTF_USESHOWWINDOW;
-       startupInfo.wShowWindow = SW_SHOW;
+  PROCESS_INFORMATION splashProcessInformation;
+  STARTUPINFO startupInfo;
+  memset(&splashProcessInformation, 0, sizeof(splashProcessInformation));
+  memset(&startupInfo, 0, sizeof(startupInfo));
+  startupInfo.cb = sizeof(startupInfo);
+  startupInfo.dwFlags = STARTF_USESHOWWINDOW;
+  startupInfo.wShowWindow = SW_SHOW;
 
-       GetModuleFileName(NULL, ownPath, (sizeof(ownPath)));
-       _snwprintf(params, _MAX_PATH, _T("SPLASH %d"), GetCurrentProcessId());
-       if (CreateProcess(ownPath, params, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &splashProcessInformation))
-       {
-               CloseHandle(splashProcessInformation.hProcess);
-               CloseHandle(splashProcessInformation.hThread);
-       }
+  GetModuleFileName(NULL, ownPath, (sizeof(ownPath)));
+  _snwprintf(params, _MAX_PATH, _T("SPLASH %d"), GetCurrentProcessId());
+  if (CreateProcess(ownPath, params, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &splashProcessInformation))
+  {
+    CloseHandle(splashProcessInformation.hProcess);
+    CloseHandle(splashProcessInformation.hThread);
+  }
 }
 
 int APIENTRY _tWinMain(HINSTANCE hInstance,
-       HINSTANCE hPrevInstance,
-       LPTSTR    lpCmdLine,
-       int       nCmdShow)
+                       HINSTANCE hPrevInstance,
+                       LPTSTR    lpCmdLine,
+                       int       nCmdShow)
 {
-       UNREFERENCED_PARAMETER(hPrevInstance);
+  UNREFERENCED_PARAMETER(hPrevInstance);
 
-       hInst = hInstance;
+  hInst = hInstance;
 
-       if (__argc == 2 && _wcsicmp(__wargv[0], _T("SPLASH")) == 0)
-       {
-               HBITMAP hSplashBitmap = static_cast<HBITMAP>(LoadImage(hInst, MAKEINTRESOURCE(IDB_SPLASH), IMAGE_BITMAP, 0, 0, 0));
-               if (hSplashBitmap)
-               {
-                       parentProcId = _wtoi(__wargv[1]);
-                       parentProcHandle = OpenProcess(SYNCHRONIZE, FALSE, parentProcId);
-                       if (IsParentProcessRunning(parentProcHandle)) SplashScreen(hSplashBitmap);
-               }
-               CloseHandle(parentProcHandle);
-               return 0;
-       }
+  if (__argc == 2 && _wcsicmp(__wargv[0], _T("SPLASH")) == 0)
+  {
+    HBITMAP hSplashBitmap = static_cast<HBITMAP>(LoadImage(hInst, MAKEINTRESOURCE(IDB_SPLASH), IMAGE_BITMAP, 0, 0, 0));
+    if (hSplashBitmap)
+    {
+      parentProcId = _wtoi(__wargv[1]);
+      parentProcHandle = OpenProcess(SYNCHRONIZE, FALSE, parentProcId);
+      if (IsParentProcessRunning(parentProcHandle)) SplashScreen(hSplashBitmap);
+    }
+    CloseHandle(parentProcHandle);
+    return 0;
+  }
 
-       if (!CheckSingleInstance()) return 1;
+  if (!CheckSingleInstance()) return 1;
 
-       if (wcsstr(lpCmdLine, _T("nosplash")) == NULL) StartSplashProcess();
+  if (wcsstr(lpCmdLine, _T("nosplash")) == NULL) StartSplashProcess();
 
-       if (!LocateJVM()) return 1;
-       if (!LoadVMOptions()) return 1;
-       if (!LoadJVMLibrary()) return 1;
-       if (!CreateJVM()) return 1;
+  if (!LocateJVM()) return 1;
+  if (!LoadVMOptions()) return 1;
+  if (!LoadJVMLibrary()) return 1;
+  if (!CreateJVM()) return 1;
 
-       hSingleInstanceWatcherThread = CreateThread(NULL, 0, SingleInstanceThread, NULL, 0, NULL);
+  hSingleInstanceWatcherThread = CreateThread(NULL, 0, SingleInstanceThread, NULL, 0, NULL);
 
-       if (!RunMainClass()) return 1;
+  if (!RunMainClass()) return 1;
 
-       jvm->DestroyJavaVM();
+  jvm->DestroyJavaVM();
 
-       terminating = true;
-       SetEvent(hEvent);
-       WaitForSingleObject(hSingleInstanceWatcherThread, INFINITE);
-       CloseHandle(hEvent);
-       CloseHandle(hFileMapping);
+  terminating = true;
+  SetEvent(hEvent);
+  WaitForSingleObject(hSingleInstanceWatcherThread, INFINITE);
+  CloseHandle(hEvent);
+  CloseHandle(hFileMapping);
 
-       return 0;
+  return 0;
 }
index b973671bec0058ad3f98edf644f9aaba2577032c..790907fb14a4bc31baed552b3e3c0e06d3fa33e9 100644 (file)
Binary files a/native/WinLauncher/WinLauncher/WinLauncher.rc and b/native/WinLauncher/WinLauncher/WinLauncher.rc differ
index 4e4a0057ec1afd33221390fdad0a05a65e8d1ff4..61721ab3e70d59747d3b114fde784ee960d58c7a 100644 (file)
Binary files a/native/WinLauncher/WinLauncher/resource.h and b/native/WinLauncher/WinLauncher/resource.h differ
index 6f78cc66b33fb2e880211fb5283ce54867472d7d..331c84157ff54252059201942736ffd7c86508ac 100644 (file)
@@ -23,5 +23,6 @@
 
 #include <vector>
 #include <string>
+#include <sstream>
 
 // TODO: reference additional headers your program requires here
index f561652450e6994bc09d5d3b3ff276495dd0604b..5b855cb0137d604e733bd076cea5947ea125ba60 100644 (file)
@@ -309,39 +309,53 @@ public class PathManager {
     return resultPath;
   }
 
+  public static String getUserPropertiesPath() {
+    if (PATHS_SELECTOR != null) {
+      return platformPath(PATHS_SELECTOR, "Library/Preferences", ".");
+    }
+    else {
+      return getUserHome();
+    }
+  }
+
   public static void loadProperties() {
-    File propFile = FileUtil.findFirstThatExist(
+    String[] propFiles = new String[]{
       System.getProperty(PROPERTIES_FILE),
-      getUserHome() + "/idea.properties",
+      getUserPropertiesPath() + "/idea.properties",
       getHomePath() + "/bin/idea.properties",
-      getHomePath() + "/community/bin/idea.properties");
-
-    if (propFile != null) {
-      try {
-        Reader fis = new BufferedReader(new FileReader(propFile));
-        try {
-          Map<String, String> properties = FileUtil.loadProperties(fis);
+      getHomePath() + "/community/bin/idea.properties"};
 
-          String home = properties.get("idea.home");
-          if (home != null && ourHomePath == null) {
-            ourHomePath = getAbsolutePath(substituteVars(home));
-          }
-
-          Properties sysProperties = System.getProperties();
-          for (String key : properties.keySet()) {
-            if (sysProperties.getProperty(key, null) == null) { // load the property from the property file only if it is not defined yet
-              String value = substituteVars(properties.get(key));
-              sysProperties.setProperty(key, value);
+    for (String path : propFiles) {
+      if (path != null) {
+        File propFile = new File(path);
+        if (propFile.exists()) {
+          try {
+            Reader fis = new BufferedReader(new FileReader(propFile));
+            try {
+              Map<String, String> properties = FileUtil.loadProperties(fis);
+
+              String home = properties.get("idea.home");
+              if (home != null && ourHomePath == null) {
+                ourHomePath = getAbsolutePath(substituteVars(home));
+              }
+
+              Properties sysProperties = System.getProperties();
+              for (String key : properties.keySet()) {
+                if (sysProperties.getProperty(key, null) == null) { // load the property from the property file only if it is not defined yet
+                  String value = substituteVars(properties.get(key));
+                  sysProperties.setProperty(key, value);
+                }
+              }
+            }
+            finally {
+              fis.close();
             }
           }
+          catch (IOException e) {
+            //noinspection HardCodedStringLiteral,UseOfSystemOutOrSystemErr
+            System.err.println("Problem reading from property file: " + propFile.getPath());
+          }
         }
-        finally{
-          fis.close();
-        }
-      }
-      catch (IOException e) {
-        //noinspection HardCodedStringLiteral,UseOfSystemOutOrSystemErr
-        System.err.println("Problem reading from property file: " + propFile.getPath());
       }
     }
   }
index 5dd02039a32de8c6934c5eab0609d25f44295fc9..555a241878d3afa34f407a60d6debc6c54850abf 100644 (file)
@@ -412,5 +412,6 @@ private layoutMac(Map _args, String target) {
   args.help_id = "PE"
   args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
   args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"];
+  args.executable = "pycharm"
   layoutMacApp(target, ch, args)
 }
index 7dfc49dfb8fe393f96be9dec80a12dbde5147221..e2c43922ae9a0cafc8f3f5b8b7936b6973c2e7ee 100644 (file)
@@ -35,6 +35,7 @@ public class StringTable extends VersionInfoBin {
       if (bin.getName().equals(key)) {
         StringTableEntry entry = (StringTableEntry) bin;
         ((WChar) entry.getMember("Value")).setValue(value);
+        ((Word) entry.getMember("wValueLength")).setValue(value.length());
         return;
       }
     }
index ece9dbd2f612b3556410e349ab10b5b556e5e878..8c3905d2980750d24e3bc42d93b719dacaf98a00 100644 (file)
@@ -179,7 +179,7 @@ public class LauncherGeneratorMain {
 
   private static Map<String, Integer> loadResourceIDs(String arg) throws IOException {
     Map<String, Integer> result = new HashMap<String, Integer>();
-    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(arg), Charset.forName("UTF-16")));
+    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(arg)));
     Pattern pattern = Pattern.compile("#define (\\w+)\\s+(\\d+)");
     try {
       while(true) {