Example #1
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;
        }
Example #2
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            var tempDocument = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            var outputFilenames = new List<string>();

            foreach (Document.Item item in tempDocument.Items)
            {
                var resItem = Host.GetResource(item.ResourceID);
                var resFileInfo = Host.GetFileInfo( resItem );
                var outputFilename = resFileInfo.Name;

                string outputFilenameBin = outputFilename + ".bin";
                outputFilenames.Add(outputFilenameBin);
            }

            Host.RefreshOutput(resource, outputFilenames);
        }
Example #3
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;

            lvFiles.Clear();
            lvFiles.Columns.Add("Filename", 172);
            lvFiles.Columns.Add("WidthCPC", 64);
            lvFiles.Columns.Add("Width", 30);
            lvFiles.Columns.Add("Height", 30);

            lvPalette.Clear();
            lvPalette.Columns.Add("Pen", 100);
            lvPalette.Columns.Add("Color", 100);
            lvPalette.Columns.Add("Gate Array", 100);

            cbMode.Items.Clear();
            cbMode.Items.Add("MODE0");
            cbMode.Items.Add("MODE1");
            cbMode.Items.Add("MODE2");

            RefreshProperties();
        }
Example #4
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            Document.Document document = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            if (document is Document.Document)
            {
                List<string> outputFilenames = new List<string>();

                string outputFilename = fileInfo.Name + ".bin";
                outputFilenames.Add( outputFilename );

                Host.RefreshOutput(resource, outputFilenames);
            }
        }
Example #5
0
        public List<int> GetBrokenResourceIDs(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return null;
            }

            if (!fileInfo.Exists)
            {
                return null;
            }

            List<int> brokenResourceIDs = new List<int>();

            Document.Document document = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            if (document != null)
            {
                foreach (Document.Item item in document.Items)
                {
                    if (Host.GetResource(item.ResourceID) == null)
                    {
                        brokenResourceIDs.Add(item.ResourceID);
                    }
                }
            }

            return brokenResourceIDs;
        }
Example #6
0
        public void UpdateDependencies(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            List<PhactoryHost.Database.Resource> dependentResources = new List<PhactoryHost.Database.Resource>();

            Document.Document document = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            if (document is Document.Document)
            {
                foreach (Document.Item item in document.Items)
                {
                    PhactoryHost.Database.Resource depResource = Host.GetResource(item.ResourceID);
                    if ( (depResource!=null) && (resource.Id != depResource.Id) )
                    {
                        dependentResources.Add(depResource);
                    }
                }
            }

            Host.RefreshDependencies(resource, dependentResources);
        }
Example #7
0
        public bool Run(PhactoryHost.Database.Resource resource)
        {
            PhactoryHost.Database.Resource parentResource = Host.GetResource(resource.IdDependencies[0]);

            Document.Document document = Host.XMLRead<Document.Document>(Host.GetFileInfo(parentResource).FullName);

            string fileToExecute = "";
            foreach (Document.Item item in document.Items)
            {
                if (item.ExecAdress != 0)
                {
                    fileToExecute = item.AmsdosFilename;
                }
            }

            string DSKFilename = Host.GetFileInfo(resource).FullName;
            DSKFilename = DSKFilename.Replace(".cpcdsk", ".dsk");

            FileInfo DSKFileInfo = new FileInfo(DSKFilename);

            string WinAPEFullPath = Host.GetPluginsPath() + "WinAPE.exe";

            string arguments = "\"" + DSKFileInfo.FullName + "\" /A";

            if (Host.IsVerboseOutput())
            {
                Host.Log(WinAPEFullPath + " " + arguments);
            }

            return Host.StartAndWaitAfterProcess(WinAPEFullPath, arguments, DSKFileInfo.DirectoryName);
        }
Example #8
0
        public static bool CheckIfResourceCanBeRemoved(PhactoryHost.Database.Resource resource)
        {
            if (resource.IsOutputResource)
            {
                string errorMessage = "Can not remove '" + resource.DisplayName + "' because it's an output resource";

                App.Controller.Log.Append(errorMessage);
                App.Controller.View.ShowErrorMessage("Can't remove resource", errorMessage);

                return false;
            }

            List<PhactoryHost.Database.Resource> resourceDependencies = GetDependentResources(resource);
            if (resourceDependencies.Count != 0)
            {
                string errorMessage = "Can not remove '" + resource.DisplayName + "' because it's referenced by :\n";
                errorMessage += "\n";
                foreach (PhactoryHost.Database.Resource res in resourceDependencies)
                {
                    errorMessage += "'" + res.DisplayName + "'\n";
                }

                App.Controller.Log.Append(errorMessage);
                App.Controller.View.ShowErrorMessage("Can't remove resource", errorMessage);

                return false;
            }

            return true;
        }
Example #9
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            if ( (fileInfo.Extension.ToLower() != ".c") && (fileInfo.Extension.ToLower() != ".asm"))
            {
                // only compiles .ASM and .C files (ignore .H)
                return;
            }

            List<string> outputFilenames = new List<string>();

            if (fileInfo.Extension.ToLower() == ".c")
            {
                // check that .c file is not an include from an other .c file
                // (in that case, skip compile)
                foreach (PhactoryHost.Database.Resource resourceDependency in Host.GetDependencyResources(resource))
                {
                    FileInfo parentFileInfo = Host.GetFileInfo(resourceDependency);
                    if (parentFileInfo.Extension.ToLower() == ".c")
                    {
                        return;
                    }
                }

                string outputFilename = fileInfo.Name;
                outputFilename = outputFilename.Replace(".c", ".asm");
                outputFilename = outputFilename.Replace(".C", ".ASM");

                outputFilenames.Add(outputFilename);
            }

            if (fileInfo.Extension.ToLower() == ".asm")
            {
                string outputFilename = fileInfo.Name;
                outputFilename = outputFilename.Replace(".asm", ".bin");
                outputFilename = outputFilename.Replace(".ASM", ".BIN");

                outputFilenames.Add(outputFilename);
            }

            Host.RefreshOutput(resource, outputFilenames);
        }
Example #10
0
        public bool Compile(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return false;
            }

            if (!IsResourceSupported(resource))
            {
                return false;
            }

            List<String> resourceFilenames = new List<String>();
            List<String> paddingFilenames = new List<String>();
            List<int> address = new List<int>();

            Document.Document document = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            if ( document == null )
            {
                return false;
            }

            document.Expand();

            foreach (Document.File file in document.Files)
            {
                PhactoryHost.Database.Resource iResource = Host.GetResource( file.ResourceID );
                if (iResource == null)
                {
                    Host.Log("Unknown resource identifier : " + file.ResourceID);
                    return false;
                }

                FileInfo iFileInfo = Host.GetFileInfo( iResource );

                resourceFilenames.Add(iFileInfo.FullName);
                paddingFilenames.Add(file.Pad256 ? "true" : "false");
                address.Add((file.SetAddress==false)?0:file.Address);
            }

            var compiler = new Phactory.Modules.BigFile.Compiler.BigFileCompiler();

            string resourceRelativePathNoExt = resource.RelativePath;
            resourceRelativePathNoExt = resourceRelativePathNoExt.Replace(".cpcbigfile", "");

            App.Controller.View.AppDoEvents();

            string baseFilename = Host.MakeFullPath(resourceRelativePathNoExt);
            string headerFilename = Host.MakeFullPath(resourceRelativePathNoExt + ".H");
            if (!compiler.Compile(baseFilename, headerFilename, resourceFilenames, paddingFilenames, address, document.TruncateFiles, document.FilesInBank, document.BaseAddress))
            {
                return false;
            }

            return true;
        }
Example #11
0
        public bool CloseResource(PhactoryHost.Database.Resource resource)
        {
            if (viewBinding.ContainsKey(resource))
            {
                viewBinding.Remove(resource);
            }

            return true;
        }
Example #12
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;

            this.textEditorControl.ActiveTextAreaControl.TextArea.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextEditor_KeyDown);
            this.textEditorControl.TextChanged += new EventHandler(TextEditor_TextChanged);
        }
Example #13
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;

            lvFiles.Clear();
            lvFiles.Columns.Add("Filename", 200);
            lvFiles.Columns.Add("Size", 100);
        }
Example #14
0
        private void GetLocalSourceDependencies(PhactoryHost.Database.Resource resource, List<PhactoryHost.Database.Resource> dependentResources, string patternSearch)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }
            if (!fileInfo.Exists)
            {
                return;
            }

            string fileContent = File.ReadAllText(fileInfo.FullName);

            int startIndex = 0;
            while (startIndex != -1)
            {
                int newStartIndex = fileContent.IndexOf(patternSearch, startIndex, StringComparison.OrdinalIgnoreCase);

                startIndex = newStartIndex;

                if (startIndex != -1)
                {
                    int indexEndLine = fileContent.IndexOf("\n", startIndex);
                    int indexFirstQuote = fileContent.IndexOf("\"", startIndex + patternSearch.Length);
                    int indexSecondQuote = fileContent.IndexOf("\"", indexFirstQuote + 1);

                    if ((indexEndLine == -1) || (indexFirstQuote == -1) || (indexSecondQuote == -1))
                    {
                        startIndex = -1;
                    }
                    else
                    {
                        string path = fileContent.Substring(indexFirstQuote + 1, indexSecondQuote - indexFirstQuote - 1);

                        FileInfo fileInfoDependency = new FileInfo(path);
                        if (!fileInfoDependency.Exists)
                        {
                            fileInfoDependency = new FileInfo(fileInfo.DirectoryName + "\\" + path);
                        }

                        PhactoryHost.Database.Resource depResource = Host.GuessResource(fileInfoDependency);
                        if ((depResource != null) && (resource != depResource))
                        {
                            dependentResources.Add(depResource);
                        }

                        startIndex = indexEndLine;
                    }
                }
            }
        }
Example #15
0
        public View(PhactoryHost.Host host)
            : this()
        {
            _host = host;

            Mode0LeftPixel.Text = "0";
            Mode0RightPixel.Text = "0";

            Mode1Pixel0.Text = "0";
            Mode1Pixel1.Text = "0";
            Mode1Pixel2.Text = "0";
            Mode1Pixel3.Text = "0";
        }
Example #16
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;

            lvFiles.Clear();
            lvFiles.Columns.Add("Filename", 200);
            lvFiles.Columns.Add("Address", 50);
            lvFiles.Columns.Add("Length", 50);
            lvFiles.Columns.Add("Length (Hex)", 80);
            lvFiles.Columns.Add("Is External From", 200);
        }
Example #17
0
        public void UpdateDependencies(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            GetDependenciesRecursive(resource);
        }
Example #18
0
        public bool Compile(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return false;
            }

            if (!IsResourceSupported(resource))
            {
                return false;
            }

            var compiler = new Phactory.Modules.Cloud.Compiler.CloudCompiler();

            Document.Document tempDocument = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            if (!tempDocument.CompileInternal())
            {
                return false;
            }

            foreach (Document.Item item in tempDocument.Items)
            {
                PhactoryHost.Database.Resource resItem = Host.GetResource(item.ResourceID);
                if (resItem == null)
                {
                    Host.Log("Unknown resource identifier : " + item.ResourceID);
                    return false;
                }

                FileInfo resFileInfo = Host.GetFileInfo(resItem);
                string outputFilename = resFileInfo.FullName;

                if (Host.IsVerboseOutput())
                {
                    Host.Log(outputFilename);
                }

                string outputFilenameBin = outputFilename + ".bin";

                if (!compiler.WriteCloudBitmap(outputFilenameBin, item.CloudMaskData, item.CloudMaskWidth, item.CloudMaskHeight ))
                {
                    return false;
                }
            }

            return true;
        }
Example #19
0
        public List<int> GetBrokenResourceIDs(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return null;
            }

            if (!fileInfo.Exists)
            {
                return null;
            }

            List<int> brokenResourceIDs = new List<int>();
            return brokenResourceIDs;
        }
Example #20
0
        // return the list of resources using a specified resource (or its output)
        public static List<PhactoryHost.Database.Resource> GetDependentResources(PhactoryHost.Database.Resource resource)
        {
            List<PhactoryHost.Database.Resource> outDependentResources = new List<PhactoryHost.Database.Resource>();

            if (resource != null)
            {
                foreach (int outputResourceId in resource.IdOutputs)
                {
                    PhactoryHost.Database.Resource iOutputResource = App.Controller.Entities.GetResource(outputResourceId);

                    GetDependentResources(outDependentResources, iOutputResource);
                }
                GetDependentResources(outDependentResources, resource);
            }

            return outDependentResources;
        }
Example #21
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;

            lvFiles.Clear();
            lvFiles.Columns.Add("Filename", 130);
            lvFiles.Columns.Add("Size", 70);
            lvFiles.Columns.Add("Width", 70);
            lvFiles.Columns.Add("Height", 70);
            lvFiles.Columns.Add("Created", 120);
            lvFiles.Columns.Add("Last Modified", 120);

            RefreshProperties();
        }
Example #22
0
        private void GetDependenciesRecursive(PhactoryHost.Database.Resource resource)
        {
            List<PhactoryHost.Database.Resource> dependentResources = new List<PhactoryHost.Database.Resource>();

            FileInfo fileInfo = Host.GetFileInfo(resource);

            if ((fileInfo.Extension.ToLower() == ".asm"))
            {
                GetLocalSourceDependencies(resource, dependentResources);
            }
            else
            if ((fileInfo.Extension.ToLower() == ".c") || (fileInfo.Extension.ToLower() == ".h") || (fileInfo.Extension.ToLower() == ".cxx"))
            {
                GetLocalSourceDependencies(resource, dependentResources);
            }

            Host.RefreshDependencies(resource, dependentResources);
        }
Example #23
0
        public bool IsResourceSupported(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return false;
            }

            foreach (PhactoryHost.PluginExtension extension in GetSupportedExtensions())
            {
                if (String.Compare(extension.GetName(), fileInfo.Extension, true) == 0)
                {
                    return true;
                }
            }

            return false;
        }
Example #24
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            Document.Document tempDocument = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);

            List<string> outputFilenames = new List<string>();

            foreach (Document.Item item in tempDocument.Items)
            {
                PhactoryHost.Database.Resource resItem = Host.GetResource(item.ResourceID);
                FileInfo resFileInfo = Host.GetFileInfo( resItem );
                string outputFilename = resFileInfo.Name;

                Document.ItemType type = item.Type;

                if (type == CPCRawBitmap.Document.ItemType.Raw)
                {
                    string outputTopFilename = outputFilename + ".rawBin";
                    outputFilenames.Add(outputTopFilename);
                }
                else if (type == CPCRawBitmap.Document.ItemType.VerticalRaw)
                {
                    string outputTopFilename = outputFilename + ".verticalRawBin";
                    outputFilenames.Add(outputTopFilename);
                }
            }

            Host.RefreshOutput(resource, outputFilenames);
        }
Example #25
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            Document.Document document = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);
            if (document is Document.Document)
            {
                string resourceRelativePath = resource.RelativePath;
                resourceRelativePath = resourceRelativePath.Replace(".cpcbigfile", "");

                List<string> outputFilenames = new List<string>();

                outputFilenames.Add( resourceRelativePath + ".h" );

                if (document.FilesInBank)
                {
                    outputFilenames.Add(resourceRelativePath + ".c4");
                    outputFilenames.Add(resourceRelativePath + ".c5");
                    outputFilenames.Add(resourceRelativePath + ".c6");
                    outputFilenames.Add(resourceRelativePath + ".c7");
                }
                else
                {
                    outputFilenames.Add(resourceRelativePath + ".bigfile");
                }

                Host.RefreshOutput(resource, outputFilenames);
            }
        }
Example #26
0
        public View(PhactoryHost.Database.Resource resource)
        {
            InitializeComponent();

            Resource = resource;
            modified = false;

            lvFiles.Clear();
            lvFiles.Columns.Add("Filename", 100);
            lvFiles.Columns.Add("Filename (AMSDOS 8.3)", 140);
            lvFiles.Columns.Add("Type", 80);
            lvFiles.Columns.Add("Length in Kb", 80);
            lvFiles.Columns.Add("Length (Base 10)", 100);
            lvFiles.Columns.Add("Length (Base 16)", 100);
            lvFiles.Columns.Add("Load Address", 100);
            lvFiles.Columns.Add("Execution Address", 100);

            RefreshMoveButtonStates();
        }
Example #27
0
        public bool Compile(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return false;
            }

            if (!IsResourceSupported(resource))
            {
                return false;
            }

            List<String> resourceFilenames = new List<String>();
            List<int> execPtrs = new List<int>();

            Document.Document document = Host.XMLRead<Document.Document>(fileInfo.FullName);

            string outputFilename = fileInfo.FullName + ".bin";

            if (File.Exists(outputFilename))
            {
                File.Delete(outputFilename);
            }

            var compiler = new Phactory.Text.Compiler.TextCompiler();

            int charsNotFound = 0;

            if (!compiler.Compile(outputFilename, document.Charset, document.Text, document.AppendEndOfText, out charsNotFound))
            {
                return false;
            }

            if (charsNotFound>0)
            {
                Plugin.ControllerCompiler.Host.Log("Warning : " + charsNotFound + " characters in text was/were not found in charset !");
            }

            return true;
        }
Example #28
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            Document.Document tempDocument = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);

            List<string> outputFilenames = new List<string>();

            string dskOutputFilename = fileInfo.Name;
            dskOutputFilename = dskOutputFilename.Replace(".cpcdsk", ".dsk");
            outputFilenames.Add(dskOutputFilename);

            if (tempDocument.GenerateHFE)
            {
                string hfeOutputFilename = fileInfo.Name;
                hfeOutputFilename = hfeOutputFilename.Replace(".cpcdsk", ".hfe");
                outputFilenames.Add(hfeOutputFilename);
            }

            string fileListFilename = fileInfo.Name;
            fileListFilename = fileListFilename.Replace(".cpcdsk", ".filelist");
            outputFilenames.Add(fileListFilename);

            Host.RefreshOutput(resource, outputFilenames);
        }
Example #29
0
        public void RefreshOutput(PhactoryHost.Database.Resource resource)
        {
            FileInfo fileInfo = Host.GetFileInfo(resource);
            if (fileInfo == null)
            {
                return;
            }

            if (!fileInfo.Exists)
            {
                return;
            }

            if (!IsResourceSupported(resource))
            {
                return;
            }

            Document.Document tempDocument = Host.XMLRead<Document.Document>(Host.GetFileInfo(resource).FullName);

            List<string> outputFilenames = new List<string>();

            foreach (Document.Item item in tempDocument.Items)
            {
                PhactoryHost.Database.Resource depResource = Host.GetResource(item.ResourceID);
                if (resource != depResource)
                {
                    FileInfo depFileInfo = Host.GetFileInfo(depResource);

                    string outputFilename = depFileInfo.Name + ".pck";
                    outputFilename.ToUpper();

                    outputFilenames.Add(outputFilename);
                }
            }

            Host.RefreshOutput(resource, outputFilenames);
        }
Example #30
0
        public bool CloseResource(PhactoryHost.Database.Resource resource)
        {
            string extension = Helper.StringHelper.GetFileExtension(resource.RelativePath);

            PhactoryHost.EditorPlugin editor = GetEditor(extension);

            bool closed = false;

            if (editor != null)
            {
                closed = editor.CloseResource(resource);
            }
            else
            {
                PhactoryHost.EditorPlugin defaultEditor = GetDefaultEditorForUnknownTypes();
                if (defaultEditor != null)
                {
                    if (defaultEditor.IsResourceOpened(resource))
                    {
                        closed = defaultEditor.CloseResource(resource);
                    }
                }
            }

            if (closed)
            {
                if (!App.Controller.IsAppClosing)
                {
                    if (App.Controller.UserConfig.OpenedResources.Contains(resource.Id))
                    {
                        App.Controller.UserConfig.OpenedResources.Remove(resource.Id);
                        App.Controller.WriteUserConfig();
                    }
                }
            }

            return closed;
        }