private Diff createDiff(File f1, File f2) throws IOException {
        final StringBuffer firstText = new StringBuffer();
        final StringBuffer secondText = new StringBuffer();
        diffCmd = diffCmd.replace("\"{0}\"", "{0}").replace("\"{1}\"", "{1}");  // compatibility // NOI18N
        String firstPath;
        String secondPath;
        if (isWindows()) {
            firstPath = "\"" + f1.getAbsolutePath() + "\""; // NOI18N
            secondPath = "\"" + f2.getAbsolutePath() + "\""; // NOI18N
        } else {
            firstPath = f1.getAbsolutePath();
            secondPath = f2.getAbsolutePath();
        }
        final String cmd = java.text.MessageFormat.format(diffCmd, firstPath, secondPath);

        final Process p[] = new Process[1];
        final Object[] ret = new Object[1];
        Runnable cancellableProcessWrapper = new Runnable() {
            public void run() {
                try {
                    LOGGER.fine("#69616 CDP: executing: " + cmd); // NOI18N
                    synchronized(p) {
                        p[0] = Runtime.getRuntime().exec(cmd);
                    }
                    Reader stdout = new InputStreamReader(p[0].getInputStream());
                    char[] buffer = new char[BUFF_LENGTH];
                    StringBuilder outBuffer = new StringBuilder();
                    int length;
                    Diff differences = new Diff();
                    while ((length = stdout.read(buffer)) > 0) {
                        for (int i = 0; i < length; i++) {
                            if (buffer[i] == '\n') {
                                //stdoutNextLine(outBuffer.toString(), differences);
                                outputLine(outBuffer.toString(), pattern, differences,
                                           firstText, secondText);
                                outBuffer.delete(0, outBuffer.length());
                            } else {
                                if (buffer[i] != 13) {
                                    outBuffer.append(buffer[i]);
                                }
                            }
                        }
                    }
                    if (outBuffer.length() > 0) outputLine(outBuffer.toString(), pattern, differences,
                                                           firstText, secondText);
                    setTextOnLastDifference(differences, firstText, secondText);
                    ret[0] =  differences;
                } catch (IOException ioex) {
                    ret[0] = new IOException("Failed to execute: "+cmd).initCause(ioex);
                }
            }
        };

        Thread t = new Thread(cancellableProcessWrapper, "Diff.exec()"); // NOI18N
        t.start();
        try {
            t.join();
            synchronized(ret) {
                if (ret[0] instanceof IOException) {
                    throw (IOException) ret[0];
                }
                return (Diff) ret[0];
            }
        } catch (InterruptedException e) {
            synchronized(p[0]) {
                p[0].destroy();
            }
            throw new InterruptedIOException();
        }

    }