#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "kernel.h"
#include "swis.h"

#define Buggy "<Obey$Dir>.Buggy"
#include "Buggy.h" // my debugging code
#include "Wimpy.h" // some Wimp definitions

// Some global variables so I need not pass them on over and over again
// ... or create them over and over again for subroutine calls
_kernel_swi_regs SWIRegs;
int WimpPollMask = PollMask_Standard;
//int WimpPollMask = PollMask_Null;
int WimpPollWait = 200;
t_WimpPollBlock WimpPollBlockStorage;
t_WimpPollBlock *WimpPollBlock;
t_TaskHandle MyTaskHandle = 0;
t_MessageTrans_FileDescriptor *MyMessages;

const char MyTaskName[] = "Sabbelei";
const char MyVersion[]  = "Version 1.00";

t_IconHandle MyBarIcon = 0;
t_Menu *MyBarMenu;
t_Window *MyInfoWindow;

// Window positioning support
int XY(char *Where) {
	int r = 0;
	int n;
	char *c = Where;
	char w;
	for (;*c!=0;c++) {
		w = *c++;
		if ((*c >= '0') && (*c <= '9')) {
			n = 0;
			while ((*c >= '0') && (*c <= '9')) { n = n*10 + (*c++-'0'); }
		}
		else {
			n = 1;
		}
		c--;
		switch (w) {
		case 'D':
			r += 4*n;
			break;
		case 'S':
			r += 20*n;
			break;
		case 'T':
			r += 44*n;
			break;
		case '+':
			r +=n;
			break;
		case '-':
			r -=n;
			break;
		}
	}
	return(r);
}


// Function for SWI Wimp_CloseDown
void WimpCloseDown(void) {
	// Call Wimp_CloseDown if I have a TaskHandle
	if (MyTaskHandle != 0) {
		SWIRegs.r[0] = TASK;
		SWIRegs.r[1] = (int)MyTaskHandle;
		_kernel_swi(Wimp_CloseDown,&SWIRegs,&SWIRegs);
	}
	// Exit
	_kernel_swi(OS_Exit,&SWIRegs,&SWIRegs);
	exit(0);
}

#define SWI(swi)  SWIcall(swi,True,#swi,__FILE__,__LINE__)
#define SWIX(swi) SWIcall(swi,False,#swi,__FILE__,__LINE__)
#define SWIE(swi) SWIcall(-1,True,#swi,__FILE__,__LINE__)

// Call an SWI and abort in case of error...
// Call with SWI NULL to just abort
_kernel_oserror *SWIcall(int SWIName, int AbortOnError, char *AbortMessage, char *File, int Line) {
	_kernel_oserror *OSError;

	//BuggyRegs(AbortMessage,4);

	// Call the SWI (if I have one)
	if (SWIName != -1) {
		OSError = _kernel_swi(SWIName,&SWIRegs,&SWIRegs);
		if (OSError == NULL) { return(OSError); }
	}

	// In case of error write debug log and optionally abort
	BuggyError(AbortMessage,File,Line);
	if (AbortOnError) {
			SWIRegs.r[0] = (int)OSError;
		SWIRegs.r[1] = 1;
		SWIRegs.r[2] = (int)AbortMessage;
		_kernel_swi(Wimp_ReportError,&SWIRegs,&SWIRegs);
		WimpCloseDown();
	}

	return(OSError);
}

void MessagesLoad(char *FileName) {
	char *MessagesBuffer;
	char *s;
	int MessageBufferLength;
	SWIRegs.r[1] = (int)FileName;
	// Get file info; return NULL if not found
	if (SWIX(MessageTrans_FileInfo) != NULL) { return; }
	// Allocate the space we need to load the file
	int i;
	i = SWIRegs.r[2];
	MyMessages = malloc(sizeof(t_MessageTrans_FileDescriptor)+SWIRegs.r[2]);
	if(MyMessages == NULL) { SWIE("MessageLoad malloc"); }
	MessagesBuffer = (char*)(MyMessages + 1); // sizeof(t_MessageTrans_FileDescriptor);

	SWIRegs.r[0] = (int)MyMessages;
	SWIRegs.r[1] = (int)FileName;
	SWIRegs.r[2] = (int)MessagesBuffer;
	SWI(MessageTrans_OpenFile);
	//BuggyBuffC("..",(char*)(MyMessages + 1),i);
	// Make stuff C friendly so that strings are strings (but skip first 4 bytes)!
	MessagesBuffer += 4; MessageBufferLength -= 4;
	for (s = MessagesBuffer;MessageBufferLength > 0; s++, MessageBufferLength--) {
		if (*s == (char)10) { *s = (char)0; }
	}
}

void MessagesClose(void) {
	if (MyMessages != NULL) {
		SWIRegs.r[0] = (int)MyMessages;
		SWI(MessageTrans_CloseFile);
		free(MyMessages);
		MyMessages = NULL;

	}
}

char *MessagesLookup(char *Token) {

	if (MyMessages != NULL) {
		// Initial version does not support variables
		SWIRegs.r[0] = (int)MyMessages;
		SWIRegs.r[1] = (int)(Token+1);
		SWIRegs.r[2] = 0; // no buffer for result
		SWIRegs.r[3] = 0; // length not important
		SWIRegs.r[4] = 0; // %0
		SWIRegs.r[5] = 0; // %1
		SWIRegs.r[6] = 0; // %2
		SWIRegs.r[7] = 0; // %3
		if (SWIX(MessageTrans_Lookup) == NULL) { return((char*)SWIRegs.r[2]); }
		else                                   { return(Token);               }

	}
	else {
		return(Token);
	}

}

char *MessagesTrans(char *Token, char *P0, char *P1, char *P2, char *P3) {
	int l;
	char *Buffer;

	// Get space I need
	l = strlen(MessagesLookup(Token));
	if (P0 != NULL) l += strlen(P0);
	if (P1 != NULL) l += strlen(P1);
	if (P2 != NULL) l += strlen(P2);
	if (P3 != NULL) l += strlen(P3);

	Buffer = malloc(l+1); // add one for terminating zero byte
	if(Buffer == NULL) { SWIE(#"MessagesTrans malloc#"); }

	if (MyMessages != NULL) {
		SWIRegs.r[0] = (int)MyMessages;
		SWIRegs.r[1] = (int)(Token+1);
		SWIRegs.r[2] = (int)Buffer;
		SWIRegs.r[3] = l;
		SWIRegs.r[4] = (int)P0;
		SWIRegs.r[5] = (int)P1;
		SWIRegs.r[6] = (int)P2;
		SWIRegs.r[7] = (int)P3;
		if (SWIX(MessageTrans_Lookup) != NULL) { strcpy(Buffer,Token);        }
	}
	else {
		strcpy(Buffer,Token);
	}

	return(Buffer);
}

char *MessagesFill(char *Token, char *P0, char *P1, char *P2, char *P3, char *Buffer, int BufferLen) {

	if (MyMessages != NULL) {
		SWIRegs.r[0] = (int)MyMessages;
		SWIRegs.r[1] = (int)Token;
		SWIRegs.r[2] = (int)Buffer;
		SWIRegs.r[3] = BufferLen;
		SWIRegs.r[4] = (int)P0;
		SWIRegs.r[5] = (int)P1;
		SWIRegs.r[6] = (int)P2;
		SWIRegs.r[7] = (int)P3;
		if (SWIX(MessageTrans_Lookup) != NULL) { strcpy(Buffer,Token); }
	}
	else {
		strcpy(Buffer,Token);
	}
	return(Buffer);
}



char *TXT(char *Text) {
	if (*Text == '>') { return(MessagesLookup(Text)); }
	else              { return(Text);                 }
}

// StringLength with delim 00, 0a and 0d
int StringLength(char *s) {
	int l = 0;
	for (;; s++) {
		if ((*s == (char)0) || (*s == (char)10) || (*s == (char)13)) { return l; }
		l++;
	}
}

// Case insensitive string compare
int StringCompare(char *a, char *b) {
	int d;
	for (;; a++, b++) {
		d = tolower(*a) - tolower(*b);
		if ((d != 0) || (*a == (char)0) || (*b == (char)0)) { return d; }
	}
}

// Function for SWI Wimp_Initalise
void WimpInitialise(void) {
	SWIRegs.r[0] = 310;
	SWIRegs.r[1] = TASK;
	SWIRegs.r[2] = (int)&MyTaskName;
	SWIRegs.r[3] = (int)NULL;
	SWI(Wimp_Initialise);
	MyTaskHandle = SWIRegs.r[1];
}

// Function for SWI Wimp_Poll
int WimpPoll(void) {
	SWI(OS_ReadMonotonicTime);
	SWIRegs.r[2] = SWIRegs.r[0] + WimpPollWait;
	SWIRegs.r[0] = WimpPollMask;
	SWIRegs.r[1] = (int)&WimpPollBlockStorage;
	SWI(Wimp_PollIdle);
	// I would expect that the block I pass to Wimp_Poll is the one filled but the PRMs do not guarantee that!
	WimpPollBlock = (t_WimpPollBlock *)SWIRegs.r[1];
	return(SWIRegs.r[0]);
}

// Function to put Icon on icon bar with SWI Wimp_CreateIcon
t_IconHandle WimpCreateIconBarIcon(char *Sprite, t_WindowHandle LeftRight) {
	t_WimpCreateIconBlock WimpCreateIconBlock;
	WimpCreateIconBlock.WindowHandle = LeftRight;
	WimpCreateIconBlock.Icon.BoundingBox.MinX = 0;
	WimpCreateIconBlock.Icon.BoundingBox.MinY = 0;
	WimpCreateIconBlock.Icon.BoundingBox.MaxX = 69;
	WimpCreateIconBlock.Icon.BoundingBox.MaxY = 68;
	WimpCreateIconBlock.Icon.IconFlags = IconFlags_IconBar;
	WimpCreateIconBlock.Icon.IconData.IconSpriteIndirect.Sprite = Sprite;
	WimpCreateIconBlock.Icon.IconData.IconSpriteIndirect.Area = WimpSpriteArea;
	WimpCreateIconBlock.Icon.IconData.IconSpriteIndirect.Length = strlen(Sprite);
	SWIRegs.r[0] = 0;
	SWIRegs.r[1] = (int)&WimpCreateIconBlock;
	SWI(Wimp_CreateIcon);
	return(SWIRegs.r[0]);
}

// Function to check if a key is pressed
int KeyPressCheck(int Key) {
	SWIRegs.r[0] = 129;
	SWIRegs.r[1] = Key ^ 0xff;
	SWIRegs.r[2] = 0xff;
	SWI(OS_Byte);
	return((SWIRegs.r[1] == 0xff));
}

// Function to check mouse buttons
int MouseButtonCheck(int Button) {
	SWIRegs.r[0] = (int)&WimpPollBlockStorage;
	SWI(Wimp_GetPointerInfo);
	return((WimpPollBlockStorage.MouseClick.Buttons == Button));
}

// Function to create a simple menu
t_Menu *CreateMenu(char *Title, ...) {
	char *Entry;
	int Count = 0;
	t_MenuHeader *MenuHeader;
	t_MenuItem   *MenuItem;
	va_list Entries;

	// Count the number of entries needed

	va_start(Entries,Title); // Get the parameter list
	for(;;) {
		Entry = va_arg(Entries, char*); // Get next one
		if(Entry == NULL) { break; }
		Count++;
	}
	va_end(Entries); // Clean up

	// Allocate the space we need
	MenuHeader = malloc(sizeof(t_MenuHeader) + Count * sizeof(t_MenuItem));
	if(MenuHeader == NULL) { SWIE("Menu malloc"); }

	// Fill Header
	if (strlen(TXT(Title)) > sizeof(MenuHeader->Title)) {
		MenuHeader->Title.IconTextIndirect.Text = TXT(Title);
		MenuHeader->Title.IconTextIndirect.Validation = NULL;
		MenuHeader->Title.IconTextIndirect.Length = strlen(TXT(Title));
	}
	else {
		strncpy(MenuHeader->Title.IconText,TXT(Title),sizeof(MenuHeader->Title.IconText));
	}
	MenuHeader->TitleForeground = 7;
	MenuHeader->TitleBackground = 2;
	MenuHeader->BodyForeground = 7;
	MenuHeader->BodyBackground = 0;
	MenuHeader->Width = 0;
	MenuHeader->Height = 44;
	MenuHeader->Gap = 0;

	// Point to first menu entry
	// Since MenuHeader is a pointer to the menu header, adding 1 points just after it!
	MenuItem = (t_MenuItem*)(MenuHeader+1);

	va_start(Entries,Title); // Get the parameter list again
	for(;;) {
		Entry = va_arg(Entries, char*); // Get next one
		if(Entry == NULL) { break; }
		MenuItem->MenuFlags = MenuFlags_Standard;
		MenuItem->MenuLink.Warning = 0;
		if (strlen(TXT(Entry)) > sizeof(MenuItem->IconData.IconText)) {
			MenuItem->IconData.IconTextIndirect.Text = TXT(Entry);
			MenuItem->IconData.IconTextIndirect.Validation = NULL;
			MenuItem->IconData.IconTextIndirect.Length = strlen(TXT(Entry));
			MenuItem->IconFlags = IconFlags_MenuItem | IconFlags_Mask_Indirect;
		}
		else {
			strncpy(MenuItem->IconData.IconText,TXT(Entry),sizeof(MenuItem->IconData.IconText));
			MenuItem->IconFlags = IconFlags_MenuItem;
		}
		MenuItem++;
	}
	// Set flag in last menu item that it is the last one
	MenuItem--;
	MenuItem->MenuFlags = (MenuItem->MenuFlags | MenuFlags_Mask_Last);
	va_end(Entries); // Clean up

	// Set flag in first if title is indirected
	if (strlen(TXT(Title)) > sizeof(MenuHeader->Title)) {
		MenuItem = (t_MenuItem*)(MenuHeader+1);
		MenuItem->MenuFlags = MenuItem->MenuFlags | MenuFlags_Title_Indirect;
	}
	return ((t_Menu*)MenuHeader);
}


// Open Menu
void OpenMenu(t_Menu *Menu) {

	t_MenuHeader *MenuHeader;
	t_MenuItem *MenuItem;

	MenuHeader = (t_MenuHeader*)Menu;

	// X position is 64 to the left of the mouse
	// Y position depends: Iconbar or not
	SWIRegs.r[1] = (int)MenuHeader;
	SWIRegs.r[2] = WimpPollBlock->MouseClick.Mouse.X - 64;
	SWIRegs.r[3] = WimpPollBlock->MouseClick.Mouse.Y - 8;
	if (WimpPollBlock->MouseClick.WindowHandle == WindowIconbar) {
		SWIRegs.r[3] = 96 + MenuHeader->Height;
		MenuItem = (t_MenuItem*)(MenuHeader+1);
		do	{
			SWIRegs.r[3] += MenuHeader->Height;
			if ((MenuItem->MenuFlags & MenuFlags_Mask_Dashes) != 0) SWIRegs.r[3] += 24;
			MenuItem++;
		}
		while ((MenuItem->MenuFlags & MenuFlags_Mask_Last) == 0);
	}
	SWI(Wimp_CreateMenu);

}

// Create a basic window
t_Window *CreateBasicWindow(char *Title, unsigned Flags, int Icons, int MaxX, int MaxY) {

	 t_WindowHeader *WindowHeader;

	WindowHeader = malloc(sizeof(t_WindowHeader) + Icons * sizeof(t_Icon));
	if(WindowHeader == NULL) { SWIE("Window malloc"); }

	WindowHeader->Visible.MinX = 0;
	WindowHeader->Visible.MinY = 0;
	WindowHeader->Visible.MaxX = MaxX;
	WindowHeader->Visible.MaxY = MaxY;
	WindowHeader->ScrollX = 0;
	WindowHeader->ScrollY = 0;
	WindowHeader->WindowStack = Window_OpenInFront;
	WindowHeader->WindowFlags = Flags;
	WindowHeader->TitleForground = 7;
	WindowHeader->TitleBackground = 2;
	WindowHeader->WorkareaForground = 7;
	WindowHeader->WorkareaBackground = 1;
	WindowHeader->ScrollbarBackground = 3;
	WindowHeader->ScrollbarForeground = 1;
	WindowHeader->TitleFocusBackground = 12;
	WindowHeader->ExtraFlags = 0;
	WindowHeader->Workarea.MinX = 0;
	WindowHeader->Workarea.MinY = -MaxY;
	WindowHeader->Workarea.MaxX = MaxX;
	WindowHeader->Workarea.MaxY = 0;
	WindowHeader->TitleIconFlags = IconFlags_WindowTitle;
	WindowHeader->WorkareaButtonType = IconButton_MenuOnly;
	WindowHeader->ToolSpriteArea = WimpSpriteArea;
	WindowHeader->MinArea = 0;
	WindowHeader->TitleIconData.IconTextIndirect.Text = TXT(Title);
	WindowHeader->TitleIconData.IconTextIndirect.Validation = NULL;
	WindowHeader->TitleIconData.IconTextIndirect.Length = strlen(TXT(Title));
	WindowHeader->IconCount = Icons;
	return((t_Window*)WindowHeader);
}

void FillIcon(t_Icon *Icon, unsigned Flags, char* Text, int Length, char *Validation, int ESG, int X, int Y, int Width, int Height) {
	Icon->BoundingBox.MinX = X;
	Icon->BoundingBox.MinY = -Y-Height;
	Icon->BoundingBox.MaxX = X+Width;
	Icon->BoundingBox.MaxY = -Y;
	Icon->IconFlags = Flags | IconFlags_Mask_Indirect | ((ESG & 0x1f)<<IconFlags_Shift_ESG);
	if (*Validation == 'R') { Icon->IconFlags |= IconFlags_Mask_Border; }
	Icon->IconData.IconTextIndirect.Text = TXT(Text);
	Icon->IconData.IconTextIndirect.Validation = Validation;
	if (Length == 0) { Icon->IconData.IconTextIndirect.Length = strlen(TXT(Text)); }
	else             { Icon->IconData.IconTextIndirect.Length = Length;                  }
	//BuggyIconI("Icon",Icon);
}

#define FillTextIcon(Window,Icon,Flags,Text,X,Y,Validation,Width) FillIcon(&Window->WindowIcon[Icon],Flags,Text,1,Validation,0,X,Y,Width,44)
#define FillEditIcon(Window,Icon,Text,Length,Validation,X,Y,Width) FillIcon(&Window->WindowIcon[Icon],IconFlags_Edit | IconFlags_Mask_Border,Text,Length,Validation,0,X,Y,Width,44)
#define FillButtonIcon(Window,Icon,Text,Validation,X,Y,Width,Height) FillIcon(&Window->WindowIcon[Icon],IconFlags_Button | IconFlags_Mask_Border,Text,1,Validation,0,X,Y,Width,Height)
#define FillOnOffIcon(Window,Icon,Validation,ESG,X,Y) FillIcon(&Window->WindowIcon[Icon],IconFlags_OnOff,Icon_NoText,1,Validation,ESG,X,Y,44,44)
#define FillClickIcon(Window,Icon,Validation,X,Y) FillIcon(&Window->WindowIcon[Icon],IconFlags_Click,Icon_NoText,1,Validation,0,X,Y,44,44)

#define FillTextIconXY(Window,Icon,Flags,Text,Validation,Xs,Xi,Ys,Yi,Width) FillIcon(&Window->WindowIcon[Icon],Flags,Text,1,Validation,0,XY(Xs)+Xi,XY(Ys)+Yi,Width,XY("T"))
#define FillEditIconXY(Window,Icon,Text,Length,Validation,Xs,Xi,Ys,Yi,Width) FillIcon(&Window->WindowIcon[Icon],IconFlags_Edit | IconFlags_Mask_Border,Text,Length,Validation,0,XY(Xs)+Xi,XY(Ys)+Yi,Width,XY("T"))
#define FillButtonIconXY(Window,Icon,Text,Validation,Xs,Xi,Ys,Yi,Width,Height) FillIcon(&Window->WindowIcon[Icon],IconFlags_Button | IconFlags_Mask_Border,Text,1,Validation,0,XY(Xs)+Xi,XY(Ys)+Yi,Width,Height)
#define FillOnOffIconXY(Window,Icon,Validation,ESG,Xs,Xi,Ys,Yi) FillIcon(&Window->WindowIcon[Icon],IconFlags_OnOff,Icon_NoText,1,Validation,ESG,XY(Xs)+Xi,XY(Ys)+Yi,XY("T"),XY("T"))
#define FillClickIconXY(Window,Icon,Validation,Xs,Xi,Ys,Yi) FillIcon(&Window->WindowIcon[Icon],IconFlags_Click,Icon_NoText,1,Validation,0,XY(Xs)+Xi,XY(Ys)+Yi,XY("T"),XY("T"))

// Get Icon Text
char *GetIconText(unsigned IconFlags, t_IconData *IconData) {

	if ((IconFlags & IconFlags_Mask_Text) == 0) {
		IconTextBuffer[0] = 0;
		return ((char*)(&IconTextBuffer));
	}

	if ((IconFlags & IconFlags_Mask_Indirect) == 0) {
		IconTextBuffer[sizeof(t_IconData)] = 0;
		strncpy(IconTextBuffer,IconData->IconText,sizeof(t_IconData));
		return ((char*)(&IconTextBuffer));
	}

	return (IconData->IconTextIndirect.Text);
}
#define GetIconTextFD(IconFlags) GetIconText(IconFlags,(t_IconData*)(&IconFlags +1))

#define GetIconTextMenuEntry(Menu,Item) GetIconText(Menu->MenuItem[Item].IconFlags,&(Menu->MenuItem[Item].IconData))

int GetMenuEntryNumber(t_Menu *Menu, char *Token)  {
	char *Entry = MessagesLookup(Token);
	int Result = -1;
	int i;
	for (i=0;Result==-1;i++) {
		if(strcmp(Entry,GetIconText(Menu->MenuItem[i].IconFlags,&(Menu->MenuItem[i].IconData))) == 0) { Result = i; }
		if ((Menu->MenuItem[i].MenuFlags & MenuFlags_Mask_Last) != 0) { break; }
	}
	return(Result);
}


// Wimp create window
t_WindowHandle WimpCreateWindow(t_Window *Window) {
	SWIRegs.r[1] = (int)Window;
	SWI(Wimp_CreateWindow);
	return((t_WindowHandle)SWIRegs.r[0]);
}

// Wimp close window
void WimpCloseWindow(void) {
	SWIRegs.r[1] = (int)(WimpPollBlock);
	SWI(Wimp_CloseWindow);
}

// Wimp open window
void WimpOpenWindow(void) {
	SWIRegs.r[1] = (int)(WimpPollBlock);
	SWI(Wimp_OpenWindow);
}

// Move to center
void MoveToCenter(t_BoxenLuder *Box) {
	int X,Y;
	// Current screen mode
	SWIRegs.r[0] = -1;
	// Read X and Y resolution
	SWIRegs.r[1] = 11; SWI(OS_ReadModeVariable); X = ++(SWIRegs.r[2]);
	SWIRegs.r[1] = 12; SWI(OS_ReadModeVariable); Y = ++(SWIRegs.r[2]);
	// Shift resolution by Eigfactor
	SWIRegs.r[1] = 4; SWI(OS_ReadModeVariable); X = X * (++(SWIRegs.r[2]));
	SWIRegs.r[1] = 5; SWI(OS_ReadModeVariable); Y = Y * (++(SWIRegs.r[2]));
	// Get offset to shift to middle X
	X = (X - (Box->MaxX - Box->MinX)) / 2;
	Box->MinX +=X;
	Box->MaxX +=X;
	// Get offset to shift to middle Y
	Y = (Y - (Box->MaxY - Box->MinY)) / 2;
	Box->MinY +=Y;
	Box->MaxY +=Y;
}

// Wimp open window
t_WindowHandle WimpOpenNewWindow(t_Window *Window, t_WindowHandle WindowHandle, int Center) {

	if (WindowHandle == -1) { WimpPollBlockStorage.OpenWindow.WindowHandle = WimpCreateWindow(Window); }
	else                    { WimpPollBlockStorage.OpenWindow.WindowHandle = WindowHandle; }
	WimpPollBlockStorage.OpenWindow.Visible.MinX = Window->WindowHeader.Visible.MinX;
	WimpPollBlockStorage.OpenWindow.Visible.MinY = Window->WindowHeader.Visible.MinY;
	WimpPollBlockStorage.OpenWindow.Visible.MaxX = Window->WindowHeader.Visible.MaxX;
	WimpPollBlockStorage.OpenWindow.Visible.MaxY = Window->WindowHeader.Visible.MaxY;
	WimpPollBlockStorage.OpenWindow.ScrollX      = Window->WindowHeader.ScrollX;
	WimpPollBlockStorage.OpenWindow.ScrollY      = Window->WindowHeader.ScrollY;
	WimpPollBlockStorage.OpenWindow.WindowStack  = Window->WindowHeader.WindowStack;

	if (Center) { MoveToCenter(&(WimpPollBlockStorage.OpenWindow.Visible)); }

	SWIRegs.r[1] = (int)(&WimpPollBlockStorage);
	SWI(Wimp_OpenWindow);

	return(WimpPollBlockStorage.OpenWindow.WindowHandle);
}

void WimpRedrawIcon(t_Window *Window,t_WindowHandle WindowHandle, t_IconHandle IconHandle) {
	t_IconSetState Buf;
	Buf.WindowHandle = WindowHandle;
	Buf.IconHandle   = IconHandle;
	Buf.EORword = 0;
	Buf.CLRword = 0;
	SWIRegs.r[1] = (int)(&Buf);
	SWI(Wimp_SetIconState);
}

int WimpGetIconState(t_WindowHandle WindowHandle, t_IconHandle IconHandle) {
	t_WimpGetIconStateBlock Block;
	Block.WindowHandle = WindowHandle;
	Block.IconHandle = IconHandle;
	SWIRegs.r[1] = (int)(&Block);
	SWI(Wimp_GetIconState);
	return((Block.Icon.IconFlags & IconFlags_Mask_Selected) == 0 ? False : True);
}




int main (int argc, char *argv[]) {

	int ReasonCode;

	BuggyClear;

	WimpInitialise();

	MyBarIcon = WimpCreateIconBarIcon("Switcher",IconBar_IconRight);

	// Load Messages
	MessagesLoad("<Obey$Dir>.Messages");


	// The classic infobox
	MyInfoWindow = CreateBasicWindow(">I_TIT",WindowFlags_Info,6,20+120+20+300+20,20+44+20+44+20+44+20);
	FillTextIconXY(MyInfoWindow,0,IconFlags_TextR,">I_NAME",           IconValidation_Flat,"S",     0,"S",   0,120);
	FillTextIconXY(MyInfoWindow,1,IconFlags_TextC,(char*)MyTaskName,   IconValidation_Text,"S2+120",0,"S",   0,300);
	FillTextIconXY(MyInfoWindow,2,IconFlags_TextR,">I_AUTHOR",         IconValidation_Flat,"S",     0,"S2T", 0,120);
	FillTextIconXY(MyInfoWindow,3,IconFlags_TextC,"Herbert zur Nedden",IconValidation_Text,"S2+120",0,"S2T", 0,300);
	FillTextIconXY(MyInfoWindow,4,IconFlags_TextR,">I_VERSION",        IconValidation_Flat,"S",     0,"S3T2",0,120);
	FillTextIconXY(MyInfoWindow,5,IconFlags_TextC,(char*)MyVersion,    IconValidation_Text,"S2+120",0,"S3T2",0,300);

//	FillTextIconXY(MyInfoWindow,5,IconFlags_TextC,MessagesTrans("L_USTIG","P1","P2","",""),IconValidation_Text,"S2+120",0,"S3T2",0,300);

	// A simple menu with just Info and Quit
	MyBarMenu = CreateMenu(">M_TITLE",">M_INFO",">M_QUIT",NULL);
	MyBarMenu->MenuItem[0].MenuLink.Window  = WimpCreateWindow(MyInfoWindow);
	int MenuEntry_Quit = GetMenuEntryNumber(MyBarMenu,">M_QUIT");

	//GetIconText(MyBarMenu->MenuItem[0].IconFlags,&(MyBarMenu->MenuItem[0].IconData));
	//GetIconText(MyBarMenu->MenuItem[1].IconFlags,&(MyBarMenu->MenuItem[1].IconData));
	//GetIconTextFD(MyBarMenu->MenuItem[0].IconFlags);
	//GetIconTextFD(MyBarMenu->MenuItem[1].IconFlags);

	while (True) {
		ReasonCode = WimpPoll();
		BuggyInt("ReasonCode",ReasonCode);

		// Handle the request
		switch(ReasonCode) {

		// Mouse click
		case ReasonCode_MouseClick:
			//BuggyBuffI("Mouse",WimpPollBlock,12);
			// Iconbar icon
			if ((WimpPollBlock->MouseClick.WindowHandle == WindowIconbar) && (WimpPollBlock->MouseClick.IconHandle == MyBarIcon)) {
				switch(WimpPollBlock->MouseClick.Buttons) {
				case MouseButtonMiddle: // Menu click
					OpenMenu(MyBarMenu);
					break;
				}
			}
			break;

		// Menu selection
		case ReasonCode_MenuSelection:
			//BuggyBuffI("Menu",WimpPollBlock,12);
			//switch(WimpPollBlock->MenuSelection.MenuItem[0]) {
			//case MenuEntry_Quit:
			//	WimpCloseDown();
			//	break;
			//}
			if (WimpPollBlock->MenuSelection.MenuItem[0] == MenuEntry_Quit) {
				WimpCloseDown();
				break;
			}

			if (MouseButtonCheck(MouseButtonRight)) { OpenMenu(MyBarMenu); }
			break;

		// Window stuff
		case ReasonCode_OpenWindow:
			//BuggyMessage("ReasonCode_OpenWindow");
			WimpOpenWindow();
			break;
		case ReasonCode_CloseWindow:
			//BuggyMessage("ReasonCode_CloseWindow");
			WimpCloseWindow();
			break;

		// User message
		case ReasonCode_UserMessage:
		case ReasonCode_UserMessageRecorded:
		case ReasonCode_UserMessageAcknowledge:
			switch(WimpPollBlock->UserMessage.MessageCode) {
			case MessageCode_Quit:
				 WimpCloseDown();
				 break;
			}
			break;
		}
	}


}

