/// __  ____ _ _ __   __ _ _   _  __ _  __ _  ___
/// \ \/ / _` | '_ \ / _` | | | |/ _` |/ _` |/ _ \
///  >  < (_| | | | | (_| | |_| | (_| | (_| |  __/
/// /_/\_\__,_|_| |_|\__, |\__,_|\__,_|\__, |\___|
///                  |___/             |___/
///
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
///
/// xolatile@chud.cyou - xanguage - Syntax definitions of programming languages that I care about (and some that I don't care about).
///
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
///
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
/// for more details, if you dare, it is a lot of text that nobody wants to read...

typedef enum {
	language_common,                language_ada,                   language_c,                     language_cpp,
	language_d,                     language_eaxhla,                language_flat,                  language_fortran,
	language_pascal,                language_python,                language_go,                    language_lua,
	language_bash,                  language_haskell,               language_valgrind,              language_holy_c,
	language_count
} language_enumeration;

typedef struct {
	natural comment_colour;
	natural processor_colour;
	natural character_colour;
	natural string_colour;
	natural keyword_colour;
	natural type_colour;
	natural bracket_colour;
	natural operator_colour;
	natural number_colour;
	natural lowercase_colour;
	natural uppercase_colour;
	natural underscore_colour;
	natural register_colour;
	natural extension_colour;
	natural fatal_colour;
	natural comment_effect;
	natural processor_effect;
	natural character_effect;
	natural string_effect;
	natural keyword_effect;
	natural type_effect;
	natural bracket_effect;
	natural operator_effect;
	natural number_effect;
	natural lowercase_effect;
	natural uppercase_effect;
	natural underscore_effect;
	natural register_effect;
	natural extension_effect;
	natural fatal_effect;
} language_structure;

#define language_lowercase "abcdefghijklmnopqrstuvwxyz"
#define language_uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define language_letters   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define language_digits    "0123456789"

#include "xanguage/common.h"
#include "xanguage/ada.h"
#include "xanguage/c.h"
#include "xanguage/c++.h"
#include "xanguage/d.h"
#include "xanguage/eaxhla.h"
#include "xanguage/flat.h"
#include "xanguage/fortran.h"
#include "xanguage/pascal.h"
#include "xanguage/python.h"
#include "xanguage/go.h"
#include "xanguage/holy_c.h"
#include "xanguage/lua.h"
#include "xanguage/bash.h"
#include "xanguage/haskell.h"
#include "xanguage/valgrind.h"

#undef language_lowercase
#undef language_uppercase
#undef language_letters
#undef language_digits

static procedure (* language_highlighter [language_count]) (language_structure * language, syntax_structure * syntax) = {
	language_highlight_common,      language_highlight_ada,         language_highlight_c,           language_highlight_cpp,
	language_highlight_d,           language_highlight_eaxhla,      language_highlight_flat,        language_highlight_fortran,
	language_highlight_pascal,      language_highlight_python,      language_highlight_go,          language_highlight_lua,
	language_highlight_bash,        language_highlight_haskell,     language_highlight_valgrind,    language_highlight_holy_c
};

static character * language_short_option [language_count] = {
	"-X",   "-A",   "-C",   "-S",   "-D",   "-E",   "-T",   "-F",   "-P",   "-Y",   "-G",   "-L",   "-B",   "-H",   "-V",   "-O"
};

static character * language_long_option [language_count] = {
	"--common",     "--ada",        "--c",          "--cpp",        "--d",          "--eaxhla",     "--flat",       "--fortran",
	"--pascal",     "--python",     "--go",         "--lua",        "--bash",       "--haskell",    "--valgrind",   "--holyc"
};

static character * language_identifier [language_count] = {
	"Common",       "Ada",          "C",            "C++",          "D",            "EAXHLA",       "Flat",         "Fortran",
	"Pascal",       "Python",       "Go",           "Lua",          "Bash",         "Haskell",      "Valgrind",     "Holy C"
};

static language_structure * language_initialize (boolean true_colour) {
	language_structure * language = allocate (sizeof (* language));

	if (true_colour == true) {
		language->comment_colour    = 0xff777777u;
		language->processor_colour  = 0xff3377aau;
		language->character_colour  = 0xff7733ccu;
		language->string_colour     = 0xffcc3377u;
		language->keyword_colour    = 0xff33cceeu;
		language->type_colour       = 0xff55cceeu;
		language->bracket_colour    = 0xffee5533u;
		language->operator_colour   = 0xffeeaa33u;
		language->number_colour     = 0xffee33aau;
		language->lowercase_colour  = 0xffccccccu;
		language->uppercase_colour  = 0xffeeeeeeu;
		language->underscore_colour = 0xffaaaaaau;
		language->register_colour   = 0xff5577aau;
		language->extension_colour  = 0xff55aaccu;
		language->fatal_colour      = 0xffcc7755u;
	} else {
		language->comment_colour    = colour_grey;
		language->processor_colour  = colour_cyan;
		language->character_colour  = colour_pink;
		language->string_colour     = colour_pink;
		language->keyword_colour    = colour_yellow;
		language->type_colour       = colour_yellow;
		language->bracket_colour    = colour_blue;
		language->operator_colour   = colour_cyan;
		language->number_colour     = colour_pink;
		language->lowercase_colour  = colour_white;
		language->uppercase_colour  = colour_white;
		language->underscore_colour = colour_white;
		language->register_colour   = colour_cyan;
		language->extension_colour  = colour_yellow;
		language->fatal_colour      = colour_red;
		language->comment_effect    = effect_bold;
		language->processor_effect  = effect_italic;
		language->character_effect  = effect_bold;
		language->string_effect     = effect_normal;
		language->keyword_effect    = effect_bold;
		language->type_effect       = effect_normal;
		language->bracket_effect    = effect_bold;
		language->operator_effect   = effect_normal;
		language->number_effect     = effect_bold;
		language->lowercase_effect  = effect_normal;
		language->uppercase_effect  = effect_bold;
		language->underscore_effect = effect_italic;
		language->register_effect   = effect_italic;
		language->extension_effect  = effect_italic;
		language->fatal_effect      = effect_bold;
	}

	return (language);
}

static language_structure * language_deinitialize (language_structure * language) {
	return (deallocate (language));
}

static procedure language_conditionally_select (language_structure * language, syntax_structure * syntax, natural select) {
	if (syntax->count == 0) {
		if ((select == file_type_c_source) || (select == file_type_c_header)) {
			language_highlight_c (language, syntax);
		} else if ((select == file_type_ada_sexy_body) || (select == file_type_ada_specification)) {
			language_highlight_ada (language, syntax);
		} else if ((select == file_type_cpp_source) || (select == file_type_cpp_header)) {
			language_highlight_cpp (language, syntax);
		} else if (select == file_type_flat_assembly) {
			language_highlight_flat (language, syntax);
		} else if (select == file_type_fortran_90_source) {
			language_highlight_fortran (language, syntax);
		} else if (select == file_type_pascal_source) {
			language_highlight_pascal (language, syntax);
		} else if (select == file_type_eax_assembly) {
			language_highlight_eaxhla (language, syntax);
		} else if (select == file_type_python_script) {
			language_highlight_python (language, syntax);
		} else {
			language_highlight_common (language, syntax);
		}
	}
}