private bool VerifyPackPrecondition(List <TristateTreeNode> nodes)
        {
            Stack <TristateTreeNode> nodeStack = new Stack <TristateTreeNode>();

            for (int i = nodes.Count - 1; i >= 0; i--)
            {
                nodeStack.Push(nodes[i]);
            }
            while (nodeStack.Count != 0)
            {
                //If a node has no children, we ignore it, since that means it's just a description node
                //IE: the nodes sitting under the "fileName.dds" nodes, with no cboxes
                TristateTreeNode node = nodeStack.Pop();
                if (node.Nodes.Count == 0)
                {
                }                              //Do nothing.  Desciptor node such as RAF Path: nodes
                else //Node has children.  Push node
                {
                    if (node.Tag == null) //Is a group node
                    {
                        for (int i = node.Nodes.Count - 1; i >= 0; i--)
                        {
                            nodeStack.Push(node.Nodes[i]);
                        }
                    }
                    else
                    {
                        ChangesViewEntry entry = (ChangesViewEntry)node.Tag;
                        //No longer necessary, sinec we now know our  hash func
                        //if (ResolveRAFPathToEntry(entry.Entry.RAFArchive.GetID() + "/" + entry.Entry.FileName) == null)
                        //{
                        //   Log("Precondition fail!: ");
                        //    Log("RAF Path Doesnt Exist: "+entry.Entry.RAFArchive.GetID()+"/"+entry.Entry.FileName);
                        //   return false;
                        //}
                        if (!File.Exists(entry.LocalPath))
                        {
                            Log("Precondition fail!: ");
                            Log("Local Path Doesnt Exist: '" + entry.LocalPath + "', so it can't be packed!");
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// Performs a save operation of the current project
        /// to the given location
        /// </summary>
        private void SaveProject(string location)
        {
            //changesView.ClearSelection();

            /**
             * Output:
             * RAF
             * [Project Name]
             * -blank-
             * > NodeBegin
             * e entry
             * < End
             */
            string crnl          = "\r\n"; //To make it viewable with notepad, as oposed to the original unix style
            string serialization = "RAF";

            serialization += crnl + projectInfo.ProjectName;
            serialization += crnl + ""; //blank

            Stack <TristateTreeNode> nodeStack = new Stack <TristateTreeNode>();

            for (int i = changesView.Nodes.Count - 1; i >= 0; i--)
            {
                nodeStack.Push(changesView.Nodes[i]);
            }
            while (nodeStack.Count != 0)
            {
                //If a node has no children, we ignore it, since that means it's just a description node
                //IE: the nodes sitting under the "fileName.dds" nodes, with no cboxes
                TristateTreeNode node = nodeStack.Pop();
                if (node == null)
                {
                    //Append < for done with this node
                    serialization += crnl + "<";
                }
                else if (node.Nodes.Count == 0)
                {
                }                                   //Do nothing.  reserved?
                else //Node has children.  Push null (for done) and all children...
                {
                    if (node.Tag == null) //Is a group node
                    {
                        nodeStack.Push(null);
                        for (int i = node.Nodes.Count - 1; i >= 0; i--)
                        {
                            nodeStack.Push(node.Nodes[i]);
                        }
                        string typeField = "e ";
                        if (node.NodeType == TristateTreeNodeType.Checkboxes)
                        {
                            typeField = "c ";
                        }
                        else if (node.NodeType == TristateTreeNodeType.Radio)
                        {
                            typeField = "R ";
                        }
                        else if (node.NodeType == TristateTreeNodeType.RadioChild)
                        {
                            typeField = "r ";
                        }
                        else if (node.NodeType == TristateTreeNodeType.Empty)
                        {
                            typeField = "E ";
                        }
                        serialization += crnl + "> " + typeField + node.Text;
                    }
                    else
                    {
                        ChangesViewEntry entry     = (ChangesViewEntry)node.Tag;
                        string           typeField = "e ";
                        if (node.NodeType == TristateTreeNodeType.Checkboxes)
                        {
                            typeField = "c ";
                        }
                        else if (node.NodeType == TristateTreeNodeType.Radio)
                        {
                            typeField = "R ";
                        }
                        else if (node.NodeType == TristateTreeNodeType.RadioChild)
                        {
                            typeField = "r ";
                        }
                        else if (node.NodeType == TristateTreeNodeType.Empty)
                        {
                            typeField = "E ";
                        }

                        if (entry.Entry != null)
                        {
                            serialization += crnl + typeField + (entry.Checked ? "1" : "0") + " " +
                                             entry.LocalPath + " | " +
                                             entry.Entry.RAFArchive.GetID() + "/" +
                                             entry.Entry.FileName;
                        }
                        else
                        {
                            serialization += crnl + typeField + (entry.Checked ? "1" : "0") + " " +
                                             entry.LocalPath + " | " +
                                             "undefined";
                        }
                    }
                }
            }

            HasProjectChanged = false;
            File.WriteAllText(location, serialization);
            UpdateProjectGUI();
        }
        private void PackNode(TristateTreeNode node)
        {
            ChangesViewEntry cventry = (ChangesViewEntry)node.Tag;

            if (cventry == null) //Group node
            {
                for (int i = 0; i < node.Nodes.Count; i++)
                {
                    PackNode(node.Nodes[i]);
                }
            }
            else
            {
                RAFFileListEntry entry     = cventry.Entry;
                string           rafPath   = entry.FileName;
                string           localPath = cventry.LocalPath;
                bool             useFile   = cventry.Checked;

                packTick = (packTick + 1) % 10;
                if (packTick == 0 || verboseLoggingCB.Checked)
                {
                    Title("Pack File: " + localPath.Replace("\\", "/").Split("/").Last());
                }

                //Console.WriteLine(Environment.CurrentDirectory + "/backup/");
                PrepareDirectory(Environment.CurrentDirectory + "/backup/");
                string fileBackupLoc = Environment.CurrentDirectory + "/backup/" + entry.FileName.Replace("/", "_");
                if (!File.Exists(fileBackupLoc))
                {
                    if (entry.IsMemoryEntry)
                    {
                        File.WriteAllText(fileBackupLoc, "this file should be deleted");
                    }
                    else
                    {
                        File.WriteAllBytes(fileBackupLoc, entry.GetContent());
                    }
                }

                //Open the RAF archive, insert.
                if (useFile)
                {
                    entry.RAFArchive.InsertFile(
                        rafPath,
                        File.ReadAllBytes(localPath),
                        new LogTextWriter(
                            (Func <string, object>) delegate(string s)
                    {
                        if (verboseLoggingCB.Checked)
                        {
                            Log(s);
                        }
                        return(null);
                    }
                            )
                        );
                }
                else
                {
                    //Insert backup
                    if (File.ReadAllText(fileBackupLoc) == "this file should be deleted")
                    {
                        //The file should be deleted...
                        entry.RAFArchive.GetDirectoryFile().DeleteFileEntry(entry);
                    }
                    else
                    {
                        entry.RAFArchive.InsertFile(
                            rafPath,
                            File.ReadAllBytes(fileBackupLoc),
                            new LogTextWriter(
                                (Func <string, object>) delegate(string s)
                        {
                            if (verboseLoggingCB.Checked)
                            {
                                Log(s);
                            }
                            return(null);
                        }
                                )
                            );
                    }
                }
                List <RAFArchive> archives = new List <RAFArchive>(rafArchives.Values);
                for (int i = 0; i < archives.Count; i++)
                {
                    SetTaskbarProgress((i + 1) * 100 / (archives.Count + 1));
                    archives[i].SaveDirectoryFile();
                }

                SetTaskbarProgress(0);
            }
        }