SonicPiScintilla::SonicPiScintilla(SonicPiLexer *lexer, SonicPiTheme *theme, QString fileName, OscSender *oscSender, QCheckBox *autoIndent)
  : QsciScintilla()
{
  setAcceptDrops(true);
  this->theme = theme;
  this->oscSender = oscSender;
  this->fileName = fileName;
  this->autoIndent = autoIndent;
  standardCommands()->clearKeys();
  standardCommands()->clearAlternateKeys();
  QString skey;
  QSettings settings("sonic-pi.net", "gui-key-bindings");

#if defined(Q_OS_MAC)
  int SPi_CTRL = Qt::META;
  int SPi_META = Qt::CTRL;
#else
  int SPi_CTRL = Qt::CTRL;
  int SPi_META = Qt::ALT;
#endif

  // basic navigation
  addKeyBinding(settings, QsciCommand::PageDown, Qt::Key_PageDown);
  addKeyBinding(settings, QsciCommand::PageUp, Qt::Key_PageUp);

  addKeyBinding(settings, QsciCommand::LineDown, Qt::Key_N | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::LineDown, Qt::Key_Down);
  addKeyBinding(settings, QsciCommand::LineDownExtend, Qt::Key_Down | Qt::SHIFT);
  addKeyBinding(settings, QsciCommand::LineUp, Qt::Key_P | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::LineUp, Qt::Key_Up);
  addKeyBinding(settings, QsciCommand::LineUpExtend, Qt::Key_Up | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::CharRight, Qt::Key_F | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::CharRight, Qt::Key_Right);
  addKeyBinding(settings, QsciCommand::CharRightExtend, Qt::Key_Right | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::WordRight, Qt::Key_F | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::WordRight, Qt::Key_Right | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::WordRightExtend, Qt::Key_Right | SPi_CTRL | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::CharLeft, Qt::Key_B | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::CharLeft, Qt::Key_Left);
  addKeyBinding(settings, QsciCommand::CharLeftExtend, Qt::Key_Left | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::WordLeft, Qt::Key_B | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::WordLeft, Qt::Key_Left | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::WordLeftExtend, Qt::Key_Left | SPi_CTRL | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::Delete, Qt::Key_D | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::Delete, Qt::Key_Delete);

  addKeyBinding(settings, QsciCommand::DeleteBack, Qt::Key_H | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::DeleteBack, Qt::Key_Backspace);

  addKeyBinding(settings, QsciCommand::Home, Qt::Key_A | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::VCHome, Qt::Key_Home);
  addKeyBinding(settings, QsciCommand::VCHomeExtend, Qt::Key_Home | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::DocumentStart, Qt::Key_Comma | Qt::SHIFT | SPi_META);
  addKeyBinding(settings, QsciCommand::DocumentStartExtend, Qt::Key_Home | SPi_CTRL | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::LineEnd, Qt::Key_E | SPi_CTRL);
  addOtherKeyBinding(settings, QsciCommand::LineEnd, Qt::Key_End);
  addKeyBinding(settings, QsciCommand::LineEndExtend, Qt::Key_End | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::DocumentEnd, Qt::Key_Greater | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::DocumentEnd, Qt::Key_Period | Qt::SHIFT | SPi_META);
  addKeyBinding(settings, QsciCommand::DocumentEndExtend, Qt::Key_End | SPi_CTRL | Qt::SHIFT);

  addKeyBinding(settings, QsciCommand::Delete, Qt::Key_D | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::VerticalCentreCaret, Qt::Key_L | SPi_CTRL);

  addKeyBinding(settings, QsciCommand::Backtab, Qt::Key_Tab | Qt::SHIFT);

  // copy paste
  addKeyBinding(settings, QsciCommand::SelectionCopy, Qt::Key_C | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::SelectionCopy, Qt::Key_C | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::SelectionCut, Qt::Key_X | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::SelectionCut, Qt::Key_X | SPi_CTRL);

  addKeyBinding(settings, QsciCommand::Paste, Qt::Key_V | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::Paste, Qt::Key_Y | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::Undo, Qt::Key_Z | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::Undo, Qt::Key_Z | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::Redo, Qt::Key_Z | Qt::SHIFT | SPi_META);
  addOtherKeyBinding(settings, QsciCommand::Redo, Qt::Key_Z | Qt::SHIFT | SPi_CTRL);
  addKeyBinding(settings, QsciCommand::SelectAll, Qt::Key_A | SPi_META);

  // delete word left and right
  addKeyBinding(settings, QsciCommand::DeleteWordLeft, Qt::Key_Backslash | SPi_META);
  addKeyBinding(settings, QsciCommand::DeleteWordLeft, Qt::Key_Backspace | SPi_META);
  addKeyBinding(settings, QsciCommand::DeleteWordRight, Qt::Key_D | SPi_META);

  standardCommands()->readSettings(settings);

  this->setMatchedBraceBackgroundColor(theme->color("MatchedBraceBackground"));
  this->setMatchedBraceForegroundColor(theme->color("MatchedBraceForeground"));

  setIndentationWidth(2);
  setIndentationGuides(true);
  setIndentationGuidesForegroundColor(theme->color("IndentationGuidesForeground"));
  setBraceMatching( SonicPiScintilla::SloppyBraceMatch);

  //TODO: add preference toggle for this:
  //this->setFolding(SonicPiScintilla::CircledTreeFoldStyle, 2);
  setCaretLineVisible(true);
  setCaretLineBackgroundColor(theme->color("CaretLineBackground"));
  setFoldMarginColors(theme->color("FoldMarginForeground"),theme->color("FoldMarginForeground"));
  setMarginLineNumbers(0, true);

  setMarginsBackgroundColor(theme->color("MarginBackground"));
  setMarginsForegroundColor(theme->color("MarginForeground"));
  setMarginsFont(QFont("Hack", 15, -1, true));
  setUtf8(true);
  setText("# Loading previous buffer contents. Please wait...");
  setLexer((QsciLexer *)lexer);

  markerDefine(RightArrow, 8);
  setMarkerBackgroundColor("deeppink", 8);

  setAutoCompletionThreshold(1);
  setAutoCompletionSource(SonicPiScintilla::AcsAPIs);
  setAutoCompletionCaseSensitivity(false);

  setSelectionBackgroundColor(theme->color("SelectionBackground"));
  setSelectionForegroundColor(theme->color("SelectionForeground"));
  setCaretWidth(5);
  setCaretForegroundColor(theme->color("CaretForeground"));
  setEolMode(EolUnix);

  SendScintilla(SCI_SETWORDCHARS, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:_?!");


}
QsciEditor::QsciEditor( QWidget *parent ) : QsciScintilla( parent ) {

	setFocus();

	/* Set tab width, and fonts */
	setTabWidth( 4 );
	setFont( QFont( "Envy Code R", 9 ) );
	setTabIndents( true );
	setIndentationsUseTabs( true );

	/* Set folding style */
	setFolding( QsciScintilla::BoxedTreeFoldStyle );

	/* Remove Horizontal Scrollbar, put a Vertical one */
	setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
	setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );

	/* Whitespace, indentation markings, and eol */
	setIndentationGuides( false );
	setWhitespaceVisibility( WsInvisible );
	setEolMode( EolUnix );

	/* Create Margins */
	setMarginWidth( 0, QString( " %1 " ).arg( lines() ) );
	setMarginWidth( 1, " " );
	setMarginWidth( 2, 10 );
	setMarginsFont( QFont( "Envy Code R", 9 ) );
	setWrapMode( QsciScintilla::WrapWord );

	/* Current Line Visibility */
	ensureCursorVisible();
	setCaretLineVisible( true );
	setCaretLineBackgroundColor( QColor( "#555555" ) );
	setCaretForegroundColor( QColor( "#FAFFAF" ) );
	setCaretWidth( 2 );

	/* Selection Color */
	// setSelectionBackgroundColor( "#333964" );
	// setSelectionForegroundColor( "*" );

	/* Margin and folding margins background colors */
	setMarginsBackgroundColor( QColor( "#A0A0A0" ) );
	setFoldMarginColors( QColor( "#666666" ), Qt::black );

	/* Set the width of the line */
	setLineWidth( 144 );
	ensureLineVisible( true );

	/* Set the paper and pen color - Editor BG and FG color */
	setPaper( Qt::black );
	setColor( Qt::white );

	/* Brace coloring */
	setBraceMatching( QsciScintilla::SloppyBraceMatch );
	setUnmatchedBraceForegroundColor( Qt::red );
	setUnmatchedBraceBackgroundColor( Qt::black );
	setMatchedBraceForegroundColor( Qt::darkGreen );
	setMatchedBraceBackgroundColor( Qt::black );

	/* Multi-selection and typing */
	SendScintilla( SCI_SETADDITIONALSELECTIONTYPING, true );
	SendScintilla( SCI_SETMULTIPLESELECTION, true );
	SendScintilla( SCI_SETMULTIPASTE, true );

	/* Scroll beyond the last line */
	SendScintilla( SCI_SETENDATLASTLINE, false );

	/* Set the editor state as not modified */
	setModified( false );

	/* Auto Save Timer: 60 sec */
	autoSaveTimer = new QBasicTimer();

	/* Enable and Show Custom context Menu */
	setContextMenuPolicy( Qt::CustomContextMenu );

	/* Connections */
	setupActions();

	/* Default Lexer */
	setLexer( new QLexerDefault() );

    QsciScintilla::FoldStyle state = static_cast<QsciScintilla::FoldStyle>( ( !folding() ) * 5 );
    if ( !state )
        foldAll( false );
    setFolding( state );
};