// // ORIGINAL CODE BASE IS Copyright (C) 2006-2010 by Alphons van der Heijden. // The code was donated on 2010-04-28 by Alphons van der Heijden to Brandon 'Dimentox Travanti' Husbands & // Malcolm J. Kudra, who in turn License under the GPLv2 in agreement with Alphons van der Heijden's wishes. // // The community would like to thank Alphons for all of his hard work, blood sweat and tears. Without his work // the community would be stuck with crappy editors. // // The source code in this file ("Source Code") is provided by The LSLEditor Group to you under the terms of the GNU // General Public License, version 2.0 ("GPL"), unless you have obtained a separate licensing agreement ("Other // License"), formally executed by you and The LSLEditor Group. // Terms of the GPL can be found in the gplv2.txt document. // // GPLv2 Header // ************ // LSLEditor, a External editor for the LSL Language. // Copyright (C) 2010 The LSLEditor Group. // // 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // ******************************************************************************************************************** // The above copyright notice and this permission notice shall be included in copies or substantial portions of the // Software. // ******************************************************************************************************************** // // // // This class is used to convert LSLI to LSL and the other way around. // using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace LSLEditor.Helpers { class LSLIConverter { private EditForm editForm; private const string BEGIN = "//@BEGIN"; private const string END = "//@END"; private static List validExtensions = new List(3) { "lsl", "lsli", "LSL", "LSLI" }; public const string EXPANDED_SUBEXT = ".expanded"; public const string LSL_EXT = ".lsl"; public const string LSLI_EXT = ".lsli"; public LSLIConverter() { } /// /// Creates a new path and name from the original path and name based on the editForm. /// E.g. turns path/to/file.lsli into path/to/file.expanded.lsl /// /// New path and scriptname public string CreateExpandedPathAndScriptName() { string nameExpanded = editForm.Text.Remove(editForm.ScriptName.Length - 4, 4).TrimEnd(' ') + EXPANDED_SUBEXT + LSL_EXT; nameExpanded = nameExpanded.IndexOf('*') > -1 ? nameExpanded.Remove(nameExpanded.IndexOf('*'), 1) : nameExpanded; return editForm.FullPathName.Remove(editForm.FullPathName.Length - 4, 4) + EXPANDED_SUBEXT + LSL_EXT; } /// /// Creates a relative path between two paths /// /// The file or folder to create a relative path towards /// The base folder /// private string GetRelativePath(string filespec, string folder) { filespec = Path.GetFullPath(filespec); if(validExtensions.Contains(filespec.Substring(filespec.LastIndexOf(".") + 1))) { int lastIndexOfSeperator = filespec.LastIndexOf('\\') > filespec.LastIndexOf('/') ? filespec.LastIndexOf('\\') : filespec.LastIndexOf('/'); filespec = filespec.Remove(lastIndexOfSeperator); } Uri pathUri = new Uri(filespec); // Folders must end in a slash if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString())) { folder += Path.DirectorySeparatorChar; } Uri folderUri = new Uri(folder); string relativePath = Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace('/', Path.DirectorySeparatorChar)); if (relativePath.Substring(relativePath.Length - 3) != Path.DirectorySeparatorChar.ToString()) { relativePath += Path.DirectorySeparatorChar; } return relativePath; } /// /// Creates a new line in the context after another line /// /// /// /// /// Context with the new line private StringBuilder WriteAfterLine(StringBuilder context, string newLine, string lineBefore) { int includeIndex = context.ToString().LastIndexOf(lineBefore) + lineBefore.Length; string hasSeperator = lineBefore.Substring(lineBefore.Length - 1, 1); if (hasSeperator != "\n") { newLine = "\n" + newLine; } hasSeperator = newLine.Substring(newLine.Length - 1, 1); if (hasSeperator != "\n") { newLine += "\n"; } context.Insert(includeIndex, newLine); return context; } /// /// Imports scripts from //@include statements /// /// Sourcecode to work with /// Path of the source code of the script /// Sourcecode with imported scripts private string ImportScripts(string strC, string pathOfScript) { StringBuilder sb = new StringBuilder(strC); string includeMatch = "([\n]|^)+//@include\\(\".*?\"\\)(\\s\\w)?"; // OLD (\n|^)+//@include\\(\".*?\"\\)(\\s?)+(\n|$) MATCHES ONLY 1 INCLUDE MatchCollection mIncludes = Regex.Matches(strC, includeMatch); // Find includes foreach (Match m in mIncludes) { string line = m.Value; string pathOfInclude = Regex.Match(line, "\".*?\"").Value.Trim('"'); int lastIndexOfLine = line.LastIndexOf("\n") > -1 && line.LastIndexOf("\n") > line.LastIndexOf(")") ? line.LastIndexOf("\n") + 1 : line.Length; // Trim end of string if if (line.Substring(line.Length - 1, 1) != "\n" && line.Substring(line.Length - 1, 1) != ")") { line = line.Remove(line.Length - 1); } string ext = pathOfInclude.Substring(pathOfInclude.LastIndexOf(".") + 1); if (validExtensions.Contains(ext)) { // If path is relative if(!Path.IsPathRooted(pathOfInclude)) { pathOfInclude = GetRelativePath(pathOfScript, Environment.CurrentDirectory) + pathOfInclude; } sb = this.WriteAfterLine(sb, BEGIN, line); string script = ""; if (File.Exists(pathOfInclude)) { // Insert included script using (StreamReader sr = new StreamReader(pathOfInclude)) { string scriptRaw = sr.ReadToEnd(); // If there are includes in the included script if (Regex.IsMatch(strC, includeMatch)) { // TODO: Kijk voor alle matches, niet alleen 1 match AT: VOLGENS MIJ GEBEURD DIT AL? //Match mInclude = Regex.Match(strC, includeMatch); // Find includes //string IncludePath = Regex.Match(mInclude.ToString(), "\".*?\"").Value.Trim('"'); // Then import these scripts too script = "\n" + ImportScripts(scriptRaw, pathOfInclude) + "\n"; } } } this.WriteAfterLine(sb, script, BEGIN + "\n"); this.WriteAfterLine(sb, END, script); } } return sb.ToString(); } /// /// Main function of the class. Call this to expand LSLI to LSL /// /// /// LSL public string ExpandToLSL(EditForm editForm) { this.editForm = editForm; string sourceCode = ImportScripts(editForm.SourceCode, editForm.FullPathName); return sourceCode; } } }