/**********************************************************************
 
	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomoki SEKIYAMA <sekiyama@yahoo.co.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/



#include <UDesktop.h>

#include "CWindowMenuAttachment.h"


CWindowMenuAttachment* CWindowMenuAttachment::sMain = nil;


CWindowMenuAttachment::CWindowMenuAttachment()
	: LAttachment(msg_AnyMessage, true), mWindowList(nil), mWindowMenu(nil)
{
	sMain = this;
	first = num = 0;
}

void
CWindowMenuAttachment::SetupMenu(LMenu *menu)
{
printf("Setup...\n");
	mWindowMenu = menu;
	if ( menu == nil )
		return;

	WindowList *prev, *list, *newList = 0;
	int n;

	WindowRef win = GetFrontWindowOfClass(kDocumentWindowClass, true);
	n = 0;

	// Make window list with recycling the last list
	do {
		prev = 0;
		for ( list = mWindowList ; list ; prev = list, list = list->next ) {
			if ( list->window == win )
				break;
		}
		if ( list ) {
			list->item_num = 0xffff;
		}
		else {
			list = new WindowList;
			list->window = win;
			list->next = newList;
			newList = list;
		}
		n++;
	} while ( win = GetNextWindowOfClass(win, kDocumentWindowClass, true) );

	// Prepend / release the last list
	WindowList *toMergeTop = 0, *toMergeLast = 0;
	while ( mWindowList ) {
		list = mWindowList->next;
		if ( mWindowList->item_num == 0xffff ) {
			if ( toMergeTop == 0 )
				toMergeTop = mWindowList;
			else
				toMergeLast->next = mWindowList;
			toMergeLast = mWindowList;
		}
		else {
			delete mWindowList;
		}
		mWindowList = list;
	}
	if ( toMergeLast ) {
		toMergeLast->next = newList;
		newList = toMergeTop;
	}
	
	// Set new menu list
	mWindowList = newList;
	
	// Get ready to insert menu items
	Str255 title;
	MenuRef macmenu = menu->GetMacMenuH();
	UInt16 item = CountMenuItems(macmenu);
	first = item+1;
	num = 0;
	
	// if there are already some menu items, add a separator line
	if ( item ) {
		menu->InsertCommand("\p-", cmd_UseMenuItem, ++item);
		num++;
		n++;
	}

	// insert menu items
	for ( list = newList ; list ; list = list->next ) {
		GetWTitle(list->window, title);
		menu->InsertCommand("\p ", cmd_UseMenuItem, item);
		SetMenuItemText(macmenu, item+1, title);
		num++;
		list->item_num = first+n-1;
		n--;
	}
}

void
CWindowMenuAttachment::UpdateMenu()
{
	ClearMenu();
	SetupMenu(mWindowMenu);
}

void
CWindowMenuAttachment::ClearMenu()
{
printf("Clear...[%d %d]\n", first, num);
	for ( UInt16 i = 0 ; i < num ; i++ ) {
		mWindowMenu->RemoveItem(first);
	}
}

WindowRef
CWindowMenuAttachment::GetWindowByItemNum(UInt16 num)
{
	for ( WindowList *list = mWindowList ; list ; list = list->next )
		if ( list->item_num == num )
			return list->window;
	return nil;
}


void
CWindowMenuAttachment::ExecuteSelf(MessageT inMessage, void* ioParam)
{
	mExecuteHost = true;
	
	if ( mWindowMenu == nil )
		return;
	
	WindowRef front = GetFrontWindowOfClass(kDocumentWindowClass, true);

	switch ( inMessage ) {
		
	case msg_CommandStatus:
		SCommandStatusP sts = (SCommandStatusP)ioParam;
		ResIDT id;
		SInt16 item;
		if ( LCommander::IsSyntheticCommand(sts->command, id, item)
				&& id == mWindowMenu->GetMenuID() && item >= first ) {
			*sts->enabled = true;
			*sts->usesMark = true;
			if ( front == GetWindowByItemNum(item) )
				*sts->mark = checkMark;
			else
				*sts->mark = noMark;
			mExecuteHost = false;
		}
		break;

	default:
		if ( LCommander::IsSyntheticCommand(inMessage, id, item)
				&& id == mWindowMenu->GetMenuID() && item >= first ) {
			SelectWindow(GetWindowByItemNum(item));
			mExecuteHost = false;
		}
	}
}