using System; using System.Collections.Generic; using System.Xml; using System.Drawing; using System.Globalization; using System.IO; using System.Text; using SMath.Manager; using SMath.Controls; using SMath.Drawing; namespace XMCDFileType { public class OpenSaveXMCD : IPluginOpenFileTypes, IPluginSaveFileTypes { private PrintPageModel globalpageModel = new PrintPageModel(); private List errStrings = new List(); private Settings mcadSettings = new Settings(); #region XMCD file open methods private void OpenXMCD(FileContext context, XmlReader Reader, ref int errorsCount, ref int yAdd, RegionsList controls, Dictionary binaryItems) { int regions = 0; List globalVars = new List(); List TextStyles = new List(); while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "pointReleaseData" || Reader.Name == "metadata" || Reader.Name == "binaryContent")) { Reader.Skip(); } else if (Reader.NodeType == XmlNodeType.EndElement && (Reader.Name == "regions" || Reader.Name == "area")) { regions--; if (regions < 0) return; else break; } // added to read the styles from the settings element else if (Reader.Name == "settings") { Styles style = new Styles(); string text = ""; if (Reader.NodeType == XmlNodeType.EndElement) continue; while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "settings") break; if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "textStyle") { TextStyles.Add(style); style = new Styles(); continue; } if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "textStyle") { style.name = Reader.GetAttribute("name"); } if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "inlineAttr") { style.fontfamily = Reader.GetAttribute("font-family"); Int32.TryParse(Reader.GetAttribute("font-size"), out style.fontsize); if (Reader.GetAttribute("font-weight").ToLower() == "bold") style.bold = true; if (Reader.GetAttribute("font-style").ToLower() == "italic") style.italics = true; if (Reader.GetAttribute("underline").ToLower() == "true") style.underline = true; } if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "pageModel") { globalpageModel.width = Convert.ToInt16(Math.Floor(Convert.ToDouble(Reader.GetAttribute("page-width").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem)))); globalpageModel.height = Convert.ToInt16(Math.Floor(Convert.ToDouble(Reader.GetAttribute("page-height").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem)))); globalpageModel.paper_code = Reader.GetAttribute("paper-code"); globalpageModel.orientation = Reader.GetAttribute("orientation"); } if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "margins") { globalpageModel.margins.left = Convert.ToInt16(Math.Floor(Convert.ToDouble(Reader.GetAttribute("left").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem)))); globalpageModel.margins.right = Convert.ToInt16(Math.Floor(Convert.ToDouble(Reader.GetAttribute("right").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem)))); globalpageModel.margins.top = Convert.ToInt16(Math.Floor(Convert.ToDouble(Reader.GetAttribute("top").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem)))); globalpageModel.margins.bottom = Convert.ToInt16(Math.Floor(Convert.ToDouble(Reader.GetAttribute("bottom").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem)))); } // // For now I read and store this. If not saved as .xmcd this data is lost. // Although I see "TheWizEd" is working on a "header/footer" region. Maybe I will be able to use that region for this data // at some point in the future. // if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "header" && !Reader.IsEmptyElement) { while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "header") break; if (Reader.Name == "footer") break; if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "left") { globalpageModel.header.left = text; text = ""; continue; } if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "center") { globalpageModel.header.center = text; text = ""; continue; } if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "right") { globalpageModel.header.right = text; text = ""; continue; } if (Reader.HasValue) text += Reader.Value; } } if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "footer" && !Reader.IsEmptyElement) { while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "footer") break; if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "left") { globalpageModel.footer.left = text; text = ""; continue; } if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "center") { globalpageModel.footer.center = text; text = ""; continue; } if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "right") { globalpageModel.footer.right = text; text = ""; continue; } if (Reader.HasValue) text += Reader.Value; } } if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "colorModel") { text = Reader.GetAttribute("default-highlight-color"); if (text.Length == 7) mcadSettings.defaultHighlightColor = text; text = Reader.GetAttribute("background-color"); if (text.Length == 7) mcadSettings.defaultBackgroundColor = text; } } } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "region") { regions++; int left, top, width, height, CLR2 = SMath.Drawing.Graphics.WebColorToColor(mcadSettings.defaultBackgroundColor); bool border, highlight; string debug, regionID = Reader.GetAttribute("region-id"), bgcolor = ""; // changed 1.28 to 1.395 and then moved this value into a variable for easier use. width = (int)(mcadSettings.scaleFactor * Convert.ToDouble(Reader.GetAttribute("width").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem))); height = (int)(mcadSettings.scaleFactor * Convert.ToDouble(Reader.GetAttribute("height").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem))); left = (int)(mcadSettings.scaleFactor * Convert.ToDouble(Reader.GetAttribute("left").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem))); top = (int)(mcadSettings.scaleFactor * Convert.ToDouble(Reader.GetAttribute("top").Replace(GlobalProfile.DecimalSymbolStandard, GlobalProfile.DecimalSymbolSystem))) + yAdd; // better way to locate region above // top = GlobalParams.Grider((int)((double)1.28 * Convert.ToDouble(Reader.GetAttribute("align-y").Replace(GlobalParams.DecimalSymbolStandard, GlobalParams.DecimalSymbolSystem))) - height / 2 + yAdd); // better way to retrieve highlight color from mathcad // if (Convert.ToBoolean(Reader.GetAttribute("show-highlight")) && bgcolor != null && bgcolor != "" && bgcolor != "inherit") // CLR2 = SMath.Drawing.Graphics.WebColorToColor(bgcolor); bgcolor = Reader.GetAttribute("background-color"); if (bgcolor.Length == 4) bgcolor = "#fff" + bgcolor.Substring(1); highlight = Convert.ToBoolean(Reader.GetAttribute("show-highlight")); if (highlight && bgcolor == "inherit") { CLR2 = SMath.Drawing.Graphics.WebColorToColor(mcadSettings.defaultHighlightColor.ToString()); } else if (highlight && (bgcolor != null) && (bgcolor != "") && (bgcolor != "inherit")) { CLR2 = SMath.Drawing.Graphics.WebColorToColor(bgcolor.ToString()); } border = Convert.ToBoolean(Reader.GetAttribute("show-border")); // if set tag attribute in .xmcd file to "debug" you can set a breakpoint here and step through debug = Reader.GetAttribute("tag"); if (debug == "debug") Console.WriteLine("debug stop"); while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "region") { regions--; if (regions < 0) return; else break; } if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "rendering" || Reader.Name == "resultFormat")) Reader.Skip(); else if (Reader.Name.ToLower() == "math") { if (Reader.NodeType == XmlNodeType.EndElement) continue; string disableCalc = Reader.GetAttribute("disable-calc"); if (string.IsNullOrEmpty(disableCalc)) disableCalc = "false"; List array = new List(); Stack parentId = new Stack(); List localVars = new List(); try { MathRegion v = new MathRegion(context.SessionProfile); v.ResetColors(context.SessionProfile.Drawing.TextColor, Color.FromArgb(CLR2)); // Parses XML to prefix math expression. RecurseParse(context, v, array, Reader, parentId); // Converts prefix notation to postfix. Term[] res = PrefixToPostfix(array.ToArray()); // Finds all global and local variables to skip trying to convert them into units. if (res[res.Length - 1].Type == TermType.Operator && res[res.Length - 1].Text == Operators.Definition) { Term[][] parts = SMath.Manager.Expression.Split(res, res.Length - 1); if (parts.Length == 2) { if (parts[0].Length == 1) globalVars.Add(parts[0][0].Text); else if (parts[0][parts[0].Length - 1].Type == TermType.Function) { for (int i = 0; i < parts[0].Length - 1; i++) localVars.Add(parts[0][i].Text); } } } // Corrects known inconsistencies between Mathcad and SMath Studio expression notations. for (int i = res.Length - 1; i >= 0; i--) { if (res[i].Type == TermType.Function) { if (res[i].Text == "log" && res[i].ArgsCount == 1) { res[i].Text = Functions.Lg; } if (context.SessionProfile.NamingType != GlobalProfile.namingWorld) { TermInfo info; if (TermInfo.IsPreserved(context.SessionProfile, res[i], out info, true)) { info.NameGuid = context.SessionProfile.NamingType; res[i].Text = info.Text; } } if (res[i].Text == "Γ") { res[i].Text = Functions.Gamma; } else if (res[i].Text == Functions.Nthroot || res[i].Text == Functions.Diff) { int glob; Term[][] temp = Expression.Split(res, i, out glob); if (temp.Length != 2) continue; for (int j = temp.Length - 1; j >= 0; j--) { for (int m = 0; m < temp[j].Length; m++) { res[i - (glob--)] = temp[j][m]; } } } else if (res[i].Text == Functions.Mat) { int glob; Term[][] temp = Expression.Split(res, i, out glob); res[i - 2] = temp[0][0]; res[i - 1] = temp[1][0]; int rows = Convert.ToInt32(temp[0][0].Text), cols = Convert.ToInt32(temp[1][0].Text); for (int j = 0, shift = i - glob; j < temp.Length - 2; j++) { int r = j / cols; int c = j % cols; int ind = r + c * rows + 2; for (int m = 0; m < temp[ind].Length; m++) { res[shift++] = temp[ind][m]; } } } } else if (res[i].Type == TermType.Operand) { bool unitize = true; foreach (string globalVar in globalVars) { if (res[i].Text == globalVar) { unitize = false; break; } } if (!unitize) continue; foreach (string localVar in localVars) { if (res[i].Text == localVar) { unitize = false; break; } } if (!unitize) continue; UnitInfo unitDef; if (UnitsManager.TryGetUnit(context.SessionProfile, Symbols.UnitChar + res[i].Text, out unitDef, true)) res[i].Text = unitDef.Text; } } v.Evaluable = !Convert.ToBoolean(disableCalc); v.Answer.FractionType = GlobalProfile.FractionsTypeNumeric; v.Size = new Size(width, height); v.Border = border; v.Location = new Point(left, top); controls.Push(v); v.Terms = res; } catch (Exception e) { // add a little extra error text string error = ""; error = String.Format("Error while parsing XML math expression: {0} [region-id: {1}] {2}", Reader.Name, regionID, e.Message); errStrings.Add(error); // errorsCount++; Reader.Skip(); } } else if (Reader.Name.ToLower() == "text") // Added text region to interpretations { if (Reader.NodeType == XmlNodeType.EndElement) continue; string text = ""; // default "Normal" Style from MathCad string textstyle = "Normal"; string fontname = "Arial"; int fontsize = 10; bool bold = false; bool underline = false; bool italics = false; TextRegion v = new TextRegion(context.SessionProfile); v.ResetColors(context.SessionProfile.Drawing.TextColor, Color.FromArgb(CLR2)); while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "text") break; if (Reader.NodeType == XmlNodeType.Element && Reader.Name.ToLower() == "p") { textstyle = Reader.GetAttribute("style"); foreach (Styles style in TextStyles) { if (style.name == textstyle) { bold = style.bold; italics = style.italics; underline = style.underline; fontsize = style.fontsize; fontname = style.fontfamily; } } if (string.IsNullOrEmpty(Reader.Value)) { if (text != "") text += "\r"; } else { text += Reader.Value; } continue; } if (Reader.NodeType == XmlNodeType.Element && Reader.Name.ToLower() == "b") { bold = true; } if (Reader.NodeType == XmlNodeType.Element && Reader.Name.ToLower() == "u") { underline = true; } if (Reader.NodeType == XmlNodeType.Element && Reader.Name.ToLower() == "i") { italics = true; } if (Reader.NodeType == XmlNodeType.Element && Reader.Name.ToLower() == "f") { if (Reader.GetAttribute("size") != null) Int32.TryParse(Reader.GetAttribute("size"), out fontsize); } if (!string.IsNullOrEmpty(Reader.Value)) text += Reader.Value; } v.Size = new Size(width, height); v.Border = border; v.Location = new Point(left, top); v.Bold = bold; v.Italic = italics; v.Underline = underline; v.FontHeight = fontsize; v.FontName = fontname; controls.Push(v); v.OnCommandSend(text); } else if (Reader.Name.ToLower() == "area") { if (Reader.NodeType == XmlNodeType.EndElement) continue; string isCollapsed = Reader.GetAttribute("is-collapsed"), showIcon = Reader.GetAttribute("show-icon"); RegionBase v1; if (Worksheet.TryGetRegionByTagName(context.SessionProfile, "area", out v1) && v1 is ISeparatorObject) { v1.ResetColors(context.SessionProfile.Drawing.TextColor, Color.FromArgb(CLR2)); top += height / 2 - 17; if (String.IsNullOrEmpty(isCollapsed)) ((ISeparatorObject)v1).Collapse(false); else { ((ISeparatorObject)v1).Collapse(Convert.ToBoolean(isCollapsed)); if (((ISeparatorObject)v1).Collapsed) top += GlobalProfile.CanvasGridSize / 2; } if (String.IsNullOrEmpty(showIcon)) ((ISeparatorObject)v1).Top = false; else ((ISeparatorObject)v1).Top = Convert.ToBoolean(showIcon); v1.Size = new Size(150, 17); v1.Border = border; v1.Location = new Point(left, top); controls.Push(v1); if (!((ISeparatorObject)v1).Top) continue; int yAddInto = (((ISeparatorObject)v1).Collapsed ? top : 0); OpenXMCD(context, Reader, ref errorsCount, ref yAddInto, controls, binaryItems); RegionBase v2; if (Worksheet.TryGetRegionByTagName(context.SessionProfile, "area", out v2) && v2 is ISeparatorObject) { v2.ResetColors(context.SessionProfile.Drawing.TextColor, Color.FromArgb(CLR2)); ((ISeparatorObject)v2).Collapse(false); ((ISeparatorObject)v2).Top = false; v2.Size = new Size(150, 17); v2.Border = border; v2.Location = new Point(left, top + height); controls.Push(v2); } yAdd += (((ISeparatorObject)v1).Collapsed ? height : 0); } } else { if (Reader.NodeType == XmlNodeType.EndElement) continue; RegionBase region; try { if (Worksheet.TryGetRegionByTagName(context.SessionProfile, Reader.Name.ToLower(), out region)) { if (Reader.Name.ToLower() == "picture") { while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "png") { string binnary = binaryItems[Reader.GetAttribute("item-idref")]; var image = Base64StringToImage(binnary); if ((((double)image.Width / (double)width) > 1.05)) { // scale image to fit dimensions var bmp = SMath.Drawing.Graphics.Specifics.CreateBitmap(width, height); using (var g = SMath.Drawing.Graphics.Specifics.GraphicsFromBitmap(bmp)) g.DrawImage(image, new Rectangle(0, 0, width, height), new RectangleF(0, 0, image.Width, image.Height)); binnary = ImageToBase64String(bmp, BitmapFormat.Png); } string rawXml = String.Empty; using (var writer = new MemoryStream()) using (var xmlWriter = XmlWriter.Create(writer)) { xmlWriter.WriteStartElement("picture"); xmlWriter.WriteStartElement("raw"); xmlWriter.WriteAttributeString("format", "png"); xmlWriter.WriteAttributeString("encoding", "base64"); xmlWriter.WriteRaw(binnary); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.Flush(); writer.Position = 0; rawXml = Encoding.UTF8.GetString(writer.ToArray()); } var properties = new PropertiesReader(); var storage = new StorageReader(properties, "picture", rawXml); region.FromXml(storage, new FileParsingContext(context.SessionProfile)); } else if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "picture") break; } } else { var properties = new PropertiesReader(Reader); var storage = new StorageReader(properties, "picture", Reader.ReadOuterXml()); Reader.MoveToElement(); region.FromXml(storage, new FileParsingContext(context.SessionProfile)); } region.ResetColors(context.SessionProfile.Drawing.TextColor, Color.FromArgb(CLR2)); region.Border = border; // tweaked size by 1 pixel region.Size = new Size(width + 1, height + 1); region.Location = new Point(left, top); if (region is RegionTranslatable) ((RegionTranslatable)region).SetCurrentValue(); controls.Push(region); } } catch { region = null; } if (region == null) { string error = ""; error = String.Format("Error parsing Text, Area, or Custom Region: {0} [region-id: {1}].", Reader.Name, regionID); errStrings.Add(error); errorsCount++; Reader.Skip(); } } } } } } private void AddTermArgument(List array, int pos) { #pragma warning disable 618 array[pos].ChildCount++; // To find a way overcome this issue #pragma warning restore 618 } private bool intoApplyTag; private void RecurseParse(FileContext context, MathRegion region, List array, XmlReader Reader, Stack parentId) { while (Reader.Read()) { Reader.MoveToContent(); if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "result") { Reader.Skip(); return; } else if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "ml:symResult" || Reader.Name == "resultFormat")) { Reader.Skip(); return; } else if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "originRef" || Reader.Name == "parentRef" || Reader.Name == "comment" || Reader.Name == "originComment" || Reader.Name == "contentHash")) { Reader.Skip(); } else if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "ml:apply" || Reader.Name == "ml:function")) { // Means that next term will be a function intoApplyTag = true; RecurseParse(context, region, array, Reader, parentId); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:unitOverride") { array.Add(new Term(Symbols.EmptyOperand, TermType.Operand, 0)); array.Insert(0, new Term(Operators.NumericEqual, TermType.Operator, 2)); RecurseParse(context, region, array, Reader, parentId); array.Insert(0, new Term(Operators.UnitOperator, TermType.Operator, 2)); } else if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "ml:lambda" || Reader.Name == "ml:sequence" || Reader.Name == "ml:eval" || Reader.Name == "ml:symEval" || Reader.Name == "ml:boundVars" || Reader.Name == "ml:provenance")) { RecurseParse(context, region, array, Reader, parentId); } else if (Reader.NodeType == XmlNodeType.EndElement && (Reader.Name == "ml:apply" || Reader.Name == "ml:matrix" || Reader.Name == "ml:define" || Reader.Name == "ml:parens" || Reader.Name == "ml:range" || Reader.Name == "ml:function")) { parentId.Pop(); if (parentId.Count != 0) AddTermArgument(array, parentId.Peek()); return; } else if (Reader.NodeType == XmlNodeType.EndElement && (Reader.Name == "math" || Reader.Name == "ml:lambda" || Reader.Name == "ml:sequence" || Reader.Name == "ml:boundVars" || Reader.Name == "ml:provenance" || Reader.Name == "ml:unitOverride")) { return; } else if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "ml:eval") { // Check if Unit tag already inserted an eval operator. region.Optimization = OptimizationType.Numeric; // default should be Numeric. if (array.Count < 1 || array[0].Type != TermType.Operator || array[0].Text != Operators.UnitOperator) { array.Add(new Term(Symbols.EmptyOperand, TermType.Operand, 0)); array.Insert(0, new Term(Operators.NumericEqual, TermType.Operator, 2)); region.Optimization = OptimizationType.Numeric; } return; } else if (Reader.NodeType == XmlNodeType.EndElement && Reader.Name == "ml:symEval") { // Check if Unit tag already inserted an eval operator. if (array.Count < 1 || array[0].Type != TermType.Operator || array[0].Text != Operators.UnitOperator) { array.Add(new Term(Symbols.EmptyOperand, TermType.Operand, 0)); array.Insert(0, new Term(Operators.NumericEqual, TermType.Operator, 2)); region.Optimization = OptimizationType.Symbolic; } return; } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:matrix") { array.Add(new Term(Functions.Mat, TermType.Function, 2)); parentId.Push(array.Count - 1); array.Add(new Term(Reader.GetAttribute("rows"), TermType.Operand, 0)); array.Add(new Term(Reader.GetAttribute("cols"), TermType.Operand, 0)); RecurseParse(context, region, array, Reader, parentId); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:derivative") { array.Add(new Term("diff", TermType.Function, 0)); parentId.Push(array.Count - 1); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:range") { array.Add(new Term("range", TermType.Function, 0)); parentId.Push(array.Count - 1); RecurseParse(context, region, array, Reader, parentId); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:define") { array.Add(new Term(Operators.Definition, TermType.Operator, 0)); parentId.Push(array.Count - 1); RecurseParse(context, region, array, Reader, parentId); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:parens") { array.Add(new Term(Brackets.LeftVisible, TermType.Bracket, 0)); parentId.Push(array.Count - 1); RecurseParse(context, region, array, Reader, parentId); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:real") { Reader.Read(); Reader.MoveToContent(); if (Reader.Value.StartsWith(Operators.Subtraction)) { array.Add(new Term(Operators.Subtraction, TermType.Operator, 1)); } array.Add(new Term(Reader.Value.TrimStart('-'), TermType.Operand, 0)); if (parentId.Count != 0) AddTermArgument(array, parentId.Peek()); Reader.Read(); Reader.MoveToContent(); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:imag") { Reader.Read(); Reader.MoveToContent(); string Value = Reader.Value; if (Value.StartsWith(Operators.Subtraction)) { array.Add(new Term(Operators.Subtraction, TermType.Operator, 1)); } Value = Reader.Value.TrimStart('-'); if (Value == "1") array.Add(new Term(Symbols.ImaginaryUnit, TermType.Operand, 0)); else { array.Add(new Term(Operators.Multiplication, TermType.Operator, 2)); array.Add(new Term(Value.TrimStart('-'), TermType.Operand, 0)); array.Add(new Term(Symbols.ImaginaryUnit, TermType.Operand, 0)); } if (parentId.Count != 0) AddTermArgument(array, parentId.Peek()); Reader.Read(); Reader.MoveToContent(); } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:placeholder") { array.Add(new Term(Symbols.EmptyOperand, TermType.Operand, 0)); if (parentId.Count != 0) AddTermArgument(array, parentId.Peek()); } else { if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:id") { // fixed so that the subscript is interpreted correctly!!!! int i = 0; bool percentFlag = false; int operandLength = 0; char[] operand_byteArray = null; string operand = ""; string subscript = ""; // Get the subscript if it exists subscript = Reader.GetAttribute("subscript"); Reader.Read(); operandLength = Reader.Value.Length; operand_byteArray = new char[operandLength + 1]; operand_byteArray = Reader.Value.ToCharArray(); for (i = 0; i < operandLength; i++) { // can replace problem characters in variable names here if (operand_byteArray[i] == '’') // problems with this char operand_byteArray[i] = '`'; // replaced it with the grave char if (operand_byteArray[i] == '%') // problems with this char percentFlag = true; } string str = new string(operand_byteArray).Substring(0, i); // MathCAD allows i as a variable // SMath does not allow imaginary #'s and i as a variable at the same time. // So, replace variable "i" with "i_" if ((operandLength == 1) && (operand_byteArray[0] == 'i')) str = str + "_"; // replace % with Percent" if (percentFlag) str = str.Replace("%", "Percent"); if (subscript != null) operand = str + GlobalProfile.DecimalSymbolStandard + subscript; else operand = str; if (!intoApplyTag) array.Add(new Term(operand, TermType.Operand, 0)); else array.Add(new Term(operand, TermType.Function, 0)); Reader.Read(); if (!intoApplyTag) { if (parentId.Count != 0) AddTermArgument(array, parentId.Peek()); continue; } } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:str") { Reader.Read(); array.Add(new Term("\"" + Reader.Value + "\"", TermType.Operand, 0)); Reader.Read(); if (parentId.Count != 0) AddTermArgument(array, parentId.Peek()); continue; } else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:unknownOp") array.Add(new Term(Operators.EmptyOperator, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:equal") array.Add(new Term(Operators.BooleanEqual, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:lessThan") array.Add(new Term(Operators.BooleanLess, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:greaterThan") array.Add(new Term(Operators.BooleanMore, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:lessOrEqual") array.Add(new Term(Operators.BooleanLessOrEqual, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:greaterOrEqual") array.Add(new Term(Operators.BooleanMoreOrEqual, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:notEqual") array.Add(new Term(Operators.BooleanNotEqual, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:not") array.Add(new Term(Operators.BooleanNot, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:and") array.Add(new Term(Operators.BooleanAnd, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:or") array.Add(new Term(Operators.BooleanOr, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:xor") array.Add(new Term(Operators.BooleanXor, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:factorial") array.Add(new Term(Operators.Factorial, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:plus") array.Add(new Term(Operators.Composition, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && (Reader.Name == "ml:minus" || Reader.Name == "ml:neg")) array.Add(new Term(Operators.Subtraction, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:mult") array.Add(new Term(Operators.Multiplication, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:div") array.Add(new Term(Operators.Division, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:pow") array.Add(new Term(Operators.Exponentiation, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:crossProduct") array.Add(new Term(Operators.VectorMultiplication, TermType.Operator, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:absval") array.Add(new Term(Functions.Abs, TermType.Function, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:sqrt") array.Add(new Term(Functions.Sqrt, TermType.Function, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:nthRoot") array.Add(new Term(Functions.Nthroot, TermType.Function, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:transpose") array.Add(new Term(Functions.Transpose, TermType.Function, 0)); else if (Reader.NodeType == XmlNodeType.Element && Reader.Name == "ml:determinant") array.Add(new Term(Functions.Det, TermType.Function, 0)); else { intoApplyTag = false; throw new NotSupportedException(); } parentId.Push(array.Count - 1); } intoApplyTag = false; } } private XmlAttribute CreateXMLAttribute(string name, string value, XmlDocument doc, XmlNode node) { XmlAttribute attribute = doc.CreateAttribute(name); attribute.Value = value; node.Attributes.Append(attribute); return attribute; } #endregion #region XMCD file save methods private readonly string uri1 = "http://schemas.mathsoft.com/worksheet30", uri2 = "http://schemas.mathsoft.com/math30"; public void SaveToXMCD(FileContext context, XmlTextWriter writer, ref int errorsCount, RegionsEnumerator enumerator) { writer.Formatting = Formatting.Indented; writer.WriteStartDocument(true); // for xml binaryContent Dictionary binaryItems = new Dictionary(); XmlDocument doc = new XmlDocument(); string settings = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + //"" + //"" + //"
" + //"