/*****
 *
 *  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
 *
 *****/

#include "csl/CSLHandler.h"

#include <stdlib.h>
#include <stdio.h>
#include <cassert>

#include "Debug.h"

#include <csl/ZExcept.hpp>

#include "Game.h"
#include "SDLEvent.h"
#include "gui/Image.h"
#include "gui/Border.h"
#include "gui/ImageArt.h"
#include "gui/Button.h"
#include "gui/InputField.h"
#include "gui/Label.h"
#include "gui/Container.h"
#include "gui/ItemContainer.h"
#include "gui/GUIHandler.h"
#include "gui/Textbox.h"
#include "gui/Paperdoll.h"
#include "gui/TextManager.h"
#include "gui/Scrollbar.h"

#include "renderer/DynamicObjects.h"
#include "renderer/SDLScreen.h"

#include "loaders/GumpLoader.h"
#include "loaders/SkillLoader.h"

#include "net/Client.h"

#include "Config.h"
#include "include.h"

#include "xml.h"

extern GUI::GUIHandler pUOGUI;

// in xml.cpp

// That is not the best way, but I only applied a patch

int on_clickhandler(GUI::Control * control);
int on_closehandler(GUI::Control * control);
int on_mousedownhandler(GUI::Control * control);
int on_mouseuphandler(GUI::Control * control);
int on_keypressedhandler(GUI::Control * control, unsigned short key);
int on_changehandler(GUI::Control * control, int pos);
extern void api_addcontrol(GUI::Control * control);
extern int act_container_id;

inline unsigned int checksum32(std::string s)
{ 
	unsigned char c1=0,c2=0,c3=0,c4=0;

	for (unsigned int i=0; i < s.length(); i++)
	{
		c1+=s[i];
		c2+=c1;
		c3+=c2;
		c4+=c3;

	}

	return (c1|(c2<<8)|(c3<<16)|(c4<<24));
}

inline unsigned int checksum16(std::string s)
{
	unsigned char c1=0,c2=0;

	for (unsigned int i=0; i < s.length(); i++)
	{
		c1+=s[i];
		c2+=c1;
	}

	return (c1|(c2<<8));
}

static std::map<Uint32,Uint32> controlid_lookup;

static void clear_controlid_list()
{
	controlid_lookup.clear();
}

static void add_controlid(std::string name, Uint32 id)
{
	controlid_lookup.insert(make_pair(checksum32(name), id));
}

static Uint32 get_controlid(std::string name)
{
	std::map<Uint32,Uint32>::iterator iter = controlid_lookup.find(checksum32(name));
	return iter != controlid_lookup.end() ? iter->second : 0;
}

ZString api_control_getid(ZCsl* aCsl)
{
	ZString name = aCsl->get("name");

	return get_controlid(name.buffer());
}

// 0.3.1
GUI::Container *gui_addform_v1(XML::Node *form, int x, int y, bool is_container)
{
	GUI::Container *container = NULL;
	int width=640,height=480, alpha=0, flags=0, fade_alpha=0, fade_time=0;
	std::string shape, onclick, onclose, onmouseup, onmousedown, onkeypressed;
	
	form->lookupAttribute("width", width);
	form->lookupAttribute("height", height);
	form->lookupAttribute("alpha", alpha);
	form->lookupAttribute("flags", flags);
	form->lookupAttribute("shape", shape);

	XML::Node *fade_node = form->findNode("fade");
	if (fade_node) {
		fade_node->lookupAttribute("alpha", fade_alpha);
		fade_node->lookupAttribute("time", fade_time);
	}

	XML::Node *event_node = form->findNode("event");

	if (event_node) {
		event_node->lookupAttribute("onclick", onclick);
		event_node->lookupAttribute("onclose", onclose);
		event_node->lookupAttribute("onmouseup", onmouseup);
		event_node->lookupAttribute("onmousedown", onmousedown);
		event_node->lookupAttribute("onkeypressed", onkeypressed);
	}	

	if (is_container) {
		container = new GUI::Container;
		container->SetPosition(x,y);
		container->SetSize(width, height);
		container->SetAlpha(alpha);
		if (fade_time != 0) 
			container->FadeTo(fade_alpha, fade_time);

		x=0,y=0;
		
		api_addcontrol(container);

		GUI::Control *control=container;
		if (!onclose.empty()) {
			control->OnClose(on_closehandler);
			control->SetScriptFunction(GUI::FUNC_ONCLOSE, (char*)onclose.c_str());
		}
		if (!onmousedown.empty()) {
			control->OnMouseDown(on_mousedownhandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEDOWN, (char*)onmousedown.c_str());
		}
		if (!onmouseup.empty()) {
			control->OnMouseUp(on_mouseuphandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEUP, (char*)onmouseup.c_str());
		}

		act_container_id = container->GetID();
	}

	int idx=0;
	XML::Node* control_node = NULL;			
	
	while ((control_node = form->findNode("control", idx++))) {
		GUI::Control *control=NULL;
		XML::Node *event_node=NULL, *gump_node=NULL, *passwd_node=NULL;
		XML::Node *check_node=NULL, *group_node=NULL,*text_node=NULL;
		
		std::string type, name;
		std::string onclick, onclose, onmouseup, onmousedown, onkeypressed;

		int left=0,top=0,width=0,height=0,freezed=0,visible=1;			
		int alpha=0,flags=0;

		if (!control_node->lookupAttribute("class", type)) continue;

		control_node->lookupAttribute("name", name);
		control_node->lookupAttribute("left", left);
		control_node->lookupAttribute("top", top);
		control_node->lookupAttribute("width", width);
		control_node->lookupAttribute("height", height);
		control_node->lookupAttribute("freezed", freezed);
		control_node->lookupAttribute("visible", visible);
		control_node->lookupAttribute("alpha", alpha);
		control_node->lookupAttribute("flags", flags);

		left+=x;
		top+=y;

		if ((event_node = control_node->findNode("event"))) {
			event_node->lookupAttribute("onclick", onclick);
			event_node->lookupAttribute("onclose", onclose);
			event_node->lookupAttribute("onmouseup", onmouseup);
			event_node->lookupAttribute("onmousedown", onmousedown);
			event_node->lookupAttribute("onkeypressed", onkeypressed);
		}	
		
		if (type=="picture" || type=="border" || type=="paperdoll") {			
			int gump=0;
			if ((gump_node = control_node->findNode("gump"))) 
				gump = gump_node->asInteger();

			//int flags = GUMPFLAG_MOVABLE | GUMPFLAG_CLOSABLE | GUMPFLAG_FOCUSABLE;
			
			if (type=="picture") {
				control = new GUI::Image(left, top, gump, flags);
			} else if (type=="border") {
				control = new GUI::Border(left,top, gump, flags);
			} else {
				control = new GUI::Paperdoll(left, top, 0);
			}
			control->SetSize(width, height);
			
		} else if (type=="button") {
			int normal=-1, over=-1, pressed=-1;
			if ((gump_node = control_node->findNode("gump"))) { 
				gump_node->lookupAttribute("normal", normal);
				gump_node->lookupAttribute("over", over);
				gump_node->lookupAttribute("pressed", pressed);
			}

			GUI::Button * button = new GUI::Button(left,top);
			
			if (normal >= 0) button->SetGump(GUI::BUTTONGUMP_NORMAL, normal);					
			if (over >= 0) button->SetGump(GUI::BUTTONGUMP_MOUSEOVER, over);				
			if (pressed >= 0) button->SetGump(GUI::BUTTONGUMP_PRESSED, pressed);
			

			if (!onclick.empty()) {
				button->OnClick(on_clickhandler);
				button->SetScriptFunction(GUI::FUNC_ONCLICK, (char*)onclick.c_str());
			}
			
			control = button;
		} else if (type=="checkbox" || type=="radio") {
			int normal=-1, checked=-1, group=0, ischecked=0;
			gump_node = control_node->findNode("gump");
			if (gump_node) { 
				gump_node->lookupAttribute("normal", normal);
				gump_node->lookupAttribute("checked", checked);
			}
			if ((check_node = control_node->findNode("checked"))) {
				ischecked = check_node->asBool();
			}
			if ((group_node = control_node->findNode("group"))) {
				group = group_node->asInteger();
			}
		} else if (type=="label" || type=="edit") {
			std::string text, align;
			int font=-1,hue=-1,password=0, label_align=-1;
			if ((text_node = control_node->findNode("text"))) {
				text = text_node->asString();
				text_node->lookupAttribute("font", font);
				text_node->lookupAttribute("hue", hue);
				text_node->lookupAttribute("align", align);
			}

			if ((passwd_node = control_node->findNode("password"))) {
				password = passwd_node->asBool();
			}
			
			if (type == "label") {
				if (align=="center") {
					label_align=1;
					left += width / 2;
					//top  += height / 2;
				} else if (align=="right") {
					label_align=2;
					left += width;
					//top  += height;
				}

				GUI::Label *label = new GUI::Label(left, top, text.c_str());

				if (font >= 0) label->setFont(font);
				if (hue >= 0) label->setHue(hue);
				if (label_align >= 0) label->setAlign(label_align);

				control = label;
			} else {
				font = font < 0 ? 3 : font;
				hue = hue < 0 ? 0 : hue;
				
				GUI::InputField * input = new GUI::InputField(left,top,width,height, text.c_str(), hue, font, password ? 42 : 0);
				input->OnKeyPress(on_keypressedhandler);
				if (!onkeypressed.empty())
					input->SetScriptFunction(GUI::FUNC_ONKEYPRESSED, (char*)onkeypressed.c_str());
				
				control = input;
			}
		}

		if (!control) continue;

		api_addcontrol(control);

		add_controlid(name,control->GetID());

		if (!onclose.empty()) {
			control->OnClose(on_closehandler);
			control->SetScriptFunction(GUI::FUNC_ONCLOSE, (char*)onclose.c_str());
		}
		if (!onmousedown.empty()) {
			control->OnMouseDown(on_mousedownhandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEDOWN, (char*)onmousedown.c_str());
		}
		if (!onmouseup.empty()) {
			control->OnMouseUp(on_mouseuphandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEUP, (char*)onmouseup.c_str());
		}
	}

	if (container) {
		if (!shape.empty())
			container->SetShape(get_controlid(shape));
		act_container_id = 0;
	}

	return container;
}

//<text font="3" hue="0x1" align="left" multiline="0">button</text> 
//<gump normal="0xD2" over="0xD2" pressed="0xD3" /> 
//<button type="button" checked="0" grouped="0" /> 
GUI::Button *gui_create_button(XML::Node *control_node, int x, int y, int w, int h, std::string onevent, int &groupid, int &orderid)
{
	int normal=-1, over=-1, pressed=-1;
	XML::Node *gump_node = gump_node = control_node->findNode("gump");
	if (gump_node) { 
		gump_node->lookupAttribute("normal", normal);
		gump_node->lookupAttribute("over", over);
		gump_node->lookupAttribute("pressed", pressed);
	}

	std::string text, align;
	int font=-1,hue=-1, label_align=-1;
	XML::Node *text_node = control_node->findNode("text");
	if (text_node) {
		text = text_node->asString();
		text_node->lookupAttribute("font", font);
		text_node->lookupAttribute("hue", hue);
		text_node->lookupAttribute("align", align);
	}

	std::string type="button";
	int checked=0, grouped=0;
	XML::Node *button_node = control_node->findNode("button");
	if (button_node) {
		button_node->lookupAttribute("type", type);
		button_node->lookupAttribute("checked", checked);
		button_node->lookupAttribute("grouped", grouped);
	}

	GUI::Button * button = new GUI::Button(x, y, w, h);

	if (normal >= 0)  button->SetGump(GUI::BUTTONGUMP_NORMAL,    normal);					
	if (over >= 0)    button->SetGump(GUI::BUTTONGUMP_MOUSEOVER, over);				
	if (pressed >= 0) button->SetGump(GUI::BUTTONGUMP_PRESSED,   pressed);

	if (!onevent.empty()) {
		button->OnClick(on_clickhandler);
		button->SetScriptFunction(GUI::FUNC_ONCLICK, (char*)onevent.c_str());
	}

	button->SetButtonType(type);
	button->SetTitle(text.c_str(), label_align, hue, font);
	button->SetChecked(checked);

	if (type == "radio") {
		if (grouped) {
			groupid++;
			orderid = 0;
		}
		button->SetGroupID(groupid);
		button->SetOrderID(orderid++);
	}

	return button;
}

// <text font="3" hue="0x1" align="left" multiline="0">button</text> 
GUI::Control *gui_create_text(XML::Node *control_node, int left, int top, int width, int height, 
							 std::string onevent, std::string type)
{
	std::string text, align;
	int font=-1,hue=-1, label_align=-1, multiline=0;
	XML::Node *text_node = control_node->findNode("text");
	if (text_node) {
		text = text_node->asString();
		text_node->lookupAttribute("font", font);
		text_node->lookupAttribute("hue", hue);
		text_node->lookupAttribute("align", align);
		text_node->lookupAttribute("multiline", multiline);
	}

	bool password = false;
	XML::Node *passwd_node = control_node->findNode("password");
	if (passwd_node)
		password = passwd_node->asBool();

	GUI::Control *control = NULL;

	if (type=="label") {
		if (align=="center") {
			label_align=1;
			left += width / 2;
			//top  += height / 2;
		} else if (align=="right") {
			label_align=2;
			left += width;
			//top  += height;
		}

		GUI::Label *label = new GUI::Label(left, top, text.c_str());

		if (font >= 0) label->setFont(font);
		if (hue >= 0) label->setHue(hue);
		if (label_align >= 0) label->setAlign(label_align);

		control = label;
	} else {
		font = font < 0 ? 3 : font;
		hue  = hue  < 0 ? 0 : hue;

		GUI::InputField * input = new GUI::InputField(left,top,width,height, text.c_str(), hue, font, password ? 42 : 0);
		input->OnKeyPress(on_keypressedhandler);
		if (!onevent.empty())
			input->SetScriptFunction(GUI::FUNC_ONKEYPRESSED, (char*)onevent.c_str());

		control = input;
	}

	return control;
}


//<gump>
//<body track="0xFF" thumb="0xFE" /> 
//<ltup normal="0xFA" over="0xFA" pressed="0xFB" /> 
//<rtdn normal="0xFD" over="0xFD" pressed="0xFD" /> 
//</gump>
//<range min="0" max="100" pos="0" /> 
//<option arrow="1" vert="1" /> 
GUI::Scrollbar *gui_create_scrollbar(XML::Node *control_node, int x, int y, int w, int h, std::string onevent)
{
	int gump_id[GUI::SCROLL_NUM_PART];;
	int min = 0, max = 100, pos = 0;
	int arrow = 0, vert = 0; 

	for (int i = 0; i < GUI::SCROLL_NUM_PART; i++)
		gump_id[i] = -1;

	XML::Node *gump_node = control_node->findNode("gump");
	if (gump_node) { 
		XML::Node* body_node = gump_node->findNode("body");
		XML::Node* ltup_node = gump_node->findNode("ltup");
		XML::Node* rtdn_node = gump_node->findNode("rtdn");
		if (body_node) {
			body_node->lookupAttribute("track", gump_id[GUI::SCROLL_TRACK]);
			body_node->lookupAttribute("thumb", gump_id[GUI::SCROLL_THUMB]);
		}
		if (ltup_node) {
			ltup_node->lookupAttribute("normal", gump_id[GUI::SCROLL_LTUP_NORMAL]);
			ltup_node->lookupAttribute("over", gump_id[GUI::SCROLL_LTUP_HOVER]);
			ltup_node->lookupAttribute("pressed", gump_id[GUI::SCROLL_LTUP_PRESSED]);
		}
		if (rtdn_node) {
			rtdn_node->lookupAttribute("normal", gump_id[GUI::SCROLL_RTDN_NORMAL]);
			rtdn_node->lookupAttribute("over", gump_id[GUI::SCROLL_RTDN_HOVER]);
			rtdn_node->lookupAttribute("pressed", gump_id[GUI::SCROLL_RTDN_PRESSED]);
		}
	}

	XML::Node *range_node = control_node->findNode("range");
	if (range_node) {
		range_node->lookupAttribute("min", min);
		range_node->lookupAttribute("max", max);
		range_node->lookupAttribute("pos", pos);
	}

	XML::Node *option_node = control_node->findNode("option");
	if (option_node) {
		option_node->lookupAttribute("arrow", arrow);
		option_node->lookupAttribute("vert", vert);
	}

	GUI::Scrollbar *scrollbar = new GUI::Scrollbar(x,y,w,h);
	scrollbar->SetVertical(vert);
	scrollbar->SetUseArrowButton(arrow);
	scrollbar->SetRange(min,max);
	scrollbar->SetPos(pos);

	for (int i = 0; i < GUI::SCROLL_NUM_PART; i++)
		scrollbar->SetGump(i, gump_id[i]);

	if (!onevent.empty()) {
		scrollbar->OnChange(on_changehandler);
		scrollbar->SetScriptFunction(GUI::FUNC_ONCHANGE, (char*)onevent.c_str());
	}

	return scrollbar;
}

// 0.4.0
GUI::Container *gui_addform_v2(XML::Node *form, int x, int y, bool is_container)
{
	GUI::Container *container = NULL;
	int width=640,height=480, alpha=0, flags=0, fade_alpha=0, fade_time=0;
	std::string shape, onclick, onclose, onmouseup, onmousedown, onkeypressed;
	
	form->lookupAttribute("width", width);
	form->lookupAttribute("height", height);
	form->lookupAttribute("alpha", alpha);
	form->lookupAttribute("flags", flags);
	form->lookupAttribute("shape", shape);

	XML::Node *fade_node = form->findNode("fade");
	if (fade_node) {
		fade_node->lookupAttribute("alpha", fade_alpha);
		fade_node->lookupAttribute("time", fade_time);
	}

	XML::Node *event_node = form->findNode("event");

	if (event_node) {
		event_node->lookupAttribute("onclick", onclick);
		event_node->lookupAttribute("onclose", onclose);
		event_node->lookupAttribute("onmouseup", onmouseup);
		event_node->lookupAttribute("onmousedown", onmousedown);
		event_node->lookupAttribute("onkeypressed", onkeypressed);
	}	

	if (is_container) {
		container = new GUI::Container;
		container->SetPosition(x,y);
		container->SetSize(width, height);
		container->SetAlpha(alpha);
		if (fade_time != 0) 
			container->FadeTo(fade_alpha, fade_time);

		x=0,y=0;
		
		api_addcontrol(container);

		GUI::Control *control=container;
		if (!onclose.empty()) {
			control->OnClose(on_closehandler);
			control->SetScriptFunction(GUI::FUNC_ONCLOSE, (char*)onclose.c_str());
		}
		if (!onmousedown.empty()) {
			control->OnMouseDown(on_mousedownhandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEDOWN, (char*)onmousedown.c_str());
		}
		if (!onmouseup.empty()) {
			control->OnMouseUp(on_mouseuphandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEUP, (char*)onmouseup.c_str());
		}

		act_container_id = container->GetID();
	}

	int idx=0;
	XML::Node* control_node = NULL;
	int groupid = 0, orderid = 0;
	
	while ((control_node = form->findNode("control", idx++))) {
		GUI::Control *control=NULL;
		XML::Node *event_node = NULL, *gump_node  = NULL, *passwd_node = NULL, *pic_node = NULL;
		XML::Node *check_node = NULL, *group_node = NULL,*text_node = NULL;
		
		std::string type, name;
		std::string onclick, onclose, onmouseup, onmousedown, onkeypressed;
		std::string evtype, onevent;

		int left  =0, top = 0, width = 0, height = 0, disable = 0,visible = 1;			
		int alpha =0, flags = 0;

		if (!control_node->lookupAttribute("class", type)) continue;

		control_node->lookupAttribute("name", name);
		control_node->lookupAttribute("left", left);
		control_node->lookupAttribute("top", top);
		control_node->lookupAttribute("width", width);
		control_node->lookupAttribute("height", height);
		control_node->lookupAttribute("alpha", alpha);
		control_node->lookupAttribute("flags", flags);

		enum FLAG { DISALBE = 0x1, VISIBLE = 0x2 };

		visible = flags & VISIBLE;
		disable = flags & DISALBE;

		left += x;
		top  += y;

		if ((event_node = control_node->findNode("event"))) {
			event_node->lookupAttribute("type", evtype);
			onevent = event_node->asString();
		}	
		
		if (type=="picture" || type=="border" || type=="paperdoll") {			
			int gump = 0, ptype = 0, hue = 0;
			if ((pic_node = control_node->findNode("picture"))) {
				pic_node->lookupAttribute("gump", gump);
				pic_node->lookupAttribute("type", ptype);
				pic_node->lookupAttribute("hue",  hue);
			}

			//int flags = GUMPFLAG_MOVABLE | GUMPFLAG_CLOSABLE | GUMPFLAG_FOCUSABLE;
			
			if (type=="picture") {
				control = new GUI::Image(left, top, gump, flags);
			} else if (type=="border") {
				control = new GUI::Border(left,top, gump, flags);
			} else {
				control = new GUI::Paperdoll(left, top, 0);
			}
			control->SetSize(width, height);
			
		} else if (type=="button") {
			control = gui_create_button(control_node, left, top, width, height, onevent, groupid, orderid);
		} else if (type=="label" || type=="edit") {
			control = gui_create_text(control_node, left, top, width, height, onevent, type);
		} else if (type=="scrollbar") {
			control = gui_create_scrollbar(control_node, left, top, width, height, onevent);
		}

		if (!control) continue;

		api_addcontrol(control);

		add_controlid(name,control->GetID());

		if (!onclose.empty()) {
			control->OnClose(on_closehandler);
			control->SetScriptFunction(GUI::FUNC_ONCLOSE, (char*)onclose.c_str());
		}
		if (!onmousedown.empty()) {
			control->OnMouseDown(on_mousedownhandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEDOWN, (char*)onmousedown.c_str());
		}
		if (!onmouseup.empty()) {
			control->OnMouseUp(on_mouseuphandler);
			control->SetScriptFunction(GUI::FUNC_ONMOUSEUP, (char*)onmouseup.c_str());
		}
	}

	if (container) {
		if (!shape.empty())
			container->SetShape(get_controlid(shape));
		act_container_id = 0;
	}

	return container;
}

ZString api_gui_addform (ZCsl* aCsl)
{
	clear_controlid_list();

	int argCount = aCsl->get("argCount").asInt();
//	int flags = GUMPFLAG_MOVABLE | GUMPFLAG_CLOSABLE | GUMPFLAG_FOCUSABLE;
	int x = aCsl->get("x").asInt();
	int y = aCsl->get("y").asInt();
	std::string gfm_file = string (aCsl->get("gfm_file").buffer ());
	bool is_container = (argCount > 3) ? ((int) aCsl->get("is_container").asInt()) : false;

	GUI::Container *container = NULL;
	
	XML::Parser parser;
	XML::Node *form=NULL, *document=NULL;
	
	try	{
		parser.loadData(gfm_file);
		document = parser.parseDocument();

		form = document->findNode("form");
		if (form) {
			std::string version = "0.3.1";
			XML::Node *version_node = form->findNode("version");
			if (version_node)
				version = version_node->asString();

			if (version.compare("0.3.1") <= 0)
				container = gui_addform_v1(form, x, y, is_container);
			else
				container = gui_addform_v2(form, x, y, is_container);
		}
	} catch (...) {
		pDebug.Log("Error: loading in %s", gfm_file.c_str());
	}

	delete document; document=NULL;

	return container ? ZString(container->GetID()) : "0";
}

bool isexistfile(std::string path)
{
	FILE *fp = fopen(path.c_str(), "r");
	if (!fp) return false;
	fclose(fp);
	return true;
}

ZString api_gui_loadform(ZCsl* aCsl)
{
	//pCSLHandler.ExecuteFunction("gui_clear");

	std::string gfm_file = string (aCsl->get("gfm_file").buffer ());
	std::string script_path = gfm_file;
	
	int i = script_path.rfind('.');
	
	if (i != -1)
		script_path.replace(script_path.begin()+i, script_path.end(), ".csl");
	else
		script_path = "";

	if (script_path.length() > 0 && isexistfile(script_path)) 
	{
		pDebug.Log (script_path.c_str ());
		pCSLHandler.Load ((char *) script_path.c_str ());

		//need split module
		//pCSLHandler.ExecuteFunction("onload");
	}

	return api_gui_addform(aCsl);
}