void CodeEditorComponent::mouseDoubleClick (const MouseEvent& e)
{
    CodeDocument::Position tokenStart (getPositionAt (e.x, e.y));
    CodeDocument::Position tokenEnd (tokenStart);

    if (e.getNumberOfClicks() > 2)
    {
        tokenStart.setLineAndIndex (tokenStart.getLineNumber(), 0);
        tokenEnd.setLineAndIndex (tokenStart.getLineNumber() + 1, 0);
    }
    else
    {
        while (CharacterFunctions::isLetterOrDigit (tokenEnd.getCharacter()))
            tokenEnd.moveBy (1);

        tokenStart = tokenEnd;

        while (tokenStart.getIndexInLine() > 0
                && CharacterFunctions::isLetterOrDigit (tokenStart.movedBy (-1).getCharacter()))
            tokenStart.moveBy (-1);
    }

    moveCaretTo (tokenEnd, false);
    moveCaretTo (tokenStart, true);
}
const bool CtrlrLuaMethodCodeEditor::isMouseOverUrl(CodeDocument::Position &position, String *url)
{
	if (position.getPosition() >= document.getNumCharacters())
	{
		return (false);
	}

	int moveLeft=0;

	while (!CharacterFunctions::isWhitespace(position.getCharacter()))
	{
		if (position.getPosition() <= 0)
			break;

		position.moveBy(-1);
		moveLeft++;
	}

	int start = position.getPosition();
	position.setPosition (position.getPosition()+moveLeft);

	while (!CharacterFunctions::isWhitespace(position.getCharacter()))
	{
		if (position.getPosition() >= document.getNumCharacters())
			break;

		position.moveBy(1);
	}

	int end = position.getPosition();

	const String word = document.getTextBetween (CodeDocument::Position(document, start), CodeDocument::Position(document, end)).trim();

	if (word.startsWith ("http://"))
	{
		if (url)
		{
			*url = word;
		}
		return (URL::isProbablyAWebsiteURL (word));
	}

	return (false);
}
void CodeEditor::codeDocumentChanged(const CodeDocument::Position& affectedTextStart, const CodeDocument::Position& affectedTextEnd)
{
	static const String BRACKETS[] = {String(L"("), String(L")"), String(L"{"), String(L"}"), String(L"["), String(L"]"), String(L"<"), String(L">"), String(L"'"), String(L"'"), String(L"\""), String(L"\"")};
	if(do_bracket_closing.getValue() && affectedTextEnd.getPosition() - affectedTextStart.getPosition() == 1){		//assume that the length of the affected text is 1
		//We're finding an opening character and inserting the other one. 
		const String C = String::charToString(affectedTextStart.getCharacter());
		int index = 0;
		for(; index < numElementsInArray(BRACKETS); index += 2){		//search for an existing parenthesis
			if(C == BRACKETS[index]){
				break;
			}
		}

		if(index < numElementsInArray(BRACKETS)){		//If the index is out of range, we couldn't find the first character
			editor->insertTextAtCaret(BRACKETS[index+1]);
			editor->moveCaretTo(affectedTextEnd, false);
		}
	}

	static const String LOOK_UP_CHARS[] = {String(L"{"), String(L"}")};

	if(do_auto_indent.getValue() && affectedTextStart.getLineNumber() < affectedTextEnd.getLineNumber()){		//assume that we're at the beginning of a line
		//calculate the number of tabs that will be inserted to the next line
		const String LINE_ABOVE = affectedTextStart.getLineText(), LINE = affectedTextEnd.getLineText();
		const int TAB_SIZE = editor->getTabSize();
		const int LENGTH_BEFORE = LINE_ABOVE.trimEnd().length();
		const int LENGTH_AFTER = LINE_ABOVE.trimStart().length();
		const String TARGET_STRINGS[] = {String::charToString(affectedTextStart.movedBy(-1).getCharacter()), String::charToString(affectedTextEnd.getCharacter())};
		int tab_size_to_add = (TARGET_STRINGS[0] == LOOK_UP_CHARS[0] && TARGET_STRINGS[1] != LOOK_UP_CHARS[1]) ? ((LENGTH_AFTER - LENGTH_BEFORE) / TAB_SIZE) + 1	//add another tab
							: (TARGET_STRINGS[1] == LOOK_UP_CHARS[1] && TARGET_STRINGS[0] != LOOK_UP_CHARS[0]) ? ((LENGTH_AFTER - LENGTH_BEFORE) / TAB_SIZE) - 1	//remove one tab
																											   : ((LENGTH_AFTER - LENGTH_BEFORE) / TAB_SIZE);

		for(; tab_size_to_add > 0; --tab_size_to_add){
			editor->insertTabAtCaret();
		}
	}
}