/* 
 * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "stdafx.h"

#include "mysql_sql_editor_be.h"

#include "../../../images/ui/editor_statement.xpm"
#include "../../../images/ui/editor_error.xpm"

using namespace bec;
using namespace grt;


Mysql_sql_editor::Mysql_sql_editor(db_mgmt_RdbmsRef rdbms)
:
Sql_editor(rdbms)
{
}


Mysql_sql_editor::~Mysql_sql_editor()
{
}


const char *Mysql_sql_editor::get_keywords(KeywordList list) const
{
  const static char general_keywords[] =
  "accessible add all alter analyze and as asc asensitive "
  "before between bigint binary blob both by "
  "call cascade case change char character check collate column condition connection constraint "
  "continue convert create cross current_date current_time current_timestamp current_user cursor "
  "database databases day_hour day_microsecond day_minute day_second dec decimal declare default "
  "delayed delete desc describe deterministic distinct distinctrow div double drop dual "
  "each else elseif enclosed escaped exists exit explain "
  "false fetch float float4 float8 for force foreign from fulltext "
  "goto grant group "
  "having high_priority hour_microsecond hour_minute hour_second "
  "if ignore in index infile inner inout insensitive insert int int1 int2 int3 int4 int8 integer "
  "interval into is iterate "
  "join "
  "key keys kill "
  "label leading leave left like limit linear lines load localtime localtimestamp lock long "
  "longblob longtext loop low_priority "
  "master_ssl_verify_server_cert match mediumblob mediumint mediumtext middleint minute_microsecond "
  "minute_second mod modifies "
  "natural not no_write_to_binlog null numeric "
  "on optimize option optionally or order out outer outfile "
  "precision primary procedure purge "
  "range read reads read_only read_write real references regexp release rename repeat replace "
  "require restrict return revoke right rlike "
  "schema schemas second_microsecond select sensitive separator set show smallint spatial specific "
  "sql sqlexception sqlstate sqlwarning sql_big_result sql_calc_found_rows sql_small_result ssl "
  "starting straight_join "
  "table terminated then tinyblob tinyint tinytext to trailing trigger true "
  "undo union unique unlock unsigned until update upgrade usage use using utc_date utc_time utc_timestamp "
  "values varbinary varchar varcharacter varying "
  "when where while with write "
  "xor "
  "year_month "
  "zerofill";
  
  const static char procedure_keywords[] = // Not reserved words but intrinsic part of procedure definitions.
  "begin comment end";
  
  const static char client_keywords[] = // Definition of keywords only used by clients, not the server itself.
  "delimiter";
  
  const static char user_keywords[] = // Definition of own keywords, not used by MySQL.
  "";

  switch (list)
  {
    case Procedure_Keywords:
      return procedure_keywords;
    case Client_Keywords:
      return client_keywords;
    case User_Keywords:
      return user_keywords;
    default:
      return general_keywords;
  }
}

const char *Mysql_sql_editor::get_function_names() const
{
  const static char function_names[] =
  "abs acos adddate aes_encrypt aes_decrypt ascii asin atan atan2 benchmark bin bit_count bit_or "
  "bit_and cast ceil ceiling current_user bit_length char_length character_length coalesce "
  "concat concat_ws connection_id conv convert count cos cot curdate curtime date_add date_format "
  "date_sub dayname dayofmonth dayofweek dayofyear decode degrees des_encrypt des_decrypt elt "
  "encode encrypt extract exp export_set field find_in_set floor format found_rows from_days "
  "from_unixtime get_lock greatest group_concat group_unique_users hex ifnull inet_aton inet_ntoa "
  "instr isnull is_free_lock last_insert_id lcase least length ln load_file locate log log2 log10 "
  "lower lpad ltrim make_set master_pos_wait max md5 mid min mod monthname now nullif octet_length "
  "oct old_password ord period_add period_diff pi position pow power quarter quote radians rand "
  "release_lock repeat reverse round rpad rtrim sec_to_time session_user subdate sign sin sha "
  "sha1 soundex space sqrt std stddev strcmp substring substring_index sum sysdate system_user "
  "tan time_format time_to_sec to_days trim ucase unique_users unix_timestamp upper user version "
  "week weekday yearweek";
  
  return function_names;
}


#include <Scintilla.h>
#include <SciLexer.h>
void Mysql_sql_editor::setup_scintilla_editor(boost::function<long (int, long, long)> send_editor)
{
  // Lexer type is MySQL.
  send_editor(SCI_SETLEXER, SCLEX_MYSQL, 0);

  // Number of styles we use with this lexer.
  send_editor(SCI_SETSTYLEBITS, send_editor(SCI_GETSTYLEBITSNEEDED, 0, 0), 0);
  // Keywords to highlight. Indices are:
  // 0 - Major keywords (reserved keywords)
  // 1 - Normal keywords (everything not reserved but integral part of the language)
  // 2 - Database objects
  // 3 - Function keywords
  // 4 - System variable keywords
  // 5 - Procedure keywords (keywords used in procedures like "begin" and "end")
  // 6..8 - User keywords 1..3
  send_editor(SCI_SETKEYWORDS, 0, (long)get_keywords(Sql_editor::General_Keywords));
  send_editor(SCI_SETKEYWORDS, 3, (long)get_function_names());
  send_editor(SCI_SETKEYWORDS, 5, (long)get_keywords(Sql_editor::Procedure_Keywords));
  send_editor(SCI_SETKEYWORDS, 6, (long)get_keywords(Sql_editor::Client_Keywords));
  send_editor(SCI_SETKEYWORDS, 7, (long)get_keywords(Sql_editor::User_Keywords));
  
  // [editor setStringProperty: SCI_STYLESETFONT, STYLE_DEFAULT value: @"Monospac821 BT"); // Very pleasing programmer's font.
#if defined(__APPLE__) || defined(_WIN32)
  send_editor(SCI_STYLESETSIZE, STYLE_DEFAULT, 14);
#else
  send_editor(SCI_STYLESETSIZE, STYLE_DEFAULT, 9);
#endif
 // send_editor(SCI_STYLESETFORE, STYLE_DEFAULT, 0x000000);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_DEFAULT, 0x000000);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_COMMENT, 0x909090);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_COMMENTLINE, 0x909090);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_HIDDENCOMMAND, 0x097BF7);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_HIDDENCOMMAND, 0xF0F0F0);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_VARIABLE, 0x378EA5);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_SYSTEMVARIABLE, 0x378EA5);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_KNOWNSYSTEMVARIABLE, 0x3A37A5);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_NUMBER, 0x30A0F0); //0xBF7F00);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_SQSTRING, 0x209F20); //0xFFAA3E);
  
  // Note: if we were using ANSI quotes we would set the DQSTRING to the same color as the 
  //       the back tick string.
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_DQSTRING, 0x274A6D);
  
  // Keyword highlighting.
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_MAJORKEYWORD, 0xBF7F00); //0x209F20);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_MAJORKEYWORD, 1);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_KEYWORD, 0xBF7F00); //0x209F20);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_KEYWORD, 1);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_PROCEDUREKEYWORD, 0x0040C0); // 0x56007F);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_PROCEDUREKEYWORD, 1);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_USER1, 0x007F00);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_USER2, 0x007F00);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_FUNCTION, 0xC040C0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_DATABASEOBJECT, 0xff0000);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_IDENTIFIER, 0x000000);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_QUOTEDIDENTIFIER, 0x275A7D);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_OPERATOR, 1);

  // Second set of highlighter states for tokens in a conditional (hidden) command.
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_COMMENT + 0x40, 0x909090);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_COMMENT + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_COMMENTLINE + 0x40, 0x909090);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_COMMENTLINE + 0x40, 0xF0F0F0);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_VARIABLE + 0x40, 0x378EA5);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_VARIABLE + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_SYSTEMVARIABLE + 0x40, 0x378EA5);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_SYSTEMVARIABLE + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_KNOWNSYSTEMVARIABLE + 0x40, 0x3A37A5);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_KNOWNSYSTEMVARIABLE + 0x40, 0xF0F0F0);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_NUMBER + 0x40, 0x30A0F0); //0xBF7F00);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_NUMBER + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_SQSTRING + 0x40, 0x209F20); //0xFFAA3E);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_SQSTRING + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_DQSTRING + 0x40, 0x274A6D);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_DQSTRING + 0x40, 0xF0F0F0);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_MAJORKEYWORD + 0x40, 0xBF7F00);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_MAJORKEYWORD + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_MAJORKEYWORD + 0x40, 1);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_KEYWORD + 0x40, 0xBF7F00); //0x209F20);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_KEYWORD + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_KEYWORD + 0x40, 1);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_PROCEDUREKEYWORD + 0x40, 0x0040C0); // 0x56007F);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_PROCEDUREKEYWORD + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_PROCEDUREKEYWORD + 0x40, 1);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_USER1 + 0x40, 0x007F00);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_USER1 + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_USER2 + 0x402, 0x007F00);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_USER2 + 0x40, 0xF0F0F0);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_FUNCTION + 0x40, 0xC040C0);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_FUNCTION + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_DATABASEOBJECT + 0x40, 0xff0000);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_DATABASEOBJECT + 0x40, 0xF0F0F0);
  
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_IDENTIFIER + 0x40, 0x000000);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_IDENTIFIER + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETFORE, SCE_MYSQL_QUOTEDIDENTIFIER + 0x40, 0x275A7D);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_QUOTEDIDENTIFIER + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETBACK, SCE_MYSQL_OPERATOR + 0x40, 0xF0F0F0);
  send_editor(SCI_STYLESETBOLD, SCE_MYSQL_OPERATOR + 0x40, 1);
  
  // Margin: Line number style.
  send_editor(SCI_STYLESETFORE, STYLE_LINENUMBER, 0x404040);
  send_editor(SCI_STYLESETBACK, STYLE_LINENUMBER, 0xE0E0E0);
  
  send_editor(SCI_SETMARGINTYPEN, 0, SC_MARGIN_NUMBER);
  int lineNumberStyleWidth = send_editor(SCI_TEXTWIDTH, STYLE_LINENUMBER, (long)"_99999");
  send_editor(SCI_SETMARGINWIDTHN, 0, lineNumberStyleWidth);
  
  // Margin: Markers.
  send_editor(SCI_SETMARGINWIDTHN, 1, 16);
  
  // Some special lexer properties.
  send_editor(SCI_SETPROPERTY, (long)"fold", (long)"1");
  send_editor(SCI_SETPROPERTY, (long)"fold.compact", (long)"0");
  send_editor(SCI_SETPROPERTY, (long)"fold.comment", (long)"1");
  
  // Folder setup.
  send_editor(SCI_SETMARGINWIDTHN, 2, 16);
  send_editor(SCI_SETMARGINMASKN, 2, SC_MASK_FOLDERS);
  send_editor(SCI_SETMARGINSENSITIVEN, 2, 1);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED);
  send_editor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER);
  for (int n= 25; n < 32; ++n) // Markers 25..31 are reserved for folding.
  {
    send_editor(SCI_MARKERSETFORE, n, 0xffffff);
    send_editor(SCI_MARKERSETBACK, n, 0x404040);
  }
  
  // Init markers & indicators for highlighting of syntax errors.
  send_editor(SCI_INDICSETFORE, 0, 0xD01921);
  send_editor(SCI_INDICSETUNDER, 0, 1);
  send_editor(SCI_INDICSETSTYLE, 0, INDIC_SQUIGGLE);
  
  // Gutter markers for errors and statments.
  send_editor(SCI_MARKERDEFINEPIXMAP, 0, (long)editor_statement);
  send_editor(SCI_MARKERSETBACK, 0, 0xD01921);
  
  send_editor(SCI_MARKERDEFINEPIXMAP, 1, (long)editor_error);
  send_editor(SCI_MARKERSETBACK, 1, 0xD01921);

  // Other settings.
  // - Set up the normal selection background color.
//Platform Specific:  send_editor(SCI_SETSELBACK, 1 value: [NSColor selectedTextBackgroundColor)];
  
  // - Tabulators + indentation
  send_editor(SCI_SETTABWIDTH, 4, 0);
  send_editor(SCI_SETUSETABS, 0, 0);
  send_editor(SCI_SETINDENT, 4, 0);
  send_editor(SCI_SETTABINDENTS, 1, 0);
}



