summaryrefslogtreecommitdiffstats
path: root/src/gui_amiga.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui_amiga.c')
-rw-r--r--src/gui_amiga.c1795
1 files changed, 1795 insertions, 0 deletions
diff --git a/src/gui_amiga.c b/src/gui_amiga.c
new file mode 100644
index 0000000000..28786aa6fd
--- /dev/null
+++ b/src/gui_amiga.c
@@ -0,0 +1,1795 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Amiga GUI support by Michael Nielsen
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <exec/types.h>
+#include <intuition/intuition.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_amiga.h"
+#include <math.h>
+#include <limits.h>
+
+#ifdef __AROS__
+#include <aros/debug.h>
+#endif
+
+#include "version.h"
+
+#if defined(FEAT_GUI_AMIGA) || defined(PROTO)
+
+#define KEYUP 76
+#define KEYDOWN 77
+#define KEYRIGHT 78
+#define KEYLEFT 79
+#define KEYBACKSPACE 0x41
+#define KEYDELETE 0x46
+#define KEYINSERT 0x47
+#define KEYHOME 0x70
+#define KEYEND 0x71
+#define KEYWHEELUP 0x7A
+#define KEYWHEELDOWN 0x7B
+
+/* When generating prototypes on Unix, these need to be defined */
+#ifdef PROTO
+# define STRPTR char *
+# define BOOL int
+# define UBYTE int
+#endif
+
+static struct PropInfo Gadget2SInfo = { AUTOKNOB+PROPBORDERLESS+FREEVERT+PROPNEWLOOK, 0, 0, MAXBODY, MAXBODY, };
+//static struct Image Image1 = { 0, 0, 10, 397, 0, NULL, 0x0000, 0x0000, NULL };
+static struct Gadget propGadget = { NULL, -12, 15, 10, -28,
+ GFLG_RELRIGHT+GFLG_RELHEIGHT,
+ GACT_RELVERIFY+GACT_RIGHTBORDER+GACT_IMMEDIATE,
+ GTYP_PROPGADGET+GTYP_GZZGADGET,
+ NULL, NULL,
+ NULL, NULL, (APTR)&Gadget2SInfo, NULL, NULL };
+
+static struct timerequest *TimerIO;
+static struct MsgPort *TimerMP;
+static BOOL TimerSent;
+
+struct GFXBase *gfxBase;
+struct ExecBase *execBase;
+struct LayersBase *layersBase;
+
+struct MyColor
+{
+ WORD pen;
+ BOOL alloced;
+};
+
+struct MyColor MyColorTable[256];
+
+struct TagItem tags[] =
+{
+ {WA_Left, 0},
+ {WA_Top, 0},
+ {WA_Width, 400},
+ {WA_Height, 400},
+ {WA_Title, (ULONG)VIM_VERSION_SHORT},
+ {WA_ScreenTitle, (ULONG)VIM_VERSION_LONG},
+ {WA_DragBar, TRUE}, /* enable dragging of the window */
+ {WA_DepthGadget, TRUE}, /* enable the depth gadget */
+ {WA_CloseGadget, TRUE}, /* enable the close gadget*/
+ {WA_SizeGadget, TRUE}, /* enable the size gadget */
+ {WA_SizeBBottom, TRUE}, /* sizegadget contained in bottom border */
+ {WA_SmartRefresh, TRUE}, /* choose smart refresh, saves us doing a lot of work */
+ {WA_ReportMouse, TRUE}, /* Report the position of the mouse */
+ {WA_GimmeZeroZero, TRUE},
+ {WA_Activate, TRUE}, /* Activate window on startup */
+ {WA_Activate, TRUE}, /* Activate window on startup */
+ {WA_NoCareRefresh, TRUE}, /* Refresh screen, don't tell us */
+ {WA_NewLookMenus, TRUE}, /* use the new options for the menu */
+ {WA_AutoAdjust, TRUE}, /* If window is too big for screen adjust size*/
+ {WA_NoCareRefresh, TRUE}, /* If window is too big for screen adjust size*/
+ {WA_MouseQueue, 1}, /* Limit number of pending mouse movement*/
+ {WA_RptQueue, 10}, /* Limit number of pending keystrokes*/
+ {WA_IDCMP, /* IDCMP, what events interest us */
+ IDCMP_NEWSIZE /* Notify us about size change of window*/
+ |IDCMP_REFRESHWINDOW /* Notify us when the window needs refreshing */
+ |IDCMP_MOUSEBUTTONS /* Notify us when the mouse buttons have been used */
+ |IDCMP_MOUSEMOVE /* Notify us when the mouse is moving */
+ |IDCMP_GADGETDOWN /* Notify us when a gadget has been selected */
+ |IDCMP_GADGETUP /* Notify us when a gadget has been released */
+ |IDCMP_MENUPICK /* Notify us when a menu has been picked */
+ |IDCMP_CLOSEWINDOW /* Notify us when the user tries to close the window */
+ |IDCMP_VANILLAKEY /* Notify us about keystrokes */
+ |IDCMP_RAWKEY /* Notify us when raw key events have been used, ie cursor*/
+ |IDCMP_INTUITICKS /* Simpler timer for the blink option */
+ |IDCMP_MENUHELP /* Allow the help key to be used during menu events */
+ |IDCMP_GADGETHELP /* Allow the help key to be used during gadget events */
+ |IDCMP_INACTIVEWINDOW /* notify of inactive window */
+ |IDCMP_ACTIVEWINDOW /* notify of inactive window */
+ },
+ {TAG_DONE, NULL}
+};
+
+#if defined(D)
+#undef D
+#endif
+
+/*#define D(_msg) fprintf(stderr, "%s\n", _msg)*/
+
+#define D(_A)
+#define kprintf(s, ...)
+
+static void AmigaError(const char *string);
+
+void HandleEvent(unsigned long * object);
+static UBYTE getrealcolor(guicolor_T i);
+
+static struct NewWindow vimNewWindow =
+{
+ 0, 0, /* window XY origin relative to TopLeft of screen */
+ 0, 0, /* window width and height */
+ 0, 1, /* detail and block pens */
+ NULL, /* IDCMP flags */
+ NULL, /* other window flags */
+ &propGadget, /* first gadget in gadget list */
+ NULL, /* custom CHECKMARK imagery */
+ "Amiga Vim gui", /* window title */
+ NULL, /* custom screen pointer */
+ NULL, /* custom bitmap */
+ 50, 50, /* minimum width and height */
+ (unsigned short)-1, (unsigned short)-1, /* maximum width and height */
+ WBENCHSCREEN /* destination screen type */
+};
+
+static struct
+{
+ unsigned int key_sym;
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {0, 0, 0}
+};
+
+#if 0
+ /* not used? */
+ static int
+hex_digit(int c)
+{
+ if (isdigit(c))
+ return c - '0';
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1000;
+}
+#endif
+
+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
+};
+
+ static void
+TextDimensions(void)
+{
+ struct TextExtent textExt;
+
+ TextExtent(gui.window->RPort, "s", 1, &textExt);
+
+ characterWidth = textExt.te_Width;
+ characterHeight = textExt.te_Height;
+}
+
+ static int
+posWidthCharToPoint(int width)
+{
+ return (width)*characterWidth;
+}
+
+ static int
+posHeightCharToPoint(int height)
+{
+ return (int)(height)*characterHeight;
+}
+
+ static int
+posWidthPointToChar(int width)
+{
+ //return (int)floor((float)width/(float)characterWidth)-1;
+ return width /characterWidth;
+}
+
+ static int
+posHeightPointToChar(int height)
+{
+ //return (int)floor((float)height/(float)characterHeight)-2;
+ return height / characterHeight;
+}
+
+ static int
+widthCharToPoint(int width)
+{
+ return (width)*(characterWidth);
+}
+
+ static int
+heightCharToPoint(int height)
+{
+ return (height)*characterHeight;
+}
+
+ static int
+widthPointToChar(int width)
+{
+ return (width)/characterWidth;
+}
+
+ static int
+heightPointToChar(int height)
+{
+ return (height)/characterHeight;
+}
+
+ static void
+refreshBorder(void)
+{
+ /*WaitBOVP(gui.window->);*/
+ 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;
+
+kprintf(" drawbox %d,%d color %d\n", col, row, color);
+
+ SetAPen(gui.window->RPort, getrealcolor(color));
+
+ x1 = posWidthCharToPoint(col);
+ y1 = posHeightCharToPoint(row + 1) - h;
+ x2 = x1 + w - 1;
+ y2 = posHeightCharToPoint(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);
+
+}
+
+ 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;
+
+ msg = (struct IntuiMessage *)GetMsg(gui.window->UserPort);
+
+ if (!msg)
+ {
+ returnEvent = ev_NullEvent;
+ }
+ else
+ {
+
+ class = msg->Class;
+ code = msg->Code;
+
+ switch(class)
+ {
+ case IDCMP_INTUITICKS:
+ /*
+ if (cursor.active)
+ {
+ cursor.current ++;
+ if (cursor.state == CursorOff)
+ {
+ printf("cursor turned on\n");
+ if (cursor.offTime < cursor.current)
+ {
+ gui_undraw_cursor();
+ cursor.state = CursorOn;
+ cursor.current = 0;
+ }
+ }
+ else if (cursor.state == CursorOn)
+ {
+ printf("cursor turned off\n");
+ if (cursor.onTime < cursor.current)
+ {
+ cursor.state = CursorOff;
+ gui_update_cursor(FALSE);
+ cursor.current = 0;
+ }
+ }
+ else if (cursor.state == CursorWait)
+ {
+ printf("cursor turned Wait\n");
+ if (cursor.waitTime < cursor.current)
+ {
+ cursor.state = CursorOn;
+ cursor.current = 0;
+ }
+ }
+ }
+ else
+ {
+ }
+ returnEvent = ev_IntuiTicks;
+ */
+ break;
+
+ case IDCMP_MOUSEBUTTONS:
+ {
+ int vim_modifiers=0;
+ D("Mouse button event detected");
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+ if (code == SELECTDOWN)
+ {
+ D("Select Down detected\n");
+ dragging = 1;
+ gui_send_mouse_event(MOUSE_LEFT,
+ mouseX = msg->MouseX - gui.window->BorderLeft,
+ mouseY = msg->MouseY - gui.window->BorderTop,
+ FALSE,
+ vim_modifiers);
+ /*gui_start_highlight(HL_ALL);*/
+ }
+ else if (code == SELECTUP)
+ {
+ D("Select UP detected\n");
+ dragging = 0;
+ gui_send_mouse_event(MOUSE_RELEASE,
+ msg->MouseX - gui.window->BorderLeft,
+ msg->MouseY - gui.window->BorderTop,
+ FALSE, vim_modifiers);
+ /*gui_stop_highlight(mask);*/
+ }
+ returnEvent = ev_MouseButtons;
+ break;
+ }
+ case IDCMP_MOUSEMOVE:
+ if ((abs(mouseX-(msg->MouseX - gui.window->BorderLeft)) > characterWidth) ||
+ (abs(mouseY-(msg->MouseY - gui.window->BorderTop))>characterHeight))
+ {
+ int vim_modifiers=0;
+
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+
+ mouseX = msg->MouseX - gui.window->BorderLeft;
+ mouseY = msg->MouseY - gui.window->BorderTop;
+ if (!dragging)
+ {
+ gui_send_mouse_event(MOUSE_SETPOS, mouseX, mouseY, FALSE, vim_modifiers);
+ break;
+ }
+ else
+ {
+ D("dragging\n");
+ gui_send_mouse_event(MOUSE_DRAG, mouseX, mouseY, FALSE, vim_modifiers);
+ }
+ }
+ returnEvent = ev_MouseMove;
+ break;
+ case IDCMP_VANILLAKEY:
+kprintf("===vanillakey %d\n", code);
+ {
+ string[0] = (char_u)code;
+ if (code == CSI)
+ {
+ /* Insert CSI as K_CSI. Untested! */
+ string[1] = KS_EXTRA;
+ string[2] = (int)KE_CSI;
+ add_to_input_buf(string, 3);
+ }
+ else if (code == 8)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'b';
+ add_to_input_buf(string, 3);
+ }
+ else if (code == 127)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'D';
+ add_to_input_buf(string, 3);
+ }
+ else
+ {
+ int len = 1;
+
+ if (input_conv.vc_type != CONV_NONE)
+ len = convert_input(string, 1, sizeof(string));
+ add_to_input_buf(string, len);
+ }
+ returnEvent = ev_KeyStroke;
+ break;
+
+ case IDCMP_RAWKEY:
+ if (msg->Qualifier & IEQUALIFIER_LSHIFT)
+ {
+ }
+ else if (msg->Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ }
+ else if (msg->Qualifier & IEQUALIFIER_CONTROL)
+ {
+ if (code == 33)
+ {
+ trash_input_buf();
+ }
+ }
+ else if (msg->Code == KEYUP)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'u';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYLEFT)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'l';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYRIGHT)
+ {
+kprintf("## keyright");
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'r';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYDOWN)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'd';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYBACKSPACE)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'b';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYDELETE)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'D';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYINSERT)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'I';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYHOME)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'h';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYEND)
+ {
+ string[0] = CSI;
+ string[1] = '@';
+ string[2] = '7';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYWHEELUP)
+ {
+ int vim_modifiers=0;
+
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+ gui_send_mouse_event(MOUSE_4, 0, 1, FALSE, vim_modifiers);
+
+ }
+ else if (msg->Code == KEYWHEELDOWN)
+ {
+ int vim_modifiers=0;
+
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+ gui_send_mouse_event(MOUSE_5, 0, 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;
+ {
+ /*
+ ** one of our menu's have been selected, let's find out which
+ */
+ union myMenuItemUnion *item;
+ int menuNumber;
+
+ menuNumber = code;
+
+ item = (union myMenuItemUnion *) ItemAddress(gui.menu, menuNumber);
+
+
+ if (item)
+ {
+ gui_menu_cb(item->myMenuItem.guiMenu);
+ }
+ }
+ break;
+ case IDCMP_CLOSEWINDOW:
+ quit_request = TRUE;
+ break;
+
+ case IDCMP_NEWSIZE:
+ {
+ int cx, cy;
+ //cx = widthPointToChar(gui.window->GZZWidth);
+ //cy = heightPointToChar(gui.window->GZZHeight);
+
+ cx = gui.window->GZZWidth;
+ cy = gui.window->GZZHeight - characterHeight;
+
+ gui_resize_shell(cx, cy);
+
+ returnEvent = ev_NewSize;
+ break;
+ }
+ case IDCMP_REFRESHWINDOW:
+ refreshBorder();
+ returnEvent = ev_RefreshWindow;
+ break;
+ case IDCMP_GADGETDOWN:
+ returnEvent = ev_GadgetDown;
+ break;
+ case IDCMP_GADGETUP:
+ returnEvent = ev_GadgetUp;
+ 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); // gui_mch_exit(1);
+ }
+
+ return returnEvent;
+ /* mouse positin gui.window->MoseY, gui.window->MouseX) */
+}
+
+ static int
+checkEventHandler(void)
+{
+ enum event happened;
+
+ do
+ {
+ happened = EventHandler() ;
+ }
+ while (happened != ev_NullEvent);
+
+ return OK;
+}
+
+ static int
+charEventHandler(int wtime)
+{
+ enum event happened;
+ int rc;
+
+ do
+ {
+ Wait(1<<gui.window->UserPort->mp_SigBit);
+
+ happened = EventHandler() ;
+ }
+ while ((happened != ev_IntuiTicks) && (happened != ev_KeyStroke) && (happened != ev_MenuPick) && (happened != ev_MouseMove) &&(happened != ev_MouseButtons) );
+
+ if (happened == ev_KeyStroke || happened == ev_MenuPick)
+ rc = OK;
+ else
+ rc = FAIL;
+
+ return rc;
+}
+
+
+/*
+ * add primary menu
+ */
+ void
+gui_mch_add_menu_item(vimmenu_T *menu, int idx)
+{
+ union myMenuItemUnion *menuItemUnion = NULL;
+ struct IntuiText *menutext = NULL;
+ vimmenu_T *parent;
+
+ assert(menu != NULL);
+ assert(menu->parent != NULL);
+ parent = menu->parent;
+
+ /* Don't add menu separator */
+ if (menu_is_separator(menu->name))
+ return;
+
+ if (parent->menuItemPtr == NULL)
+ return;
+
+ /* TODO: use menu->mnemonic and menu->actext */
+ menutext = (struct IntuiText *) malloc(sizeof(struct IntuiText));
+
+ SetAttrib(menutext, FrontPen, 3);
+ SetAttrib(menutext, BackPen, 1);
+ SetAttrib(menutext, DrawMode, COMPLEMENT);
+ SetAttrib(menutext, LeftEdge, 0);
+ SetAttrib(menutext, TopEdge, 0);
+ SetAttrib(menutext, ITextFont, NULL);
+ SetAttrib(menutext, NextText, NULL);
+
+ menuItemUnion = malloc(sizeof(*menuItemUnion));
+
+ SetAttrib(&menuItemUnion->menuItem, NextItem, parent->menuItemPtr);
+ SetAttrib(&menuItemUnion->menuItem, LeftEdge, 0);
+ SetAttrib(&menuItemUnion->menuItem, Width, characterWidth*strlen(menu->dname));
+ SetAttrib(&menuItemUnion->menuItem, Height, characterHeight+2);
+ SetAttrib(&menuItemUnion->menuItem, Flags, ITEMTEXT+ITEMENABLED+HIGHCOMP);
+ SetAttrib(&menuItemUnion->menuItem, MutualExclude, 0);
+ SetAttrib(&menuItemUnion->menuItem, ItemFill, (APTR)menutext);
+ SetAttrib(&menuItemUnion->menuItem, SelectFill, NULL);
+ SetAttrib(&menuItemUnion->menuItem, Command, NULL);
+ SetAttrib(&menuItemUnion->menuItem, SubItem, NULL);
+ SetAttrib(&menuItemUnion->menuItem, NextSelect, MENUNULL);
+
+ menutext->IText = malloc(strlen(menu->dname) + 1);
+
+ strcpy(menutext->IText, menu->dname);
+
+ menuItemUnion->menuItem.NextItem = NULL;
+
+
+ if (parent)
+ {
+ if (!parent->menuItemPtr)
+ {
+ D("Adding first subElement");
+ SetAttrib(&menuItemUnion->menuItem, TopEdge, 0);
+ parent->menuPtr->FirstItem = &menuItemUnion->menuItem;
+ parent->menuItemPtr = &menuItemUnion->menuItem;
+ }
+ else
+ {
+ struct MenuItem *tmpMenuItem;
+ tmpMenuItem = parent->menuItemPtr;
+ while (tmpMenuItem->NextItem)
+ {
+ tmpMenuItem = tmpMenuItem->NextItem;
+ }
+ tmpMenuItem->NextItem = &menuItemUnion->menuItem;
+ SetAttrib(&menuItemUnion->menuItem, TopEdge, tmpMenuItem->TopEdge+tmpMenuItem->Height);
+ }
+ }
+ menu->menuPtr= NULL;
+ menu->menuItemPtr = &menuItemUnion->menuItem;
+ menuItemUnion->myMenuItem.guiMenu = menu;
+}
+
+
+ static struct Menu *
+getMenu(struct RastPort *rast, int left, STRPTR name)
+{
+ struct Menu *menu;
+ struct TextExtent textExt;
+
+ menu = malloc(sizeof(*menu));
+ menu->NextMenu = NULL;
+ menu->LeftEdge = left;
+
+ TextExtent(rast, name, strlen(name), &textExt);
+
+ menu->TopEdge = 0;
+ menu->Width = textExt.te_Width;
+ menu->Height = textExt.te_Height;
+ menu->Flags = ITEMTEXT+HIGHCOMP+MENUENABLED;
+ menu->MenuName = name;
+ menu->FirstItem = NULL;
+
+ return menu;
+}
+
+/*
+ * add 1st level submenu item
+ */
+ void
+gui_mch_add_menu(vimmenu_T *menu, int idx)
+{
+ struct Menu *newMenu;
+ int pos = 0;
+
+ if (!menu_is_menubar(menu->name))
+ return;
+
+ menu->menuPtr = newMenu = getMenu(gui.window->RPort, 0, menu->dname);
+ menu->menuItemPtr = NULL;
+ newMenu->NextMenu = NULL;
+
+ if (!gui.menu)
+ {
+ D("Adding head menu");
+ gui.menu = newMenu ;
+ }
+ else
+ {
+ struct Menu *tmpMenu;
+
+ tmpMenu = gui.menu;
+ while (tmpMenu->NextMenu)
+ tmpMenu = tmpMenu->NextMenu;
+ tmpMenu->NextMenu = newMenu;
+ pos = tmpMenu->LeftEdge +
+ TextLength(gui.window->RPort, tmpMenu->MenuName,
+ strlen(tmpMenu->MenuName));
+ newMenu->LeftEdge = pos;
+ }
+}
+
+ void
+gui_mch_toggle_tearoffs(enable)
+ int enable;
+{
+ /* no tearoff menus */
+}
+
+ 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)
+{
+ D("gui_mch_prepare");
+
+ execBase = (struct ExecBase *)OpenLibrary("exec.library", NULL);
+ gfxBase = (struct GFXBase *)OpenLibrary("graphics.library", NULL);
+ layersBase = (struct LayersBase *)OpenLibrary("layers.library", NULL);
+
+ if (!execBase)
+ {
+ D("Cannot open exec.library, aborting");
+ }
+ if (!gfxBase)
+ {
+ D("Cannot open graphics.library, aborting");
+ }
+ if (!layersBase)
+ {
+ D("Cannot open graphics.library, aborting");
+ }
+ D("gui_mch_prepare done ");
+}
+
+ void
+atexitDoThis(void)
+{
+kprintf("atexitdothis###\n");
+ 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 (execBase && gfxBase && layersBase)
+ 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("timer.device", UNIT_VBLANK, &TimerIO->tr_node, 0)) return FAIL;
+
+ gui.window = OpenWindowTagList(&vimNewWindow, tags);
+ 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;
+
+ return returnCode;
+}
+
+ void
+gui_mch_new_colors(void)
+{
+kprintf("### gui_mch_new_colors\n");
+ SetAPen(gui.window->RPort, getrealcolor(gui.norm_pixel));
+ SetBPen(gui.window->RPort, getrealcolor(gui.back_pixel));
+
+ D("gui_mch_new_colors");
+}
+
+ int
+gui_mch_open(void)
+{
+ D("gui_mch_open");
+
+ highlight_gui_started();
+ return OK;
+}
+
+ void
+gui_mch_exit(int returnCode)
+{
+kprintf("###gui_mch_exit\n");
+ D("****gui_mch_exit");
+
+ 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;
+
+ for(i = 0; i < sizeof(MyColorTable) / sizeof(MyColorTable[0]); i++)
+ {
+ if (MyColorTable[i].alloced)
+ {
+ ReleasePen(gui.window->WScreen->ViewPort.ColorMap, MyColorTable[i].pen);
+ MyColorTable[i].alloced = FALSE;
+ }
+ }
+
+ D("Closeing window ");
+ CloseWindow(gui.window);
+ CloseLibrary((struct Library*)execBase);
+ CloseLibrary((struct Library*)gfxBase);
+ gui.window = NULL;
+ gui.in_use = FALSE;
+ //getout(1);
+ }
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ if (gui.window)
+ {
+ *x = gui.window->LeftEdge;
+ *y = gui.window->TopEdge;
+ }
+ 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, x, y, gui.window->Width, gui.window->Height);
+ }
+}
+
+ void
+gui_mch_set_shellsize(int width, int height,
+ int min_width, int min_height, int base_width, int base_height)
+{
+ D("gui_mch_set_shellsize");
+
+ ChangeWindowBox(gui.window, gui.window->LeftEdge,
+ gui.window->TopEdge, widthCharToPoint(width) + gui.window->BorderLeft + gui.window->BorderRight,
+ heightCharToPoint(height) + gui.window->BorderTop + gui.window->BorderBottom);
+ checkEventHandler();
+}
+
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+// *screen_w = widthPointToChar(gui.window->GZZWidth);
+// *screen_h = heightPointToChar(gui.window->GZZHeight);
+ *screen_w = gui.window->GZZWidth;
+ *screen_h = gui.window->GZZHeight - characterHeight;
+
+
+kprintf("=== get_screen_dimensions: screen %d,%d character %d,%d console %d,%d\n",
+gui.window->GZZWidth,
+gui.window->GZZHeight,
+characterWidth,
+characterHeight,
+*screen_w,
+*screen_h);
+
+}
+
+ void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+ D("gui_mch_set_text_area_pos");
+}
+
+ void
+gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
+{
+ /* done by default */
+ /* TODO: disable scrollbar when it's too small */
+}
+
+ void
+gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
+{
+ ULONG total = max;
+ ULONG visible = size;
+ ULONG top = val;
+ ULONG hidden;
+ ULONG overlap = 0;
+ UWORD body, pot;
+
+kprintf("__set_scrollbar_thumb val %d size %d max %d\n", val, size, max);
+
+ if (total > visible)
+ hidden = total - visible;
+ else
+ hidden = 0;
+
+ if (top > hidden)
+ top = hidden;
+
+ body = (hidden > 0) ?
+ (UWORD)(((ULONG)(visible - overlap) * MAXBODY) / (total - overlap)) :
+ MAXBODY;
+
+ pot = (hidden > 0) ? (UWORD)(((ULONG) top * MAXPOT) / hidden) : 0;
+
+kprintf("__pot %x body %x\n", pot, body);
+
+ NewModifyProp(&propGadget, gui.window, NULL,
+ Gadget2SInfo.Flags,
+ MAXPOT, pot,
+ MAXBODY, body,
+ 1);
+ return;
+
+}
+
+ void
+gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
+{
+ D("gui_mch_set_scrollbar_pos");
+ /*NewModifyProp(&propGadget, gui.window, NULL, MAXPOT, MAXPOT/sb->max*y, MAXPOT, MAXBODY/sb->max/sb->size, 1);*/
+}
+
+ void
+gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
+{
+ /* this is done by default */
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+ /* this is done by default */
+}
+#endif
+
+int gui_mch_init_font(char_u *font_name, int fontset)
+{
+ /*D("gui_mch_init_font");*/
+
+ 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("gui_mch_get_font");*/
+ return NULL;
+}
+
+ void
+gui_mch_set_font(GuiFont font)
+{
+ /*D("gui_mch_set_font");*/
+}
+
+#if 0 /* not used */
+ int
+gui_mch_same_font(GuiFont f1, GuiFont f2)
+{
+ D("gui_mch_same_font");
+}
+#endif
+
+ void
+gui_mch_free_font(GuiFont font)
+{
+ if (font)
+ D("gui_mch_free_font");
+}
+
+#define RGB(a, b, c) ((a && 0xff) * 0x10000 + (b * 0xff) * 0x100 + (c & 0xff))
+
+/*
+ * Get color handle for color "name".
+ * Return INVALCOLOR when not possible.
+ */
+
+ typedef struct guicolor_tTable
+ {
+ char *name;
+ unsigned long color;
+ UBYTE red;
+ UBYTE green;
+ UBYTE blue;
+ } guicolor_tTable;
+
+ static guicolor_tTable table[] =
+ {
+ {"Grey", 0, 190,190,190},
+ {"Black", 1, 0, 0, 0},
+ {"DarkBlue", 2, 0, 0, 139},
+ {"DarkGreen", 3, 0, 100, 0},
+ {"DarkCyan", 4, 0, 139, 139},
+ {"DarkRed", 5, 139, 0, 0},
+ {"DarkMagenta", 6, 139, 0, 139},
+ {"Brown", 7, 165, 42, 42},
+ {"Gray", 8, 190, 190, 190},
+ {"Grey", 9, 190, 190, 190},
+ {"LightGray", 10, 211, 211, 211},