Index: /pro-violet-viettel/refs/LectureEditor/menus.as
===================================================================
--- /pro-violet-viettel/refs/LectureEditor/menus.as	(revision 297)
+++ /pro-violet-viettel/refs/LectureEditor/menus.as	(revision 297)
@@ -0,0 +1,1136 @@
+﻿////////////////////////////////////////////////////////////////////////////////
+// File:   MENU.AS
+// Desc:   File chứa các hàm và dữ liệu phục vụ việc khởi tạo, xử lý các chức
+//         năng của Menu, Toolbar, các nút bấm trên giao diện chính, các hộp
+//         nhập liệu (dialog) và hộp thoại (alert),...
+//
+// Author: Đinh Hải Minh, VicoSoft
+// Date:   01/12/2003
+////////////////////////////////////////////////////////////////////////////////
+
+import mx.controls.Alert;
+
+function CreateMenuBar() {
+	/*
+	//
+	// CREATE THE MENUBAR OF APPLICATION
+	//
+
+	// Delete all menu items
+	while( mnuBar.getMenuAt(0) ) mnuBar.removeMenuAt(0);
+
+	var menuObj = new XML(
+		"<node label=\"" + lang.mnuFile + "\">"+
+		"<node label=\"" + lang.mnuNew + " (F2)\"/>"+
+		"<node label=\"" + lang.mnuOpen + "... (F3)\"/>"+
+		"<node label=\"" + lang.mnuSave + "\"/>"+
+		"<node label=\"" + lang.mnuSaveAs + "...\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuLibrary + "... (Ctrl+L)\"/>"+
+		"<node label=\"" + lang.mnuPack + "... (F4)\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuExit + "\"/>"+
+		"</node>");
+	mnuBar.addMenu(menuObj);
+
+	var menuObj = new XML(
+		"<node label=\"" + lang.mnuEdit + "\">"+
+		"<node label=\"" + lang.mnuUndo + " (Ctrl+Z)\"/>"+
+		"<node label=\"" + lang.mnuRedo + " (Ctrl+Y)\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuCut + " (Ctrl+X)\"/>"+
+		"<node label=\"" + lang.mnuCopy + " (Ctrl+C)\"/>"+
+		"<node label=\"" + lang.mnuPaste + " (Ctrl+V)\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuMoveUp + " (Alt+↑)\"/>"+
+		"<node label=\"" + lang.mnuMoveDn + " (Alt+↓)\"/>"+
+		"</node>");
+	mnuBar.addMenu(menuObj);
+
+	menuObj = new XML(
+		"<node label=\"" + lang.mnuContent + "\">"+
+		"<node label=\"" + lang.mnuAdd + " (F5)\"/>"+
+		"<node label=\"" + lang.mnuChange + " (F6)\"/>"+
+		"<node label=\"" + lang.mnuSync + " (F7)\"/>"+
+		"<node label=\"" + lang.mnuDelete + "\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuCover + "\"/>"+
+		"<node label=\"" + lang.mnuLayout + " (F8)\"/>"+
+		"<node label=\"" + lang.mnuBackGround + "\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuFullScr + " (F9)\"/>"+
+		"</node>");
+	mnuBar.addMenu(menuObj);
+
+	menuObj = new XML(
+		"<node label=\"" + lang.mnuOption + "\">"+
+		(webbase? "":
+		"<node label=\"" + lang.mnuUpdateModules + "\"/>"+
+		"<node label=\"" + lang.mnuUpdateLayouts + "\"/>"+
+		"<node label=\"" + lang.mnuUpdateLibs + "\"/>"+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuSupport + "\">"+
+		"<node label=\"" + lang.mnuUniKey + "\"/>"+
+		"<node label=\"" + lang.mnuTeamViewer + "\"/>"+
+		"</node>"+
+		"<node type=\"separator\"/>")+
+		"<node label=\"" + lang.mnuOrigin + "\"/>"+
+		"<node label=\"" + lang.mnuConfig + "\"/>"+
+		"</node>");
+	mnuBar.addMenu(menuObj);
+
+	menuObj = new XML(
+		"<node label=\"" + lang.mnuHelp + "\">"+
+		"<node label=\"" + lang.mnuHelpContent + " (F1)\"/>"+
+		(webbase? "":
+		"<node label=\"" + lang.mnuUpgrade + "\"/>")+
+		"<node type=\"separator\"/>"+
+		"<node label=\"" + lang.mnuAbout + "...\"/>"+
+		"</node>");
+	mnuBar.addMenu(menuObj);
+
+	if (online) {
+	menuObj = new XML(
+		"<node label=\"" + lang.mnuAccount + "\">"+
+		"<node label=\"" + lang.mnuInfo + "\"/>"+
+		"<node label=\"" + lang.mnuPayment + "\"/>"+
+		"<node label=\"" + lang.mnuLicense + "\"/>"+
+		"<node label=\"" + lang.mnuLogout + "\"/>"+
+		"</node>");
+	mnuBar.addMenu(menuObj);
+	}
+
+	//
+	// GET SUBMENUS OF MENUBAR AND HANDLE THEM
+	//
+	mnuFile = mnuBar.getMenuAt(0);
+	mnuEdit = mnuBar.getMenuAt(1);
+	mnuSlide = mnuBar.getMenuAt(2);
+	mnuOption = mnuBar.getMenuAt(3);
+	mnuHelp = mnuBar.getMenuAt(4);
+	//if (online) mnuAccount = mnuBar.getMenuAt(5);
+	mnuFile.addEventListener("change", onSelectFile);
+	mnuEdit.addEventListener("change", onSelectEdit);
+	mnuSlide.addEventListener("change", onSelectSlide);
+	mnuOption.addEventListener("change", onSelectWindow);
+	mnuHelp.addEventListener("change", onSelectHelp);
+	//if (online) mnuAccount.addEventListener("change", onSelectAccount);
+	
+	// hide the Menu Bar
+	//mnuBar.visible = false;
+	*/
+
+	//
+	// TOOLTIP TEXT OF INTERFACE BUTTONS
+	//
+	btnNew.tooltipText     = lang.mnuNew;
+	btnOpen.tooltipText    = lang.mnuOpen + "...";
+	btnSave.tooltipText    = lang.mnuSave;
+	btnSaveAs.tooltipText  = lang.mnuSaveAs + "...";
+	btnUndo.tooltipText    = lang.mnuUndo;
+	btnRedo.tooltipText    = lang.mnuRedo;
+	btnSync.tooltipText    = lang.mnuSync + "...";
+	btnLibrary.tooltipText = lang.mnuLibrary + "...";
+	btnPack.tooltipText    = lang.mnuPack + "...";
+	btnCover.tooltipText   = lang.mnuCover + "...";
+	btnBackground.tooltipText  = lang.mnuBackGround + "...";
+	btnLayout.tooltipText  = lang.mnuLayout;
+	btnPreview.tooltipText = lang.mnuFullScr;
+	btnHelp.tooltipText    = lang.mnuHelpContent;
+	btnSetting.tooltipText = lang.mnuConfig + "...";
+
+	btnMoveUp.onRollOver   = function() {StartTooltip(lang.mnuMoveUp)};
+	btnMoveDown.onRollOver = function() {StartTooltip(lang.mnuMoveDn)};
+	btnCutItem.onRollOver  = function() {StartTooltip(lang.mnuCut)};
+	btnCopyItem.onRollOver = function() {StartTooltip(lang.mnuCopy)};
+	btnPasteItem.onRollOver = function() {StartTooltip(lang.mnuPaste)};
+	btnAdd.onRollOver      = function() {StartTooltip(lang.mnuAdd)};
+	btnDetail.onRollOver   = function() {StartTooltip(lang.mnuChange)};
+	btnDelete.onRollOver   = function() {StartTooltip(lang.mnuDelete)};
+
+	btnMoveUp.onRollOut    = btnMoveUp.onPress   = StopTooltip;
+	btnMoveDown.onRollOut  = btnMoveDown.onPress = StopTooltip;
+	btnCutItem.onRollOut   = btnCutItem.onPress = StopTooltip;
+	btnCopyItem.onRollOut  = btnCopyItem.onPress = StopTooltip;
+	btnPasteItem.onRollOut = btnPasteItem.onPress = StopTooltip;
+	btnAdd.onRollOut       = btnAdd.onPress      = StopTooltip;
+	btnDelete.onRollOut    = btnDelete.onPress   = StopTooltip;
+	btnDetail.onRollOut    = btnDetail.onPress   = StopTooltip;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HANDLE FUNCTIONS FOR ALL SUBMENUS
+//
+function onSelectFile(itemObj) {
+	if( itemObj.menuItem == mnuFile.getItemAt(0) ) btnNew.onRelease();
+	if( itemObj.menuItem == mnuFile.getItemAt(1) ) btnOpen.onRelease();
+	if( itemObj.menuItem == mnuFile.getItemAt(2) ) btnSave.onRelease();
+	if( itemObj.menuItem == mnuFile.getItemAt(3) ) SaveAndExec(undefined, true);
+	if( itemObj.menuItem == mnuFile.getItemAt(5) ) btnLibrary.onRelease();
+	if( itemObj.menuItem == mnuFile.getItemAt(6) ) btnPack.onRelease();
+	if( itemObj.menuItem == mnuFile.getItemAt(8) ) ExitProgram();
+}
+
+btnSaveAs.onRelease = function() {
+	SaveAndExec(undefined, true);
+}
+
+function onSelectEdit(itemObj) {
+	if( itemObj.menuItem == mnuEdit.getItemAt(0) ) ProcessUndo();
+	if( itemObj.menuItem == mnuEdit.getItemAt(1) ) ProcessRedo();
+	if( itemObj.menuItem == mnuEdit.getItemAt(3) ) btnCutOnRelease();
+	if( itemObj.menuItem == mnuEdit.getItemAt(4) ) btnCopyOnRelease();
+	if( itemObj.menuItem == mnuEdit.getItemAt(5) ) btnPasteOnRelease();
+	if( itemObj.menuItem == mnuEdit.getItemAt(7) ) btnMoveUp.onRelease();
+	if( itemObj.menuItem == mnuEdit.getItemAt(8) ) btnMoveDown.onRelease();
+}
+
+btnUndo.onRelease = function() {
+	ProcessUndo();
+}
+
+btnRedo.onRelease = function() {
+	ProcessRedo();
+}
+
+function onSelectSlide(itemObj) {
+	if(itemObj.menuItem == mnuSlide.getItemAt(0)) btnAdd.onRelease();
+	if(itemObj.menuItem == mnuSlide.getItemAt(1)) btnDetail.onRelease();
+	if(itemObj.menuItem == mnuSlide.getItemAt(2)) SyncVideoAudio();
+	if(itemObj.menuItem == mnuSlide.getItemAt(3)) btnDelete.onRelease();
+	if(itemObj.menuItem == mnuSlide.getItemAt(5)) SelectCoverPage();
+	if(itemObj.menuItem == mnuSlide.getItemAt(6)) btnLayout.onRelease();
+	if(itemObj.menuItem == mnuSlide.getItemAt(7)) SelectBackGround();
+	if(itemObj.menuItem == mnuSlide.getItemAt(9)) btnPreview.onRelease();
+}
+
+btnSync.onRelease = function() {
+	SyncVideoAudio();
+}
+
+btnCover.onRelease = function() {
+	SelectCoverPage();
+}
+
+btnBackground.onRelease = function() {
+	SelectBackGround();
+}
+
+function onSelectWindow(itemObj) {
+	if (webbase) {
+		if(itemObj.menuItem == mnuOption.getItemAt(0)) ResetWindowSize();
+		if(itemObj.menuItem == mnuOption.getItemAt(1)) ShowConfigDlg();
+		return;
+	}
+	if(itemObj.menuItem == mnuOption.getItemAt(0)) UpdatePlugin();
+	if(itemObj.menuItem == mnuOption.getItemAt(1)) UpdateLayout();
+	if(itemObj.menuItem == mnuOption.getItemAt(2)) UpdateCommonLib();
+	if(itemObj.menuItem == mnuOption.getItemAt(4).childNodes[0]) RunApplication((isWow64? "UniKey64": "UniKey") + "\\UniKeyNT.exe");
+	if(itemObj.menuItem == mnuOption.getItemAt(4).childNodes[1]) RunApplication("TeamViewer\\TeamViewerQS_vi.exe");
+	if(itemObj.menuItem == mnuOption.getItemAt(6)) ResetWindowSize();
+	if(itemObj.menuItem == mnuOption.getItemAt(7)) ShowConfigDlg();
+}
+
+btnSetting.onRelease = function() {
+	ShowConfigDlg();
+}
+
+function onSelectHelp(itemObj) {
+	if(itemObj.menuItem == mnuHelp.getItemAt(0)) btnHelp.onRelease();
+	if (webbase) {
+		if(itemObj.menuItem == mnuHelp.getItemAt(2)) AboutProgram();
+		return;
+	}
+	if(itemObj.menuItem == mnuHelp.getItemAt(1)) AutoUpgrade();
+	if(itemObj.menuItem == mnuHelp.getItemAt(3)) AboutProgram();
+}
+
+function onSelectAccount(itemObj) {
+	if(itemObj.menuItem == mnuAccount.getItemAt(0)) EditAccountInfo();
+	if(itemObj.menuItem == mnuAccount.getItemAt(1)) ManageCastAccount();
+	if(itemObj.menuItem == mnuAccount.getItemAt(2)) ShowVioletLicense();
+	if(itemObj.menuItem == mnuAccount.getItemAt(3)) LogoutViolet();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// COMMON FUNCTIONS
+//
+function StartTooltip(tooltipText) {
+	if( !movTimer && tooltipText ) {
+		createEmptyMovieClip("movTimer", 1);
+		movTimer.counter = 0;
+
+		movTimer.onEnterFrame = function() {
+			this.counter++;
+			if( this.counter == 10) {
+				if(!txtTooltip) createTextField("txtTooltip", 2, _xmouse+16, _ymouse+16, 0, 0);
+				txtTooltip.text = tooltipText;
+				txtTooltip.autoSize = true;
+				txtTooltip.border = true;
+				txtTooltip.background = true;
+				txtTooltip.backgroundColor = 0xFFFFCC;
+				
+				var newFormat = new TextFormat();
+				newFormat.font = "Arial";
+				newFormat.size = 12;
+				txtTooltip.setTextFormat(newFormat);
+				delete newFormat;
+				
+				if( txtTooltip._x + txtTooltip._width > 800 ) txtTooltip._x = 800 - txtTooltip._width;
+			}
+			if( this.counter == 130) StopTooltip();
+		}
+	}
+}
+
+function StopTooltip() {
+	if( txtTooltip ) txtTooltip.removeTextField();
+	if( movTimer ) movTimer.removeMovieClip();
+}
+
+function ShowGrayScreen(show) {
+	if( show==undefined ) show = true;
+	btnSemitrans.count += (show? 1: -1);
+	show = (btnSemitrans.count > 0);
+	btnSemitrans._visible = show;
+	fscommand("Enable Drop", !show);
+}
+
+function ShowDialog(frameLabel, winTitle) {
+	if (!wndDialog.content.loaded) return;
+	if (!wndDialog._visible) ShowGrayScreen();
+	wndDialog.content.gotoAndStop(frameLabel);
+	wndDialog.title = winTitle;
+	wndDialog.setSize(wndDialog.content._width+6, wndDialog.content._height+34);
+	wndDialog._x = 400 - wndDialog._width/2;
+	wndDialog._y = 290 - wndDialog._height/2;
+	wndDialog._visible = true;
+}
+
+function ShowMessage(message, title, showMessageCallBack, showMessageObj)
+{
+	messageShowing = true;
+	ShowGrayScreen();
+	Alert.buttonWidth = 60;
+	Alert.okLabel = lang.btnOK;
+	Alert.show(
+		message, title, Alert.OK, _root,
+		function(evt) {
+			messageShowing = false;
+			ShowGrayScreen(false); 
+			if (showMessageCallBack!=undefined)
+				showMessageCallBack.call(showMessageObj);
+		},
+		null, Alert.OK );
+}
+
+function ShowQuestion(message, caption, cancel, yesFunction, noFunction) {
+	messageShowing = true;
+	ShowGrayScreen();
+	Alert.buttonWidth = 60;
+	Alert.yesLabel = lang.btnYes;
+	Alert.noLabel = lang.btnNo;
+	Alert.cancelLabel = cancel;
+	
+	var msgButtons = Alert.YES | Alert.NO;
+	if( cancel!="" ) msgButtons |= Alert.CANCEL;
+	
+	Alert.show(
+		message, caption, msgButtons, _root,
+		function(evt) {
+			messageShowing = false;
+			ShowGrayScreen(false);
+			if( evt.detail==Alert.YES) yesFunction();
+			if( evt.detail==Alert.NO ) noFunction();
+		},
+		"Question Movie", Alert.YES
+	);
+}
+
+function LoadPopupMovie(title, filename, onClickOK, onClickCancel, parentObj, languagePath) {
+	if (languagePath != undefined) {
+		plang = lang.createEmptyMovieClip("popup", lang.getNextHighestDepth());
+		loadVariables(appPath + languagePath + slash + language + ".txt", lang.popup);
+		lang.popup.onData = function() {
+			LoadPopupMovie(title, filename, onClickOK, onClickCancel, parentObj);
+		};
+		return;
+	}
+	var frame = "";
+	if (filename.indexOf("|") != -1) {
+		var a = filename.split("|");
+		filename = a[0];
+		frame = a[1];
+	}
+	var initObj = {title: title, contentPath: _root.appPath + filename, closeButton: true};
+	var mcPopup = mx.managers.PopUpManager.createPopUp(_root, mx.containers.Window, true, initObj);
+	var oldPressEnter = _root.onPressEnter;
+	var oldPressEsc = _root.onPressEsc;
+	var oldPressDelete = _root.oldPressDelete;
+	_root.onPressEnter = undefined;
+	_root.onPressEsc = undefined;
+	_root.oldPressDelete= undefined;
+	parentObj.SetBehindDialog(true);
+	mcPopup._visible = false;
+
+	mcPopup.onCloseDialog = function() {
+		mcPopup.deletePopUp();
+		lang.popup.removeMovieClip();
+		_root.onPressEnter = oldPressEnter;
+		_root.onPressEsc = oldPressEsc;
+		_root.oldPressDelete = oldPressDelete;
+		parentObj.SetBehindDialog(false);
+		onClickCancel();
+	};
+	mcPopup.onFinishInput = function(retVal) {
+		mcPopup.onCloseDialog();
+		onClickOK(retVal);
+	};
+	mcPopup.setDlgSize = function() {
+		var movie = mcPopup.content;
+		var size = movie.getMovieSize? movie.getMovieSize(): {width: movie._width, height: movie._height};
+		mcPopup.setSize(size.width + 6, size.height + 34);
+		mcPopup._x = 400 - mcPopup.width/2;
+		mcPopup._y = 290 - mcPopup.height/2;
+		mcPopup._visible = true;
+	}
+	mcPopup.addEventListener("complete", function() {if (frame!="") mcPopup.content.gotoAndStop(frame); mcPopup.setDlgSize()});
+	mcPopup.addEventListener("click", function() {if (onClickCancel!==false) mcPopup.onCloseDialog()});
+
+	return mcPopup;
+}
+
+function ClearAllData() {
+	dataXML.firstChild.removeNode();
+	movScene.ClearBackGround();
+	while (movScene.bkgnd_node.childNodes.length > 0) movScene.bkgnd_node.lastChild.removeNode();
+	while (treItem.length > 0) treItem.removeItemAt(0);
+	currentFile = "";
+	dataChanged = "false";
+	undoData.splice(0);
+	undoPos = 0;
+	GetRelatedFiles();
+}
+
+function ExecWithConfirmSave(execFunction)
+{
+	if( dataChanged == "true" ) {
+		ShowQuestion(
+			lang.msgConfirmSave, lang.msgTitle, lang.btnContinue,
+			function() { SaveAndExec(execFunction) },
+			execFunction
+		);
+	} else {
+		execFunction();
+	}
+}
+
+function ChangeTempPath(tmpPathName) {
+	var pos = tempPath.length;
+	var tmp = GetFullFileName(tmpPathName);
+	if( tmp.substr(0, pos) == tempPath )
+		return defaultFilePath + tmp.substr(pos);
+	return tmpPathName;
+}
+
+function EncodeXml(s)
+{
+	s = Replace(s, '&', "&amp;");
+	s = Replace(s, '"', "&quot;");
+	s = Replace(s, '<', "&lt;");
+	s = Replace(s, '>', "&gt;");
+	return escape(s);
+}
+
+function SaveAndExec(execFunction, isSaveAs)
+{
+	if( currentFile == "" || isSaveAs ) {
+		if (online) {
+			ShowGrayScreen();
+			var pop = LoadPopupMovie(lang.mnuSaveAs, "Popup" + slash + "Space.swf",
+			function(param) {SaveToFile(execFunction, param)},
+			function() {ShowGrayScreen(false)});
+			pop.defExt = "xvl";
+			pop.filter = ["xvl"];
+			return;
+		}
+		fscommand("Save As", "");
+		ShowGrayScreen();
+		command = "";
+		onEnterFrame = function() {
+			if( command == "" ) return;
+			ShowGrayScreen(false);
+			if( command == "Save As OK" ) {
+				GetDataChangePath(GetFullFileName, dataXML.firstChild);
+				currentFile = savedFileName;
+				GetDataChangePath(GetRelativeFileName, dataXML.firstChild);
+				SaveToFile(execFunction, true);
+				fscommand("Set Title", currentFile);
+			}
+			else {
+				onEnterFrame = WaitForAppCommand;
+				command = "";
+			}
+		}
+		return;
+	}
+	SaveToFile(execFunction);
+}
+
+function SaveToFile(execFunction, param) {
+	var isFirstSave = (param != undefined);
+	if(  isFirstSave ) {
+		var pos1 = currentFile.lastIndexOf(slash) + 1;
+		var pos2 = currentFile.lastIndexOf(".");
+		defaultFilePath = currentFile.substring(pos1, pos2) + " files" + slash;
+		GetDataChangePath(ChangeTempPath, dataXML.firstChild);
+		filesForRetrieve = fileList;
+		GetRelatedFiles();
+	}
+
+	ascData = new XML(dataXML.toString());
+	if (movScene.bkgnd_node.childNodes.length > 0)
+		if( !ascData.firstChild.firstChild ) ascData.firstChild.appendChild(movScene.bkgnd_node.cloneNode(true));
+		else ascData.firstChild.insertBefore(movScene.bkgnd_node.cloneNode(true), ascData.firstChild.firstChild);
+
+	if( online ) {
+		var xml:XML = new XML();
+		xml.ignoreWhite = true;
+		xml.onLoad = function(success) {
+			if (!checkSuccess(success, "errServerConnect", "Không thể kết nối tới server.")) return;
+			var attr = this.firstChild.attributes;
+			if (!checkSuccess(attr.err=="", attr.errCode, attr.err)) return;
+			currentFile = attr.id;
+			fscommand("Set Title", attr.name);
+			dataChanged = "false";
+			execFunction();
+		}
+		var request = spaceUrl + "save";
+		if (isFirstSave) request += "?userid="+param.userid + "&dir="+param.dir + "&name="+param.name;
+		else request += "?fileid="+currentFile;
+		ascData.sendAndLoad(request, xml);
+		return;
+	}
+
+	UnicodeAscii(EncodeXml, ascData.firstChild);
+	ascData = defXmlDecl + GetAlignedXml(ascData, 0);
+
+	fscommand("Save", "");
+	command = "";
+	onEnterFrame = function() {
+		if( command == "" ) return;
+		onEnterFrame = WaitForAppCommand;
+		if( command == "Save OK" ) execFunction();
+		if( command == "Save Error" ) ShowMessage(lang.msgSaveError, lang.msgTitle1);
+		if( isFirstSave ) fscommand("Retrieve", "");
+		else fscommand("Cleanup", "");
+		delete ascData;
+		command = "";
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MENU FILE FUNCTIONS
+//
+btnNew.onRelease = function() {
+	ExecWithConfirmSave(CreateNewData);
+}
+
+function InitializeDataXML() {
+	var lectureNode = commonXML.createElement("LECTURE_INFO");
+	if( appUserName ) {
+		lectureNode.attributes.Info = unescape(appUserName) + " - " + unescape(appAddress);
+		lectureNode.attributes.Check = lectureNode.attributes.Info.length + 13;
+	}
+	lectureNode.attributes.CommonDir = commonDir;
+	lectureNode.attributes.Layout = "Layout1.swf";
+	lectureNode.attributes.Title = "";
+	lectureNode.attributes.Version = version;
+	dataXML.appendChild(lectureNode);
+}
+
+function CreateNewData() {
+	ClearAllData();
+	InitializeDataXML();
+	movScene.onLoadXMLData();
+	fscommand("Set Title", "");
+}
+
+btnOpen.onRelease = function() {
+	ExecWithConfirmSave(
+	function() {
+		if (online) {
+			ShowGrayScreen();
+			var pop = LoadPopupMovie(lang.mnuOpen, "Popup" + slash + "Space.swf",
+			function(param) {
+				ClearAllData();
+				currentFile = param.id;
+				fscommand("Set Title", param.name);
+				LoadXMLData(spaceUrl + "file?id="+param.id+"&userid="+param.userid);
+			},
+			function() {ShowGrayScreen(false)});
+			pop.defExt = "xvl";
+			pop.filter = ["xvl"];
+			return;
+		}
+		command = "";
+		openedFileName = "";
+		fscommand("Open", "");
+		ShowGrayScreen();
+		
+		onEnterFrame = function() {
+			if( command == "" ) return;
+			ShowGrayScreen(false);
+			if( command == "Open OK" ) OpenNewFile();
+			onEnterFrame = WaitForAppCommand;
+			command = "";
+		}
+	});
+}
+
+function OpenNewFile() {
+	ClearAllData();
+	currentFile = openedFileName;
+	fscommand("Set Title", currentFile);
+	LoadXMLData(currentFile);
+}
+
+btnSave.onRelease = function() {
+	SaveAndExec();
+}
+
+btnLibrary.onRelease = function() {
+	ShowGrayScreen();
+	var pop = LoadPopupMovie(lang.mnuLibrary, "Popup" + slash + "Library.swf",
+	function(filename) {
+		ClearAllData();
+		openedFileName = filename;
+		LoadXMLData(filename);
+	},
+	function() {ShowGrayScreen(false)});
+	pop.libPaths = _root.lecturePaths;
+	pop.remember = true;
+	pop.okTitle = lang.mnuOpen;
+}
+
+btnPack.onRelease = function() {
+	GetRelatedFiles(true);
+
+	var slashPos = currentFile.lastIndexOf(slash);
+	if( !online && currentFile.substr(slashPos + 1) == "Scenario.xvl" ) {
+		ShowQuestion(lang.msgHasPacked, lang.msgTitle4, lang.btnCancel,
+		function() {
+			oldpackType = packageType;
+			packageType = 0;
+			packagePath = currentFile.substring(0, slashPos)
+			CreatePackage("Overwrite");
+			dataChanged = "false";
+		}, 
+		function() {
+			ShowDialog("Pack", lang.mnuPack);
+		});
+		return;
+	}
+
+	ShowDialog("Pack", lang.mnuPack);
+}
+
+function CreatePackage(status, paid) {
+	if (online && (isNaN(userLevel) || userLevel < 1) && !paid) {
+		ShowGrayScreen();
+		LoadPopupMovie("lang.dlgLicenseTitle", "Popup" + slash + "UserManager.swf|Package",
+		function() {CreatePackage(status, true)},
+		function() {ShowGrayScreen(false)},
+		null, "Language" + slash + "User");
+		return;
+	}
+	if( webbase ) {
+		treItem.enabled = false;
+		xml = new XML();
+		xml.onLoad = function() {
+			treItem.enabled = true;
+			var param = "userid=" + userId;
+			param += "&name=" + escape(packagePath);
+			param += "&id=" + this.firstChild.attributes.id;
+			getUrl(rootPath + "Service/packdownload.php?" + param);
+		}
+		var lv:LoadVars = new LoadVars();
+		lv.userid = userId;
+		lv.name = packagePath;
+		lv.type = packageType;
+		lv.dataNum = dataFileNum;
+		lv.commonNum = commonFileNum;
+		lv.fileList = fileListStr.split("|").join(",");
+		if (packageType == 1) lv.packagePlayer = packagePlayer;
+		if (packageType == 3) {
+			lv.scormVersion = scormVersion;
+			lv.scormTitle = packXML.firstChild.attributes.Title;
+			lv.scormOrgData = GetAlignedXml(CreateOrganization(packXML), 3);
+		}
+		lv.dataXml = defXmlDecl + GetAlignedXml(packXML, 0);
+		lv.sendAndLoad(rootPath + "Service/package.php", xml);
+		return;
+	}
+
+	if( status==undefined ) status = "";
+	SwitchCurrentVideo(movScene.currMovie, "close");
+	treItem.enabled = false;
+	
+	ascData = new XML(packXML.toString());
+	UnicodeAscii(EncodeXml, ascData.firstChild);
+	if( packageType == 3 ) {
+		scormTitle = ascData.firstChild.attributes.Title;
+		scormOrgData = GetAlignedXml(CreateOrganization(ascData), 3);
+	}
+	ascData = defXmlDecl + GetAlignedXml(ascData, 0);
+
+	fscommand("Pack", status);
+	command = "";
+		
+	onEnterFrame = function() {
+		if( command == "" ) return;
+		if( command == "Create Error" ) {
+			ShowMessage(lang.msgDirError, lang.msgTitle1);
+		}
+		if( command == "Copy Error" || command == "Save Error" ) {
+			ShowMessage(lang.msgPackError + copiedFile + "\r\r ", lang.msgTitle1);
+		}
+		if( command == "Dir Existed" ) {
+			ShowQuestion(
+				lang.msgPackOver, lang.msgTitle, lang.btnCancel,
+				function() { CreatePackage("Overwrite", paid) },
+				function() { CreatePackage("Merge", paid) }
+			);
+		}
+		SwitchCurrentVideo(movScene.currMovie, "replay");
+		treItem.enabled = true;
+
+		if( packageType == 0 ) packageType = oldpackType;
+		onEnterFrame = WaitForAppCommand;
+		delete ascData;
+		command = "";
+	}
+}
+
+function ExitProgram()
+{
+	if (online) {
+		var lv:LoadVars = new LoadVars();
+		lv.send(userUrl + "logout");
+	}
+	ExecWithConfirmSave(
+	function() {
+		SaveConfig();
+		fscommand("Quit", "");
+	});
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MENU EDIT FUNCTIONS
+//
+function UpdateUndoData() {
+	undoData.splice(undoPos);
+	if(undoData.length >= maxUndo) undoData.shift();
+	var node = dataXML.firstChild.cloneNode(true);
+	node.attributes.selectedIndex = treItem.selectedIndex;
+	undoData.push(node);
+	undoPos = undoData.length;
+	dataChanged = "true";
+}
+
+function RestoreFromUndoData() {
+	while (treItem.length > 0) treItem.removeItemAt(0);
+	var layout = dataXML.firstChild.attributes.Layout;
+	var title = dataXML.firstChild.attributes.Title;
+	dataXML.firstChild.removeNode();
+	dataXML.appendChild(undoData[undoPos].cloneNode(true));
+	UpdateScreen(true);
+	treItem.selectedIndex = dataXML.firstChild.attributes.selectedIndex;
+	delete dataXML.firstChild.attributes.selectedIndex;
+
+	if( layout != dataXML.firstChild.attributes.Layout ||
+		title != dataXML.firstChild.attributes.Title )
+	{
+		movScene.currentItem = treItem.selectedNode.attributes.item;
+		movScene.currentSection = treItem.selectedNode.attributes.section;
+		movScene.UpdateTemplate();
+	} else {
+		onChangeHandle();
+	}
+}
+
+function ProcessUndo() {
+	if( undoPos == 0 ) return;
+	if( undoPos == undoData.length ) {UpdateUndoData(); undoPos--;}
+	undoPos--;
+	RestoreFromUndoData();
+}
+
+function ProcessRedo() {
+	if( undoPos == undoData.length ) return;
+	undoPos++;
+	RestoreFromUndoData();
+	if( undoPos == undoData.length - 1 ) undoData.pop();
+}
+
+btnCutItem.onRelease = btnCutOnRelease = function() {
+	CopyToClipboard(DeleteItem);
+}
+
+btnCopyItem.onRelease = btnCopyOnRelease = function() {
+	CopyToClipboard();
+}
+
+function GetElementChangePath(change, node) {
+	if( node.attributes.hyperlink.charAt(0) == "1" ) {
+		node.attributes.hyperlink = "1|" + change(node.attributes.hyperlink.substr(2));
+	}
+	if( node.nodeName == "IMAGE" || node.nodeName == "MEDIA" ) {
+		node.attributes.url = change(node.attributes.url);
+	}
+	if( node.nodeName == "PLUGIN" ) {
+		ChangeXMLFileInfo(node.firstChild, change, pluXML.childNodes[1].childNodes[1].attributes[node.firstChild.nodeName]);
+		var subNodes = node.firstChild.childNodes;
+		for( var i=0; i<subNodes.length; i++ )
+			if( subNodes[i].attributes.hyperlink.charAt(0) == "1" )
+				subNodes[i].attributes.hyperlink = "1|" + change(subNodes[i].attributes.hyperlink.substr(2));
+		var langAttr = node.childNodes[1].firstChild.attributes;
+		for (var a in langAttr) if (a.substr(0, 5)=="file_") langAttr[a] = change(langAttr[a]);
+	}
+}
+
+function GetNodeChangePath(change, itemData) {
+	for( var k=0; k<itemData.childNodes.length; k++ ) {
+		var node = itemData.childNodes[k];
+		GetElementChangePath(change, node);
+	}
+}
+
+function GetDataChangePath(change, itemData) {
+	if( itemData.nodeName == "LECTURE_INFO" ) ChangeLayoutFileParam(itemData, change);
+	if( itemData.nodeName == "LECTURE_INFO" || itemData.nodeName == "SECTION_INFO" || itemData.nodeName == "BACKGROUND_INFO" )
+		for( var i = 0; i < itemData.childNodes.length; i++ )
+		GetDataChangePath(change, itemData.childNodes[i]);
+	else
+		GetNodeChangePath(change, itemData);
+}
+
+function CopyToClipboard(execFunction) {
+	if( treItem.length == 0 ) return;
+
+	var section = treItem.selectedNode.attributes.section-1;
+	var item = treItem.selectedNode.attributes.item-1;
+	var itemData = (item>=0) ?
+		dataXML.firstChild.childNodes[section].childNodes[item] :
+		dataXML.firstChild.childNodes[section];
+
+	var copiedData = itemData.cloneNode(true);
+	GetDataChangePath(GetFullFileName, copiedData);
+
+	command = "";
+	ascData = new XML(copiedData.toString());
+	UnicodeAscii(escape, ascData);
+	fscommand("Set Clipboard", dataID + ascData.toString());
+	onEnterFrame = function() {
+		if( command == "" ) return;
+		if( command == "Set OK" ) execFunction();
+		onEnterFrame = WaitForAppCommand;
+		delete ascData;
+		command = "";
+	}
+}
+
+btnPasteItem.onRelease = btnPasteOnRelease = function() {
+	command = "";
+	clipboardData = "";
+	fscommand("Get Clipboard");
+
+	onEnterFrame = function() {
+		if( command == "" ) return;
+		if( command == "Get Text" ) {
+			if( clipboardData.substr(0, dataID.length) == dataID ) {
+				var xmlClipboard = new XML(clipboardData.substr(dataID.length));
+				var itemData = xmlClipboard.firstChild;
+				UnicodeAscii(unescape, itemData);
+				GetDataChangePath(GetRelativeFileName, itemData);
+
+				var section = treItem.selectedItem.attributes.section;
+				if( itemData.nodeName == "SECTION_INFO" ) AddSectionData(itemData);
+				else if( section != undefined) AddItemData(section - 1, itemData);
+			}
+		}
+		onEnterFrame = WaitForAppCommand;
+		command = "";
+	}
+}
+	
+////////////////////////////////////////////////////////////////////////////////
+// MENU CONTENT FUNCTIONS
+//
+btnAdd.onRelease = function() {
+	isChanging = false;
+	inputingCover = false;
+	ShowDialog("Item", lang.dlgItem);
+}
+	
+btnDetail.onRelease = function() {
+	if( treItem.length == 0 ) return;
+	treCurrentNode = treItem.selectedNode;
+	var section = treItem.selectedNode.attributes.section-1;
+
+	var item = treItem.selectedNode.attributes.item-1;
+	if(item>=0) changingNode = dataXML.firstChild.childNodes[section].childNodes[item];
+	else changingNode = dataXML.firstChild.childNodes[section];
+	wndDialog.content.node = changingNode.cloneNode(true);
+	isChanging = true;
+	inputingCover = dataXML.firstChild.childNodes[section].attributes.coverpage=="true";
+
+	if(item<0 && inputingCover ) return;
+
+	if(item>=0) ShowDialog("Item", lang.dlgItem);
+	else ShowDialog("Section", lang.dlgSection);
+}
+
+btnDelete.onRelease = function() {
+	if( treItem.length == 0 ) return;
+	ShowQuestion(lang.msgConfirmDel, lang.msgTitle3, "", DeleteItem);
+}
+
+function SyncVideoAudio() {
+	var section = treItem.selectedNode.attributes.section - 1;
+	var item = treItem.selectedNode.attributes.item - 1;
+	if (item >= 0) {
+		if (movScene.sectionSync) {ShowMessage(lang.msgSyncSection, lang.msgTitle1); return;}
+		movScene.selectItem(movScene.currentItem, true);
+		if (!movScene.firstMediaObj) {ShowMessage(lang.msgSyncNoVideo, lang.msgTitle1); return;}
+		if (movScene.currentIndex == undefined) {ShowMessage(lang.msgSyncNoAction, lang.msgTitle1); return;}
+		wndDialog.content.node = dataXML.firstChild.childNodes[section].childNodes[item];
+	} else {
+		if (movScene.currentItemNum < 2) {ShowMessage(lang.msgSyncNoAction, lang.msgTitle1); return;}
+		movScene.UpdateBackGround();
+		movScene.sectionSync = true;
+		movScene.firstMediaObj = movScene.movPageBkGnd.firstMediaObj;
+		if (!movScene.firstMediaObj) {ShowMessage(lang.msgSyncNoVideo, lang.msgTitle1); return;}
+		movScene.selectItem(1);
+		wndDialog.content.node = dataXML.firstChild.childNodes[section];
+	}
+	movScene.firstMediaObj.autoPlay = true;
+	delete movScene.onEnterFrame;
+	ShowDialog("Sync", lang.mnuSync);
+	wndDialog._x = 15;
+}
+
+function SelectCoverPage() {
+	isChanging = false;
+	inputingCover = true;
+	ShowDialog("Item", lang.dlgItem);
+}
+
+function SelectBackGround() {
+	retFrame = "";
+	ShowDialog("BkGnd", lang.mnuBackGround);
+}
+
+function AddCoverPage(node) {
+	if( !isChanging ) {
+		if( dataXML.firstChild.firstChild.attributes.coverpage=="true" ) {
+			UpdateUndoData();
+			dataXML.firstChild.firstChild.firstChild.removeNode();
+			dataXML.firstChild.firstChild.appendChild(node);
+			var i = 0;
+			while( treItem.getItemAt(i).attributes.section != 1 ) i++;
+			treItem.selectedIndex = i+1;
+			onChangeHandle();
+			GetRelatedFiles();
+		} else {
+			movScene.ClearBackGround();
+			var sectionInfo = dataXML.createElement("SECTION_INFO");
+			sectionInfo.attributes.label = lang.coverPage;
+			sectionInfo.attributes.coverpage = "true";
+			sectionInfo.attributes.invisible = "true";
+			sectionInfo.appendChild(node);
+			AddSectionData(sectionInfo, 0);
+		}
+	} else {
+		UpdateUndoData();
+		changingNode.parentNode.insertBefore(node, changingNode);
+		changingNode.removeNode();
+		onChangeHandle();
+		GetRelatedFiles();
+	}
+}
+
+btnLayout.onRelease = function() {
+	ShowDialog("Layout", lang.mnuLayout);
+}
+
+btnPreview.onRelease = function() {
+	if( btnSceneBkGnd._visible ) { ClosePreview(); return; }
+	fscommand("Set Style", "Popup");
+	btnSceneBkGnd._visible = true;
+	movPlayer.swapDepths(movScenePrev);
+	movPlayer._yscale = 100;
+	movPlayer._xscale = 100;
+	movPlayer._x = 0;
+	movPlayer._y = -10;
+}
+
+function ClosePreview() {
+	if( !btnSceneBkGnd._visible ) return;
+	fscommand("Set Style", "Normal");
+	btnSceneBkGnd._visible = false;
+	movPlayer.swapDepths(movScenePrev);
+	movPlayer._x = 275;
+	movPlayer._y = 100;
+	movPlayer._xscale = 500/8;
+	movPlayer._yscale = 375/6;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MENU MODIFY FUNCTIONS
+//
+function EditFile(fileName) {
+	command = "";
+	fscommand("Edit File", fileName);
+	onEnterFrame = function() {
+		if( command == "" ) return;
+		if( command == "Launch Error" ) ShowMessage(lang.msgEditError, lang.msgTitle1);
+		onEnterFrame = WaitForAppCommand;
+		command = "";
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MENU WINDOWS FUNCTIONS
+//
+function ResetWindowSize() {
+	windowState = 1;
+	windowTop = 0;
+	windowLeft = 0;
+	windowRight = 0;
+	windowBottom = 0;
+	fscommand("Set State", "");
+}
+
+function SetFlashViewMode(mode) {
+	fscommand("View Mode", mode);
+	flashViewMode = mode;
+}
+
+function ShowConfigDlg() {
+	ShowDialog("Config", lang.mnuConfig);
+}
+
+function UpdatePlugin() {
+	ShowDialog("Plugin", lang.mnuUpdateModules);
+}
+
+function UpdateLayout() {
+	ShowDialog("LayUpdate", lang.mnuUpdateLayouts);
+}
+
+function UpdateCommonLib() {
+	ShowDialog("LibUpdate", lang.mnuUpdateLibs);
+}
+
+function SaveConfigXML(action, data) {
+	ascData = new XML(data.toString());
+	UnicodeAscii(EncodeXml, ascData.firstChild);
+	ascData = defXmlDecl + GetAlignedXml(ascData, 0);
+	fscommand(action, "ascData");
+}
+
+function RunApplication(filename) {
+	SendRequest("Run App", filename, function(response, data) {
+		if (response != "Run OK") ShowMessage(lang.msgCanNotRun + " " + filename, lang.msgTitle1);
+	});
+}
+////////////////////////////////////////////////////////////////////////////////
+// MENU HELP FUNCTIONS
+//
+btnHelp.onRelease = function() {
+	getURL("http://hoctructuyen.violet.vn/present/list/cat_id/7795643", "_blank");
+}
+
+function AutoUpgrade() {
+	ShowDialog("Upgrade", lang.mnuUpgrade);
+}
+
+function AboutProgram() {
+	ShowDialog("About", lang.mnuAbout);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MENU ACCOUNT FUNCTIONS
+//
+function EditAccountInfo() {
+	ShowGrayScreen();
+	LoadPopupMovie(lang.dlgLoginTitle, "Popup" + slash + "UserManager.swf|Update",
+	null, function() {ShowGrayScreen(false)}, null, "Language" + slash + "User");
+}
+
+function ManageCastAccount() {
+	ShowGrayScreen();
+	LoadPopupMovie(lang.dlgLoginTitle, "Popup" + slash + "UserManager.swf|Payment",
+	null, function() {ShowGrayScreen(false)}, null, "Language" + slash + "User");
+}
+
+function ShowVioletLicense() {
+	ShowGrayScreen();
+	LoadPopupMovie(lang.dlgLoginTitle, "Popup" + slash + "UserManager.swf|License",
+	null, function() {ShowGrayScreen(false)}, null, "Language" + slash + "User");
+}
+
+function LoginViolet() {
+	ShowGrayScreen();
+	LoadPopupMovie(lang.dlgLoginTitle, "Popup" + slash + "UserManager.swf|Login",
+	function(lv) {
+		ShowGrayScreen(false);
+		userId = lv.id;
+		userLevel = lv.level;
+		userPhone = lv.phone;
+		userMoney = lv.money;
+		appUserName = lv.fullname;
+		appAddress = lv.school + ", " + lv.province;
+		dataXML.firstChild.attributes.Info = unescape(appUserName) + " - " + unescape(appAddress);
+		dataXML.firstChild.attributes.Check = dataXML.firstChild.attributes.Info.length + 13;
+		movScene.movTemplate.userInfo = movDefLayout.userInfo = dataXML.firstChild.attributes.Info;
+		licenseInfo = {type: lv.licType, customer: lv.licCustomer, create: lv.licCreate, expire: lv.licExpire}
+	}, false, null, "Language" + slash + "User");
+}
+
+// Thay cho phần LoginViolet:
+dataXML.firstChild.attributes.Info = unescape(appUserName) + " - " + unescape(appAddress);
+dataXML.firstChild.attributes.Check = dataXML.firstChild.attributes.Info.length + 13;
+movScene.movTemplate.userInfo = movDefLayout.userInfo = dataXML.firstChild.attributes.Info;
+licenseInfo = {type: licType, customer: licCustomer, create: licCreate, expire: licExpire}
+
+
+function LogoutViolet() {
+	ExecWithConfirmSave(function() {
+		CreateNewData();
+		var lv:LoadVars = new LoadVars();
+		lv.send(userUrl + "logout");
+		userId = 0;
+		LoginViolet();
+	});
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RIGHT CLICK MENU ITEMS
+//
+function InitTreeContextMenu() {
+	var cmTree = new ContextMenu();
+	var cmiAbout = new ContextMenuItem("About ViOLET...", function() {getURL("http://www.bachkim.vn", "_blank")});
+	var cmiCut = new ContextMenuItem("Cut (Ctrl+X)", btnCutOnRelease);
+	var cmiCopy = new ContextMenuItem("Copy (Ctrl+C)", btnCopyOnRelease);
+	var cmiPaste = new ContextMenuItem("Paste (Ctrl+V)", btnPasteOnRelease);
+	var cmiAdd = new ContextMenuItem("Add (F5)", btnAdd.onRelease);
+	var cmiChange = new ContextMenuItem("Change (F6)", btnDetail.onRelease);
+	var cmiDelete = new ContextMenuItem("Delete (Del)", btnDelete.onRelease);
+	cmiCut.separatorBefore = true;
+	cmiAdd.separatorBefore = true;
+	cmTree.hideBuiltInItems();
+	cmTree.customItems.push(cmiAbout, cmiCut, cmiCopy, cmiPaste, cmiAdd, cmiChange, cmiDelete);
+	treItem.menu = cmTree;
+}
Index: /pro-violet-viettel/refs/LectureEditor/scene.as
===================================================================
--- /pro-violet-viettel/refs/LectureEditor/scene.as	(revision 297)
+++ /pro-violet-viettel/refs/LectureEditor/scene.as	(revision 297)
@@ -0,0 +1,1394 @@
+﻿////////////////////////////////////////////////////////////////////////////////
+// File:    SCENE.AS
+// Mô tả:   File chứa các biến, các hàm phục vụ việc xử lý các thao tác trên
+//          3 đối tượng của giao diện chính (gồm TreeView, Preview, FileList)
+//          và cập nhật dữ liệu dùng chung (biến dataXML)
+//
+// Tác giả: Đinh Hải Minh, VicoSoft
+// Ngày:    02/12/2003
+////////////////////////////////////////////////////////////////////////////////
+
+//******************************************************************************
+// Khởi tạo các biến toàn cục và thuộc tính ban đầu của các đối tượng
+// Nạp file Player để hiển thị PREVIEW của bài giảng
+//******************************************************************************
+
+version = "1.81";
+if (language == undefined) language = "Vietnamese";
+if (vietType == undefined) vietType = false;
+if (tokenPassword == undefined) tokenPassword = "violet";
+if (applicationId == undefined) applicationId = "Violet";
+slash = "\\";
+
+btnSemitrans.count = 0;
+btnSemitrans._visible = false;
+btnSceneBkGnd._visible = false;
+btnSemitrans.useHandCursor = false;
+btnSceneBkGnd.useHandCursor = false;
+scpFileList.content.movFileItem._visible = false;
+treItem.addEventListener("change", onTreeViewChange);
+
+if (_url.substr(0, 7)=="http://") { rootPath = _url.substr(0, -25); slash = "/"; webbase = true; }
+else if (_url.substr(0, 8)=="file:///") { rootPath = _url.substr(8, -33).split("|").join(":"); slash = "/"; }
+else if (_url.substr(0, 7)=="file://") rootPath = _url.substr(7, -32).split("|").join(":");
+
+dataDir = 'Data';
+commonDir = 'Common';
+commonLibDir = 'Addins';
+maxUndo = 10;
+dataID = "[VIOLET Data]";
+dataChanged = "false";
+commonXML = new XML();
+currentFile = "";
+defXmlDecl = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+packagePlayer = "Player.exe";
+playerMovie = rootPath + "Frame" + slash + "Player.swf";
+appPath = rootPath + "Lecture" + slash;
+commonPath = appPath + "Layout" + slash;
+
+pluginUrl = "http://edustore.vn/violet/";
+userUrl = "http://api.violet.vn/user/";
+spaceUrl = "http://api.violet.vn/space/";
+userId = 0;
+
+curPos = new Array();
+repPos = new Array();
+undoData = new Array();
+undoPos = 0;
+
+if( !command ) command = "";
+onEnterFrame = WaitForAppCommand;
+wndDialog.contentPath = appPath + "Dialogs.swf";
+wndDialog.addEventListener("click", function(){this.content.gotoAndStop(1)});
+createEmptyMovieClip("lang", 0);
+InitTreeContextMenu();
+
+#include "scorm.as"
+#include "versions.as"
+#include "utils.as"
+
+//******************************************************************************
+// Hàm khởi động ứng dụng Flash, được gọi sau khi các biến của Flash đã được
+// khởi tạo trong hàm OnInitDialog của chương trình C++. Hàm này sẽ được
+// thực hiện khi chương trình C++ gửi message "Init OK" hoặc "Init&Open File"
+// Tác dụng:
+//   - Nạp cấu hình (cửa sổ và các tùy chọn của Violet)
+//   - Nạp dữ liệu ngôn ngữ giao tiếp
+//   - Nạp module Player, để hiển thị bài giảng đang soạn
+//   - Nạp bộ gõ tiếng Việt (nếu cần)
+//******************************************************************************
+
+function InitFlashApp(execFunc) {
+	LoadPluginInfo();
+	LoadConfig();
+	LoadLanguage();
+	if( !vietType ) {
+		onLoadTypingObj = function() {
+			typingObj.deactive();
+			delete typingObj;
+		}
+	}
+	var loader = new MovieClipLoader();
+	loader.loadClip(playerMovie, movPlayer);
+	loader.addListener({onLoadInit: function() {
+		movScene = movPlayer.scene;
+		LoadCommonLibs(commonLibList, appPath + commonLibDir);
+		if( fullscreen == true ) btnPreview.onRelease();
+		if (execFunc) execFunc();
+		else {
+			movScene.dataXML = dataXML;
+			movScene.onLoadXMLData();
+		}
+	}});
+
+	if( autoDemoTime ) setInterval(function() {
+		if( movScene.NextScreen() == -1 ) {
+			SaveConfig();
+			fscommand("Quit", "");
+		}
+	}, Number(autoDemoTime)*1000);
+}
+
+//******************************************************************************
+// Hàm xử lý các lệnh (chứa trong biến command) nhận về từ chương trình C++
+// Tác dụng:
+//   - Xử lý lệnh khi người dùng nhấn nút CLOSE trên cửa sổ chương trình C++
+//   - Xử lý phím Enter và Esc, chủ yếu thực hiện khi đang hiện các Dialog
+//   - Xử lý các phím tắt của chương trình tương ứng với các mục menu
+//******************************************************************************
+
+function WaitForAppCommand() {
+	if( messageShowing ) command = "";
+	if( command == "" ) return;
+
+	if( command == "Init OK" ) {
+		dataXML = new XML(defXmlDecl);
+		InitializeDataXML();
+		InitFlashApp();
+		if (online) InitFlashKeys();
+	}
+	if( command == "Press Delete" ) onPressDelete();
+	if( command == "Press Enter" ) onPressEnter();
+	if( command == "Press Esc" ) onPressEsc();
+	if( command == "Press Undo" ) onPressUndo();
+	if( command == "Press Redo" ) onPressRedo();
+	if( command == "Press Cut" ) onPressCtrlX();
+	if( command == "Press Copy" ) onPressCtrlC();
+	if( command == "Press Paste" ) onPressCtrlV();
+	if( command == "Press SelAll" ) onPressCtrlA();
+	if( command == "Drop Element" ) onDropElement();
+	if( command == "Press Help" ) btnHelp.onRelease();
+
+	if( !btnSemitrans._visible ) {
+		if( command == "Init&Open File" ) InitFlashApp(OpenNewFile);
+		if( command == "Open File" ) ExecWithConfirmSave(OpenNewFile);
+		if( command == "Press New" ) btnNew.onRelease();
+		if( command == "Press Open" ) btnOpen.onRelease();
+		if( command == "Press Lib" ) btnLibrary.onRelease();
+		if( command == "Press Save" ) btnSave.onRelease();
+		if( command == "Press Pack" ) btnPack.onRelease();
+		if( command == "Quit App" ) ExitProgram();
+
+		if( command == "Press Undo" ) ProcessUndo();
+		if( command == "Press Redo" ) ProcessRedo();
+		if( command == "Press Cut" ) btnCutOnRelease();
+		if( command == "Press Copy" ) btnCopyOnRelease();
+		if( command == "Press Paste" ) btnPasteOnRelease();
+		if( command == "Press MoveUp" ) btnMoveUp.onRelease();
+		if( command == "Press MoveDn" ) btnMoveDown.onRelease();
+		
+		if( command == "Press Add" ) btnAdd.onRelease();
+		if( command == "Press Update" ) btnDetail.onRelease();
+		if( command == "Press Delete" ) btnDelete.onRelease();
+		if( command == "Press Sync" ) SyncVideoAudio();
+
+		if( command == "Press Layout" ) btnLayout.onRelease();
+		if( command == "Press Preview" ) btnPreview.onRelease();
+	}
+	command = "";
+}
+
+function InitFlashKeys() {
+	var keyListener = new Object();
+	keyListener.onKeyDown = function() {
+		if (messageShowing) return;
+		var keyCode = Key.getCode();
+		switch (keyCode) {
+			case Key.DELETEKEY: onPressDelete(); break;
+			case Key.ENTER: onPressEnter(); break;
+			case Key.ESCAPE: onPressEsc(); break;
+			case 90 /*Z*/: if (Key.isDown(Key.CONTROL)) onPressUndo(); break;
+			case 89 /*Y*/: if (Key.isDown(Key.CONTROL)) onPressRedo(); break;
+			case 88 /*X*/: if (Key.isDown(Key.CONTROL)) onPressCtrlX(); break;
+			case 67 /*C*/: if (Key.isDown(Key.CONTROL)) onPressCtrlC(); break;
+			case 86 /*V*/: if (Key.isDown(Key.CONTROL)) onPressCtrlV(); break;
+			case 65 /*A*/: if (Key.isDown(Key.CONTROL)) onPressCtrlA(); break;
+			case 112 /*F1*/: btnHelp.onRelease(); break;
+		}
+		if( !btnSemitrans._visible )
+		switch (keyCode) {
+			case 90 /*Z*/: if (Key.isDown(Key.CONTROL)) ProcessUndo(); break;
+			case 89 /*Y*/: if (Key.isDown(Key.CONTROL)) ProcessRedo(); break;
+			case 88 /*X*/: if (Key.isDown(Key.CONTROL)) btnCutOnRelease(); break;
+			case 67 /*C*/: if (Key.isDown(Key.CONTROL)) btnCopyOnRelease(); break;
+			case 86 /*V*/: if (Key.isDown(Key.CONTROL)) btnPasteOnRelease(); break;
+
+			case 76 /*L*/: if (Key.isDown(Key.CONTROL)) btnLibrary.onRelease(); break;
+			case 83 /*S*/: if (Key.isDown(Key.CONTROL)) btnSave.onRelease(); break;
+			case 113 /*F2*/: btnNew.onRelease(); break;
+			case 114 /*F3*/: btnOpen.onRelease(); break;
+			case 115 /*F4*/: btnPack.onRelease(); break;
+			case 116 /*F5*/: btnAdd.onRelease(); break;
+			case 117 /*F6*/: btnDetail.onRelease(); break;
+			case 118 /*F7*/: SyncVideoAudio(); break;
+			case 119 /*F8*/: btnLayout.onRelease(); break;
+			case 120 /*F9*/: btnPreview.onRelease(); break;
+			case Key.DELETEKEY: btnDelete.onRelease(); break;
+		}
+	}
+	Key.addListener(keyListener);
+}
+
+//******************************************************************************
+// Hàm nạp thông tin về các plugin và các layout, dùng cho hàm chuyển đổi
+// version, cho cửa sổ soạn thảo slide và cho bảng lựa chọn Layout
+// Tác dụng:
+//   - Đọc các thông tin XML trong file Plugin.xml và Layouts.xml
+//******************************************************************************
+
+function LoadPluginInfo() {
+	pluginXML = new XML();
+	pluginXML.ignoreWhite = true;
+	pluginXML.load(appPath + "Plugins.xml");
+	pluginXML.onLoad = function() {
+		pluXML = pluginXML.firstChild;
+		LoadOldPlgLang(pluXML.firstChild.childNodes);
+	}
+
+	layoutXML = new XML();
+	layoutXML.ignoreWhite = true;
+	layoutXML.load(appPath + "Layout" + slash + "Layouts.xml");
+
+	var libXML = new XML();
+	libXML.ignoreWhite = true;
+	libXML.load(appPath + "Libraries.xml");
+	libXML.onLoad = function() {
+		libraryPaths = libXML.firstChild.childNodes[0];
+		symbolPaths = libXML.firstChild.childNodes[1];
+		lecturePaths = libXML.firstChild.childNodes[2];
+		libraryPaths.attributes.libPath = libPath1[0];
+		lecturePaths.attributes.libPath = libPath2[0];
+		libraryPaths.attributes.libCurrentSelected = libPath1[1];
+		lecturePaths.attributes.libCurrentSelected = libPath2[1];
+		libraryPaths.attributes.libCurrentPage = libPath1[2];
+		lecturePaths.attributes.libCurrentPage = libPath2[2];
+	}
+	delete pluginXmlData;
+	delete layoutXmlData;
+}
+
+//******************************************************************************
+// Hàm nạp dữ liệu ngôn ngữ, dùng khi khởi động và khi thay đổi ngôn ngữ
+// Tác dụng: Đọc các file ngôn ngữ trong Langugue và Langugue\Plugins
+//******************************************************************************
+
+function LoadLanguage() {
+	lang.onData = function() {
+		CreateMenuBar();
+		AutoCheckVersion();
+		//if (online && userId==0) LoginViolet();
+	}
+	loadVariables(appPath + "Language" + slash + language + ".txt", lang);
+	RemoveAllChild(lang);
+	var plang = lang.createEmptyMovieClip("plgLang", 0);
+	var llang = lang.createEmptyMovieClip("layLang", 1);
+	loadVariables(appPath + "Language" + slash + "Plugins" + slash + language + ".txt", plang);
+	loadVariables(appPath + "Layout" + slash + "Language" + slash + language + ".txt", llang);
+	LoadLibLanguage(commonLibList, commonLibDir);
+}
+
+function LoadOldPlgLang(plulist) {
+	for( var i = 0; i < plulist.length; i++ ) {
+		var name = plulist[i].attributes.name;
+		if (name=="vpTest" || name=="vpDrag" || name=="vpCross") {
+			var lang = lang.createEmptyMovieClip(name, lang.getNextHighestDepth());
+			loadVariables(appPath + plulist[i].attributes.language + slash + language + ".txt", lang);
+		}
+	}
+}
+
+function LoadLibLanguage(libStr, libDir) {
+	var libs = libStr.split(",");
+	for (var i = 0; i < libs.length; i++) {
+		if (libs[i].substr(-4).toLowerCase() != ".swf") continue;
+		var name = libs[i].substr(0, -4);
+		var file = libDir + slash + name + "_lang" + slash + language + ".txt";
+		if (lang[name]) lang[name].removeMovieClip();
+		var lib = lang.createEmptyMovieClip(name, lang.getNextHighestDepth());
+		loadVariables(file, lib);
+	}
+}
+
+function GetPluginTitle(node) {
+	var isXml = (typeof(node) != "string");
+	var name = isXml? node.attributes.name: node;
+	var title = lang.plgLang[name];
+	if (!title && isXml) title = node.attributes.title;
+	return title? title: name;
+}
+
+function RunAfterLoadPlgLang(plgNode, UpdateList) {
+	for (var i = 0; i < plgNode.childNodes.length; i++) {
+		if (!_root.lang.plgLang[plgNode.attributes.name]) break;
+	}
+	if (i < plgNode.childNodes.length) {
+		loadVariables(pluginUrl + "language/" + language + ".txt", lang.plgLang);
+		lang.plgLang.onData = UpdateList;
+		needUpdatePluginLang = true;
+	}
+	else UpdateList();
+}
+
+function UpdatePluginLang() {
+	if (!needUpdatePluginLang) return;
+	fscommand("Download Plugin", pluginUrl + "language/Language.zip");
+	needUpdatePluginLang = false;
+}
+
+//******************************************************************************
+// Hàm tự động kiểm tra phiên bản phần mềm và xử lý khi phiên bản đã cũ
+// Tác dụng: Đọc file thông tin violet.inf trên server, so sánh phiên bản và
+//   + nếu update_level = 0 thì không làm gì
+//   + nếu update_level = 1 thì thông báo và chạy tiếp
+//   + nếu update_level = 2 thì thông báo và ngừng chương trình
+//******************************************************************************
+
+function AutoCheckVersion() {
+	var verlv = new LoadVars();
+	verlv.load("http://www.bachkim.vn/resource/violet.inf");
+	verlv.onLoad = function(success) {
+		if (!success) return;
+		var lastest = Number(verlv.violet_version);
+		var prever = Number(verlv.violet_preversion);
+		var level = Number(verlv.update_level);
+		if (level > 0 && prever < version && version < lastest) {
+			ShowMessage(lang.msgNeedUpdate, lang.msgTitle, function() {
+				if (level == 2) fscommand("Quit", "");
+			});
+		}
+	}
+}
+
+//******************************************************************************
+// Hàm nạp dữ liệu từ file ngoài (*.XVL), được gọi trong chức năng MỞ FILE
+// Tác dụng: Tạo biến dataXML và gọi lệnh để đọc dữ liệu từ file vào biến này
+//******************************************************************************
+
+function LoadXMLData(fileName) {
+	dataXML = new XML();
+	dataXML.onLoad = onLoadData;
+	dataXML.ignoreWhite = true;
+	dataXML.load(fileName);
+	movScene.dataXML = dataXML;
+}
+
+//******************************************************************************
+// Hàm thông báo lỗi nếu có lỗi khi mở file, được gọi trong hàm onLoadData()
+//******************************************************************************
+
+function ErrorMessage(message) {
+	ShowMessage(message, lang.msgTitle1);
+	CreateNewData();
+}
+
+//******************************************************************************
+// Hàm cập nhật toàn bộ màn hình Violet mỗi khi dữ liệu dataXML thay đổi một
+// cách bất kỳ. Hàm được gọi khi load một XML mới hoặc khi undo, redo.
+// Tác dụng: Cập nhất nội dung Tree mới và cập nhật phần danh sách file.
+//******************************************************************************
+
+function UpdateScreen() {
+	var index = 0;
+	var a = new XML();
+
+	for( var i=0; i<dataXML.firstChild.childNodes.length; i++ )
+	{
+		var x = a.createElement("node");
+		x.attributes.label = dataXML.firstChild.childNodes[i].attributes.label;
+		x.attributes.section = i+1;
+		x.attributes.item = 0;
+		
+		for( var j=0; j<dataXML.firstChild.childNodes[i].childNodes.length; j++ )
+		{
+			var y = a.createElement("node");
+			y.attributes.label = dataXML.firstChild.childNodes[i].childNodes[j].attributes.label;
+			y.attributes.section = i+1;
+			y.attributes.item = j+1;
+			x.appendChild(y);
+		}
+		
+		a.appendChild(x);
+		treItem.addItem(a.childNodes[i]);
+		treItem.setIsOpen(treItem.getNodeDisplayedAt(index), true, false, null);
+		index += (x.childNodes.length+1);
+	}
+	treItem.setFocus();
+	GetRelatedFiles();
+}
+
+//******************************************************************************
+// Hàm sự kiện được gọi sau khi đã đọc xong dữ liệu từ file XVL vào biến
+// dataXML bằng hàm LoadXMLData(fileName) ở trên
+// Tác dụng:
+//   - Thiết lập nội dung của TreeView
+//   - Xử lý hiển thị vùng PREVIEW của bài giảng
+//   - Xử lý phần danh sách các file dữ liệu
+//******************************************************************************
+
+function onLoadData(success)
+{
+	if( !success ) {
+		ErrorMessage(lang.msgOpenError);
+		return;
+	}
+	if( dataXML.firstChild.nodeName != "LECTURE_INFO" ) {
+		ErrorMessage(lang.msgInvalidFile);
+		return;
+	}
+	if( dataXML.status<0 ) {
+		ErrorMessage(lang.msgCorruptFile);
+		return;
+	}
+
+	if( dataXML.firstChild.attributes.Version ) {
+		var encode = GetAttribute(dataXML.xmlDecl, "encoding"); 
+		if (encode == null) UnicodeAscii(unescape, dataXML.firstChild);
+	}
+
+	ChangeDataVersion();
+	if (currentFile == "") {
+		var change = function(fn) {return GetFullFileName(fn, openedFileName)};
+		GetDataChangePath(change, dataXML.firstChild);
+	}
+	movScene.GetBackGround();
+	dataXML.firstChild.attributes.Version = version;
+	dataXML.firstChild.attributes.CommonDir = commonDir;
+	if( !appUserName ) delete dataXML.firstChild.attributes.Info;
+	else {
+		dataXML.firstChild.attributes.Info = unescape(appUserName) + " - " + unescape(appAddress);
+		dataXML.firstChild.attributes.Check = dataXML.firstChild.attributes.Info.length + 13;
+	}
+	if (autoPackage) {
+		GetRelatedFiles(true);
+		CreatePackage("Overwrite");
+		fscommand("Quit", "");
+		return;
+	}
+	UpdateScreen();
+	movScene.onLoadXMLData();
+}
+
+//******************************************************************************
+// Hàm xử lý việc lựa chọn các item khác nhau của TreeView
+// Tác dụng: Phần PREVIEW sẽ nhảy đến trang màn hình tương ứng với mục đã
+// chọn trên TreeView
+//******************************************************************************
+
+function onChangeHandle(obj) {
+	var section = treItem.selectedNode.attributes.section;
+	var item = treItem.selectedNode.attributes.item;
+	movScene.gotoScreen(section, item, true);
+	oldTreeSelect = treItem.selectedIndex;
+}
+
+//******************************************************************************
+// Hàm xử lý sự kiện khi người dùng click chuột trên TreeView
+// Tác dụng: Gọi hàm onChangeHandle() để thay đổi nội dung TreeView theo mục
+// lựa chọn, và kiểm tra nếu như nhấn double-click sẽ gọi chức năng sửa đổi mục
+//******************************************************************************
+
+function onTreeViewChange(obj) {
+	var again = (treItem.selectedIndex == oldTreeSelect);
+	if( !again ) onChangeHandle(obj);
+	if( IsDblClick(_root) && again) btnDetail.onRelease();
+}
+
+//******************************************************************************
+// Hàm thiết lập vị trí hiện hành của TreeView, được gọi khi người dùng chọn
+// chủ đề hoặc chọn mục trên phần PREVIEW
+// Tác dụng:
+//   Tìm item trên TreeView có các thông số chủ đề và mục giống như trong phần
+//   PREVIEW bài giảng, sau đó thiết lập item này là vị trí hiện hành
+// Tham số:
+//   section, item: chủ đề và mục đang được lựa chọn trên PREVIEW
+//******************************************************************************
+
+function gotoTreeItem(section, item) {
+	var i = 0;
+	if( section>0 && treItem.length>0 ) {
+		while( i<treItem.length && treItem.getItemAt(i).attributes.section!=section ) {
+			i++;
+		}
+		var node = treItem.getItemAt(i);
+		if( !getIsOpen(node) ) treItem.setIsOpen(node, true, false, null);
+	
+		while( i<treItem.length && treItem.getItemAt(i).attributes.item!=item ) {
+			i++;
+		}
+	}
+	if( i<treItem.length ) treItem.selectedIndex = oldTreeSelect = i;
+}
+
+//******************************************************************************
+// Hàm thêm chủ đề và mục mới, được gọi ở bước cuối trong chức năng "Thêm mục"
+// (trường hợp người dùng CÓ nhập chủ đề mới)
+// Tác dụng:
+//   Thêm một chủ đề mới vào vị trí cuối cùng, sau đó thêm mục đầu tiên vào
+//   chủ đề rỗng này
+// Tham số:
+//   itemData: dữ liệu dạng XML node của chủ đề cần thêm vào
+//******************************************************************************
+
+function AddSectionData(itemData, pos) {
+	var a = new XML();
+	var x = a.createElement("node");
+	x.attributes.label = itemData.attributes.label;
+	x.attributes.section = (pos!=undefined)? pos+1: dataXML.firstChild.childNodes.length+1;
+	x.attributes.item = 0;
+
+	for( var j=0; j<itemData.childNodes.length; j++ )
+	{
+		var y = a.createElement("node");
+		y.attributes.label = itemData.childNodes[j].attributes.label;
+		y.attributes.section = x.attributes.section;
+		y.attributes.item = j+1;
+		x.appendChild(y);
+	}
+	a.appendChild(x);
+	
+	var i = (pos==undefined)? treItem.length: 0;
+	while( i<treItem.length && treItem.getItemAt(i).attributes.section != x.attributes.section ) i++;
+	var trePos = i;
+	while( i<treItem.length ) {
+		var node = treItem.getItemAt(i);
+		node.attributes.section++;
+		if( node.attributes.item==0 ) treItem.setIsOpen(node, true, false, null);
+		i++;
+	}
+	treItem.addItemAt(trePos, a.lastChild);
+	treItem.setIsOpen(x, true, false, null);
+
+	UpdateUndoData();
+	if( pos==undefined ) dataXML.firstChild.appendChild(itemData);
+	else dataXML.firstChild.insertBefore(itemData, dataXML.firstChild.childNodes[pos]);
+	movScene.RefreshSectionButton();
+	treItem.selectedIndex = trePos + 1;
+	onChangeHandle(0);
+
+	GetRelatedFiles();
+}
+
+//******************************************************************************
+// Hàm thêm mục mới, được gọi ở bước cuối trong chức năng "Thêm mục" (trường
+// hợp người dùng KHÔNG nhập chủ đề mới)
+// Tác dụng: Thêm một mục mới vào vị trí cuối cùng của chủ đề đã có.
+// Tham số:
+//   index: thứ tự của chủ đề (tính từ 0)
+//   itemData: dữ liệu dạng XML node của mục cần thêm vào
+//******************************************************************************
+
+function AddItemData(index, itemData) {
+	if( index < 0 ) index = 0;
+	if( !dataXML.firstChild.childNodes[index] ) return;
+	
+	for( var i=0; i<treItem.length; i++ ) {
+		if( treItem.getItemAt(i).attributes.section == index+1 ) break;
+	}
+	var sectionNode = treItem.getItemAt(i);
+	var itemNode = commonXML.createElement("node");
+	itemNode.attributes.label = itemData.attributes.label;
+	itemNode.attributes.section = index + 1;
+	itemNode.attributes.item = sectionNode.childNodes.length + 1;
+
+	var newPos = i + 1 + sectionNode.childNodes.length;
+	treItem.setIsOpen(sectionNode, true, false, null);
+	treItem.addItemAt(newPos, itemNode);
+	sectionNode.appendChild(itemNode);
+	
+	UpdateUndoData();
+	dataXML.firstChild.childNodes[index].appendChild(itemData);
+	movScene.RefreshItemButton();
+	treItem.selectedIndex = newPos;
+	onChangeHandle(0);
+
+	GetRelatedFiles();
+}
+
+//******************************************************************************
+function ChangeHyperlink()
+{
+	for( var i=0; i<dataXML.firstChild.childNodes.length; i++ ) {
+		var secNode = dataXML.firstChild.childNodes[i];
+		for( var j=0; j<secNode.childNodes.length; j++ ) {
+			var iteNode = secNode.childNodes[j];
+			for( var k=0; k<iteNode.childNodes.length; k++ ) {
+				var node = iteNode.childNodes[k];
+				ChangeHyperlinkNode(node);
+				if( node.nodeName == "PLUGIN" ) {
+					var subNodes = node.firstChild.childNodes;
+					for( var m=0; m<subNodes.length; m++ ) ChangeHyperlinkNode(subNodes[m]);
+				}
+			}
+		}
+	}
+}
+
+//******************************************************************************
+function ChangeHyperlinkNode(node)
+{
+	if( node.attributes.hyperlink.charAt(0) == "2" ) {
+		var a = node.attributes.hyperlink.split("|");
+		for( var c=0; c<curPos.length; c+=2 ) {
+			if( Number(a[1])==curPos[c] && Number(a[2])==curPos[c+1] ) {
+				if( repPos[c]==-1 ) delete node.attributes.hyperlink;
+				else node.attributes.hyperlink = "2|" + repPos[c] + "|" + repPos[c+1];
+				break;
+			}
+		}
+	}
+}
+
+//******************************************************************************
+// Hàm xóa mục, chủ đề,... được gọi khi người dùng chọn chức năng xóa mục và
+// đã trả lời xác nhận là có chắc chắn xóa
+// Tác dụng:
+//   Xóa đối tượng đang được lựa chọn trên TreeView (trang bìa, chủ đề hoặc
+//   mục). Nếu xóa một chủ đề thì toàn bộ các mục trong đó cũng bị xóa theo
+//******************************************************************************
+
+function DeleteItem(delOnly)
+{
+	var section = treItem.selectedNode.attributes.section;
+	var item = treItem.selectedNode.attributes.item;
+	var i = treItem.selectedIndex;
+	var oldSel = i;
+
+	if( !delOnly ) {
+		curPos.splice(0);
+		repPos.splice(0);
+		UpdateUndoData();
+	}
+
+	//
+	// Nếu mục đang chọn là duy nhất trong chủ đề thì sẽ xóa cả chủ đề đi
+	//
+	if( item == 1 && treItem.getItemAt(i+1).attributes.section != section ) {
+		item = 0; i--;
+	}
+
+	//
+	// Nếu đang chọn mục thì sẽ xóa mục
+	//
+	if( item > 0 ) {
+		dataXML.firstChild.childNodes[section-1].childNodes[item-1].removeNode();
+
+		if( !delOnly ) {
+			curPos.push(section);
+			curPos.push(item);
+			repPos.push(-1);
+			repPos.push(-1);
+		}
+		treItem.getItemAt(i).removeTreeNode();
+		treItem.removeItemAt(i);
+		while( i<treItem.length && treItem.getItemAt(i).attributes.section == section ) {
+			curPos.push(section);
+			curPos.push(treItem.getItemAt(i).attributes.item);
+			repPos.push(section);
+			repPos.push(treItem.getItemAt(i).attributes.item-1);
+			treItem.getItemAt(i).attributes.item--;
+			i++;
+		}
+	}
+	//
+	// còn nếu đang chọn chủ đề thì sẽ xóa chủ đề
+	//
+	else {
+		dataXML.firstChild.childNodes[section-1].removeNode();
+
+		while( i<treItem.length && treItem.getItemAt(i).attributes.section == section ) {
+			if( !delOnly ) {
+				curPos.push(section);
+				curPos.push(treItem.getItemAt(i).attributes.item);
+				repPos.push(-1);
+				repPos.push(-1);
+			}
+			treItem.getItemAt(i).removeTreeNode();
+			treItem.removeItemAt(i);
+		}
+		while( i<treItem.length ) {
+			var node = treItem.getItemAt(i);
+			if( !delOnly ) {
+				curPos.push(node.attributes.section);
+				curPos.push(node.attributes.item);
+				repPos.push(node.attributes.section-1);
+				repPos.push(node.attributes.item);
+			}
+			node.attributes.section--;
+			if( node.attributes.item==0 ) treItem.setIsOpen(node, true, false, null);
+			i++;
+		}
+	}
+
+	if( delOnly ) return;
+
+	if( treItem.length > 0 ) {
+		if( oldSel<treItem.length ) treItem.selectedIndex = oldSel;
+		else treItem.selectedIndex = treItem.length - 1;
+		onChangeHandle(0);
+	} else {
+		movScene.gotoScreen(0, 0, true);
+	}
+	
+	movScene.RefreshSectionButton();
+	movScene.RefreshItemButton();
+	ChangeHyperlink();
+	GetRelatedFiles();
+}
+
+//******************************************************************************
+// Hàm xử lý sự kiện click của nút dịch chuyển lên
+// Tác dụng:
+//   Dịch chuyển một chủ đề hoặc mục lên trước một mức. Các mục có thể dịch
+//   chuyển qua lại được giữa các chủ đề. Khi dịch chuyển một chủ đề thì toàn
+//   bộ mục trong đó cũng được dịch chuyển theo
+//******************************************************************************
+
+btnMoveUp.onRelease = function() {
+	if( treItem.length == 0 ) return;
+	var index = treItem.selectedIndex;
+	var node = treItem.getItemAt(index);
+	var item = node.attributes.item;
+	var section = node.attributes.section;
+	if( section == 0 ) return;
+	
+	curPos.splice(0);
+	repPos.splice(0);
+	UpdateUndoData();
+
+	//
+	// Nếu là thao tác dịch chuyển mục
+	//
+	if( item != 0 ) {
+		if( item == 1 && section==1 ) return;
+
+		//
+		// Nếu là mục đầu tiên thì mục sẽ được chuyển vào vị trí cuối cùng
+		// của chủ đề liền trước
+		//
+		if( item == 1 ) {
+			//
+			// Xóa mục ở chủ đề cũ
+			//
+			var dataNode = dataXML.firstChild.childNodes[section-1].firstChild;
+			DeleteItem(true);
+			movScene.RefreshSectionButton();
+
+			//
+			// Thêm mục vào chủ đề mới
+			//
+			var sectionNode;
+			for( var i=0; i<treItem.length; i++ ) {
+				sectionNode = treItem.getItemAt(i);
+				if( sectionNode.attributes.section == section-1 ) break;
+			}
+			treItem.setIsOpen(sectionNode, true, false, null);
+			var newPos = i + 1 + sectionNode.childNodes.length;
+			
+			node.attributes.section = section-1;
+			node.attributes.item = sectionNode.childNodes.length + 1;
+			treItem.addItemAt(newPos, node);
+			sectionNode.appendChild(node);
+			treItem.selectedIndex = newPos;
+
+			curPos.push(section);
+			curPos.push(1);
+			repPos.push(section-1);
+			repPos.push(node.attributes.item);
+
+			dataXML.firstChild.childNodes[section-2].appendChild(dataNode);
+		}
+		//
+		// còn nếu không phải là đầu tiên thì mục sẽ được hoán đổi vị trí
+		// với mục liền trước
+		//
+		else {
+			//
+			// Hoán đổi mục trong TreeView
+			//
+			var sectionNode = treItem.getItemAt(index).parentNode;
+			sectionNode.childNodes[item-1].removeNode();
+			sectionNode.insertBefore(node, sectionNode.childNodes[item-2]);
+
+			treItem.removeItemAt(index);
+			treItem.addItemAt(index-1, node);
+			treItem.getItemAt(index).attributes.item++;
+			treItem.getItemAt(index-1).attributes.item--;
+			treItem.selectedIndex = index-1;
+		
+			//
+			// Hoán đổi mục trong dataXML
+			//
+			var data = dataXML.firstChild.childNodes[section-1];
+			var temp = data.childNodes[item-1];
+			data.childNodes[item-1].removeNode();
+			data.insertBefore(temp, data.childNodes[item-2]);
+
+			curPos.push(section);
+			curPos.push(item);
+			repPos.push(section);
+			repPos.push(item-1);
+			curPos.push(section);
+			curPos.push(item-1);
+			repPos.push(section);
+			repPos.push(item);
+
+			movScene.RefreshItemButton();
+		}
+	}
+	
+	//
+	// còn nếu thao tác là dịch chuyển chủ đề
+	//
+	else {
+		if( section == 1 ) return;
+
+		//
+		// Đóng chủ đề hiện hành và chủ đề liền trước nó (nếu đang được mở)
+		// để dễ dàng hoán đổi đổi vị trí
+		//
+		prevNode = treItem.getItemAt(index-1);
+		if( prevNode.attributes.item != 0 ) prevNode = prevNode.parentNode;
+		treItem.setIsOpen(node, false, false, null);
+		treItem.setIsOpen(prevNode, false, false, null);
+
+		//
+		// Hoán đổi vị trí hai chủ đề (đã được đóng) trong TreeView
+		//
+		var i = treItem.getDisplayIndex(node);
+		treItem.removeItemAt(i);
+		treItem.addItemAt(i-1, node);
+		treItem.setIsOpen(node, true, false, null);
+		treItem.setIsOpen(prevNode, true, false, null);
+		node.attributes.section--;
+		prevNode.attributes.section++;
+		for( i=0; i<node.childNodes.length; i++ ) {
+			curPos.push(node.childNodes[i].attributes.section);
+			curPos.push(node.childNodes[i].attributes.item);
+			repPos.push(node.childNodes[i].attributes.section-1);
+			repPos.push(node.childNodes[i].attributes.item);
+			node.childNodes[i].attributes.section--;
+		}
+		for( i=0; i<prevNode.childNodes.length; i++ ) {
+			curPos.push(prevNode.childNodes[i].attributes.section);
+			curPos.push(prevNode.childNodes[i].attributes.item);
+			repPos.push(prevNode.childNodes[i].attributes.section+1);
+			repPos.push(prevNode.childNodes[i].attributes.item);
+			prevNode.childNodes[i].attributes.section++;
+		}
+		treItem.selectedIndex = treItem.getDisplayIndex(node);
+
+		//
+		// Hoán đổi vị trí hai chủ đề trong biến dataXML
+		//
+		var data = dataXML.firstChild;
+		var temp = data.childNodes[section-1];
+		data.childNodes[section-1].removeNode();
+		data.insertBefore(temp, data.childNodes[section-2]);
+
+		movScene.RefreshSectionButton();
+	}
+	ChangeHyperlink();
+	onChangeHandle(0);
+}
+
+//******************************************************************************
+// Hàm xử lý sự kiện click của nút dịch chuyển xuống
+// Tác dụng:
+//   Dịch chuyển một chủ đề hoặc mục về phía sau một mức. Các tính năng khác
+//   tương tự như trong hàm sự kiện của nút dịch lên
+//******************************************************************************
+
+btnMoveDown.onRelease = function() {
+	if( treItem.length == 0 ) return;
+	var index = treItem.selectedIndex;
+	var node = treItem.getItemAt(index);
+	var item = node.attributes.item;
+	var section = node.attributes.section;
+	if( section == 0 ) return;
+	
+	curPos.splice(0);
+	repPos.splice(0);
+	UpdateUndoData();
+
+	if( item != 0 ) {
+		if( item == node.parentNode.childNodes.length &&
+			section == dataXML.firstChild.childNodes.length )
+			return;
+			
+		if( item == node.parentNode.childNodes.length ) {
+			var dataSection = dataXML.firstChild.childNodes[section-1];
+			var dataNode = dataSection.childNodes[item-1];
+			if( dataSection.childNodes.length==1 ) {index--; section--}
+			DeleteItem(true);
+			movScene.RefreshSectionButton();
+
+			var sectionNode = treItem.getItemAt(index);
+			treItem.setIsOpen(sectionNode, true, false, null);
+			
+			node.attributes.section = section+1;
+			node.attributes.item = 1;
+			sectionNode.insertBefore(node, sectionNode.firstChild);
+			
+			i = index + 1;
+			while( treItem.getItemAt(i).attributes.section == section+1 && i<treItem.length) {
+				curPos.push(section+1);
+				curPos.push(treItem.getItemAt(i).attributes.item);
+				repPos.push(section+1);
+				repPos.push(treItem.getItemAt(i).attributes.item+1);
+				treItem.getItemAt(i).attributes.item++;
+				i++;
+			}
+			treItem.addItemAt(index+1, node);
+			treItem.selectedIndex = index+1;
+
+			curPos.push(section);
+			curPos.push(item);
+			repPos.push(section+1);
+			repPos.push(1);
+
+			dataSection = dataXML.firstChild.childNodes[section];
+			dataSection.insertBefore(dataNode, dataSection.firstChild);
+		} else {
+			var sectionNode = treItem.getItemAt(index).parentNode;
+			sectionNode.childNodes[item-1].removeNode();
+			sectionNode.insertBefore(node, sectionNode.childNodes[item]);
+
+			treItem.removeItemAt(index);
+			treItem.addItemAt(index+1, node);
+			treItem.getItemAt(index).attributes.item--;
+			treItem.getItemAt(index+1).attributes.item++;
+			treItem.selectedIndex = index+1;
+
+			var data = dataXML.firstChild.childNodes[section-1];
+			var temp = data.childNodes[item-1];
+			data.childNodes[item-1].removeNode();
+			data.insertBefore(temp, data.childNodes[item]);
+
+			curPos.push(section);
+			curPos.push(item);
+			repPos.push(section);
+			repPos.push(item+1);
+			curPos.push(section);
+			curPos.push(item+1);
+			repPos.push(section);
+			repPos.push(item);
+
+			movScene.RefreshItemButton();
+		}
+	} else {
+		if( section == node.parentNode.childNodes.length ) return;
+		treItem.setIsOpen(node, false, false, null);
+		nextNode = treItem.getItemAt(index+1);
+		treItem.setIsOpen(nextNode, false, false, null);
+
+		treItem.removeItemAt(index);
+		treItem.addItemAt(index+1, node);
+		treItem.setIsOpen(node, true, false, null);
+		treItem.setIsOpen(nextNode, true, false, null);
+		node.attributes.section++;
+		nextNode.attributes.section--;
+		for( i=0; i<node.childNodes.length; i++ ) {
+			curPos.push(node.childNodes[i].attributes.section);
+			curPos.push(node.childNodes[i].attributes.item);
+			repPos.push(node.childNodes[i].attributes.section+1);
+			repPos.push(node.childNodes[i].attributes.item);
+			node.childNodes[i].attributes.section++;
+		}
+		for( i=0; i<nextNode.childNodes.length; i++ ) {
+			curPos.push(nextNode.childNodes[i].attributes.section);
+			curPos.push(nextNode.childNodes[i].attributes.item);
+			repPos.push(nextNode.childNodes[i].attributes.section-1);
+			repPos.push(nextNode.childNodes[i].attributes.item);
+			nextNode.childNodes[i].attributes.section--;
+		}
+		treItem.selectedIndex = treItem.getDisplayIndex(node);
+
+		var data = dataXML.firstChild;
+		var temp = data.childNodes[section-1];
+		data.childNodes[section-1].removeNode();
+		data.insertBefore(temp, data.childNodes[section]);
+
+		movScene.RefreshSectionButton();
+	}
+	ChangeHyperlink();
+	onChangeHandle(0);
+}
+
+//******************************************************************************
+// Hàm kiểm tra xem tên file đã nằm trong danh sách hay chưa
+// Công việc:
+//   - Duyệt tất cả danh sách tên file (fileList) ở những vị trí chẵn, nếu
+//     có phần tử trùng tên với tên file đang xét thì return lại kết quả
+// Tham số:
+//   - fileName: tên file có đầy đủ đường dẫn
+// Trả về:
+//   - true nếu fileName đã nằm trong danh sách
+//   - false nếu fileName chưa nằm trong danh sách
+//******************************************************************************
+
+function AlreadyInList(fileName) {
+	for( var i=0; i<fileList.length; i+=2 ) {
+		if( fileName == fileList[i] ) return true;
+	}
+	return false;
+}
+
+function UniqueFileName(fileName, id) {
+	var dp = fileName.lastIndexOf(".");
+	var newName = fileName.substr(0, dp) + (id==0? "": "(" +id +")") + fileName.substr(dp);
+	for( var i=1; i<fileList.length; i+=2 ) {
+		if( newName == fileList[i] ) return UniqueFileName(fileName, id + 1);
+	}
+	return newName;
+}
+
+//******************************************************************************
+// Hàm thêm file vào danh sách, được gọi khi xây dựng danh sách file dữ liệu
+// Tác dụng:
+//   - Thêm tên file đầy đủ (gồm cả đường dẫn) vào danh sách
+//   - Thêm tên file không có đường dẫn vào danh sách
+//   - Tạo lập một đối tượng hiển thị (tương ứng với file) trong ScrollPane,
+//     đối tượng này bao gồm 1 biểu tượng và tên file không có đường dẫn
+// Tham số:
+//   - id: thứ tự của file
+//   - fileName: tên file có đầy đủ đường dẫn
+// Trả về:
+//   - tên file không có đường dẫn
+//******************************************************************************
+
+function AddToList(fileName, fileType)
+{
+	if( fileName == "" || fileName == undefined ) return "";
+	if( fileType != "LIBFILE_INFO" ) {
+		fileName = GetFullFileName(fileName);
+	}
+
+	var destDir = isCommon ? commonDir : dataDir;
+	switch( fileType ) {
+	case "COMMON_FILE":
+		destDir = commonDir;
+		commonFileNum ++;
+		break;
+	case "EXEC_FILE":
+		destDir = "fscommand";
+		execFileNum ++;
+		break;
+	default:
+		destDir = dataDir;
+		dataFileNum ++;
+	}
+	var pos = Math.max(fileName.lastIndexOf("\\"), fileName.lastIndexOf("/"));
+	var subName = fileName.substr(pos+1);
+	var destFile = destDir + "/" + GetSafeFileName(subName);
+
+	if( AlreadyInList(fileName) ) return destFile;
+	destFile = UniqueFileName(destFile, 0);
+	fileList.push(fileName);
+	fileList.push(destFile);
+	fileListStr = fileList.join("|");
+	if( fileType == "COMMON_FILE" ) return destFile;
+
+	if( !eval("scpFileList.content.movFileItem"+file_id)) {
+		scpFileList.content.movFileItem.duplicateMovieClip("movFileItem"+file_id, file_id);
+	}
+	var item = eval("scpFileList.content.movFileItem"+file_id);
+	item._x = file_id*130 + 26;
+	item.label = subName;
+	item.lblFileName.autoSize = "left";
+	item.lblFileName._y = 16 - item.lblFileName._height/2;
+	
+	var pos = subName.lastIndexOf(".") + 1;
+	var extname = subName.substr(pos).toLowerCase();
+	item.movIcon.gotoAndStop(1);
+	if( extname == "jpg" || extname == "jpeg") item.movIcon.gotoAndStop(2);
+	if( extname == "swf" ) item.movIcon.gotoAndStop(3);
+	if( extname == "flv" ) item.movIcon.gotoAndStop(4);
+	if( extname == "mp3" ) item.movIcon.gotoAndStop(5);
+	
+	if( extname != "swf" ) item.fullName = fileName;
+	else item.fullName = fileName.substr(0, fileName.length-3) + "fla";
+
+	item.onRelease = function() {
+		this.onDragOut();
+		EditFile(this.fullName);
+	}
+	item.onDragOut = function() {
+		this._x --;
+		this._y --;
+		this.onRollOut();
+	}
+	item.onPress = item.onDragOver = function() {
+		this._x ++;
+		this._y ++;
+		this.onRollOver();
+	}
+	item.onRollOut = function() {
+		this._alpha = 65;
+		this.lblFileName.textColor = 0x5F5F5F;
+	}
+	item.onRollOver = function() {
+		this._alpha = 100;
+		this.lblFileName.textColor = 0x000000;
+	}
+	item.onRollOut();
+
+	file_id++;
+	return destFile;
+}
+
+//******************************************************************************
+// Hàm xác định danh sách các file dữ liệu, được gọi trong các thao tác thêm
+// xóa mục dữ liệu có chứa file, thêm xóa trang bìa, mở file, tạo mới,...
+// Tác dụng:
+//   - Tạo danh sách file dữ liệu (có cả tên đầy đủ và tên không đường dẫn)
+//   - Tạo một XML mới mà tất cả tên file trong đó đều không có đường dẫn.
+//     XML này và danh sách file dữ liệu trên sẽ được dùng để phục vụ cho
+//     việc "Tạo phần mềm" của chương trình C++
+//   - Tạo nội dung của đối tượng ScrollPane danh sách file
+// Kết quả:
+//   - biến fileList: mảng danh sách tên file dữ liệu
+//   - biến packXML: XML mà dữ tên file đã được cắt đường dẫn
+//   - scpFileList.content: nội dung của ScrollPane danh sách file
+//******************************************************************************
+
+function GetRelatedFiles(isPacking) {
+	if( fileList ) delete fileList;
+	fileList = new Array();
+
+	if( !dataXML.firstChild.firstChild ) dataXML.firstChild.appendChild(movScene.bkgnd_node);
+	else dataXML.firstChild.insertBefore(movScene.bkgnd_node, dataXML.firstChild.firstChild);
+
+	packXML = new XML(dataXML.toString());
+	commonFileNum = dataFileNum = execFileNum = 0;
+	file_id = 0;
+
+	var slashPos = Math.max(currentFile.lastIndexOf("\\"), currentFile.lastIndexOf("/"));
+	var subName = currentFile.substr(slashPos+1);
+	var dotPos = subName.lastIndexOf(".");
+	subName = subName.substring(0, dotPos);
+	if( !packXML.firstChild.attributes.AppName || subName != "Scenario" )
+		packXML.firstChild.attributes.AppName = subName;
+
+	var layout = dataXML.firstChild.attributes.Layout;
+	if( layout != "" ) AddToList(commonPath + layout, "COMMON_FILE");
+	ChangeLayoutFileParam(packXML.firstChild, AddToList);
+
+	for (var i = 0; i < commonLib.libList.length; i++) RemoveCommonLib(packXML, commonLib.libList[i].file);
+	AddCommonLib(packXML, GetEffectLib(dataXML.firstChild.attributes.PageTransition));
+
+	for( var i=0; i<dataXML.firstChild.childNodes.length; i++ ) {
+		var node = dataXML.firstChild.childNodes[i];
+		for( var j=0; j<node.childNodes.length; j++ ) {
+			var subnode = node.childNodes[j];
+			var packnode = packXML.firstChild.childNodes[i].childNodes[j];
+			for( var k=0; k<subnode.childNodes.length; k++ ) {
+				var element = subnode.childNodes[k];
+				var pkNode = packnode.childNodes[k];
+				if( element.nodeName == "IMAGE" || element.nodeName == "MEDIA" ) {
+					pkNode.attributes.url = AddToList(element.attributes.url);
+				}
+				if( element.nodeName == "PLUGIN" ) {
+					var plgNode = pkNode.firstChild;
+					ChangeXMLFileInfo(plgNode, AddToList, pluXML.childNodes[1].childNodes[1].attributes[plgNode.nodeName]);
+					if (isPacking) {
+						pkNode.attributes.url = AddToList(appPath + element.attributes.player, "COMMON_FILE");
+						if (vietType && GetXMLUsingKB(plgNode, pluXML.childNodes[1].childNodes[0].attributes[plgNode.nodeName])) {
+							AddCommonLib(packXML, "Vnkey.swf");
+						}
+					}
+					var subNodes = element.firstChild.childNodes;
+					for( var p=0; p<subNodes.length; p++ ) {
+						var hl = subNodes[p].attributes.hyperlink;
+						var pkSubNode = pkNode.firstChild.childNodes[p];
+						if( hl.charAt(0) == "1" ) pkSubNode.attributes.hyperlink = "1|" + AddToList(hl.substr(2), "EXEC_FILE");
+					}
+					var langAttr = pkNode.childNodes[1].firstChild.attributes;
+					for (var a in langAttr) if (a.substr(0, 5)=="file_") langAttr[a] = AddToList(langAttr[a]);
+					if (plgNode.attributes.library) {
+						AddCommonLib(packXML, commonLib[plgNode.attributes.library + "_info"].file);
+						var attachment = commonLib[plgNode.attributes.library].firstChild.attributes.attachment;
+						if (attachment != undefined) AddToList(appPath + commonLibDir + slash + attachment, "COMMON_FILE");
+					}
+				}
+				if( element.attributes.hyperlink.charAt(0) == "1" ) {
+					pkNode.attributes.hyperlink = "1|" + AddToList(element.attributes.hyperlink.substr(2), "EXEC_FILE");
+				}
+				AddCommonLib(packXML, GetEffectLib(element.attributes.animation));
+				AddCommonLib(packXML, GetEffectLib(element.attributes.effects));
+			}
+		}
+	}
+
+	dataXML.firstChild.firstChild.removeNode();
+	var bgNode = packXML.firstChild.firstChild;
+	if (bgNode.childNodes.length == 0) bgNode.removeNode();
+
+	var width = file_id*130 + 20;
+	while( eval("scpFileList.content.movFileItem"+file_id)) {
+		eval("scpFileList.content.movFileItem"+file_id).removeMovieClip();
+		file_id++;
+	}
+	scpFileList.content.movBkGnd._width = (width < 732) ? 732 : width;
+	scpFileList.redraw(true);
+}
+
+//******************************************************************************
+// Hàm thay đổi các đường dẫn trong XMLNode của Plugin (khi save as, copy-paste)
+// Tác dụng: Đọc thông tin trong infostr dạng "name.attr", sau đó thay đổi tất
+//   cả thuộc tính "attr" của các node có tên là "name". Nếu infostr có dạng
+//   "name.attr(html)" thì sẽ thay đổi path trong các tag <IMG> của html đó.
+//   Nếu không có attr thì sẽ thay đổi nội dung của textNode.
+//******************************************************************************
+
+function ChangeXMLFileInfo(node, change, infostr) {
+	if (infostr == undefined) return;
+	var infos = infostr.split(";");
+	for (var i = 0; i < infos.length; i++) {
+		var html = infos[i].substr(-6) == "(html)";
+		if (html) infos[i] = infos[i].substr(0, infos[i].length - 6);
+		var info = infos[i].split(".");
+		if (info[0] != node.nodeName || (info[1] != undefined && node.attributes[info[1]] == undefined)) continue;
+		if (info[1] != undefined) node.attributes[info[1]] = ChangeFileInfo(html, change, node.attributes[info[1]]);
+		else node.firstChild.nodeValue = ChangeFileInfo(html, change, node.firstChild.nodeValue);
+	}
+	for (var i = 0; i < node.childNodes.length; i++) {
+		ChangeXMLFileInfo(node.childNodes[i], change, infostr);
+	}
+}
+
+function ChangeFileInfo(html, change, data) {
+	return html? GetHtmlChangePath(change, data): change(data);
+}
+
+//******************************************************************************
+// Hàm cho biết có sử dụng một mục nào đó có dùng bộ gõ tiếng Việt hay không,
+//   để khi đóng gói thì copy file Vnkey.swf theo
+// Tác dụng: Đọc thông tin trong infostr dạng "name.attr.value", nếu node có
+//   tên là name, thuộc tính attr bằng value thì là có dùng bộ gõ tiếng Việt
+//******************************************************************************
+
+function GetXMLUsingKB(node, infostr) {
+	if (infostr == undefined) return false;
+	if (infostr == "") return true;
+	var infos = infostr.split(";");
+	for (var i = 0; i < infos.length; i++) {
+		var info = infos[i].split(".");
+		if (info[0] == node.nodeName && node.attributes[info[1]] == info[2]) return true;
+	}
+	for (var i = 0; i < node.childNodes.length; i++) {
+		if (GetXMLUsingKB(node.childNodes[i], infostr)) return true;
+	}
+	return false;
+}
+
+//******************************************************************************
+// Hàm thay đổi các đường dẫn nếu có trong các tham số của Layout
+// Tác dụng: Lấy danh sách tham số Layout, duyệt các tham số, nếu kiểu là
+// dạng file name thì thay đổi
+//******************************************************************************
+
+function ChangeLayoutFileParam(node, change) {
+	var layout = node.attributes.Layout;
+	var paramStr = "";
+	var layoutInfo = layoutXML.firstChild.childNodes;
+	for (var i = 0; i < layoutInfo.length; i++) 
+		if (layout == layoutInfo[i].attributes.file)
+			paramStr = layoutInfo[i].attributes.param;
+
+	var a = paramStr.split("|");
+	for (var i = 0; i < a.length; i++) {
+		var b = a[i].split(",");
+		if (b[1] == "ImageFile" && dataXML.firstChild.attributes[b[0]])
+			node.attributes[b[0]] = change(dataXML.firstChild.attributes[b[0]]);
+	}
+}
+
+
+//******************************************************************************
+// Hàm xử lý add thêm common library vào danh sách
+// Tác dụng: Duyệt trường commonLib của XML, nếu không thấy có libName thì
+// add thêm vào
+//******************************************************************************
+
+function AddCommonLib(xml, libName) {
+	if (!libName) return;
+	var libs = xml.firstChild.attributes.commonLib? xml.firstChild.attributes.commonLib.split(","): new Array();
+	for (var i = 0; i < libs.length; i++) if (libs[i] == libName) return;
+	libs.push(libName);
+	AddToList(appPath + commonLibDir + slash + libName, "COMMON_FILE");
+	xml.firstChild.attributes.commonLib = libs.join(",");
+}
+
+//******************************************************************************
+// Hàm xử lý bớt đi common library từ trong danh sách
+// Tác dụng: Duyệt trường commonLib của XML, nếu thấy có libName thì bỏ đi
+//******************************************************************************
+
+function RemoveCommonLib(xml, libName) {
+	if (!xml.firstChild.attributes.commonLib) return;
+	var libs = xml.firstChild.attributes.commonLib.split(",");
+	for (var i = 0; i < libs.length; i++) if (libs[i] == libName) break;
+	if (i == libs.length) return;
+	libs.splice(i, 1);
+	if (libs.length > 0) xml.firstChild.attributes.commonLib = libs.join(",");
+	else delete xml.firstChild.attributes.commonLib;
+}
+
+//******************************************************************************
+// Hàm ghi các thông tin cấu hình vào Cookies
+// Tác dụng: Dùng đối tượng ShareObject của Flash để ghi vào file sau đây
+//   C:\Documents and Settings\Administrator\Application Data\Macromedia\
+//   Flash Player\localhost\...\Violet.sol
+//******************************************************************************
+
+function SaveConfig()
+{
+	var configSO = SharedObject.getLocal("Violet");
+	configSO.data.windowState = windowState;
+	configSO.data.windowTop = windowTop;
+	configSO.data.windowLeft = windowLeft;
+	configSO.data.windowRight = windowRight;
+	configSO.data.windowBottom = windowBottom;
+	configSO.data.flashViewMode = flashViewMode;
+	configSO.data.language = language;
+	configSO.data.vietType = vietType;
+	configSO.data.cfgUseSnap = cfgUseSnap;
+	configSO.data.cfgShowGrid = cfgShowGrid;
+	configSO.data.cfgGridWidth = cfgGridWidth;
+	configSO.data.cfgVideoFormat = cfgVideoFormat;
+	configSO.data.libPath1 = libraryPaths.attributes.libPath + "|" + libraryPaths.attributes.libCurrentSelected + "|" + libraryPaths.attributes.libCurrentPage;
+	configSO.data.libPath2 = lecturePaths.attributes.libPath + "|" + lecturePaths.attributes.libCurrentSelected + "|" + lecturePaths.attributes.libCurrentPage;
+	configSO.data.fullscreen = btnSceneBkGnd._visible;
+	if(usingNum != 200) configSO.data.remainNum = usingNum;
+	configSO.flush();
+	delete configSO;
+}
+
+//******************************************************************************
+// Hàm đọc các thông tin cấu hình trong Cookies ra các biến tương ứng
+// Tác dụng: Dùng đối tượng ShareObject của Flash để đọc từ file cấu hình mà
+// hàm SaveConfig ghi ra, sau đó thiết lập chương trình theo các thông tin này
+//******************************************************************************
+
+function LoadConfig()
+{
+	windowState = 3;
+	windowTop = 0;
+	windowLeft = 0;
+	windowRight = 0;
+	windowBottom = 0;
+	flashViewMode = "original size";
+
+	cfgUseSnap = true;
+	cfgShowGrid = true;
+	cfgGridWidth = 10;
+	cfgVideoFormat = "flv";
+	
+	var configSO = SharedObject.getLocal("Violet");
+	for( var a in configSO.data ) {
+		if( a == "windowState" ) windowState = configSO.data[a];
+		if( a == "windowTop" ) windowTop = configSO.data[a];
+		if( a == "windowLeft" ) windowLeft = configSO.data[a];
+		if( a == "windowRight" ) windowRight = configSO.data[a];
+		if( a == "windowBottom" ) windowBottom = configSO.data[a];
+		if( a == "flashViewMode" ) SetFlashViewMode(configSO.data[a]);
+		if( a == "language" ) language = configSO.data[a];
+		if( a == "vietType" ) vietType = configSO.data[a];
+		if( a == "cfgUseSnap" ) cfgUseSnap = configSO.data[a];
+		if( a == "cfgShowGrid" ) cfgShowGrid = configSO.data[a];
+		if( a == "cfgGridWidth" ) cfgGridWidth = configSO.data[a];
+		if( a == "cfgVideoFormat" ) cfgVideoFormat = configSO.data[a];
+		if( a == "libPath1" ) libPath1 = configSO.data[a].split("|");
+		if( a == "libPath2" ) libPath2 = configSO.data[a].split("|");
+		if( a == "fullscreen" ) fullscreen = configSO.data[a];
+		if( a == "remainNum" ) remainNum = configSO.data[a];
+	}
+	delete configSO;
+
+	if( remainNum != undefined && usingNum != 200 && Number(remainNum) <= Number(usingNum) )
+		fscommand("bug", "");
+
+	if( flashViewMode == "original size" ) mnuWindow.getItemAt(2).attributes.selected = true;
+	if( flashViewMode == "full size" ) mnuWindow.getItemAt(3).attributes.selected = true;
+	if (!webbase) fscommand("Set State", "");
+}
