Example #1
0
    const String appendPath (const String& path, const String& subpath)
    {
        if (File::isAbsolutePath (subpath)
             || subpath.startsWithChar ('$')
             || subpath.startsWithChar ('~')
             || (CharacterFunctions::isLetter (subpath[0]) && subpath[1] == ':'))
            return subpath.replaceCharacter ('\\', '/');

        String path1 (path.replaceCharacter ('\\', '/'));
        if (! path1.endsWithChar ('/'))
            path1 << '/';

        return path1 + subpath.replaceCharacter ('\\', '/');
    }
Example #2
0
    Pimpl (String name, const int timeOutMillisecs)
        : handle (0), refCount (1)
    {
        name = name.replaceCharacter ('\\', '/');
        handle = CreateMutexW (0, TRUE, ("Global\\" + name).toWideCharPointer());

        // Not 100% sure why a global mutex sometimes can't be allocated, but if it fails, fall back to
        // a local one. (A local one also sometimes fails on other machines so neither type appears to be
        // universally reliable)
        if (handle == 0)
            handle = CreateMutexW (0, TRUE, ("Local\\" + name).toWideCharPointer());

        if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
        {
            if (timeOutMillisecs == 0)
            {
                close();
                return;
            }

            switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs))
            {
            case WAIT_OBJECT_0:
            case WAIT_ABANDONED:
                break;

            case WAIT_TIMEOUT:
            default:
                close();
                break;
            }
        }
    }
bool ScriptableEngine::compileScript (const String& scriptCode)
{
    asIScriptEngine* currentEngine = (asIScriptEngine*) engine;

    if (currentEngine != 0 && status != Invalid)
    {
        int r;

	    // remove carriage returns if any...
	    String scriptCodeProcessed = scriptCode.replaceCharacter('\r','\n');
	    scriptCodeProcessed += T(' '); // hack if the script is empty

        // create the module
        asIScriptModule* module = currentEngine->GetModule (0, asGM_CREATE_IF_NOT_EXISTS);

	    // add a script section
        r = module->AddScriptSection ("main", (const char*) scriptCodeProcessed, scriptCodeProcessed.length());
	    if (r < 0)
		    return false;

	    // build the script
        r = module->Build();
	    if (r < 0)
		    return false;

        status = Compiled;

    	return true;
    }

    return false;
}
//==============================================================================
bool ScriptableEngine::compileScript (const String& strScript, const String& strSection)
{
    jassert (engine != 0);

	compileFailed = false;

	// do garbage collect
	engine->GarbageCollect (true);

	// remove carriage returns if any...
	String preScript = strScript.replaceCharacter('\r','\n');
	preScript += T(' '); // hack if the script is empty

	// call the pre compiler callback
	preCompileCallback ();

	// add a script section
	int r = engine->AddScriptSection (0, (const char*) strSection, (const char*) strScript, outVector.size(), 0);
	if (r < 0)
	{
		compileFailed = true;
		return false;
	}

	// build the script
	r = engine->Build (0);
	if (r < 0)
	{
		compileFailed = true;
		return false;
	}

	return true;
}
static void addKDialogArgs (StringArray& args, String& separator,
                            const String& title, const File& file, const String& filters,
                            bool isDirectory, bool isSave, bool selectMultipleFiles)
{
    args.add ("kdialog");

    if (title.isNotEmpty())
        args.add ("--title=" + title);

    if (uint64 topWindowID = getTopWindowID())
    {
        args.add ("--attach");
        args.add (String (topWindowID));
    }

    if (selectMultipleFiles)
    {
        separator = "\n";
        args.add ("--multiple");
        args.add ("--separate-output");
        args.add ("--getopenfilename");
    }
    else
    {
        if (isSave)             args.add ("--getsavefilename");
        else if (isDirectory)   args.add ("--getexistingdirectory");
        else                    args.add ("--getopenfilename");
    }

    File startPath;

    if (file.exists())
    {
        startPath = file;
    }
    else if (file.getParentDirectory().exists())
    {
        startPath = file.getParentDirectory();
    }
    else
    {
        startPath = File::getSpecialLocation (File::userHomeDirectory);

        if (isSave)
            startPath = startPath.getChildFile (file.getFileName());
    }

    args.add (startPath.getFullPathName());
    args.add (filters.replaceCharacter (';', ' '));
}
Example #6
0
String getFileNameFromPath (const char* sourceFileName, int numberOfParents)
{
    String fullPath (sourceFileName);

#if BEAST_WINDOWS
    // Convert everything to forward slash
    fullPath = fullPath.replaceCharacter ('\\', '/');
#endif

    String path;

    int chopPoint = fullPath.lastIndexOfChar ('/');
    path = fullPath.substring (chopPoint + 1);

    while (chopPoint >= 0 && numberOfParents > 0)
    {
        --numberOfParents;
        fullPath = fullPath.substring (0, chopPoint);
        chopPoint = fullPath.lastIndexOfChar ('/');
        path = fullPath.substring (chopPoint + 1) + '/' + path;
    }

    return path;
}
 String windowsStylePath (const String& path)    { return path.replaceCharacter ('/', '\\'); }
 String unixStylePath (const String& path)       { return path.replaceCharacter ('\\', '/'); }
Example #9
0
//==============================================================================
String File::parseAbsolutePath (const String& p)
{
    if (p.isEmpty())
        return String::empty;

#if JUCE_WINDOWS
    // Windows..
    String path (p.replaceCharacter ('/', '\\'));

    if (path.startsWithChar (File::separator))
    {
        if (path[1] != File::separator)
        {
            /*  When you supply a raw string to the File object constructor, it must be an absolute path.
                If you're trying to parse a string that may be either a relative path or an absolute path,
                you MUST provide a context against which the partial path can be evaluated - you can do
                this by simply using File::getChildFile() instead of the File constructor. E.g. saying
                "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
                path if that's what was supplied, or would evaluate a partial path relative to the CWD.
            */
            jassertfalse;

            path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
        }
    }
    else if (! path.containsChar (':'))
    {
        /*  When you supply a raw string to the File object constructor, it must be an absolute path.
            If you're trying to parse a string that may be either a relative path or an absolute path,
            you MUST provide a context against which the partial path can be evaluated - you can do
            this by simply using File::getChildFile() instead of the File constructor. E.g. saying
            "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
            path if that's what was supplied, or would evaluate a partial path relative to the CWD.
        */
        jassertfalse;

        return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
    }
#else
    // Mac or Linux..

    // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
    // to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
    // If that's why you've ended up here, use File::getChildFile() to build your paths instead.
    jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));

    String path (p);

    if (path.startsWithChar ('~'))
    {
        if (path[1] == File::separator || path[1] == 0)
        {
            // expand a name of the form "~/abc"
            path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
                    + path.substring (1);
        }
        else
        {
            // expand a name of type "~dave/abc"
            const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));

            struct passwd* const pw = getpwnam (userName.toUTF8());
            if (pw != nullptr)
                path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
        }
    }
    else if (! path.startsWithChar (File::separator))
    {
        /*  When you supply a raw string to the File object constructor, it must be an absolute path.
            If you're trying to parse a string that may be either a relative path or an absolute path,
            you MUST provide a context against which the partial path can be evaluated - you can do
            this by simply using File::getChildFile() instead of the File constructor. E.g. saying
            "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
            path if that's what was supplied, or would evaluate a partial path relative to the CWD.
        */
        jassert (path.startsWith ("./") || path.startsWith ("../")); // (assume that a path "./xyz" is deliberately intended to be relative to the CWD)

        return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
    }
#endif

    while (path.endsWithChar (separator) && path != separatorString) // careful not to turn a single "/" into an empty string.
        path = path.dropLastCharacters (1);

    return path;
}
Example #10
0
void UploadWindow::filesDropped(const StringArray& filenames, int mouseX, int mouseY)
{
	StringArray extensions;
	extensions.addTokens(".jpg;.jpeg;.jpe;.png;.tif;.tiff;.png;.gif;.mpg;.mpeg;.mpe;.mov;.qt;.avi;.wmv", ";", "");

	UploadRequest* ur = new UploadRequest();
	for (int i = 0; i < filenames.size(); i++)
	{
		File imageFile(File::getCurrentWorkingDirectory().getChildFile (filenames[i]));
        
		if (imageFile.existsAsFile() && extensions.contains(imageFile.getFileExtension(), true))
		{
			ur->addImageFile(imageFile);
		}
		else if (imageFile.isDirectory())
		{
			Array<File> results;			
			imageFile.findChildFiles(results, File::findFiles, true);

			for (int i = 0; i < results.size(); i++)
			{
				if (extensions.contains(results[i].getFileExtension(), true))
					ur->addImageFile(results[i]);
			}
		}
	}

	if (ur->getNumImages() > 0)
	{
		Settings* settings = Settings::getInstance();
		if (settings->password.isEmpty() || settings->email.isEmpty())
			settings->showSettingsDialog();

		if (settings->password.isEmpty() || settings->email.isEmpty())
			return;

		if (!smugMug.isLoggedIn())
			smugMug.login(Settings::getInstance()->email, Settings::getInstance()->password);

		if (!smugMug.isLoggedIn())
		{
			AlertWindow::showMessageBox(AlertWindow::WarningIcon, "Komodo Drop", "Error: Unable to connect to Smugmug.");
			return;
		}

		String defaultAlbumName;
		File root(filenames[0]);
		if (filenames.size() == 1 && root.isDirectory())
			defaultAlbumName = root.getFileName();
		else 
			defaultAlbumName = root.getParentDirectory().getFileName();

#ifdef JUCE_DEBUG
		defaultAlbumName = defaultAlbumName.replaceCharacter('_', ' ');
#endif

		SmugID albumId;
		bool open = false;
		if (Settings::getInstance()->silentUpload)
		{
			OwnedArray<Album> albums;
			smugMug.getAlbumList(albums);
			
			for (int i = 0; i < albums.size(); i++)
			{
				if (albums[i]->title == defaultAlbumName)
				{
					albumId = albums[i]->id;
					break;
				}
			}
			if (albumId.id == -1)
			{
				StringPairArray params;
				albumId = smugMug.createAlbum(defaultAlbumName, 0, params);
			}
			ur->setName(defaultAlbumName);
		}
		else
		{
			bool newAlbum;
			int catId;
			String title;
			StringPairArray params;

			UploadDialog* ud = new UploadDialog(&smugMug, defaultAlbumName, newAlbum, title, albumId, catId, params, open);
			if (ud->runModalLoop() == 1)
			{
				ur->setName(title);
				if (newAlbum)
					albumId = smugMug.createAlbum(title, catId, params);
			}
			else
			{
				return;
			}
		}

		if (albumId.id != -1)
		{
			ur->setOpenBrowser(open);
			ur->setAlbumId(albumId);
			smugMug.uploadImages(ur);
			startTimer(333);
			repaint();
		}
		else
		{
			delete ur;
		}
	}
	else
	{
		delete ur;
	}
	return;
}
//------------------------------------------------------------------------------
OpenSoundMessage::OpenSoundMessage(char *data, const int size)
  : OpenSoundBase(),
    bufferSize(0),
    outgoingSize(0),
    buffer(0)
{
    int i;
    GetTheBytes tempBytes;
    int32 tempint;
    float *tempf;
    String tempstr;
    //This represents which part of the Message we're currently reading from.
    int currentSection = 0;
    int currentTag = 1; //Because Type Tags start with ','.

    for(i=0;i<size;++i)
    {
        //Address.
        if(currentSection == 0)
        {
            if((data[i] != 0) && (data[i] != ','))
                address += data[i];
            else if(data[i] == ',')
            {
                typeTag = ",";
                ++currentSection;
            }
        }
        //Type Tag.
        else if(currentSection == 1)
        {
            if(data[i] != 0)
                typeTag += data[i];
            else if((i%4) == 3) //i.e. we're on the last byte of a 4 byte boundary.
                ++currentSection;
        }
        //The actual data.
        else
        {
            if(currentTag >= static_cast<int>(typeTag.length()))
                break;
            else if(typeTag[currentTag] == 'f')
            {
                tempBytes.a = data[i];
                ++i;
                tempBytes.b = data[i];
                ++i;
                tempBytes.c = data[i];
                ++i;
                tempBytes.d = data[i];

                tempint = ntohl(*(reinterpret_cast<int32 *>(&tempBytes)));
                tempf = reinterpret_cast<float *>(&tempint);
                floatArray.add (*tempf);

                ++currentTag;
            }
            else if(typeTag[currentTag] == 'i')
            {
                tempBytes.a = data[i];
                ++i;
                tempBytes.b = data[i];
                ++i;
                tempBytes.c = data[i];
                ++i;
                tempBytes.d = data[i];

                tempint = ntohl(*(reinterpret_cast<int32 *>(&tempBytes)));
                intArray.add (tempint);

                ++currentTag;
            }
            else if(typeTag[currentTag] == 's')
            {
                tempstr = "";
                while(data[i] != 0)
                {
                    tempstr += data[i];

                    ++i;
                }

				//@TODO
				//Not sure with this, it was
				//tempstr[tempstr.length()] = static_cast<char>(NULL); //Terminator.

				tempstr = tempstr.replaceCharacter (tempstr.getLastCharacter(),
													static_cast<char>(NULL)); //Terminator.

                stringArray.add (tempstr);

                //Handle any padding bytes.
                while((i%4) != 0)
                    ++i;

                ++currentTag;
            }
        }
    }
}
Example #12
0
String File::parseAbsolutePath (const String& p)
{
    if (p.isEmpty())
        return String();

#if JUCE_WINDOWS
    // Windows..
    String path (p.replaceCharacter ('/', '\\'));

    if (path.contains ("\\..\\"))
        path = removeEllipsis (path);

    if (path.startsWithChar (separator))
    {
        if (path[1] != separator)
        {
            /*  When you supply a raw string to the File object constructor, it must be an absolute path.
                If you're trying to parse a string that may be either a relative path or an absolute path,
                you MUST provide a context against which the partial path can be evaluated - you can do
                this by simply using File::getChildFile() instead of the File constructor. E.g. saying
                "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
                path if that's what was supplied, or would evaluate a partial path relative to the CWD.
            */
            jassertfalse;

            path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
        }
    }
    else if (! path.containsChar (':'))
    {
        /*  When you supply a raw string to the File object constructor, it must be an absolute path.
            If you're trying to parse a string that may be either a relative path or an absolute path,
            you MUST provide a context against which the partial path can be evaluated - you can do
            this by simply using File::getChildFile() instead of the File constructor. E.g. saying
            "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
            path if that's what was supplied, or would evaluate a partial path relative to the CWD.
        */
		// #ZEN(Changed 2016/04/03): Removed jassert, put in DBG call instead due to live constant ed.
		//jassertfalse;
		DBG("Passed relative path to juce_File line 130! Jassert Bypassed");

        return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
    }
#else
    // Mac or Linux..

    // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
    // to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
    // If that's why you've ended up here, use File::getChildFile() to build your paths instead.
    jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));

    String path (p);

    if (path.contains ("/../"))
        path = removeEllipsis (path);

    if (path.startsWithChar ('~'))
    {
        if (path[1] == separator || path[1] == 0)
        {
            // expand a name of the form "~/abc"
            path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
                    + path.substring (1);
        }
        else
        {
            // expand a name of type "~dave/abc"
            const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));

            if (struct passwd* const pw = getpwnam (userName.toUTF8()))
                path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
        }
    }
    else if (! path.startsWithChar (separator))
    {
       #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
        if (! (path.startsWith ("./") || path.startsWith ("../")))
        {
            /*  When you supply a raw string to the File object constructor, it must be an absolute path.
                If you're trying to parse a string that may be either a relative path or an absolute path,
                you MUST provide a context against which the partial path can be evaluated - you can do
                this by simply using File::getChildFile() instead of the File constructor. E.g. saying
                "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
                path if that's what was supplied, or would evaluate a partial path relative to the CWD.
            */
            jassertfalse;

           #if JUCE_LOG_ASSERTIONS
            Logger::writeToLog ("Illegal absolute path: " + path);
           #endif
        }
       #endif

        return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
    }
#endif

    while (path.endsWithChar (separator) && path != separatorString) // careful not to turn a single "/" into an empty string.
        path = path.dropLastCharacters (1);

    return path;
}
void FileChooser::showPlatformDialog (Array<File>& results,
                                      const String& title,
                                      const File& file,
                                      const String& filters,
                                      bool isDirectory,
                                      bool /* selectsFiles */,
                                      bool isSave,
                                      bool /* warnAboutOverwritingExistingFiles */,
                                      bool selectMultipleFiles,
                                      FilePreviewComponent* /* previewComponent */)
{
    String separator;
    StringArray args;

    const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
    const bool isKdeFullSession = SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String::empty)
                                    .equalsIgnoreCase ("true");

    if (exeIsAvailable ("kdialog") && (isKdeFullSession || ! exeIsAvailable ("zenity")))
    {
        // use kdialog for KDE sessions or if zenity is missing
        args.add ("kdialog");

        if (title.isNotEmpty())
            args.add ("--title=" + title);

        if (selectMultipleFiles)
        {
            separator = "\n";
            args.add ("--multiple");
            args.add ("--separate-output");
            args.add ("--getopenfilename");
        }
        else
        {
            if (isSave)             args.add ("--getsavefilename");
            else if (isDirectory)   args.add ("--getexistingdirectory");
            else                    args.add ("--getopenfilename");
        }

        String startPath;

        if (file.exists())
        {
            startPath = file.getFullPathName();
        }
        else if (file.getParentDirectory().exists())
        {
            startPath = file.getParentDirectory().getFullPathName();
        }
        else
        {
            startPath = File::getSpecialLocation (File::userHomeDirectory).getFullPathName();

            if (isSave)
                startPath += "/" + file.getFileName();
        }

        args.add (startPath);
        args.add (filters.replaceCharacter (';', ' '));
        args.add ("2>/dev/null");
    }
    else
    {
        // zenity
        args.add ("zenity");
        args.add ("--file-selection");

        if (title.isNotEmpty())
            args.add ("--title=" + title);

        if (selectMultipleFiles)
        {
            separator = ":";
            args.add ("--multiple");
            args.add ("--separator=" + separator);
        }
        else
        {
            if (isDirectory)  args.add ("--directory");
            if (isSave)       args.add ("--save");
        }

        if (file.isDirectory())
            file.setAsCurrentWorkingDirectory();
        else if (file.getParentDirectory().exists())
            file.getParentDirectory().setAsCurrentWorkingDirectory();
        else
            File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory();

        if (! file.getFileName().isEmpty())
            args.add ("--filename=" + file.getFileName());
    }

    ChildProcess child;

    if (child.start (args, ChildProcess::wantStdOut))
    {
        const String result (child.readAllProcessOutput().trim());

        if (result.isNotEmpty())
        {
            StringArray tokens;

            if (selectMultipleFiles)
                tokens.addTokens (result, separator, "\"");
            else
                tokens.add (result);

            for (int i = 0; i < tokens.size(); ++i)
                results.add (File::getCurrentWorkingDirectory().getChildFile (tokens[i]));
        }

        child.waitForProcessToFinish (60 * 1000);
    }

    previousWorkingDirectory.setAsCurrentWorkingDirectory();
}
Example #14
0
//==============================================================================
static bool parseFile (const File& rootFolder,
                       const File& newTargetFile,
                       OutputStream& dest,
                       const File& file,
                       StringArray& alreadyIncludedFiles,
                       const StringArray& includesToIgnore,
                       const StringArray& wildcards,
                       bool isOuterFile,
                       bool stripCommentBlocks)
{
    if (! file.exists())
    {
        std::cout << "!! ERROR - file doesn't exist!";
        return false;
    }

    StringArray lines;
    lines.addLines (file.loadFileAsString());

    if (lines.size() == 0)
    {
        std::cout << "!! ERROR - input file was empty: " << file.getFullPathName();
        return false;
    }

    bool lastLineWasBlank = true;

    for (int i = 0; i < lines.size(); ++i)
    {
        String line (lines[i]);
        String trimmed (line.trimStart());

        if ((! isOuterFile) && trimmed.startsWith ("//================================================================"))
            line = String::empty;

        if (trimmed.startsWithChar ('#')
             && trimmed.removeCharacters (" \t").startsWithIgnoreCase ("#include\""))
        {
            const int endOfInclude = line.indexOfChar (line.indexOfChar ('\"') + 1, '\"') + 1;
            const String lineUpToEndOfInclude (line.substring (0, endOfInclude));
            const String lineAfterInclude (line.substring (endOfInclude));

            const String filename (line.fromFirstOccurrenceOf ("\"", false, false)
                                       .upToLastOccurrenceOf ("\"", false, false));
            const File targetFile (file.getSiblingFile (filename));

            if (targetFile.exists() && targetFile.isAChildOf (rootFolder))
            {
                if (matchesWildcard (filename.replaceCharacter ('\\', '/'), wildcards)
                     && ! includesToIgnore.contains (targetFile.getFileName()))
                {
                    if (line.containsIgnoreCase ("FORCE_AMALGAMATOR_INCLUDE")
                        || ! alreadyIncludedFiles.contains (targetFile.getFullPathName()))
                    {
                        if (! canFileBeReincluded (targetFile))
                            alreadyIncludedFiles.add (targetFile.getFullPathName());

                        dest << newLine << "/*** Start of inlined file: " << targetFile.getFileName() << " ***/" << newLine;

                        if (! parseFile (rootFolder, newTargetFile,
                                         dest, targetFile, alreadyIncludedFiles, includesToIgnore,
                                         wildcards, false, stripCommentBlocks))
                        {
                            return false;
                        }

                        dest << "/*** End of inlined file: " << targetFile.getFileName() << " ***/" << newLine << newLine;

                        line = lineAfterInclude;
                    }
                    else
                    {
                        line = String::empty;
                    }
                }
                else
                {
                    line = lineUpToEndOfInclude.upToFirstOccurrenceOf ("\"", true, false)
                            + targetFile.getRelativePathFrom (newTargetFile.getParentDirectory())
                                        .replaceCharacter ('\\', '/')
                            + "\""
                            + lineAfterInclude;
                }
            }
        }

        if ((stripCommentBlocks || i == 0) && trimmed.startsWith ("/*") && (i > 10 || ! isOuterFile))
        {
            int originalI = i;
            String originalLine = line;

            for (;;)
            {
                int end = line.indexOf ("*/");

                if (end >= 0)
                {
                    line = line.substring (end + 2);

                    // If our comment appeared just before an assertion, leave it in, as it
                    // might be useful..
                    if (lines [i + 1].contains ("assert")
                         || lines [i + 2].contains ("assert"))
                    {
                        i = originalI;
                        line = originalLine;
                    }

                    break;
                }

                line = lines [++i];

                if (i >= lines.size())
                    break;
            }

            line = line.trimEnd();
            if (line.isEmpty())
                continue;
        }

        line = line.trimEnd();

        {
            // Turn initial spaces into tabs..
            int numIntialSpaces = 0;
            int len = line.length();
            while (numIntialSpaces < len && line [numIntialSpaces] == ' ')
                ++numIntialSpaces;

            if (numIntialSpaces > 0)
            {
                int tabSize = 4;
                int numTabs = numIntialSpaces / tabSize;
                line = String::repeatedString ("\t", numTabs) + line.substring (numTabs * tabSize);
            }

            if (! line.containsChar ('"'))
            {
                // turn large areas of spaces into tabs - this will mess up alignment a bit, but
                // it's only the amalgamated file, so doesn't matter...
                line = line.replace ("        ", "\t", false);
                line = line.replace ("    ", "\t", false);
            }
        }

        if (line.isNotEmpty() || ! lastLineWasBlank)
            dest << line << newLine;

        lastLineWasBlank = line.isEmpty();
    }

    return true;
}