text: /******************************************************************************
  	Project: 	MicroMacro
  	Author: 	SolarStrike Software
  	URL:		www.solarstrike.net
  	License:	Modified BSD (see license.txt)
  ******************************************************************************/
  
  extern "C"
  {
  	#include <lua.h>
  	#include <lauxlib.h>
  	#include <lualib.h>
  }
  
  #include "wininclude.h"
  #include "cli_lua.h"
  #include "macro.h"
  #include "error.h"
  
  int Cli_lua::regmod(lua_State *L)
  {
  	static const luaL_Reg _funcs[] = {
  		{"clear", Cli_lua::clear},
  		{"resetColor", Cli_lua::resetColor},
  		{"getColor", Cli_lua::getColor},
  		{"setColor", Cli_lua::setColor},
  		{"getAttributes", Cli_lua::getAttributes},
  		{"setAttributes", Cli_lua::setAttributes},
  		{NULL, NULL}
  	};
  
  	luaL_newlib(L, _funcs);
  
  	lua_pushinteger(L, 0);
  	lua_setfield(L, -2, "BLACK");
  	lua_pushinteger(L, 1);
  	lua_setfield(L, -2, "BLUE");
  	lua_pushinteger(L, 2);
  	lua_setfield(L, -2, "GREEN");
  	lua_pushinteger(L, 3);
  	lua_setfield(L, -2, "CYAN");
  	lua_pushinteger(L, 4);
  	lua_setfield(L, -2, "RED");
  	lua_pushinteger(L, 5);
  	lua_setfield(L, -2, "MAGENTA");
  	lua_pushinteger(L, 6);
  	lua_setfield(L, -2, "YELLOW");
  	lua_pushinteger(L, 7);
  	lua_setfield(L, -2, "WHITE");
  	lua_pushinteger(L, 8);
  	lua_setfield(L, -2, "GRAY");
  	lua_pushinteger(L, 9);
  	lua_setfield(L, -2, "LIGHT_BLUE");
  	lua_pushinteger(L, 10);
  	lua_setfield(L, -2, "LIGHT_GREEN");
  	lua_pushinteger(L, 11);
  	lua_setfield(L, -2, "LIGHT_CYAN");
  	lua_pushinteger(L, 12);
  	lua_setfield(L, -2, "LIGHT_RED");
  	lua_pushinteger(L, 13);
  	lua_setfield(L, -2, "LIGHT_MAGENA");
  	lua_pushinteger(L, 14);
  	lua_setfield(L, -2, "LIGHT_YELLOW");
  	lua_pushinteger(L, 15);
  	lua_setfield(L, -2, "LIGHT_WHITE");
  
  	lua_setglobal(L, CLI_MODULE_NAME);
  
  
  	return MicroMacro::ERR_OK;
  }
  
  /*	cli.clear()
  	Returns:	nil
  
  	Clears the console screen. Nothing fancy.
  */
  int Cli_lua::clear(lua_State *L)
  {
  	HANDLE stdOut = Macro::instance()->getAppHandle();
  	COORD coord = {0, 0};
  	DWORD count;
  
  	CONSOLE_SCREEN_BUFFER_INFO csbi;
  	GetConsoleScreenBufferInfo(stdOut, &csbi);
  
  	FillConsoleOutputCharacter(stdOut, ' ', csbi.dwSize.X * csbi.dwSize.Y,
  		coord, &count);
  
  	SetConsoleCursorPosition(stdOut, coord);
  	return 0;
  }
  
  /*	cli.resetColor()
  	Returns:	nil
  
  	Resets the console's text attributes back to default
  */
  int Cli_lua::resetColor(lua_State *L)
  {
  	HANDLE stdOut = Macro::instance()->getAppHandle();
  	DWORD attributes = Macro::instance()->getConsoleDefaultAttributes();
  	SetConsoleTextAttribute(stdOut, attributes);
  
  	return 0;
  }
  
  /*	cli.getColor()
  	Returns:	number
  
  	Returns the console's current attribute mask detailing its text color
  */
  int Cli_lua::getColor(lua_State *L)
  {
  	if( lua_gettop(L) != 0 )
  		wrongArgs(L);
  
  	CONSOLE_SCREEN_BUFFER_INFO csbi;
  	GetConsoleScreenBufferInfo(Macro::instance()->getAppHandle(), &csbi);
  	lua_pushinteger(L, csbi.wAttributes);
  
  	return 1;
  }
  
  /*	cli.getColor(number color)
  	Returns:	nil
  
  	Change the console's text (and/or background) color
  */
  int Cli_lua::setColor(lua_State *L)
  {
  	int top = lua_gettop(L);
  	if( top != 1 && top != 2 )
  		wrongArgs(L);
  	checkType(L, LT_NUMBER, 1);
  
  
  	DWORD foreground = lua_tointeger(L, 1);
  	DWORD background = 0;
  	if( top >= 2 )
  	{
  		checkType(L, LT_NUMBER, 2);
  		background = lua_tointeger(L, 2);
  	}
  
  	DWORD attributes = foreground + (16*background);
  	HANDLE stdOut = Macro::instance()->getAppHandle();
  	SetConsoleTextAttribute(stdOut, attributes);
  	return 0;
  }
  
  
  /*	cli.getAttributes()
  	Returns (on success):	number windowWidth
  							number windowHeight
  							number bufferWidth
  							number bufferHeight
  							number cursorX
  							number cursorY
  
  	Returns (on failure): nil
  
  	Returns a set of console attributes.
  	Values are in characters, not pixels!
  */
  int Cli_lua::getAttributes(lua_State *L)
  {
  	if( lua_gettop(L) != 0 )
  		wrongArgs(L);
  
  	CONSOLE_SCREEN_BUFFER_INFO lpcsbi;
  	if( GetConsoleScreenBufferInfo(Macro::instance()->getAppHandle()/*GetStdHandle(STD_OUTPUT_HANDLE)*/, &lpcsbi) )
  	{
  		lua_pushnumber(L, lpcsbi.srWindow.Right + 1);
  		lua_pushnumber(L, lpcsbi.srWindow.Bottom - lpcsbi.srWindow.Top + 1);
  		lua_pushnumber(L, lpcsbi.dwSize.X);
  		lua_pushnumber(L, lpcsbi.dwSize.Y);
  		lua_pushnumber(L, lpcsbi.dwCursorPosition.X + 1);
  		lua_pushnumber(L, lpcsbi.dwCursorPosition.Y + 1);
  		return 6;
  	}
  	else
  		return 0; // Error
  }
  
  
  /*	cli.getAttributes(number windowWidth, number windowHeight,
  								number bufferWidth, number bufferHeight)
  	Returns:	nil
  
  	Modify the console's attributes.
  	Values should be in characters, not pixels.
  */
  int Cli_lua::setAttributes(lua_State *L)
  {
  	int args = lua_gettop(L);
  	if( args != 2 && args != 4 )
  		wrongArgs(L);
  
  	checkType(L, LT_NUMBER, 1);
  	checkType(L, LT_NUMBER, 2);
  
  	if( args >= 4 )
  	{
  		checkType(L, LT_NUMBER, 3);
  		checkType(L, LT_NUMBER, 4);
  	}
  
  	// Get original buffer size
  	CONSOLE_SCREEN_BUFFER_INFO lpcsbi;
  	GetConsoleScreenBufferInfo(Macro::instance()->getAppHandle()/*GetStdHandle(STD_OUTPUT_HANDLE)*/, &lpcsbi);
  
  	// For window size
  	SMALL_RECT rect;
  	rect.Right = lua_tointeger(L, 1) - 1;
  	rect.Bottom = lua_tointeger(L, 2) - 1;
  	rect.Left = 0;
  	rect.Top = 0;
  
  	// For buffer size
  	COORD coord;
  	coord.X = lpcsbi.dwSize.X;
  	coord.Y = lpcsbi.dwSize.Y;
  
  	// Set buffer size
  	if( args >= 4 )
  	{
  		coord.X = lua_tointeger(L, 3);
  		coord.Y = lua_tointeger(L, 4);
  	}
  
  	// Ensure that the buffer will be of proper size
  	COORD tmpCoord;
  	tmpCoord.X = coord.X;
  	tmpCoord.Y = coord.Y;
  	if( lpcsbi.dwSize.X > tmpCoord.X )
  		tmpCoord.X = lpcsbi.dwSize.X;
  	if( lpcsbi.dwSize.Y > tmpCoord.Y )
  		tmpCoord.Y = lpcsbi.dwSize.Y;
  
  	// Note: We set the buffer both before and after because it is
  	// easier than checking current vs. future screen size vs. buffer size
  	SetConsoleScreenBufferSize(Macro::instance()->getAppHandle()/*GetStdHandle(STD_OUTPUT_HANDLE)*/, tmpCoord);
  	SetConsoleWindowInfo(Macro::instance()->getAppHandle()/*GetStdHandle(STD_OUTPUT_HANDLE)*/, true, &rect);
  	SetConsoleScreenBufferSize(Macro::instance()->getAppHandle()/*GetStdHandle(STD_OUTPUT_HANDLE)*/, coord);
  
  	return 0;
  }
  