/* vi:set ts=8 sts=4 sw=4:
 *
 * VIM - Vi IMproved by Bram Moolenaar
 * AROS UI support by Franck Charlet
 *
 * Do ":help uganda"  in Vim to read copying and usage conditions.
 * Do ":help credits" in Vim to see a list of people who contributed.
 * See README.txt for an overview of the Vim source code.
 */

// TODO: - Create a mode to scroll without moving the caret (for the scrollbars).
//       - See to handle different font.

#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <utility/tagitem.h>
#include <graphics/text.h>
#include <graphics/rastport.h>
#include <graphics/layers.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/layers.h>
#include <devices/timer.h>
#include <assert.h>
#include "vim.h"
#include "gui_aros.h"
#include <math.h>
#include <limits.h>
#include <proto/gadtools.h>
#include <intuition/extensions.h>
#include <graphics/text.h>

#define DEBUG 10
#include <aros/debug.h>
#include <devices/rawkeycodes.h>

#define GUI_MCH_NBR_MENUS 8192

#ifdef FEAT_ASL
#include <proto/asl.h>
#endif

#include "version.h"

#define RGB(a, b, c) ((a && 0xff) * 0x10000 + (b * 0xff) * 0x100 + (c & 0xff))

/* When generating prototypes on Unix, these need to be defined */
#ifdef PROTO
# define STRPTR char *
# define BOOL int
# define UBYTE int
#endif

#define IDCMP ( IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE \
                | IDCMP_MENUPICK | IDCMP_MENUHELP | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY \
                | IDCMP_VANILLAKEY | IDCMP_ACTIVEWINDOW | IDCMP_GADGETDOWN | IDCMP_GADGETUP \
                | IDCMP_INACTIVEWINDOW | IDCMP_GADGETHELP | IDCMP_INTUITICKS | IDCMP_REFRESHWINDOW)

#define WFLAGS ( WFLG_REPORTMOUSE | WFLG_ACTIVATE | WFLG_SMART_REFRESH )

static struct timerequest *TimerIO;
static struct MsgPort *TimerMP;
static BOOL	TimerSent;

struct GFXBase *gfxBase;
struct ExecBase *SysBase;
struct LayersBase *layersBase;
struct Library *DiskfontBase;
struct NewMenu *menuPtr;

int cur_menu_nbr;

#ifdef FEAT_ASL
static struct FileRequester *file_req;
#endif

ULONG Last_Seconds;
ULONG Last_Micros;

struct MyColor
{
    WORD pen;
    BOOL alloced;
};

/*
 * Get color handle for color "name".
 * Return INVALCOLOR when not possible.
 */

typedef struct guicolor_tTable
{
    char *name;
    UBYTE red;
    UBYTE green;
    UBYTE blue;
    char allocated;
} guicolor_tTable;

static guicolor_tTable table[2048] =
{
 	{ "Grey", 0xbe,0xbe,0xbe},
	{ "Black", 0x00, 0x00, 0x00},
    { "LightRed", 0xff, 0x00, 0x00, 0 },
    { "LightMagenta", 0xff, 0x00, 0xff, 0 },
    { "grey40", 0x66, 0x66, 0x66, 0 },
    { "alice", 0xf0, 0xf8, 0xff, 0 },
    { "aliceblue", 0xf0, 0xf8, 0xff, 0 },
    { "antique", 0xfa, 0xeb, 0xd7, 0 },
    { "antiquewhite", 0xfa, 0xeb, 0xd7, 0 },
    { "antiquewhite1", 0xff, 0xef, 0xdb, 0 },
    { "antiquewhite2", 0xee, 0xdf, 0xcc, 0 },
    { "antiquewhite3", 0xcd, 0xc0, 0xb0, 0 },
    { "antiquewhite4", 0x8b, 0x83, 0x78, 0 },
    { "aquamarine", 0x7f, 0xff, 0xd4, 0 },
    { "aquamarine1", 0x7f, 0xff, 0xd4, 0 },
    { "aquamarine2", 0x76, 0xee, 0xc6, 0 },
    { "aquamarine3", 0x66, 0xcd, 0xaa, 0 },
    { "aquamarine4", 0x45, 0x8b, 0x74, 0 },
    { "azure", 0xf0, 0xff, 0xff, 0 },
    { "azure1", 0xf0, 0xff, 0xff, 0 },
    { "azure2", 0xe0, 0xee, 0xee, 0 },
    { "azure3", 0xc1, 0xcd, 0xcd, 0 },
    { "azure4", 0x83, 0x8b, 0x8b, 0 },
    { "beige", 0xf5, 0xf5, 0xdc, 0 },
    { "bisque", 0xff, 0xe4, 0xc4, 0 },
    { "bisque1", 0xff, 0xe4, 0xc4, 0 },
    { "bisque2", 0xee, 0xd5, 0xb7, 0 },
    { "bisque3", 0xcd, 0xb7, 0x9e, 0 },
    { "bisque4", 0x8b, 0x7d, 0x6b, 0 },
    { "blanched", 0xff, 0xeb, 0xcd, 0 },
    { "blanchedalmond", 0xff, 0xeb, 0xcd, 0 },
    { "blue", 0x8a, 0x2b, 0xe2, 0 },
    { "blue1", 0x00, 0x00, 0xff, 0 },
    { "blue2", 0x00, 0x00, 0xee, 0 },
    { "blue3", 0x00, 0x00, 0xcd, 0 },
    { "blue4", 0x00, 0x00, 0x8b, 0 },
    { "blueviolet", 0x8a, 0x2b, 0xe2, 0 },
    { "brown", 0xa5, 0x2a, 0x2a, 0 },
    { "brown1", 0xff, 0x40, 0x40, 0 },
    { "brown2", 0xee, 0x3b, 0x3b, 0 },
    { "brown3", 0xcd, 0x33, 0x33, 0 },
    { "brown4", 0x8b, 0x23, 0x23, 0 },
    { "burlywood", 0xde, 0xb8, 0x87, 0 },
    { "burlywood1", 0xff, 0xd3, 0x9b, 0 },
    { "burlywood2", 0xee, 0xc5, 0x91, 0 },
    { "burlywood3", 0xcd, 0xaa, 0x7d, 0 },
    { "burlywood4", 0x8b, 0x73, 0x55, 0 },
    { "cadet", 0x5f, 0x9e, 0xa0, 0 },
    { "cadetblue", 0x5f, 0x9e, 0xa0, 0 },
    { "cadetblue1", 0x98, 0xf5, 0xff, 0 },
    { "cadetblue2", 0x8e, 0xe5, 0xee, 0 },
    { "cadetblue3", 0x7a, 0xc5, 0xcd, 0 },
    { "cadetblue4", 0x53, 0x86, 0x8b, 0 },
    { "chartreuse", 0x7f, 0xff, 0x00, 0 },
    { "chartreuse1", 0x7f, 0xff, 0x00, 0 },
    { "chartreuse2", 0x76, 0xee, 0x00, 0 },
    { "chartreuse3", 0x66, 0xcd, 0x00, 0 },
    { "chartreuse4", 0x45, 0x8b, 0x00, 0 },
    { "chocolate", 0xd2, 0x69, 0x1e, 0 },
    { "chocolate1", 0xff, 0x7f, 0x24, 0 },
    { "chocolate2", 0xee, 0x76, 0x21, 0 },
    { "chocolate3", 0xcd, 0x66, 0x1d, 0 },
    { "chocolate4", 0x8b, 0x45, 0x13, 0 },
    { "coral", 0xff, 0x7f, 0x50, 0 },
    { "coral1", 0xff, 0x72, 0x56, 0 },
    { "coral2", 0xee, 0x6a, 0x50, 0 },
    { "coral3", 0xcd, 0x5b, 0x45, 0 },
    { "coral4", 0x8b, 0x3e, 0x2f, 0 },
    { "cornflower", 0x64, 0x95, 0xed, 0 },
    { "cornflowerblue", 0x64, 0x95, 0xed, 0 },
    { "cornsilk", 0xff, 0xf8, 0xdc, 0 },
    { "cornsilk1", 0xff, 0xf8, 0xdc, 0 },
    { "cornsilk2", 0xee, 0xe8, 0xcd, 0 },
    { "cornsilk3", 0xcd, 0xc8, 0xb1, 0 },
    { "cornsilk4", 0x8b, 0x88, 0x78, 0 },
    { "cyan", 0x00,0xff,0xff, 0 },
    { "cyan1", 0x00,0xff,0xff, 0 },
    { "cyan2", 0x00,0xee,0xee, 0 },
    { "cyan3", 0x00,0xcd,0xcd, 0 },
    { "cyan4", 0x00,0x8b,0x8b, 0 },
    { "dark", 0x8b,0x00,0x00, 0 },
    { "darkblue", 0x00,0x00,0x8b, 0 },
    { "darkcyan", 0x00,0x8b,0x8b, 0 },
    { "darkgoldenrod", 0xb8,0x86,0x0b, 0 },
    { "darkgoldenrod1", 0xff,0xb9,0x0f, 0 },
    { "darkgoldenrod2", 0xee,0xad,0x0e, 0 },
    { "darkgoldenrod3", 0xcd,0x95,0x0c, 0 },
    { "darkgoldenrod4", 0x8b,0x65,0x08, 0 },
    { "darkgray", 0xa9,0xa9,0xa9, 0 },
    { "darkgreen", 0x00,0x64,0x00, 0 },
    { "darkgrey", 0xa9,0xa9,0xa9, 0 },
    { "darkkhaki", 0xbd,0xb7,0x6b, 0 },
    { "darkmagenta", 0x8b,0x00,0x8b, 0 },
    { "darkolivegreen", 0x55,0x6b,0x2f, 0 },
    { "darkolivegreen1", 0xca,0xff,0x70, 0 },
    { "darkolivegreen2", 0xbc,0xee,0x68, 0 },
    { "darkolivegreen3", 0xa2,0xcd,0x5a, 0 },
    { "darkolivegreen4", 0x6e,0x8b,0x3d, 0 },
    { "darkorange", 0xff,0x8c,0x00, 0 },
    { "darkorange1", 0xff,0x7f,0x00, 0 },
    { "darkorange2", 0xee,0x76,0x00, 0 },
    { "darkorange3", 0xcd,0x66,0x00, 0 },
    { "darkorange4", 0x8b,0x45,0x00, 0 },
    { "darkorchid", 0x99,0x32,0xcc, 0 },
    { "darkorchid1", 0xbf,0x3e,0xff, 0 },
    { "darkorchid2", 0xb2,0x3a,0xee, 0 },
    { "darkorchid3", 0x9a,0x32,0xcd, 0 },
    { "darkorchid4", 0x68,0x22,0x8b, 0 },
    { "darkred", 0x8b,0x00,0x00, 0 },
    { "darksalmon", 0xe9,0x96,0x7a, 0 },
    { "darkseagreen", 0x8f,0xbc,0x8f, 0 },
    { "darkseagreen1", 0xc1,0xff,0xc1, 0 },
    { "darkseagreen2", 0xb4,0xee,0xb4, 0 },
    { "darkseagreen3", 0x9b,0xcd,0x9b, 0 },
    { "darkseagreen4", 0x69,0x8b,0x69, 0 },
    { "darkslateblue", 0x48,0x3d,0x8b, 0 },
    { "darkslategray", 0x2f,0x4f,0x4f, 0 },
    { "darkslategray1", 0x97,0xff,0xff, 0 },
    { "darkslategray2", 0x8d,0xee,0xee, 0 },
    { "darkslategray3", 0x79,0xcd,0xcd, 0 },
    { "darkslategray4", 0x52,0x8b,0x8b, 0 },
    { "darkslategrey", 0x2f,0x4f,0x4f, 0 },
    { "darkturquoise", 0x00,0xce,0xd1, 0 },
    { "darkviolet", 0x94,0x00,0xd3, 0 },
    { "deep", 0xff,0x14,0x93, 0 },
    { "deeppink", 0xff,0x14,0x93, 0 },
    { "deeppink1", 0xff,0x14,0x93, 0 },
    { "deeppink2", 0xee,0x12,0x89, 0 },
    { "deeppink3", 0xcd,0x10,0x76, 0 },
    { "deeppink4", 0x8b,0x0a,0x50, 0 },
    { "deepskyblue", 0x00,0xbf,0xff, 0 },
    { "deepskyblue1", 0x00,0xbf,0xff, 0 },
    { "deepskyblue2", 0x00,0xb2,0xee, 0 },
    { "deepskyblue3", 0x00,0x9a,0xcd, 0 },
    { "deepskyblue4", 0x00,0x68,0x8b, 0 },
    { "dim", 0x69,0x69,0x69, 0 },
    { "dimgray", 0x69,0x69,0x69, 0 },
    { "dimgrey", 0x69,0x69,0x69, 0 },
    { "dodger", 0x1e,0x90,0xff, 0 },
    { "dodgerblue", 0x1e,0x90,0xff, 0 },
    { "dodgerblue1", 0x1e,0x90,0xff, 0 },
    { "dodgerblue2", 0x1c,0x86,0xee, 0 },
    { "dodgerblue3", 0x18,0x74,0xcd, 0 },
    { "dodgerblue4", 0x10,0x4e,0x8b, 0 },
    { "firebrick", 0xb2,0x22,0x22, 0 },
    { "firebrick1", 0xff,0x30,0x30, 0 },
    { "firebrick2", 0xee,0x2c,0x2c, 0 },
    { "firebrick3", 0xcd,0x26,0x26, 0 },
    { "firebrick4", 0x8b,0x1a,0x1a, 0 },
    { "floral", 0xff,0xfa,0xf0, 0 },
    { "floralwhite", 0xff,0xfa,0xf0, 0 },
    { "forest", 0x22,0x8b,0x22, 0 },
    { "forestgreen", 0x22,0x8b,0x22, 0 },
    { "gainsboro", 0xdc,0xdc,0xdc, 0 },
    { "ghost", 0xf8,0xf8,0xff, 0 },
    { "ghostwhite", 0xf8,0xf8,0xff, 0 },
    { "gold", 0xff,0xd7,0x00, 0 },
    { "gold1", 0xff,0xd7,0x00, 0 },
    { "gold2", 0xee,0xc9,0x00, 0 },
    { "gold3", 0xcd,0xad,0x00, 0 },
    { "gold4", 0x8b,0x75,0x00, 0 },
    { "goldenrod", 0xda,0xa5,0x20, 0 },
    { "goldenrod1", 0xff,0xc1,0x25, 0 },
    { "goldenrod2", 0xee,0xb4,0x22, 0 },
    { "goldenrod3", 0xcd,0x9b,0x1d, 0 },
    { "goldenrod4", 0x8b,0x69,0x14, 0 },
    { "gray", 0xbe,0xbe,0xbe, 0 },
    { "gray0", 0x00,0x00,0x00, 0 },
    { "gray1", 0x03,0x03,0x03, 0 },
    { "gray10", 0x1a,0x1a,0x1a, 0 },
    { "gray100", 0xff,0xff,0xff, 0 },
    { "gray11", 0x1c,0x1c,0x1c, 0 },
    { "gray12", 0x1f,0x1f,0x1f, 0 },
    { "gray13", 0x21,0x21,0x21, 0 },
    { "gray14", 0x24,0x24,0x24, 0 },
    { "gray15", 0x26,0x26,0x26, 0 },
    { "gray16", 0x29,0x29,0x29, 0 },
    { "gray17", 0x2b,0x2b,0x2b, 0 },
    { "gray18", 0x2e,0x2e,0x2e, 0 },
    { "gray19", 0x30,0x30,0x30, 0 },
    { "gray2", 0x05,0x05,0x05, 0 },
    { "gray20", 0x33,0x33,0x33, 0 },
    { "gray21", 0x36,0x36,0x36, 0 },
    { "gray22", 0x38,0x38,0x38, 0 },
    { "gray23", 0x3b,0x3b,0x3b, 0 },
    { "gray24", 0x3d,0x3d,0x3d, 0 },
    { "gray25", 0x40,0x40,0x40, 0 },
    { "gray26", 0x42,0x42,0x42, 0 },
    { "gray27", 0x45,0x45,0x45, 0 },
    { "gray28", 0x47,0x47,0x47, 0 },
    { "gray29", 0x4a,0x4a,0x4a, 0 },
    { "gray3", 0x08,0x08,0x08, 0 },
    { "gray30", 0x4d,0x4d,0x4d, 0 },
    { "gray31", 0x4f,0x4f,0x4f, 0 },
    { "gray32", 0x52,0x52,0x52, 0 },
    { "gray33", 0x54,0x54,0x54, 0 },
    { "gray34", 0x57,0x57,0x57, 0 },
    { "gray35", 0x59,0x59,0x59, 0 },
    { "gray36", 0x5c,0x5c,0x5c, 0 },
    { "gray37", 0x5e,0x5e,0x5e, 0 },
    { "gray38", 0x61,0x61,0x61, 0 },
    { "gray39", 0x63,0x63,0x63, 0 },
    { "gray4", 0x0a,0x0a,0x0a, 0 },
    { "gray40", 0x66,0x66,0x66, 0 },
    { "gray41", 0x69,0x69,0x69, 0 },
    { "gray42", 0x6b,0x6b,0x6b, 0 },
    { "gray43", 0x6e,0x6e,0x6e, 0 },
    { "gray44", 0x70,0x70,0x70, 0 },
    { "gray45", 0x73,0x73,0x73, 0 },
    { "gray46", 0x75,0x75,0x75, 0 },
    { "gray47", 0x78,0x78,0x78, 0 },
    { "gray48", 0x7a,0x7a,0x7a, 0 },
    { "gray49", 0x7d,0x7d,0x7d, 0 },
    { "gray5", 0x0d,0x0d,0x0d, 0 },
    { "gray50", 0x7f,0x7f,0x7f, 0 },
    { "gray51", 0x82,0x82,0x82, 0 },
    { "gray52", 0x85,0x85,0x85, 0 },
    { "gray53", 0x87,0x87,0x87, 0 },
    { "gray54", 0x8a,0x8a,0x8a, 0 },
    { "gray55", 0x8c,0x8c,0x8c, 0 },
    { "gray56", 0x8f,0x8f,0x8f, 0 },
    { "gray57", 0x91,0x91,0x91, 0 },
    { "gray58", 0x94,0x94,0x94, 0 },
    { "gray59", 0x96,0x96,0x96, 0 },
    { "gray6", 0x0f,0x0f,0x0f, 0 },
    { "gray60", 0x99,0x99,0x99, 0 },
    { "gray61", 0x9c,0x9c,0x9c, 0 },
    { "gray62", 0x9e,0x9e,0x9e, 0 },
    { "gray63", 0xa1,0xa1,0xa1, 0 },
    { "gray64", 0xa3,0xa3,0xa3, 0 },
    { "gray65", 0xa6,0xa6,0xa6, 0 },
    { "gray66", 0xa8,0xa8,0xa8, 0 },
    { "gray67", 0xab,0xab,0xab, 0 },
    { "gray68", 0xad,0xad,0xad, 0 },
    { "gray69", 0xb0,0xb0,0xb0, 0 },
    { "gray7", 0x12,0x12,0x12, 0 },
    { "gray70", 0xb3,0xb3,0xb3, 0 },
    { "gray71", 0xb5,0xb5,0xb5, 0 },
    { "gray72", 0xb8,0xb8,0xb8, 0 },
    { "gray73", 0xba,0xba,0xba, 0 },
    { "gray74", 0xbd,0xbd,0xbd, 0 },
    { "gray75", 0xbf,0xbf,0xbf, 0 },
    { "gray76", 0xc2,0xc2,0xc2, 0 },
    { "gray77", 0xc4,0xc4,0xc4, 0 },
    { "gray78", 0xc7,0xc7,0xc7, 0 },
    { "gray79", 0xc9,0xc9,0xc9, 0 },
    { "gray8", 0x14,0x14,0x14, 0 },
    { "gray80", 0xcc,0xcc,0xcc, 0 },
    { "gray81", 0xcf,0xcf,0xcf, 0 },
    { "gray82", 0xd1,0xd1,0xd1, 0 },
    { "gray83", 0xd4,0xd4,0xd4, 0 },
    { "gray84", 0xd6,0xd6,0xd6, 0 },
    { "gray85", 0xd9,0xd9,0xd9, 0 },
    { "gray86", 0xdb,0xdb,0xdb, 0 },
    { "gray87", 0xde,0xde,0xde, 0 },
    { "gray88", 0xe0,0xe0,0xe0, 0 },
    { "gray89", 0xe3,0xe3,0xe3, 0 },
    { "gray9", 0x17,0x17,0x17, 0 },
    { "gray90", 0xe5,0xe5,0xe5, 0 },
    { "gray91", 0xe8,0xe8,0xe8, 0 },
    { "gray92", 0xeb,0xeb,0xeb, 0 },
    { "gray93", 0xed,0xed,0xed, 0 },
    { "gray94", 0xf0,0xf0,0xf0, 0 },
    { "gray95", 0xf2,0xf2,0xf2, 0 },
    { "gray96", 0xf5,0xf5,0xf5, 0 },
    { "gray97", 0xf7,0xf7,0xf7, 0 },
    { "gray98", 0xfa,0xfa,0xfa, 0 },
    { "gray99", 0xfc,0xfc,0xfc, 0 },
    { "green", 0xad,0xff,0x2f, 0 },
    { "green1", 0x00,0xff,0x00, 0 },
    { "green2", 0x00,0xee,0x00, 0 },
    { "green3", 0x00,0xcd,0x00, 0 },
    { "green4", 0x00,0x8b,0x00, 0 },
    { "greenyellow", 0xad,0xff,0x2f, 0 },
    { "grey0", 0x00,0x00,0x00, 0 },
    { "grey1", 0x03,0x03,0x03, 0 },
    { "grey10", 0x1a,0x1a,0x1a, 0 },
    { "grey100", 0xff,0xff,0xff, 0 },
    { "grey11", 0x1c,0x1c,0x1c, 0 },
    { "grey12", 0x1f,0x1f,0x1f, 0 },
    { "grey13", 0x21,0x21,0x21, 0 },
    { "grey14", 0x24,0x24,0x24, 0 },
    { "grey15", 0x26,0x26,0x26, 0 },
    { "grey16", 0x29,0x29,0x29, 0 },
    { "grey17", 0x2b,0x2b,0x2b, 0 },
    { "grey18", 0x2e,0x2e,0x2e, 0 },
    { "grey19", 0x30,0x30,0x30, 0 },
    { "grey2", 0x05,0x05,0x05, 0 },
    { "grey20", 0x33,0x33,0x33, 0 },
    { "grey21", 0x36,0x36,0x36, 0 },
    { "grey22", 0x38,0x38,0x38, 0 },
    { "grey23", 0x3b,0x3b,0x3b, 0 },
    { "grey24", 0x3d,0x3d,0x3d, 0 },
    { "grey25", 0x40,0x40,0x40, 0 },
    { "grey26", 0x42,0x42,0x42, 0 },
    { "grey27", 0x45,0x45,0x45, 0 },
    { "grey28", 0x47,0x47,0x47, 0 },
    { "grey29", 0x4a,0x4a,0x4a, 0 },
    { "grey3", 0x08,0x08,0x08, 0 },
    { "grey30", 0x4d,0x4d,0x4d, 0 },
    { "grey31", 0x4f,0x4f,0x4f, 0 },
    { "grey32", 0x52,0x52,0x52, 0 },
    { "grey33", 0x54,0x54,0x54, 0 },
    { "grey34", 0x57,0x57,0x57, 0 },
    { "grey35", 0x59,0x59,0x59, 0 },
    { "grey36", 0x5c,0x5c,0x5c, 0 },
    { "grey37", 0x5e,0x5e,0x5e, 0 },
    { "grey38", 0x61,0x61,0x61, 0 },
    { "grey39", 0x63,0x63,0x63, 0 },
    { "grey4", 0x0a,0x0a,0x0a, 0 },
    { "grey4", 0x66,0x66,0x66, 0 },
    { "grey41", 0x69,0x69,0x69, 0 },
    { "grey42", 0x6b,0x6b,0x6b, 0 },
    { "grey43", 0x6e,0x6e,0x6e, 0 },
    { "grey44", 0x70,0x70,0x70, 0 },
    { "grey45", 0x73,0x73,0x73, 0 },
    { "grey46", 0x75,0x75,0x75, 0 },
    { "grey47", 0x78,0x78,0x78, 0 },
    { "grey48", 0x7a,0x7a,0x7a, 0 },
    { "grey49", 0x7d,0x7d,0x7d, 0 },
    { "grey5", 0x0d,0x0d,0x0d, 0 },
    { "grey50", 0x7f,0x7f,0x7f, 0 },
    { "grey51", 0x82,0x82,0x82, 0 },
    { "grey52", 0x85,0x85,0x85, 0 },
    { "grey53", 0x87,0x87,0x87, 0 },
    { "grey54", 0x8a,0x8a,0x8a, 0 },
    { "grey55", 0x8c,0x8c,0x8c, 0 },
    { "grey56", 0x8f,0x8f,0x8f, 0 },
    { "grey57", 0x91,0x91,0x91, 0 },
    { "grey58", 0x94,0x94,0x94, 0 },
    { "grey59", 0x96,0x96,0x96, 0 },
    { "grey6", 0x0f,0x0f,0x0f, 0 },
    { "grey60", 0x99,0x99,0x99, 0 },
    { "grey61", 0x9c,0x9c,0x9c, 0 },
    { "grey62", 0x9e,0x9e,0x9e, 0 },
    { "grey63", 0xa1,0xa1,0xa1, 0 },
    { "grey64", 0xa3,0xa3,0xa3, 0 },
    { "grey65", 0xa6,0xa6,0xa6, 0 },
    { "grey66", 0xa8,0xa8,0xa8, 0 },
    { "grey67", 0xab,0xab,0xab, 0 },
    { "grey68", 0xad,0xad,0xad, 0 },
    { "grey69", 0xb0,0xb0,0xb0, 0 },
    { "grey7", 0x12,0x12,0x12, 0 },
    { "grey70", 0xb3,0xb3,0xb3, 0 },
    { "grey71", 0xb5,0xb5,0xb5, 0 },
    { "grey72", 0xb8,0xb8,0xb8, 0 },
    { "grey73", 0xba,0xba,0xba, 0 },
    { "grey74", 0xbd,0xbd,0xbd, 0 },
    { "grey75", 0xbf,0xbf,0xbf, 0 },
    { "grey76", 0xc2,0xc2,0xc2, 0 },
    { "grey77", 0xc4,0xc4,0xc4, 0 },
    { "grey78", 0xc7,0xc7,0xc7, 0 },
    { "grey79", 0xc9,0xc9,0xc9, 0 },
    { "grey8", 0x14,0x14,0x14, 0 },
    { "grey80", 0xcc,0xcc,0xcc, 0 },
    { "grey81", 0xcf,0xcf,0xcf, 0 },
    { "grey82", 0xd1,0xd1,0xd1, 0 },
    { "grey83", 0xd4,0xd4,0xd4, 0 },
    { "grey84", 0xd6,0xd6,0xd6, 0 },
    { "grey85", 0xd9,0xd9,0xd9, 0 },
    { "grey86", 0xdb,0xdb,0xdb, 0 },
    { "grey87", 0xde,0xde,0xde, 0 },
    { "grey88", 0xe0,0xe0,0xe0, 0 },
    { "grey89", 0xe3,0xe3,0xe3, 0 },
    { "grey9", 0x17,0x17,0x17, 0 },
    { "grey90", 0xe5,0xe5,0xe5, 0 },
    { "grey91", 0xe8,0xe8,0xe8, 0 },
    { "grey92", 0xeb,0xeb,0xeb, 0 },
    { "grey93", 0xed,0xed,0xed, 0 },
    { "grey94", 0xf0,0xf0,0xf0, 0 },
    { "grey95", 0xf2,0xf2,0xf2, 0 },
    { "grey96", 0xf5,0xf5,0xf5, 0 },
    { "grey97", 0xf7,0xf7,0xf7, 0 },
    { "grey98", 0xfa,0xfa,0xfa, 0 },
    { "grey99", 0xfc,0xfc,0xfc, 0 },
    { "honeydew", 0xf0,0xff,0xf0, 0 },
    { "honeydew1", 0xf0,0xff,0xf0, 0 },
    { "honeydew2", 0xe0,0xee,0xe0, 0 },
    { "honeydew3", 0xc1,0xcd,0xc1, 0 },
    { "honeydew4", 0x83,0x8b,0x83, 0 },
    { "hot", 0xff,0x69,0xb4, 0 },
    { "hotpink", 0xff,0x69,0xb4, 0 },
    { "hotpink1", 0xff,0x6e,0xb4, 0 },
    { "hotpink2", 0xee,0x6a,0xa7, 0 },
    { "hotpink3", 0xcd,0x60,0x90, 0 },
    { "hotpink4", 0x8b,0x3a,0x62, 0 },
    { "indian", 0xcd,0x5c,0x5c, 0 },
    { "indianred", 0xcd,0x5c,0x5c, 0 },
    { "indianred1", 0xff,0x6a,0x6a, 0 },
    { "indianred2", 0xee,0x63,0x63, 0 },
    { "indianred3", 0xcd,0x55,0x55, 0 },
    { "indianred4", 0x8b,0x3a,0x3a, 0 },
    { "ivory", 0xff,0xff,0xf0, 0 },
    { "ivory1", 0xff,0xff,0xf0, 0 },
    { "ivory2", 0xee,0xee,0xe0, 0 },
    { "ivory3", 0xcd,0xcd,0xc1, 0 },
    { "ivory4", 0x8b,0x8b,0x83, 0 },
    { "khaki", 0xf0,0xe6,0x8c, 0 },
    { "khaki1", 0xff,0xf6,0x8f, 0 },
    { "khaki2", 0xee,0xe6,0x85, 0 },
    { "khaki3", 0xcd,0xc6,0x73, 0 },
    { "khaki4", 0x8b,0x86,0x4e, 0 },
    { "lavender", 0xff,0xf0,0xf5, 0 },
    { "lavenderblush", 0xff,0xf0,0xf5, 0 },
    { "lavenderblush1", 0xff,0xf0,0xf5, 0 },
    { "lavenderblush2", 0xee,0xe0,0xe5, 0 },
    { "lavenderblush3", 0xcd,0xc1,0xc5, 0 },
    { "lavenderblush4", 0x8b,0x83,0x86, 0 },
    { "lawn", 0x7c,0xfc,0x00, 0 },
    { "lawngreen", 0x7c,0xfc,0x00, 0 },
    { "lemon", 0xff,0xfa,0xcd, 0 },
    { "lemonchiffon", 0xff,0xfa,0xcd, 0 },
    { "lemonchiffon1", 0xff,0xfa,0xcd, 0 },
    { "lemonchiffon2", 0xee,0xe9,0xbf, 0 },
    { "lemonchiffon3", 0xcd,0xc9,0xa5, 0 },
    { "lemonchiffon4", 0x8b,0x89,0x70, 0 },
    { "light", 0x90,0xee,0x90, 0 },
    { "lightblue", 0xad,0xd8,0xe6, 0 },
    { "lightblue1", 0xbf,0xef,0xff, 0 },
    { "lightblue2", 0xb2,0xdf,0xee, 0 },
    { "lightblue3", 0x9a,0xc0,0xcd, 0 },
    { "lightblue4", 0x68,0x83,0x8b, 0 },
    { "lightcoral", 0xf0,0x80,0x80, 0 },
    { "lightcyan", 0xe0,0xff,0xff, 0 },
    { "lightcyan1", 0xe0,0xff,0xff, 0 },
    { "lightcyan2", 0xd1,0xee,0xee, 0 },
    { "lightcyan3", 0xb4,0xcd,0xcd, 0 },
    { "lightcyan4", 0x7a,0x8b,0x8b, 0 },
    { "lightgoldenrod", 0xee,0xdd,0x82, 0 },
    { "lightgoldenrod1", 0xff,0xec,0x8b, 0 },
    { "lightgoldenrod2", 0xee,0xdc,0x82, 0 },
    { "lightgoldenrod3", 0xcd,0xbe,0x70, 0 },
    { "lightgoldenrod4", 0x8b,0x81,0x4c, 0 },
    { "lightgoldenrodyellow", 0xfa,0xfa,0xd2, 0 },
    { "lightgray", 0xd3,0xd3,0xd3, 0 },
    { "lightgreen", 0x90,0xee,0x90, 0 },
    { "lightgrey", 0xd3,0xd3,0xd3, 0 },
    { "lightpink", 0xff,0xb6,0xc1, 0 },
    { "lightpink1", 0xff,0xae,0xb9, 0 },
    { "lightpink2", 0xee,0xa2,0xad, 0 },
    { "lightpink3", 0xcd,0x8c,0x95, 0 },
    { "lightpink4", 0x8b,0x5f,0x65, 0 },
    { "lightsalmon", 0xff,0xa0,0x7a, 0 },
    { "lightsalmon1", 0xff,0xa0,0x7a, 0 },
    { "lightsalmon2", 0xee,0x95,0x72, 0 },
    { "lightsalmon3", 0xcd,0x81,0x62, 0 },
    { "lightsalmon4", 0x8b,0x57,0x42, 0 },
    { "lightseagreen", 0x20,0xb2,0xaa, 0 },
    { "lightskyblue", 0x87,0xce,0xfa, 0 },
    { "lightskyblue1", 0xb0,0xe2,0xff, 0 },
    { "lightskyblue2", 0xa4,0xd3,0xee, 0 },
    { "lightskyblue3", 0x8d,0xb6,0xcd, 0 },
    { "lightskyblue4", 0x60,0x7b,0x8b, 0 },
    { "lightslateblue", 0x84,0x70,0xff, 0 },
    { "lightslategray", 0x77,0x88,0x99, 0 },
    { "lightslategrey", 0x77,0x88,0x99, 0 },
    { "lightsteelblue", 0xb0,0xc4,0xde, 0 },
    { "lightsteelblue1", 0xca,0xe1,0xff, 0 },
    { "lightsteelblue2", 0xbc,0xd2,0xee, 0 },
    { "lightsteelblue3", 0xa2,0xb5,0xcd, 0 },
    { "lightsteelblue4", 0x6e,0x7b,0x8b, 0 },
    { "lightyellow", 0xff,0xff,0xe0, 0 },
    { "lightyellow1", 0xff,0xff,0xe0, 0 },
    { "lightyellow2", 0xee,0xee,0xd1, 0 },
    { "lightyellow3", 0xcd,0xcd,0xb4, 0 },
    { "lightyellow4", 0x8b,0x8b,0x7a, 0 },
    { "lime", 0x32,0xcd,0x32, 0 },
    { "limegreen", 0x32,0xcd,0x32, 0 },
    { "linen", 0xfa,0xf0,0xe6, 0 },
    { "magenta", 0xff,0x00,0xff, 0 },
    { "magenta1", 0xff,0x00,0xff, 0 },
    { "magenta2", 0xee,0x00,0xee, 0 },
    { "magenta3", 0xcd,0x00,0xcd, 0 },
    { "magenta4", 0x8b,0x00,0x8b, 0 },
    { "maroon", 0xb0,0x30,0x60, 0 },
    { "maroon1", 0xff,0x34,0xb3, 0 },
    { "maroon2", 0xee,0x30,0xa7, 0 },
    { "maroon3", 0xcd,0x29,0x90, 0 },
    { "maroon4", 0x8b,0x1c,0x62, 0 },
    { "medium", 0x93,0x70,0xdb, 0 },
    { "mediumaquamarine", 0x66,0xcd,0xaa, 0 },
    { "mediumblue", 0x00,0x00,0xcd, 0 },
    { "mediumorchid", 0xba,0x55,0xd3, 0 },
    { "mediumorchid1", 0xe0,0x66,0xff, 0 },
    { "mediumorchid2", 0xd1,0x5f,0xee, 0 },
    { "mediumorchid3", 0xb4,0x52,0xcd, 0 },
    { "mediumorchid4", 0x7a,0x37,0x8b, 0 },
    { "mediumpurple", 0x93,0x70,0xdb, 0 },
    { "mediumpurple1", 0xab,0x82,0xff, 0 },
    { "mediumpurple2", 0x9f,0x79,0xee, 0 },
    { "mediumpurple3", 0x89,0x68,0xcd, 0 },
    { "mediumpurple4", 0x5d,0x47,0x8b, 0 },
    { "mediumseagreen", 0x3c,0xb3,0x71, 0 },
    { "mediumslateblue", 0x7b,0x68,0xee, 0 },
    { "mediumspringgreen", 0x00,0xfa,0x9a, 0 },
    { "mediumturquoise", 0x48,0xd1,0xcc, 0 },
    { "mediumvioletred", 0xc7,0x15,0x85, 0 },
    { "midnight", 0x19,0x19,0x70, 0 },
    { "midnightblue", 0x19,0x19,0x70, 0 },
    { "mint", 0xf5,0xff,0xfa, 0 },
    { "mintcream", 0xf5,0xff,0xfa, 0 },
    { "misty", 0xff,0xe4,0xe1, 0 },
    { "mistyrose", 0xff,0xe4,0xe1, 0 },
    { "mistyrose1", 0xff,0xe4,0xe1, 0 },
    { "mistyrose2", 0xee,0xd5,0xd2, 0 },
    { "mistyrose3", 0xcd,0xb7,0xb5, 0 },
    { "mistyrose4", 0x8b,0x7d,0x7b, 0 },
    { "moccasin", 0xff,0xe4,0xb5, 0 },
    { "navajo", 0xff,0xde,0xad, 0 },
    { "navajowhite", 0xff,0xde,0xad, 0 },
    { "navajowhite1", 0xff,0xde,0xad, 0 },
    { "navajowhite2", 0xee,0xcf,0xa1, 0 },
    { "navajowhite3", 0xcd,0xb3,0x8b, 0 },
    { "navajowhite4", 0x8b,0x79,0x5e, 0 },
    { "navy", 0x00,0x00,0x80, 0 },
    { "navyblue", 0x00,0x00,0x80, 0 },
    { "old", 0xfd,0xf5,0xe6, 0 },
    { "oldlace", 0xfd,0xf5,0xe6, 0 },
    { "olive", 0x6b,0x8e,0x23, 0 },
    { "olivedrab", 0x6b,0x8e,0x23, 0 },
    { "olivedrab1", 0xc0,0xff,0x3e, 0 },
    { "olivedrab2", 0xb3,0xee,0x3a, 0 },
    { "olivedrab3", 0x9a,0xcd,0x32, 0 },
    { "olivedrab4", 0x69,0x8b,0x22, 0 },
    { "orange", 0xff,0x45,0x00, 0 },
    { "orange1", 0xff,0xa5,0x00, 0 },
    { "orange2", 0xee,0x9a,0x00, 0 },
    { "orange3", 0xcd,0x85,0x00, 0 },
    { "orange4", 0x8b,0x5a,0x00, 0 },
    { "orangered", 0xff,0x45,0x00, 0 },
    { "orangered1", 0xff,0x45,0x00, 0 },
    { "orangered2", 0xee,0x40,0x00, 0 },
    { "orangered3", 0xcd,0x37,0x00, 0 },
    { "orangered4", 0x8b,0x25,0x00, 0 },
    { "orchid", 0xda,0x70,0xd6, 0 },
    { "orchid1", 0xff,0x83,0xfa, 0 },
    { "orchid2", 0xee,0x7a,0xe9, 0 },
    { "orchid3", 0xcd,0x69,0xc9, 0 },
    { "orchid4", 0x8b,0x47,0x89, 0 },
    { "pale", 0xdb,0x70,0x93, 0 },
    { "palegoldenrod", 0xee,0xe8,0xaa, 0 },
    { "palegreen", 0x98,0xfb,0x98, 0 },
    { "palegreen1", 0x9a,0xff,0x9a, 0 },
    { "palegreen2", 0x90,0xee,0x90, 0 },
    { "palegreen3", 0x7c,0xcd,0x7c, 0 },
    { "palegreen4", 0x54,0x8b,0x54, 0 },
    { "paleturquoise", 0xaf,0xee,0xee, 0 },
    { "paleturquoise1", 0xbb,0xff,0xff, 0 },
    { "paleturquoise2", 0xae,0xee,0xee, 0 },
    { "paleturquoise3", 0x96,0xcd,0xcd, 0 },
    { "paleturquoise4", 0x66,0x8b,0x8b, 0 },
    { "palevioletred", 0xdb,0x70,0x93, 0 },
    { "palevioletred1", 0xff,0x82,0xab, 0 },
    { "palevioletred2", 0xee,0x79,0x9f, 0 },
    { "palevioletred3", 0xcd,0x68,0x89, 0 },
    { "palevioletred4", 0x8b,0x47,0x5d, 0 },
    { "papaya", 0xff,0xef,0xd5, 0 },
    { "papayawhip", 0xff,0xef,0xd5, 0 },
    { "peach", 0xff,0xda,0xb9, 0 },
    { "peachpuff", 0xff,0xda,0xb9, 0 },
    { "peachpuff1", 0xff,0xda,0xb9, 0 },
    { "peachpuff2", 0xee,0xcb,0xad, 0 },
    { "peachpuff3", 0xcd,0xaf,0x95, 0 },
    { "peachpuff4", 0x8b,0x77,0x65, 0 },
    { "peru", 0xcd,0x85,0x3f, 0 },
    { "pink", 0xff,0xc0,0xcb, 0 },
    { "pink1", 0xff,0xb5,0xc5, 0 },
    { "pink2", 0xee,0xa9,0xb8, 0 },
    { "pink3", 0xcd,0x91,0x9e, 0 },
    { "pink4", 0x8b,0x63,0x6c, 0 },
    { "plum", 0xdd,0xa0,0xdd, 0 },
    { "plum1", 0xff,0xbb,0xff, 0 },
    { "plum2", 0xee,0xae,0xee, 0 },
    { "plum3", 0xcd,0x96,0xcd, 0 },
    { "plum4", 0x8b,0x66,0x8b, 0 },
    { "powder", 0xb0,0xe0,0xe6, 0 },
    { "powderblue", 0xb0,0xe0,0xe6, 0 },
    { "purple", 0xa0,0x20,0xf0, 0 },
    { "purple1", 0x9b,0x30,0xff, 0 },
    { "purple2", 0x91,0x2c,0xee, 0 },
    { "purple3", 0x7d,0x26,0xcd, 0 },
    { "purple4", 0x55,0x1a,0x8b, 0 },
    { "red", 0xff,0x00,0x00, 0 },
    { "red1", 0xff,0x00,0x00, 0 },
    { "red2", 0xee,0x00,0x00, 0 },
    { "red3", 0xcd,0x00,0x00, 0 },
    { "red4", 0x8b,0x00,0x00, 0 },
    { "rosy", 0xbc,0x8f,0x8f, 0 },
    { "rosybrown", 0xbc,0x8f,0x8f, 0 },
    { "rosybrown1", 0xff,0xc1,0xc1, 0 },
    { "rosybrown2", 0xee,0xb4,0xb4, 0 },
    { "rosybrown3", 0xcd,0x9b,0x9b, 0 },
    { "rosybrown4", 0x8b,0x69,0x69, 0 },
    { "royal", 0x41,0x69,0xe1, 0 },
    { "royalblue", 0x41,0x69,0xe1, 0 },
    { "royalblue1", 0x48,0x76,0xff, 0 },
    { "royalblue2", 0x43,0x6e,0xee, 0 },
    { "royalblue3", 0x3a,0x5f,0xcd, 0 },
    { "royalblue4", 0x27,0x40,0x8b, 0 },
    { "saddle", 0x8b,0x45,0x13, 0 },
    { "saddlebrown", 0x8b,0x45,0x13, 0 },
    { "salmon", 0xfa,0x80,0x72, 0 },
    { "salmon1", 0xff,0x8c,0x69, 0 },
    { "salmon2", 0xee,0x82,0x62, 0 },
    { "salmon3", 0xcd,0x70,0x54, 0 },
    { "salmon4", 0x8b,0x4c,0x39, 0 },
    { "sandy", 0xf4,0xa4,0x60, 0 },
    { "sandybrown", 0xf4,0xa4,0x60, 0 },
    { "sea", 0x2e,0x8b,0x57, 0 },
    { "seagreen", 0x2e,0x8b,0x57, 0 },
    { "seagreen1", 0x54,0xff,0x9f, 0 },
    { "seagreen2", 0x4e,0xee,0x94, 0 },
    { "seagreen3", 0x43,0xcd,0x80, 0 },
    { "seagreen4", 0x2e,0x8b,0x57, 0 },
    { "seashell", 0xff, 0xf5, 0xee, 0 },
    { "seashell1", 0xff,0xf5,0xee, 0 },
    { "seashell2", 0xee,0xe5,0xde, 0 },
    { "seashell3", 0xcd,0xc5,0xbf, 0 },
    { "seashell4", 0x8b,0x86,0x82, 0 },
    { "sienna", 0xa0,0x52,0x2d, 0 },
    { "sienna1", 0xff,0x82,0x47, 0 },
    { "sienna2", 0xee,0x79,0x42, 0 },
    { "sienna3", 0xcd,0x68,0x39, 0 },
    { "sienna4", 0x8b,0x47,0x26, 0 },
    { "sky", 0x87,0xce,0xeb, 0 },
    { "skyblue", 0x87,0xce,0xeb, 0 },
    { "skyblue1", 0x87,0xce,0xff, 0 },
    { "skyblue2", 0x7e,0xc0,0xee, 0 },
    { "skyblue3", 0x6c,0xa6,0xcd, 0 },
    { "skyblue4", 0x4a,0x70,0x8b, 0 },
    { "slate", 0x6a,0x5a,0xcd, 0 },
    { "slateblue", 0x6a,0x5a,0xcd, 0 },
    { "slateblue1", 0x83,0x6f,0xff, 0 },
    { "slateblue2", 0x7a,0x67,0xee, 0 },
    { "slateblue3", 0x69,0x59,0xcd, 0 },
    { "slateblue4", 0x47,0x3c,0x8b, 0 },
    { "slategray", 0x70,0x80,0x90, 0 },
    { "slategray1", 0xc6,0xe2,0xff, 0 },
    { "slategray2", 0xb9,0xd3,0xee, 0 },
    { "slategray3", 0x9f,0xb6,0xcd, 0 },
    { "slategray4", 0x6c,0x7b,0x8b, 0 },
    { "slategrey", 0x70,0x80,0x90, 0 },
    { "snow", 0xff,0xfa,0xfa, 0 },
    { "snow1", 0xff,0xfa,0xfa, 0 },
    { "snow2", 0xee,0xe9,0xe9, 0 },
    { "snow3", 0xcd,0xc9,0xc9, 0 },
    { "snow4", 0x8b,0x89,0x89, 0 },
    { "spring", 0x00,0xff,0x7f, 0 },
    { "springgreen", 0x00,0xff,0x7f, 0 },
    { "springgreen1", 0x00,0xff,0x7f, 0 },
    { "springgreen2", 0x00,0xee,0x76, 0 },
    { "springgreen3", 0x00,0xcd,0x66, 0 },
    { "springgreen4", 0x00,0x8b,0x45, 0 },
    { "steel", 0x46,0x82,0xb4, 0 },
    { "steelblue", 0x46,0x82,0xb4, 0 },
    { "steelblue1", 0x63,0xb8,0xff, 0 },
    { "steelblue2", 0x5c,0xac,0xee, 0 },
    { "steelblue3", 0x4f,0x94,0xcd, 0 },
    { "steelblue4", 0x36,0x64,0x8b, 0 },
    { "tan", 0xd2,0xb4,0x8c, 0 },
    { "tan1", 0xff,0xa5,0x4f, 0 },
    { "tan2", 0xee,0x9a,0x49, 0 },
    { "tan3", 0xcd,0x85,0x3f, 0 },
    { "tan4", 0x8b,0x5a,0x2b, 0 },
    { "thistle", 0xd8,0xbf,0xd8, 0 },
    { "thistle1", 0xff,0xe1,0xff, 0 },
    { "thistle2", 0xee,0xd2,0xee, 0 },
    { "thistle3", 0xcd,0xb5,0xcd, 0 },
    { "thistle4", 0x8b,0x7b,0x8b, 0 },
    { "tomato", 0xff,0x63,0x47, 0 },
    { "tomato1", 0xff,0x63,0x47, 0 },
    { "tomato2", 0xee,0x5c,0x42, 0 },
    { "tomato3", 0xcd,0x4f,0x39, 0 },
    { "tomato4", 0x8b,0x36,0x26, 0 },
    { "turquoise", 0x40,0xe0,0xd0, 0 },
    { "turquoise1", 0x00,0xf5,0xff, 0 },
    { "turquoise2", 0x00,0xe5,0xee, 0 },
    { "turquoise3", 0x00,0xc5,0xcd, 0 },
    { "turquoise4", 0x00,0x86,0x8b, 0 },
    { "violet", 0xee,0x82,0xee, 0 },
    { "violetred", 0xd0,0x20,0x90, 0 },
    { "violetred1", 0xff,0x3e,0x96, 0 },
    { "violetred2", 0xee,0x3a,0x8c, 0 },
    { "violetred3", 0xcd,0x32,0x78, 0 },
    { "violetred4", 0x8b,0x22,0x52, 0 },
    { "wheat", 0xf5,0xde,0xb3, 0 },
    { "wheat1", 0xff,0xe7,0xba, 0 },
    { "wheat2", 0xee,0xd8,0xae, 0 },
    { "wheat3", 0xcd,0xba,0x96, 0 },
    { "wheat4", 0x8b,0x7e,0x66, 0 },
    { "white", 0xff,0xff,0xff, 0 },
    { "whitesmoke", 0xf5,0xf5,0xf5, 0 },
    { "yellow", 0xff,0xff,0x00, 0 },
    { "yellow1", 0xff,0xff,0x00, 0 },
    { "yellow2", 0xee,0xee,0x00, 0 },
    { "yellow3", 0xcd,0xcd,0x00, 0 },
    { "yellow4", 0x8b,0x8b,0x00, 0 },
    { "yellowgreen", 0x9a,0xcd,0x32, 0 },
    { NULL, 0, 0, 0, 0 }
};

struct Trans_key
{
    int amiga_key;
    int vim_key;
    int vim_shift_key;
};

struct Trans_key table_keys[] =
{
    { RAWKEY_BACKSPACE, K_BS },

    { RAWKEY_TAB, K_TAB, K_S_TAB },

    { RAWKEY_INSERT, K_INS, K_INS },
    { RAWKEY_HOME, K_HOME, K_S_HOME },
    { RAWKEY_END, K_END, K_S_END },
    { RAWKEY_PAGEUP, K_PAGEUP, K_PAGEUP },
    { RAWKEY_PAGEDOWN, K_PAGEDOWN, K_PAGEDOWN },
    { RAWKEY_HELP, K_HELP, K_HELP },

    { RAWKEY_UP, K_UP, K_S_UP },
    { RAWKEY_LEFT, K_LEFT, K_S_LEFT },
    { RAWKEY_DOWN, K_DOWN, K_S_DOWN },
    { RAWKEY_RIGHT, K_RIGHT, K_S_RIGHT },

    { RAWKEY_KP_7, K_K7, K_K7 },
    { RAWKEY_KP_8, K_K8, K_K8 },
    { RAWKEY_KP_9, K_K9, K_K9 },
    { RAWKEY_KP_4, K_K4, K_K4 },
    { RAWKEY_KP_5, K_K5, K_K5 },
    { RAWKEY_KP_6, K_K6, K_K6 },
    { RAWKEY_KP_1, K_K1, K_K1 },
    { RAWKEY_KP_2, K_K2, K_K2 },
    { RAWKEY_KP_3, K_K3, K_K3 },
    { RAWKEY_KP_0, K_K0, K_K0 },
    { RAWKEY_KP_DECIMAL, K_KPOINT, K_KPOINT },
    { RAWKEY_KP_PLUS, K_KPLUS, K_KPLUS },
    { RAWKEY_KP_ENTER, K_KENTER, K_KENTER },

    { RAWKEY_F1, K_F1, K_S_F1 },
    { RAWKEY_F2, K_F2, K_S_F2 },
    { RAWKEY_F3, K_F3, K_S_F3 },
    { RAWKEY_F4, K_F4, K_S_F4 },
    { RAWKEY_F5, K_F5, K_S_F5 },
    { RAWKEY_F6, K_F6, K_S_F6 },
    { RAWKEY_F7, K_F7, K_S_F7 },
    { RAWKEY_F8, K_F8, K_S_F8 },
    { RAWKEY_F9, K_F9, K_S_F9 },
    { RAWKEY_F10, K_F10, K_S_F10 },
    { RAWKEY_F11, K_F11, K_S_F11 },
    { RAWKEY_F12, K_F12, K_S_F12 },
};

struct MyColor MyColorTable[2048];

void HandleEvent(unsigned long * object);
static UBYTE getrealcolor(guicolor_T i);

static struct
{
    unsigned int  key_sym;
    char_u  vim_code0;
    char_u  vim_code1;
} special_keys[] =
{
    { 0, 0, 0 }
};

static int characterWidth = -1;
static int characterHeight = -1;

static struct
{
    BOOL active;
    enum
    {
        CursorOff,
        CursorOn,
        CursorWait
    } state;
    int onTime;
    int	offTime;
    int	waitTime;
    int	current;
} cursor =
{
    TRUE,
    CursorWait,
    10,
    10,
    7,
    0
};

enum DrawBoxMode
{
    DB_Filled,
    DB_NotFilled
};

struct TextAttr aros_font =
{
    (STRPTR) "",     /* name */
    0,               /* size */
    0,               /* style */
    0                /* flags */
};


static void TextDimensions(void)
{
    struct TextExtent textExt;

    TextExtent(gui.window->RPort, (unsigned char *) "hq", 1, &textExt);

    characterWidth = textExt.te_Width;
    characterHeight = textExt.te_Height;
}

static int WidthCharToPoint(int width)
{
    return width * characterWidth;
}

static int HeightCharToPoint(int height)
{
    return height * characterHeight;
}

static void refreshBorder(void)
{
    RefreshWindowFrame(gui.window);
}

static void drawBox(enum DrawBoxMode mode,
                    unsigned short col,
                    unsigned short row,
                    int w,
                    int h,
                    guicolor_T color)
{
    LONG apen = GetAPen(gui.window->RPort);
    LONG x1, y1, x2, y2;

    SetAPen(gui.window->RPort, getrealcolor(color));

    x1 = WidthCharToPoint(col);
    y1 = HeightCharToPoint(row + 1) - h;
    x2 = x1 + w - 1;
    y2 = HeightCharToPoint(row + 1) - 1;

    switch(mode)
    {
        case DB_Filled:
            RectFill(gui.window->RPort, x1, y1, x2, y2);
            break;

        case DB_NotFilled:
            Move(gui.window->RPort, x1, y1);
            Draw(gui.window->RPort, x2, y1);
            Draw(gui.window->RPort, x2, y2);
            Draw(gui.window->RPort, x1, y2);
            Draw(gui.window->RPort, x1, y1);
            break;
    }

    SetAPen(gui.window->RPort, apen);
}

scrollbar_T *own_gui_find_scrollbar(struct Gadget *bargad)
{
    win_T *wp;

    if (gui.bottom_sbar.bargad == bargad)
        return &gui.bottom_sbar;

    FOR_ALL_WINDOWS(wp)
    {
        if (wp->w_scrollbars[SBAR_LEFT].bargad == bargad)
            return &wp->w_scrollbars[SBAR_LEFT];
        if (wp->w_scrollbars[SBAR_RIGHT].bargad == bargad)
            return &wp->w_scrollbars[SBAR_RIGHT];
    }
    return NULL;
}

static int_u trans_modifiers(int modifiers)
{
    int_u vimModifiers = 0;

    if (modifiers & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_CAPSLOCK))
        vimModifiers |= MOD_MASK_SHIFT;
    if (modifiers & (IEQUALIFIER_CONTROL))
        vimModifiers |= MOD_MASK_CTRL;
    if (modifiers & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
        vimModifiers |= MOD_MASK_ALT;
    if (modifiers & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND))
        vimModifiers |= MOD_MASK_META;
    return (vimModifiers);
}

/* Add possible keys to queue */
/* note: fetching vim_key may be wrong on big endian machines */
void convert_raw_input(char_u *string, int *len, int code, int modifiers)
{
    int i;

    for(i = 0; i < sizeof(table_keys) / sizeof(table_keys[0]); i++)
    {
        if(table_keys[i].amiga_key == code)
        {
            string[*len] = CSI;
            *len = *len + 1;
            if(modifiers & MOD_MASK_SHIFT)
                string[*len] = KEY2TERMCAP0(table_keys[i].vim_shift_key);
            else
                string[*len] = KEY2TERMCAP0(table_keys[i].vim_key);
            *len = *len + 1;
            if(modifiers & MOD_MASK_SHIFT)
                string[*len] = KEY2TERMCAP1(table_keys[i].vim_shift_key);
            else
                string[*len] = KEY2TERMCAP1(table_keys[i].vim_key);
            *len = *len + 1;
            break;
        }
    }
}

static enum event EventHandler(void)
{
    struct IntuiMessage *msg;
    enum event returnEvent = ev_Ignore;
    int class, code;
    static int dragging = 0;
    static int mouseX, mouseY;
    char_u string[40];
    BOOL quit_request = FALSE;
    int vim_modifiers = 0;
    int len = 0;
    int mode;
    int cx;
    int cy;
    int click_was_double;
    scrollbar_T *scrollbar;
    struct MenuItem *item;
    int menuNumber;

    msg = (struct IntuiMessage *) GetMsg(gui.window->UserPort);

    if (!msg)
    {
        returnEvent = ev_NullEvent;
    }
    else
    {
        class = msg->Class;
        code = msg->Code;

        switch(class)
        {
            case IDCMP_INTUITICKS:
               break;

            case IDCMP_MOUSEBUTTONS:
                if(msg->MouseX >= 0 &&
                   msg->MouseX < gui.window->Width &&
                   msg->MouseY >= 0 &&
                   msg->MouseY < gui.window->Height)
                {
                   vim_modifiers = trans_modifiers(msg->Qualifier);

                   /* Look for double clicks */
                   click_was_double = DoubleClick(Last_Seconds,
                                                  Last_Micros,
                                                  msg->Seconds,
                                                  msg->Micros);

                   Last_Seconds = msg->Seconds;
                   Last_Micros = msg->Micros;

                   if (code == SELECTDOWN)
                   {
                       dragging = 1;
                       gui_send_mouse_event(MOUSE_LEFT,
                                            mouseX = msg->MouseX,
                                            mouseY = msg->MouseY,
                                            click_was_double,
                                            vim_modifiers);
                   }
                   else if (code == SELECTUP)
                   {
                       dragging = 0;
                       gui_send_mouse_event(MOUSE_RELEASE,
                                            msg->MouseX,
                                            msg->MouseY,
                                            click_was_double,
                                            vim_modifiers);
                   }
               }
               returnEvent = ev_MouseButtons;
               break;

            case IDCMP_MOUSEMOVE:
                if(msg->MouseX >= 0 &&
                   msg->MouseX < gui.window->Width &&
                   msg->MouseY >= 0 &&
                   msg->MouseY < gui.window->Height)
               {
                   vim_modifiers = trans_modifiers(msg->Qualifier);

                   mouseX = msg->MouseX;
                   mouseY = msg->MouseY;
                   if (dragging)
                   {
                       gui_send_mouse_event(MOUSE_DRAG, mouseX, mouseY, FALSE, vim_modifiers);
                   }
               }

               if(gui.sel_bargad)
               {
                   if(gui.sel_bargad->bargad->Flags & GFLG_SELECTED)
                   {
                       long newtop = 0;
                       GetAttr(PGA_Top, (Object *) gui.sel_bargad->bargad, (void *) &newtop);
                       gui_drag_scrollbar(gui.sel_bargad, newtop, TRUE);
                       out_flush();
                   }
                   else
                   {
                        gui.sel_bargad = NULL;
                   }
               }
               returnEvent = ev_MouseMove;
               break;

            case IDCMP_VANILLAKEY:
               returnEvent = ev_KeyStroke;

               vim_modifiers = trans_modifiers(msg->Qualifier);
               len = 0;

               if (vim_modifiers)
               {
                   string[len++] = CSI;
                   string[len++] = KS_MODIFIER;
                   string[len++] = vim_modifiers;
               }

               if (code == CSI)
               {
                   /* Insert CSI as K_CSI.  Untested! */
                   string[len++] = (char_u) code;
                   string[len++] = KS_EXTRA;
                   string[len++] = (int) KE_CSI;
                   add_to_input_buf(string, len);
               }
               else if (code == 127)
               {
                   mode = get_shape_idx(FALSE);
                   if(mode == SHAPE_IDX_I || mode == SHAPE_IDX_R || mode == SHAPE_IDX_CI)
                   {
                       string[len++] = CSI;
                       string[len++] = 'k';
                       string[len++] = 'D';
                       add_to_input_buf(string, len);
                   }
               }
               else
               {
                   if(code == 8)
                   {
                       mode = get_shape_idx(FALSE);
                       if(mode != SHAPE_IDX_I &&
                          mode != SHAPE_IDX_R &&
                          mode != SHAPE_IDX_CI &&
                          mode != SHAPE_IDX_C)
                       {
                            break;
                       }
                       if ((State & CMDLINE) != CMDLINE)
                       {
                           string[len++] = CSI;
                           string[len++] = 'k';
                           string[len++] = 'b';
                           add_to_input_buf(string, len);
                           break;
                       }
                   }
                   string[len++] = (char_u) code;
                   if (input_conv.vc_type != CONV_NONE)
                   {
                       len += convert_input(&string[len - 1], 1, sizeof(string));
                   }
                   //D(bug("LEN: %d %d %d", code, len, vim_modifiers));

                   add_to_input_buf(string, len);
               }
               break;

            case IDCMP_RAWKEY:
               vim_modifiers = trans_modifiers(msg->Qualifier);
               len = 0;

               if (vim_modifiers)
               {
                   string[len++] = CSI;
                   string[len++] = KS_MODIFIER;
                   string[len++] = vim_modifiers;
               }

               convert_raw_input(string, &len, code, vim_modifiers);

               //D(bug("RAW: %d %d\n", code, vim_modifiers));

               if(len) add_to_input_buf(string, len);

               if (msg->Code == RAWKEY_NM_WHEEL_UP)
               {
                   gui_send_mouse_event(MOUSE_4,
                                        msg->MouseX,
                                        msg->MouseY - (gui.screen->BarHeight + 1),
                                        FALSE,
                                        vim_modifiers);
               }
               else if (msg->Code == RAWKEY_NM_WHEEL_DOWN)
               {
                   gui_send_mouse_event(MOUSE_5,
                                        msg->MouseX,
                                        msg->MouseY - (gui.screen->BarHeight + 1),
                                        FALSE,
                                        vim_modifiers);
               }

               returnEvent = ev_KeyStroke;
               break;

            case IDCMP_MENUVERIFY:
               returnEvent = ev_MenuVerify;
               /* Menu verification requested */
               switch (code)
               {
                   case MENUWAITING:
                       /*
                        ** It's not for us, the user is accessing another
                        ** programs menu, this is a good time to do some
                        ** cleanup etc
                        */
                       break;
                   case MENUHOT:
                       /*
                        ** It is our menu that is going hot, we have kontrol
                        ** Menu action can be cancelled by
                        ** msg->Code = MENUCANCEL;
                        */
                       break;
                   default:
                       break;
               }
               break;

            case IDCMP_MENUPICK:
               returnEvent = ev_MenuPick;

               menuNumber = code;
               item = (struct MenuItem *) ItemAddress(gui.menu, menuNumber);
               if (item)
               {
                   gui_menu_cb(GTMENUITEM_USERDATA(item));
               }
               break;

            case IDCMP_CLOSEWINDOW:
                quit_request = TRUE;
                break;

            case IDCMP_NEWSIZE:
               cx = gui.window->Width;;
               cy = gui.window->Height - (gui.screen->BarHeight + 1);
               cx = ((cx / characterWidth) * characterWidth);;
               cy = ((cy / characterHeight) * characterHeight) + characterHeight;
               gui_resize_shell(cx, cy);
               RefreshWindowFrame(gui.window);
               returnEvent = ev_NewSize;
               break;

            case IDCMP_REFRESHWINDOW:
               refreshBorder();
               returnEvent = ev_RefreshWindow;
               break;

            case IDCMP_GADGETDOWN:
            case IDCMP_GADGETUP:

                scrollbar = own_gui_find_scrollbar((struct Gadget *) msg->IAddress);
                switch(class)
                {
                    case IDCMP_GADGETUP:
                        gui.sel_bargad = NULL;
                        returnEvent = ev_GadgetUp;
                        break;
                    case IDCMP_GADGETDOWN:
                        gui.sel_bargad = scrollbar;
                        returnEvent = ev_GadgetDown;
                        break;
                }
                if(scrollbar)
                {
                    long newtop = 0;
                    GetAttr(PGA_Top, (Object *) scrollbar->bargad, (void *) &newtop);
                    gui_drag_scrollbar(scrollbar, newtop, FALSE);
                    out_flush();
                }
                break;

            case IDCMP_MENUHELP:
                returnEvent = ev_MenuHelp;
                break;

            case IDCMP_GADGETHELP:
                returnEvent = ev_GadgetHelp;
                break;

            case IDCMP_INACTIVEWINDOW:
                gui.in_focus = FALSE;
                gui_update_cursor(TRUE, FALSE);
                break;

            case IDCMP_ACTIVEWINDOW:
                gui.in_focus = TRUE;
                gui_update_cursor(TRUE, FALSE);
                break;

            default:
                break;

        }
        ReplyMsg((struct Message *) msg);
    }

    if (quit_request)
    {
        getout(0);
    }

    return returnEvent;
}

static int checkEventHandler(void)
{
    enum event happened;

    do
    {
        happened = EventHandler();
    }
    while  (happened != ev_NullEvent);

    return OK;
}

int gui_mch_set_blinking(long wait, long on, long off)
{
    cursor.waitTime = wait / 100;
    cursor.onTime = on / 100;
    cursor.offTime = off / 100;
    return OK;
}

void gui_mch_prepare(int *argc, char **argv)
{
    SysBase = (struct ExecBase *) OpenLibrary((STRPTR) "exec.library", 0);
    gfxBase = (struct GFXBase *) OpenLibrary((STRPTR) "graphics.library", 0);
    layersBase = (struct LayersBase *) OpenLibrary((STRPTR) "layers.library", 0);
    DiskfontBase = OpenLibrary((STRPTR) "diskfont.library", 0);
#ifdef FEAT_ASL
    AslBase = OpenLibrary((STRPTR) "asl.library", 0);
#endif

    if (!SysBase || !gfxBase || !layersBase || ! DiskfontBase
#ifdef FEAT_ASL
        || !AslBase
#endif
       )
    {
        exit(3);
    }
}

void atexitDoThis(void)
{
    gui_mch_exit(-1);
}

/*
 * Check if the GUI can be started.  Called before gvimrc is sourced.
 * Return OK or FAIL.
 */
int gui_mch_init_check(void)
{
    if (SysBase && gfxBase && layersBase && AslBase && DiskfontBase)
        return OK;
    return FAIL;
}

int gui_mch_init(void)
{
    int returnCode = FAIL; /* assume failure */

    TimerMP = CreateMsgPort();
    if (!TimerMP) return FAIL;

    TimerIO = (struct timerequest *) CreateIORequest(TimerMP, sizeof(*TimerIO));
    if (!TimerIO) return FAIL;

    if (OpenDevice((STRPTR) "timer.device", UNIT_VBLANK, &TimerIO->tr_node, 0)) return FAIL;

    gui.screen = OpenScreenTags( NULL,
                                 SA_Left, 0,
                                 SA_Top, 0,
                                 SA_Type, CUSTOMSCREEN,
                                 SA_Overscan, OSCAN_TEXT,
                                 SA_LikeWorkbench , TRUE,
                                 SA_AutoScroll, TRUE,
                                 SA_Title, (ULONG) VIM_VERSION_LONG,
                                 TAG_DONE
                               );

    gui.window = OpenWindowTags(NULL, WA_Left, 0,
                                      WA_Top, (gui.screen->BarHeight + 1),
                                      WA_Width, gui.screen->Width,
                                      WA_Height, gui.screen->Height - (gui.screen->BarHeight + 1),
                                      WA_Borderless, TRUE,
                                      WA_Backdrop, TRUE,
                                      WA_IDCMP, IDCMP,
                                      WA_Flags, WFLAGS,
                                      WA_AutoAdjust, FALSE,
                                      WA_CustomScreen, gui.screen,
                                      WA_MouseQueue, 1,
                                      WA_RptQueue, 10,
                                      WA_NoCareRefresh, TRUE,
                                      WA_GimmeZeroZero, TRUE,
                                      TAG_END);

    if (gui.window)
    {
        gui.in_use = TRUE;
        gui.in_focus = TRUE;
        gui.norm_pixel = gui.def_norm_pixel = 1;
        gui.back_pixel = gui.def_back_pixel = 0;

        set_normal_colors();
        gui_check_colors();

        SetDrMd(gui.window->RPort, JAM2);
        gui_mch_set_colors(gui.norm_pixel, gui.back_pixel);

        atexit(atexitDoThis);

        TextDimensions();
        returnCode = OK; /* we've had success */
        if (gui_win_x != -1 && gui_win_y != -1)
        {
            gui_mch_set_winpos(gui_win_x, gui_win_y);
        }

        gui_mch_clear_all();
    }
    gui.menu = NULL;

    menuPtr = (struct NewMenu *) malloc(GUI_MCH_NBR_MENUS * sizeof(struct NewMenu));
    memset(menuPtr, 0, GUI_MCH_NBR_MENUS * sizeof(struct NewMenu));
    cur_menu_nbr = 0;

    return returnCode;
}

void gui_mch_new_colors(void)
{
    SetAPen(gui.window->RPort, getrealcolor(gui.norm_pixel));
    SetBPen(gui.window->RPort, getrealcolor(gui.back_pixel));
}

int gui_mch_open(void)
{
    highlight_gui_started();
    return OK;
}

char_u *gui_mch_browse(int saving,
                       char_u *title,
                       char_u *dflt,          /* default name */
                       char_u *ext,           /* default extension */
                       char_u *initdir,       /* NULL = current dir */
                       char_u *filter)        /* filter */
{
    char_u *result = NULL;

#ifdef FEAT_ASL
    file_req = AllocAslRequestTags(ASL_FileRequest, TAG_DONE);
    if(file_req)
    {
        if(AslRequestTags(file_req,
                          ASLFR_TitleText, title,
                          ASLFR_Window, gui.window,
                          ASLFR_InitialFile, dflt,
                          ASLFR_InitialDrawer, initdir,
                          ASLFR_InitialPattern, filter,
                          ASLFR_DoSaveMode, saving == BROWSE_SAVE ? TRUE : FALSE,
                          ASLFR_DrawersOnly, saving == BROWSE_DIR ? TRUE : FALSE,
                          ASLFR_DoPatterns, TRUE,
                          ASLFR_RejectIcons, TRUE,
                          TAG_END))
        {
            long sellen = strlen((char *) file_req->fr_Drawer) + strlen((char *) file_req->fr_File) + 2;
            if((result = (char_u *) malloc(sellen)))
            {
                memset(result, 0, sellen);
                strcpy((char *) result, (char *) file_req->rf_Dir);
                if(strlen((char *) file_req->rf_Dir)) strcat((char *) result, "/");
                strcat((char *) result, (char *) file_req->rf_File);
            }
        }
        FreeAslRequest(file_req);
    }
#else
    /* TODO: create an alternative to asl ? */
#endif

    return(result);
}

void gui_mch_exit(int returnCode)
{
	if (TimerSent)
    {
        if (!CheckIO(&TimerIO->tr_node)) AbortIO(&TimerIO->tr_node);
        WaitIO(&TimerIO->tr_node);
        TimerSent = FALSE;
    }

    if (TimerIO)
    {
        CloseDevice(&TimerIO->tr_node);
        DeleteIORequest(&TimerIO->tr_node);
        TimerIO = NULL;
    }

    if (TimerMP)
    {
        DeleteMsgPort(TimerMP);
        TimerMP = NULL;
    }

    if (gui.window)
    {
        int i;

        i = 0;
        for(;;)
        {
            if(menuPtr[i].nm_Label != NM_BARLABEL)
            {
                if(menuPtr[i].nm_Label) free((void *) menuPtr[i].nm_Label);
            }
            if(menuPtr[i].nm_CommKey)
            {
                free((void *) menuPtr[i].nm_CommKey);
            }
            if(menuPtr[i].nm_Type == NM_END) break;
            i++;
        }

        for(i = 0; i < sizeof(table) / sizeof(table[0]); i++)
        {
            if (MyColorTable[i].alloced)
            {
                ReleasePen(gui.window->WScreen->ViewPort.ColorMap, MyColorTable[i].pen);
                MyColorTable[i].alloced = FALSE;
            }
			if(table[i].allocated == TRUE)
			{
				if(table[i].name) free(table[i].name);
			}
        }

		CloseWindow(gui.window);

        CloseScreen(gui.screen);

#ifdef FEAT_ASL
        CloseLibrary((struct Library *) AslBase);
#endif

        CloseLibrary((struct Library *) DiskfontBase);
        CloseLibrary((struct Library *) layersBase);
        CloseLibrary((struct Library *) SysBase);
        CloseLibrary((struct Library *) gfxBase);

        if(menuPtr) free(menuPtr);
			cur_menu_nbr = 0;

        gui.window = NULL;
        gui.in_use = FALSE;
    }
}

/*
 * Get the position of the top left corner of the window.
 */
int gui_mch_get_winpos(int *x, int *y)
{
    if (gui.window)
    {
        *x = 0;
        *y = 0;
    }
    else
    {
        return FAIL;
    }

    return OK;
}

/*
 * Set the position of the top left corner of the window to the given
 * coordinates.
 */
void gui_mch_set_winpos(int x, int y)
{
    if (gui.window)
    {
        ChangeWindowBox(gui.window,
                        0,
                        (gui.screen->BarHeight + 1),
                        gui.window->Width,
                        gui.window->Height - (gui.screen->BarHeight + 1)
                       );
    }
}

void gui_mch_set_shellsize(int width, int height,
                           int min_width, int min_height,
                           int base_width, int base_height,
                           int direction)
{
    ChangeWindowBox(gui.window,
                    0,
                    (gui.screen->BarHeight + 1),
                    WidthCharToPoint(width),
                    HeightCharToPoint(height) - (gui.screen->BarHeight + 1)
                   );
    checkEventHandler();
}

void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
{
    *screen_w = gui.window->Width;
    *screen_h = gui.window->Height - (gui.screen->BarHeight + 1);
}

void gui_mch_set_text_area_pos(int x, int y, int w, int h)
{

}

/* ----------------------------------------------------------
   Scrollbars functions
   ---------------------------------------------------------- */
void gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
{
    sb->bargad = NULL;
    sb->orientation = orient;
    sb->enabled = FALSE;
    sb->old_size = -1;
    sb->old_max = -1;
    sb->old_val = -1;
    sb->old_x = -1;
    sb->old_y = -1;
    sb->old_w = -1;
    sb->old_h = -1;
    if(sb->orientation == SBAR_HORIZ)
    {
        sb->bargad = NewObject(NULL, (STRPTR) PROPGCLASS,
                               GA_Top, 0,
                               GA_Left, 0,
                               GA_Width, 0,
                               GA_Height, 0,
                               GA_Immediate, TRUE,
                               GA_RelVerify, TRUE,
                               GA_FollowMouse, TRUE,
                               PGA_Borderless, TRUE,
                               PGA_Freedom, FREEHORIZ,
                               PGA_Total, 0,
                               PGA_Visible, 0,
                               PGA_Top, 0,
                               PGA_NewLook, TRUE,
                               TAG_END);
    }
    else
    {
        sb->bargad = NewObject(NULL, (STRPTR) PROPGCLASS,
                               GA_Top, 0,
                               GA_Left, 0,
                               GA_Width, 0,
                               GA_Height, 0,
                               GA_Immediate, TRUE,
                               GA_RelVerify, TRUE,
                               GA_FollowMouse, TRUE,
                               PGA_Borderless, TRUE,
                               PGA_Freedom, FREEVERT,
                               PGA_Total, 0,
                               PGA_Visible, 0,
                               PGA_Top, 0,
                               PGA_NewLook, TRUE,
                               TAG_END);
    }

    if(sb->bargad) AddGadget(gui.window, sb->bargad, -1);
}

void gui_mch_destroy_scrollbar(scrollbar_T *sb)
{
    if(sb->bargad)
    {
        RemoveGadget(gui.window, sb->bargad);
        DisposeObject(sb->bargad);
    }
}
 
void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
{
    if(sb->bargad)
    {
        if(flag)
        {
            SetGadgetAttrs(sb->bargad, gui.window, NULL,
                           GA_Disabled, FALSE,
                           TAG_END);
        }
        else
        {
            SetGadgetAttrs(sb->bargad, gui.window, NULL,
                           GA_Disabled, TRUE,
                           TAG_END);
        }
    }
}

void gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
{
    if(sb->bargad)
    {
        if(sb->old_size != size ||
           sb->old_max != max ||
           sb->old_val != val)
        {
            SetGadgetAttrs(sb->bargad, gui.window, NULL,
                           PGA_Visible, size,
                           PGA_Total, max,
                           PGA_Top, val,
                           TAG_END);
            sb->old_size = size;
            sb->old_max = max;
            sb->old_val = val;
        }
    }
    return;

}

void gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
{
    if(sb->bargad)
    {
        if(sb->old_x != x ||
           sb->old_y != y ||
           sb->old_y != w ||
           sb->old_y != h)
        {
            if(sb->orientation == SBAR_HORIZ)
            {
                SetGadgetAttrs(sb->bargad, gui.window, NULL,
                               GA_Width, w,
                               GA_Height, h,
                               GA_Left, x,
                               GA_Top, y - 1,
                               TAG_END);
            }
            else
            {
                /* Nasty hack */
                if(x) x = gui.window->Width - w;
                else x = gui.window->Width - w - w;

                SetGadgetAttrs(sb->bargad, gui.window, NULL,
                               GA_Width, w,
                               GA_Height, h,
                               GA_Top, y,
                               GA_Left, x,
                               TAG_END);
            }
            sb->old_x = x;
            sb->old_y = y;
            sb->old_w = w;
            sb->old_h = h;
        }
    }
}

/* ----------------------------------------------------------
   Font functions
   ---------------------------------------------------------- */
char *gui_mch_get_fontname(GuiFont font, char *name)
{
//    D(bug("gui_mch_get_fontname() %s\n", name));
    // ???
    return name;
}

int gui_mch_init_font(char_u *font_name, int fontset)
{
//    D(bug("gui_mch_init_font() %s %d\n", font_name, fontset));
    
    gui.char_width = characterWidth;
    gui.char_height = characterHeight;
    gui.char_ascent = gui.window->RPort->TxBaseline;

    return OK;
}

int gui_mch_adjust_charsize()
{
    return FAIL;
}

GuiFont gui_mch_get_font(char_u *name, int giveErrorIfMissing)
{
//    D(bug("gui_mch_get_font() %s\n", name));

    return (int) NULL;
}

void gui_mch_set_font(GuiFont font)
{
//    D(bug("gui_mch_set_font()\n"));

    gui.currFont = font;
}

void gui_mch_free_font(GuiFont font)
{
//    D(bug("gui_mch_free_font()\n"));
    if (font)
    {
//        D("gui_mch_free_font");
    }
}

int gui_mch_adjust_charheight(void)
{
//    D(bug("gui_mch_adjust_charheight()\n"));
    // ???
    return FAIL;
}

/* ----------------------------------------------------------
   Colors functions
   ---------------------------------------------------------- */
int gui_mch_get_color_value_char(char value)
{
    int hex_table[] =
    {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1,
        0xa, 0xb, 0xc, 0xd, 0xe, 0xf
    };
    // Uppercase
    if(value >= 'a' && value <= 'f') value -= 0x20;
    if(value < '0' || value > 'F') return(-1);
    return(hex_table[value - '0']);
}

guicolor_T gui_mch_get_color(char_u *name)
{
    guicolor_T color = INVALCOLOR;

    int i;
    int number_char;
    if(name[0] == '#')
    {
        /* color by value */

        /* Search it in our table */
        for (i = 0; table[i].name != NULL; i++)
        {
            if (stricmp((char *) name, table[i].name) == 0)
            {
                /* Return it's offset if found */
                return(i);
            }
        }

        /* Otherwise, add it */
        table[i].name = strdup((char *) name);
        table[i].allocated = TRUE;
       
        table[i].red = 0;
        table[i].green = 0;
        table[i].blue = 0;
        name++;
        if(name[0] == '\0') return INVALCOLOR;
        if((number_char = gui_mch_get_color_value_char(*name++)) == -1) return(INVALCOLOR);
            table[i].red = (table[i].red << 4) | number_char;
        if(name[0] == '\0') return INVALCOLOR;
        if((number_char = gui_mch_get_color_value_char(*name++)) == -1) return(INVALCOLOR);
            table[i].red = (table[i].red << 4) | number_char;
        if(name[0] == '\0') return i;

        if((number_char = gui_mch_get_color_value_char(*name++)) == -1) return(INVALCOLOR);
            table[i].green = (table[i].green << 4) | number_char;
        if(name[0] == '\0') return INVALCOLOR;
        if((number_char = gui_mch_get_color_value_char(*name++)) == -1) return(INVALCOLOR);
            table[i].green = (table[i].green << 4) | number_char;
        if(name[0] == '\0') return i;

        if((number_char = gui_mch_get_color_value_char(*name++)) == -1) return(INVALCOLOR);
            table[i].blue = (table[i].blue << 4) | number_char;
        if(name[0] == '\0') return INVALCOLOR;
        if((number_char = gui_mch_get_color_value_char(*name++)) == -1) return(INVALCOLOR);
            table[i].blue = (table[i].blue << 4) | number_char;

        // Return it's newly created index from the table
        return i;
    }
    else
    {
        /* color by name */
        for (i = 0; table[i].name != NULL; i++)
        {
            if (stricmp((char *) name, table[i].name) == 0)
            {
                color = i;
                break;
            }
        }
    }
    return color;
}

static UBYTE getrealcolor(guicolor_T i)
{
    if (!MyColorTable[i].alloced)
    {
        MyColorTable[i].pen = ObtainBestPen(gui.window->WScreen->ViewPort.ColorMap,
                                            table[i].red * 0x01010101,
                                            table[i].green * 0x01010101,
                                            table[i].blue * 0x01010101,
                                            OBP_FailIfBad, FALSE,
                                            OBP_Precision, PRECISION_GUI,
                                            TAG_DONE);
        if (MyColorTable[i].pen != -1)
        {
            MyColorTable[i].alloced = TRUE;
        }
    }

    return MyColorTable[i].pen;
}

void gui_mch_set_colors(guicolor_T fg, guicolor_T bg)
{
    SetABPenDrMd(gui.window->RPort, getrealcolor(fg), getrealcolor(bg), JAM2);
}

void gui_mch_set_fg_color(guicolor_T color)
{
    SetAPen(gui.window->RPort, getrealcolor(color));
    SetDrMd(gui.window->RPort, JAM2);
}

void gui_mch_set_bg_color(guicolor_T color)
{
    SetBPen(gui.window->RPort, getrealcolor(color));
}

void gui_mch_set_sp_color(guicolor_T color)
{
    // could it be for SetOPen ?
}

long_u gui_mch_get_rgb(guicolor_T pixel)
{
    ULONG coltable[3], color;

    GetRGB32(gui.window->WScreen->ViewPort.ColorMap,
             getrealcolor(pixel),
             1,
             coltable);

    color = ((coltable[0] & 0xFF000000) >> 8) |
            ((coltable[1] & 0xFF000000) >> 16) |
            ((coltable[2] & 0xFF000000) >> 24);

    return color;
}

/* ----------------------------------------------------------
   Mouse functions
   ---------------------------------------------------------- */
void gui_mch_getmouse(int *x, int *y)
{
    *x = gui.window->GZZMouseX;
    *y = gui.window->GZZMouseY;
}

/*
 * Get current y mouse coordinate in text window.
 * Return -1 when unknown.
 */
int gui_mch_get_mouse_x()
{
    return gui.window->GZZMouseX;
}

int gui_mch_get_mouse_y()
{
    return gui.window->GZZMouseY;
}

void gui_mch_setmouse(int x, int y)
{
    /* TODO */
}

/* ----------------------------------------------------------
   Text drawing functions
   ---------------------------------------------------------- */
void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
{
    char tempstring[300];

    memcpy(tempstring, s, len);
    tempstring[len] = '\0';

    if (flags & DRAW_TRANSP)
    {
        SetDrMd(gui.window->RPort, JAM1);
        Move(gui.window->RPort,
             WidthCharToPoint(col),
             HeightCharToPoint(row) + gui.window->RPort->TxBaseline);
        Text(gui.window->RPort, s, len);
    }
    else
    {
        SetDrMd(gui.window->RPort, JAM2);
        Move(gui.window->RPort,
             WidthCharToPoint(col),
             HeightCharToPoint(row) + gui.window->RPort->TxBaseline);
        Text(gui.window->RPort, s, len);
    }

    if (flags & DRAW_BOLD)
    {
        SetDrMd(gui.window->RPort, JAM1);
        Move(gui.window->RPort,
             WidthCharToPoint(col) + 1,
             HeightCharToPoint(row) + gui.window->RPort->TxBaseline);
        Text(gui.window->RPort, s, len);
    }

    if (flags & DRAW_UNDERL)
    {
        Move(gui.window->RPort,
             WidthCharToPoint(col),
             HeightCharToPoint(row + 1) - 1);
        Draw(gui.window->RPort, WidthCharToPoint(col + len) - 1, HeightCharToPoint(row + 1) - 1);
    }

    SetDrMd(gui.window->RPort, JAM2);
}

void gui_mch_insert_lines(int row, int num_lines)
{
     ScrollWindowRaster(gui.window,
                        0,
                        -characterHeight * num_lines,
                        WidthCharToPoint(gui.scroll_region_left),
                        HeightCharToPoint(row),
                        WidthCharToPoint(gui.scroll_region_right + 1) - 1,
                        HeightCharToPoint(gui.scroll_region_bot +1 ) - 1);

    gui_clear_block(row,
                    gui.scroll_region_left,
                    row + num_lines - 1,
                    gui.scroll_region_right);

}

void gui_mch_draw_hollow_cursor(guicolor_T color)
{
    drawBox(DB_NotFilled, gui.col, gui.row, characterWidth, characterHeight, color);
}

void gui_mch_draw_part_cursor(int w,
                              int h,
                              guicolor_T color)
{
    drawBox(DB_Filled, gui.col, gui.row, w, h, color);
}

void gui_mch_settitle(char_u *title, char_u *icon)
{
    SetWindowTitles(gui.window, title, (STRPTR) ~0);
}

void gui_mch_stop_blink(void)
{
    gui_undraw_cursor();
}

void gui_mch_start_blink(void)
{
    gui_update_cursor(FALSE, FALSE);
}

void gui_mch_clear_block(int row1, int col1, int row2, int col2)
{
    UBYTE apen = GetAPen(gui.window->RPort);

    SetAPen(gui.window->RPort, getrealcolor(gui.back_pixel));
    RectFill(gui.window->RPort,
             WidthCharToPoint(col1),
             HeightCharToPoint(row1),
             WidthCharToPoint(col2 + 1) - 1,
             HeightCharToPoint(row2 + 1) - 1);
    SetAPen(gui.window->RPort, apen);
}

void gui_mch_clear_all(void)
{
    SetRast(gui.window->RPort, GetBPen(gui.window->RPort));
    refreshBorder();
}

void gui_mch_delete_lines(int row, int num_lines)
{
    ScrollWindowRaster(gui.window,
                       0,
                       characterHeight * num_lines,
                       WidthCharToPoint(gui.scroll_region_left),
                       HeightCharToPoint(row),
                       WidthCharToPoint(gui.scroll_region_right + 1) - 1,
                       HeightCharToPoint(gui.scroll_region_bot + 1) - 1
                      );

    gui_clear_block(gui.scroll_region_bot - num_lines + 1,
                    gui.scroll_region_left,
                    gui.scroll_region_bot,
                    gui.scroll_region_right
                   );

}

/* ----------------------------------------------------------
   Keyboard functions
   ---------------------------------------------------------- */
int gui_mch_haskey(char_u *name)
{
    int i;

    for (i = 0; special_keys[i].vim_code1 != NUL; i++)
    {
        if (name[0] == special_keys[i].vim_code0 &&
            name[1] == special_keys[i].vim_code1)
        {
            return OK;
        }
    }
    return FAIL;
}

/* ----------------------------------------------------------
   Misc. functions
   ---------------------------------------------------------- */
void gui_mch_beep(void)
{
    /* I'm not certain that it works properly under AROS */
	/*DisplayBeep(NULL); */
}

void gui_mch_flash(int msec)
{
    SetDrMd(gui.window->RPort, COMPLEMENT);
    RectFill(gui.window->RPort,
             0,
             0,
             gui.window->Width - 1,
             gui.window->Height - 1);
    Delay(msec * 50 / 1000);
    RectFill(gui.window->RPort,
             0,
             0,
             gui.window->Width - 1,
             gui.window->Height - 1);
    SetDrMd(gui.window->RPort, JAM2);
}

void gui_mch_invert_rectangle( int r, int c, int nr, int nc)
{

}

void gui_mch_iconify(void)
{

}

#if defined(FEAT_EVAL) || defined(PROTO)
/*
 * Bring the Vim window to the foreground.
 */
void gui_mch_set_foreground()
{
    WindowToFront(gui.window);
}
#endif

void gui_mch_update(void)
{
    checkEventHandler();
}

int gui_mch_wait_for_chars(int wtime)
{
    ULONG timermask = 1L << TimerMP->mp_SigBit;
    ULONG winmask = 1L << gui.window->UserPort->mp_SigBit;
    int retval = FAIL;

    if (wtime == -1) wtime = 1000000000;
    if (wtime < 20) wtime = 20;

    SetSignal(0, timermask);
    TimerIO->tr_node.io_Command = TR_ADDREQUEST;
    TimerIO->tr_time.tv_secs = wtime / 1000;
    TimerIO->tr_time.tv_micro = (wtime % 1000) * 1000;
    SendIO(&TimerIO->tr_node);
    TimerSent = TRUE;

    for(;;)
    {
        ULONG sigs = Wait(winmask | timermask);

        if (sigs & winmask)
        {
            checkEventHandler();
            if (!vim_is_input_buf_empty())
            {
                retval = OK;
                if (!CheckIO(&TimerIO->tr_node)) AbortIO(&TimerIO->tr_node);
                WaitIO(&TimerIO->tr_node);
                TimerSent = FALSE;
                break;
            }
        }

        if (sigs & timermask)
        {
            struct Message *msg;

            if ((msg = GetMsg(TimerMP)))
            {
                ReplyMsg(msg);
                TimerSent = FALSE;
                retval = FAIL;
                break;
            }
        }
    }

    return retval;
}

void gui_mch_flush(void)
{
//    RefreshWindowFrame(gui.window);
}

/* ----------------------------------------------------------
   Menus functions
   ---------------------------------------------------------- */
int search_insert_idx(vimmenu_T *parent, char *name)
{
    int i;
    int j;
    int parent_exist;
    vimmenu_T *oldmenu;

    /* Search if the parent exists */
    parent_exist = FALSE;
    for(i = 0; i < cur_menu_nbr; i++)
    {
        oldmenu = (vimmenu_T *) menuPtr[i].nm_UserData;
        if(oldmenu == parent)
        {
            parent_exist = TRUE;
            i++;
  //          D(bug("(FOUND: %s/%s %d %d) ", parent->name, name, i, cur_menu_nbr ));
            break;
        }
    }

    if(parent_exist)
    {
        /* Search for last entry with this parent from the found position */
        parent_exist = FALSE;
        for(; i < cur_menu_nbr; i++)
        {
            oldmenu = ((vimmenu_T *) menuPtr[i].nm_UserData)->parent;
            if(oldmenu != parent)
            {
                 /* We can't be bothered by menu titles */
                if(oldmenu)
                {
                    /* Was it already a sub menu ? Then go back 1 level */
                    if(oldmenu->parent) continue;
                }
                    
                //D(bug(" (INSERT: %s/%s %d %d)\n", parent->name, name, i, cur_menu_nbr));
                /* Prepare slot for insertion */
                for(j = cur_menu_nbr - 1; j >= i; j--)
                {
                    memcpy(&menuPtr[j + 1], &menuPtr[j], sizeof(struct NewMenu));
                }
                memset(&menuPtr[i], 0, sizeof(struct NewMenu));
                /* And return the menu entry where it should be inserted */
                return(i);
            }
        }
    }

    return(-1);
}

void gui_mch_add_menu_item(vimmenu_T *menu, int idx)
{
    struct NewMenu *menuitem;
    char string[512];
    int entry_type = NM_ITEM;
    int entry_idx;

    if(menu->parent)
    {
        if(stricmp((char *) menu->parent->name, "popupi") == 0 ||
           stricmp((char *) menu->parent->name, "popupo") == 0 ||
           stricmp((char *) menu->parent->name, "popups") == 0 ||
           stricmp((char *) menu->parent->name, "popupn") == 0 ||
           stricmp((char *) menu->parent->name, "popupv") == 0 ||
           stricmp((char *) menu->parent->name, "popupc") == 0 ||
           stricmp((char *) menu->parent->name, "popup") == 0)
        {
            return;
        }

        if(menu->parent->parent)
        {
            entry_type = NM_SUB;
        }
        entry_idx = search_insert_idx(menu->parent, (char *) menu->name);
        if(entry_idx == -1) menuitem = &menuPtr[cur_menu_nbr];
        else menuitem = &menuPtr[entry_idx];
    }
    else
    {
        return;
    }

    if (menu_is_separator(menu->name))
    {
        menuitem->nm_Type = entry_type;
        menuitem->nm_Label = NM_BARLABEL;
    }
    else
    {
        menuitem->nm_Type = entry_type;
        sprintf(string, "%s", menu->dname);
        menuitem->nm_Label = (STRPTR) strdup(string);
        if(menu->actext)
        {
            menuitem->nm_CommKey = (STRPTR) strdup((char *) menu->actext);
            menuitem->nm_Flags = NM_COMMANDSTRING;
        }
    }
    menuitem->nm_UserData = menu;
    cur_menu_nbr++;
}

void gui_mch_add_menu(vimmenu_T *menu, int idx)
{
    struct NewMenu *menubar;
    int entry_type = NM_ITEM;
    int entry_idx;

    if (menu_is_popup(menu->name))
    {
        return;
    }

    if(menu->parent)
    {
        entry_idx = search_insert_idx(menu->parent, (char *) menu->name);
        if(entry_idx == -1) menubar = &menuPtr[cur_menu_nbr];
        else menubar = &menuPtr[entry_idx];

        if (menu_is_separator(menu->name))
        {
            menubar->nm_Type = entry_type;
            menubar->nm_Label = NM_BARLABEL;
        }
        else
        {
            menubar->nm_Type = entry_type;
            menubar->nm_Label = menu->dname;
        }
    }
    else
    {
        /* root */
        menubar = &menuPtr[cur_menu_nbr];
        menubar->nm_Type = NM_TITLE;
        menubar->nm_Label = menu->dname;
    }
    menubar->nm_UserData = menu;
    cur_menu_nbr++;
}

void gui_mch_toggle_tearoffs(int enable)
{
    /* no tearoff menus */
}

void gui_mch_enable_menu(int flag)
{

}

void gui_mch_set_menu_pos(int x, int y, int w, int h)
{

}

void gui_mch_destroy_menu(vimmenu_T *menu)
{
    ClearMenuStrip(gui.window);
    if(gui.menu) FreeMenus(gui.menu);
    gui.menu = NULL;
}

void gui_mch_menu_grey(vimmenu_T *menu, int grey)
{

}

void gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
{
    ClearMenuStrip(gui.window);
    if(gui.menu) FreeMenus(gui.menu);
    gui.menu = NULL;
}

void gui_mch_draw_menubar(void)
{
    APTR vi;

    gui.menu = CreateMenus(menuPtr, TAG_END);
    if(gui.menu)
    {
        vi = GetVisualInfo(gui.screen, NULL);
        LayoutMenus(gui.menu, vi,
                              GTMN_NewLookMenus, TRUE,
                              TAG_END);
        SetMenuStrip(gui.window, gui.menu);
    }
}

int clip_mch_own_selection(VimClipboard *cbd)
{
    return OK;
}

void gui_mch_show_popupmenu(vimmenu_T *menu)
{
    /* TODO */
}

void clip_mch_lose_selection(VimClipboard *cbd)
{

}

void clip_mch_request_selection(VimClipboard *cbd)
{

}

void clip_mch_set_selection(VimClipboard *cbd)
{

}
