/*	RMenu.cpp
 *
 *		Compile the menu resources
 *
 *
 *		Menu resources have the following format:
 *
 *			menu <id>
 *				begin
 *					menu "name"
 *						begin
 *							item "name" id  [ accel ]
 *							separator
 *						end
 *					menu "name"
 *						begin
 *							item "name" id [accel]
 *						end
 *				end
 */

/*  RCompile - UNIX Resource compiler for YAAF Library
 *  Copyright (C) 1998 William Edward Woody
 *  
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *  
 *  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.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 *  02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <string.h>
#include "swap.h"
#include "RCompile.h"
#include "lex.h"

/************************************************************************/
/*																		*/
/*	Forwards															*/
/*																		*/
/************************************************************************/

extern unsigned char *CompileMenu(unsigned char *);

/************************************************************************/
/*																		*/
/*	Menu Compiler														*/
/*																		*/
/************************************************************************/

/*	CompileItem
 *
 *		Parse the 'item name...' stuff
 */

static unsigned char *CompileItem(unsigned char *ptr)
{
	char name[256];
	short id;
	short accel;
	int i;
	short size;
	char *x;
	
	i = GetNextToken();
	if (i != KLexString) {
		PrintError("Expected string");
		return ptr;
	}
	strcpy(name,GToken);
	
	i = GetNextToken();
	if (i != KLexInteger) {
		PrintError("Expected integer");
		return ptr;
	}
	id = GInteger;
	
	i = GetNextToken();
	if (i != KLexChar) {
		PushBackToken(i);
		accel = 0;
	} else {
		accel = GToken[0];
	}
	
	size = strlen(name) + 5;
	if (size > 254) size = 254;
	if ((size % 2) == 1) size++;
	
	/*
	 *	Now write the item
	 */
	
	*ptr++ = 0x80;				// header item
	*ptr++ = size;
	
	*((short *)ptr) = NSwapWord(id);
	ptr += 2;
	*((short *)ptr) = NSwapWord(accel);
	ptr += 2;
	
	x = name;
	for (i = 5; i < size; i++) {
		*ptr++ = *x++;
	}
	*ptr++ = 0;
	
	return ptr;
}

/*	CompileSeparator
 *
 *		Compile the separator statement. Actually does little more
 *	than write data to the data stream
 */

static unsigned char *CompileSeparator(unsigned char *ptr)
{
	*ptr++ = 0x81;
	*ptr++ = 0x00;
	return ptr;
}

/*	CompileMenuContents
 *
 *		Compile the contents
 */

static unsigned char *CompileMenuContents(unsigned char *ptr)
{
	int i;
	
	/*
	 *	get the 'begin'
	 */
	
	i = GetNextToken();
	if (i != KTokenBegin) {
		PrintError("Expected 'begin'");
		return ptr;
	}
	
	/*
	 *	Now start parsing the menu item contents
	 */
	
	for (;;) {
		i = GetNextToken();
		if (i == -1) {
			PrintError("Unexpected end of file");
			return ptr;
		}
		
		if (i == KTokenSeparator) {
			ptr = CompileSeparator(ptr);
		} else if (i == KTokenMenu) {
			ptr = CompileMenu(ptr);
		} else if (i == KTokenItem) {
			ptr = CompileItem(ptr);
		} else if (i == KTokenEnd) {
			*ptr++ = 0x00;
			*ptr++ = 0x00;
			break;
		} else {
			PrintError("Unexpected symbol");
			return ptr;
		}
	}
	
	return ptr;
}

/*	CompileMenu
 *
 *		Compile a menu. Get the name and then the contents
 */

unsigned char *CompileMenu(unsigned char *ptr)
{
	char buffer[256];
	int i;
	short len;
	char *x;
	
	i = GetNextToken();
	if (i != KLexString) {
		PrintError("Expected menu name");
		return ptr;
	}
	strcpy(buffer,GToken);

	/*
	 *	Add the menu object
	 */
	
	len = strlen(buffer) + 1;
	if (len > 254) len = 254;
	if (1 == (len % 2)) len++;
	*ptr++ = 0x82;
	*ptr++ = len;
	
	x = buffer;
	for (i = 1; i < len; i++) {
		*ptr++ = *x++;
	}
	*ptr++ = 0;
	
	/*
	 *	And get the contents
	 */
	
	return CompileMenuContents(ptr);
}

/************************************************************************/
/*																		*/
/*	Compile Resources													*/
/*																		*/
/************************************************************************/

/*	CompileMenuResource
 *
 *		Compile the menu resource
 */

long CompileMenuResource(unsigned char *ptr)
{
	unsigned char *e = ptr;
	int i;
	
	/*
	 *	get the 'begin'
	 */
	
	i = GetNextToken();
	if (i != KTokenBegin) {
		PrintError("Expected 'begin'");
		return 0;
	}
	
	/*
	 *	Now start parsing the menu item contents
	 */
	
	for (;;) {
		i = GetNextToken();
		if (i == -1) {
			PrintError("Unexpected end of file");
			return 0;
		}
		
		if (i == KTokenMenu) {
			ptr = CompileMenu(ptr);
		} else if (i == KTokenEnd) {
			*ptr++ = 0x00;
			*ptr++ = 0x00;
			break;
		} else {
			PrintError("Unexpected symbol");
			return 0;
		}
	}
	
	return ptr - e;
}
