Abstract class which all HTML subwriters must extend. This class contains some of the basic HTML-writing helper values and contains some of the values used by many of the subclasses. HTML subwriters are the top level writing classes employed by the Html_MainWriter.
        /// <summary> Constructor for a new instance of the Text_MainWriter class </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
        /// <param name="Paged_Results"> Single page of results for a search or browse, within the entire set </param>
        /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
        /// <param name="Current_Item"> Current item to display </param>
        /// <param name="Current_Page"> Current page within the item</param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="Item_List"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Search_History"> List of recent searches performed against this digital library </param>
        /// <param name="Icon_Dictionary"> Dictionary of information about every wordmark/icon in this digital library, used to build the wordmarks subpage </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the main home page are organized </param>
        /// <param name="Public_Folder"> Object contains the information about the public folder to display </param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Checked_Items"> List of all items which are currently checked out for single fair use and the IP address currently viewing the item</param>
        /// <param name="IP_Restrictions"> Any possible restriction on item access by IP ranges </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Site_Map"> Optional site map object used to render a navigational tree-view on left side of static web content pages </param>
        /// <param name="Items_In_Title"> List of items within the current title ( used for the Item Group display )</param>
        /// <param name="Static_Web_Content"> HTML content-based browse, info, or imple CMS-style web content objects.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Html_MainWriter(SobekCM_Navigation_Object Current_Mode,
            Item_Aggregation Hierarchy_Object,
            Search_Results_Statistics Results_Statistics,
            List<iSearch_Title_Result> Paged_Results,
            Item_Aggregation_Child_Page Browse_Object,
            SobekCM_Item Current_Item,
            Page_TreeNode Current_Page,
            SobekCM_Skin_Object HTML_Skin,
            User_Object Current_User,
            Language_Support_Info Translator,
            Aggregation_Code_Manager Code_Manager,
            Item_Lookup_Object Item_List,
            Statistics_Dates Stats_Date_Range,
            Recent_Searches Search_History,
            Dictionary<string, Wordmark_Icon> Icon_Dictionary,
            List<Thematic_Heading> Thematic_Headings,
            Public_User_Folder Public_Folder,
            Dictionary<string, string> Aggregation_Aliases,
            SobekCM_Skin_Collection Web_Skin_Collection,
            Checked_Out_Items_List Checked_Items,
            IP_Restriction_Ranges IP_Restrictions,
            Portal_List URL_Portals,
            SobekCM_SiteMap Site_Map,
            SobekCM_Items_In_Title Items_In_Title,
            HTML_Based_Content Static_Web_Content,
            Custom_Tracer Tracer )
            : base(Current_Mode, Hierarchy_Object, Results_Statistics, Paged_Results, Browse_Object,  Current_Item, Current_Page, Static_Web_Content)
        {
            // Save parameters
            htmlSkin = HTML_Skin;
            translator = Translator;
            codeManager = Code_Manager;
            itemList = Item_List;
            statsDateRange = Stats_Date_Range;
            searchHistory = Search_History;
            currentUser = Current_User;
            iconList = Icon_Dictionary;
            thematicHeadings = Thematic_Headings;
            publicFolder = Public_Folder;
            aggregationAliases = Aggregation_Aliases;
            webSkins = Web_Skin_Collection;
            checkedItems = Checked_Items;
            ipRestrictionInfo = IP_Restrictions;
            urlPortals = URL_Portals;
            siteMap = Site_Map;
            itemsInTitle = Items_In_Title;

            // Set some defaults

            // Handle basic events which may be fired by the internal header
            if (HttpContext.Current.Request.Form["internal_header_action"] != null)
            {
                // Pull the action value
                string internalHeaderAction = HttpContext.Current.Request.Form["internal_header_action"].Trim();

                // Was this to hide or show the header?
                if ((internalHeaderAction == "hide") || (internalHeaderAction == "show"))
                {
                    // Pull the current visibility from the session
                    bool shown = !((HttpContext.Current.Session["internal_header"] != null) && (HttpContext.Current.Session["internal_header"].ToString() == "hidden"));
                    if ((internalHeaderAction == "hide") && (shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "hidden";
                        currentMode.Redirect();
                        return;
                    }
                    if ((internalHeaderAction == "show") && (!shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "shown";
                        currentMode.Redirect();
                        return;
                    }
                }
            }

            try
            {

                // Create the html sub writer now
                switch (Current_Mode.Mode)
                {
                    case Display_Mode_Enum.Internal:
                        subwriter = new Internal_HtmlSubwriter(iconList, currentUser, codeManager);
                        break;

                    case Display_Mode_Enum.Statistics:
                        subwriter = new Statistics_HtmlSubwriter(searchHistory, codeManager, statsDateRange);
                        break;

                    case Display_Mode_Enum.Preferences:
                        subwriter = new Preferences_HtmlSubwriter(currentMode);
                        break;

                    case Display_Mode_Enum.Error:
                        subwriter = new Error_HtmlSubwriter(false);
                        // Send the email now
                        if (currentMode.Caught_Exception != null)
                        {
                            if (currentMode.Error_Message.Length == 0)
                                currentMode.Error_Message = "Unknown exception caught";
                            Email_Information(currentMode.Error_Message, currentMode.Caught_Exception, Tracer, false);
                        }
                        break;

                    case Display_Mode_Enum.Legacy_URL:
                        subwriter = new LegacyUrl_HtmlSubwriter();
                        break;

                    case Display_Mode_Enum.Item_Print:
                        subwriter = new Print_Item_HtmlSubwriter(currentItem, codeManager, translator, currentMode);
                        break;

                    case Display_Mode_Enum.Contact:

                        StringBuilder builder = new StringBuilder();
                        builder.Append("\n\nSUBMISSION INFORMATION\n");
                        builder.Append("\tDate:\t\t\t\t" + DateTime.Now.ToString() + "\n");
                        string lastMode = String.Empty;
                        try
                        {
                            if (HttpContext.Current.Session["Last_Mode"] != null)
                                lastMode = HttpContext.Current.Session["Last_Mode"].ToString();
                            builder.Append("\tIP Address:\t\t\t" + HttpContext.Current.Request.UserHostAddress + "\n");
                            builder.Append("\tHost Name:\t\t\t" + HttpContext.Current.Request.UserHostName + "\n");
                            builder.Append("\tBrowser:\t\t\t" + HttpContext.Current.Request.Browser.Browser + "\n");
                            builder.Append("\tBrowser Platform:\t\t" + HttpContext.Current.Request.Browser.Platform + "\n");
                            builder.Append("\tBrowser Version:\t\t" + HttpContext.Current.Request.Browser.Version + "\n");
                            builder.Append("\tBrowser Language:\t\t");
                            bool first = true;
                            string[] languages = HttpContext.Current.Request.UserLanguages;
                            if (languages != null)
                                foreach (string thisLanguage in languages)
                                {
                                    if (first)
                                    {
                                        builder.Append(thisLanguage);
                                        first = false;
                                    }
                                    else
                                    {
                                        builder.Append(", " + thisLanguage);
                                    }
                                }

                            builder.Append("\n\nHISTORY\n");
                            if (HttpContext.Current.Session["LastSearch"] != null)
                                builder.Append("\tLast Search:\t\t" + HttpContext.Current.Session["LastSearch"] + "\n");
                            if (HttpContext.Current.Session["LastResults"] != null)
                                builder.Append("\tLast Results:\t\t" + HttpContext.Current.Session["LastResults"] + "\n");
                            if (HttpContext.Current.Session["Last_Mode"] != null)
                                builder.Append("\tLast Mode:\t\t\t" + HttpContext.Current.Session["Last_Mode"] + "\n");
                            builder.Append("\tURL:\t\t\t\t" + HttpContext.Current.Items["Original_URL"]);
                        }
                        catch
                        {

                        }
                        subwriter = new Contact_HtmlSubwriter(lastMode, builder.ToString(), currentMode, hierarchyObject);
                        break;

                    case Display_Mode_Enum.Contact_Sent:
                        subwriter = new Contact_HtmlSubwriter(String.Empty, String.Empty, currentMode, hierarchyObject);
                        break;

                    case Display_Mode_Enum.Simple_HTML_CMS:
                        subwriter = new Web_Content_HtmlSubwriter(hierarchyObject, currentMode, htmlSkin, htmlBasedContent, siteMap);
                        break;

                    case Display_Mode_Enum.My_Sobek:
                        subwriter = new MySobek_HtmlSubwriter(results_statistics, paged_results, codeManager, itemList, hierarchyObject, htmlSkin, translator, currentMode, currentItem, currentUser, iconList, statsDateRange, webSkins, Tracer);
                        break;

                    case Display_Mode_Enum.Administrative:
                        subwriter = new Admin_HtmlSubwriter(codeManager, itemList, hierarchyObject, htmlSkin, translator, currentMode, aggregationAliases, webSkins, currentUser, ipRestrictionInfo, iconList, urlPortals, thematicHeadings, Tracer);
                        break;

                    case Display_Mode_Enum.Results:
                        subwriter = new Search_Results_HtmlSubwriter(results_statistics, paged_results, codeManager, translator, itemList, currentUser);
                        break;

                    case Display_Mode_Enum.Public_Folder:
                        subwriter = new Public_Folder_HtmlSubwriter(results_statistics, paged_results, codeManager, translator, itemList, currentUser, publicFolder);
                        break;

                    case Display_Mode_Enum.Search:
                    case Display_Mode_Enum.Aggregation:
                        subwriter = new Aggregation_HtmlSubwriter(hierarchyObject, currentMode, htmlSkin, translator, thisBrowseObject, results_statistics, paged_results, codeManager, itemList, thematicHeadings, currentUser, htmlBasedContent, Tracer);
                        break;

                    case Display_Mode_Enum.Item_Display:
                        if ((!currentMode.Invalid_Item) && (currentItem != null))
                        {
                            bool show_toc = false;
                            if (HttpContext.Current.Session["Show TOC"] != null)
                            {
                                Boolean.TryParse(HttpContext.Current.Session["Show TOC"].ToString(), out show_toc);
                            }

                            // Check that this item is not checked out by another user
                            bool itemCheckedOutByOtherUser = false;
                            if (currentItem.Behaviors.CheckOut_Required)
                            {
                                if (!checkedItems.Check_Out(currentItem.Web.ItemID, HttpContext.Current.Request.UserHostAddress))
                                {
                                    itemCheckedOutByOtherUser = true;
                                }
                            }

                            // Check to see if this is IP restricted
                            string restriction_message = String.Empty;
                            if (currentItem.Behaviors.IP_Restriction_Membership > 0)
                            {
                                if (HttpContext.Current != null)
                                {
                                    int user_mask = (int)HttpContext.Current.Session["IP_Range_Membership"];
                                    int comparison = currentItem.Behaviors.IP_Restriction_Membership & user_mask;
                                    if (comparison == 0)
                                    {
                                        int restriction = currentItem.Behaviors.IP_Restriction_Membership;
                                        int restriction_counter = 0;
                                        while (restriction % 2 != 1)
                                        {
                                            restriction = restriction >> 1;
                                            restriction_counter++;
                                        }
                                        restriction_message = ipRestrictionInfo[restriction_counter].Item_Restricted_Statement;
                                    }
                                }
                            }

                            // Create the item viewer writer
                            subwriter = new Item_HtmlSubwriter(currentItem, currentPage, currentUser, codeManager, translator, show_toc, (SobekCM_Library_Settings.JP2ServerUrl.Length > 0), currentMode, hierarchyObject, restriction_message, itemsInTitle, Tracer);
                            ((Item_HtmlSubwriter)subwriter).Item_Checked_Out_By_Other_User = itemCheckedOutByOtherUser;
                        }
                        else
                        {
                            // Create the invalid item html subwrite and write the HTML
                            subwriter = new Error_HtmlSubwriter(true);
                        }
                        break;

                }
            }
            catch (Exception ee)
            {
                // Send to the dashboard
                if ((HttpContext.Current.Request.UserHostAddress == "127.0.0.1") || (HttpContext.Current.Request.UserHostAddress == HttpContext.Current.Request.ServerVariables["LOCAL_ADDR"]) || (HttpContext.Current.Request.Url.ToString().IndexOf("localhost") >= 0))
                {
                    Tracer.Add_Trace("Html_MainWriter.Constructor", "Exception caught!", Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Html_MainWriter.Constructor", ee.Message, Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Html_MainWriter.Constructor", ee.StackTrace, Custom_Trace_Type_Enum.Error);

                    // Wrap this into the SobekCM Exception
                    SobekCM_Traced_Exception newException = new SobekCM_Traced_Exception("Exception caught while building the mode-specific HTML Subwriter", ee, Tracer);

                    // Save this to the session state, and then forward to the dashboard
                    HttpContext.Current.Session["Last_Exception"] = newException;
                    HttpContext.Current.Response.Redirect("dashboard.aspx", false);
                    Current_Mode.Request_Completed = true;

                    return;
                }
                else
                {
                    subwriter = new Error_HtmlSubwriter(false);
                }
            }

            if (subwriter != null)
            {
                subwriter.Mode = currentMode;
                subwriter.Skin = htmlSkin;
                subwriter.Current_Aggregation = hierarchyObject;
            }
        }
        /// <summary> Constructor for a new instance of the Html_MainWriter class </summary>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        public Html_MainWriter( RequestCache RequestSpecificValues )
            : base(RequestSpecificValues)
        {
            // Check the IE hack CSS is loaded
            if (HttpContext.Current.Application["NonIE_Hack_CSS"] == null)
            {
                string css_file = HttpContext.Current.Server.MapPath("default/SobekCM_NonIE.css");
                if (File.Exists(css_file))
                {
                    try
                    {
                        StreamReader reader = new StreamReader(css_file);
                        HttpContext.Current.Application["NonIE_Hack_CSS"] = reader.ReadToEnd().Trim();
                        reader.Close();
                    }
                    catch (Exception)
                    {
                        HttpContext.Current.Application["NonIE_Hack_CSS"] = "/* ERROR READING FILE: default/SobekCM_NonIE.css */";
                        throw;
                    }
                }
                else
                {
                    HttpContext.Current.Application["NonIE_Hack_CSS"] = String.Empty;
                }
            }

            // Handle basic events which may be fired by the internal header
            if (HttpContext.Current.Request.Form["internal_header_action"] != null)
            {
                // Pull the action value
                string internalHeaderAction = HttpContext.Current.Request.Form["internal_header_action"].Trim();

                // Was this to hide or show the header?
                if ((internalHeaderAction == "hide") || (internalHeaderAction == "show"))
                {
                    // Pull the current visibility from the session
                    bool shown = !((HttpContext.Current.Session["internal_header"] != null) && (HttpContext.Current.Session["internal_header"].ToString() == "hidden"));
                    if ((internalHeaderAction == "hide") && (shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "hidden";
                        UrlWriterHelper.Redirect(RequestSpecificValues.Current_Mode);
                        return;
                    }
                    if ((internalHeaderAction == "show") && (!shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "shown";
                        UrlWriterHelper.Redirect(RequestSpecificValues.Current_Mode);
                        return;
                    }
                }
            }

            try
            {

                // Create the html sub writer now
                switch (RequestSpecificValues.Current_Mode.Mode)
                {
                    case Display_Mode_Enum.Internal:
                        subwriter = new Internal_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Statistics:
                        subwriter = new Statistics_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Preferences:
                        subwriter = new Preferences_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Error:
                        subwriter = new Error_HtmlSubwriter(false, RequestSpecificValues);
                        // Send the email now
                        if (RequestSpecificValues.Current_Mode.Caught_Exception != null)
                        {
                            if ( String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Error_Message))
                                RequestSpecificValues.Current_Mode.Error_Message = "Unknown exception caught";
                            Email_Information(RequestSpecificValues.Current_Mode.Error_Message, RequestSpecificValues.Current_Mode.Caught_Exception, RequestSpecificValues.Tracer, false);
                        }
                        break;

                    case Display_Mode_Enum.Legacy_URL:
                        subwriter = new LegacyUrl_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Item_Print:
                        subwriter = new Print_Item_HtmlSubwriter( RequestSpecificValues );
                        break;

                    case Display_Mode_Enum.Contact:

                        StringBuilder builder = new StringBuilder();
                        builder.Append("\n\nSUBMISSION INFORMATION\n");
                        builder.Append("\tDate:\t\t\t\t" + DateTime.Now.ToString() + "\n");
                        string lastMode = String.Empty;
                        try
                        {
                            if (HttpContext.Current.Session["Last_Mode"] != null)
                                lastMode = HttpContext.Current.Session["Last_Mode"].ToString();
                            builder.Append("\tIP Address:\t\t\t" + HttpContext.Current.Request.UserHostAddress + "\n");
                            builder.Append("\tHost Name:\t\t\t" + HttpContext.Current.Request.UserHostName + "\n");
                            builder.Append("\tBrowser:\t\t\t" + HttpContext.Current.Request.Browser.Browser + "\n");
                            builder.Append("\tBrowser Platform:\t\t" + HttpContext.Current.Request.Browser.Platform + "\n");
                            builder.Append("\tBrowser Version:\t\t" + HttpContext.Current.Request.Browser.Version + "\n");
                            builder.Append("\tBrowser Language:\t\t");
                            bool first = true;
                            string[] languages = HttpContext.Current.Request.UserLanguages;
                            if (languages != null)
                                foreach (string thisLanguage in languages)
                                {
                                    if (first)
                                    {
                                        builder.Append(thisLanguage);
                                        first = false;
                                    }
                                    else
                                    {
                                        builder.Append(", " + thisLanguage);
                                    }
                                }

                            builder.Append("\n\nHISTORY\n");
                            if (HttpContext.Current.Session["LastSearch"] != null)
                                builder.Append("\tLast Search:\t\t" + HttpContext.Current.Session["LastSearch"] + "\n");
                            if (HttpContext.Current.Session["LastResults"] != null)
                                builder.Append("\tLast Results:\t\t" + HttpContext.Current.Session["LastResults"] + "\n");
                            if (HttpContext.Current.Session["Last_Mode"] != null)
                                builder.Append("\tLast Mode:\t\t\t" + HttpContext.Current.Session["Last_Mode"] + "\n");
                            builder.Append("\tURL:\t\t\t\t" + HttpContext.Current.Items["Original_URL"]);
                        }
                        catch
                        {

                        }
                        subwriter = new Contact_HtmlSubwriter(lastMode, builder.ToString(), RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Contact_Sent:
                        subwriter = new Contact_HtmlSubwriter(String.Empty, String.Empty, RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Simple_HTML_CMS:
                        subwriter = new Web_Content_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.My_Sobek:
                        subwriter = new MySobek_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Administrative:
                        subwriter = new Admin_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Results:
                        subwriter = new Search_Results_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Public_Folder:
                        subwriter = new Public_Folder_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Search:
                    case Display_Mode_Enum.Aggregation:
                        subwriter = new Aggregation_HtmlSubwriter(RequestSpecificValues);
                        break;

                    case Display_Mode_Enum.Item_Display:
                        if ((!RequestSpecificValues.Current_Mode.Invalid_Item.HasValue || !RequestSpecificValues.Current_Mode.Invalid_Item.Value ) && (RequestSpecificValues.Current_Item != null))
                        {
                            bool show_toc = false;
                            if (HttpContext.Current.Session["Show TOC"] != null)
                            {
                                Boolean.TryParse(HttpContext.Current.Session["Show TOC"].ToString(), out show_toc);
                            }

                            // Check that this item is not checked out by another user
                            bool itemCheckedOutByOtherUser = false;
                            if (RequestSpecificValues.Current_Item.Behaviors.CheckOut_Required)
                            {
                                if (!Engine_ApplicationCache_Gateway.Checked_List.Check_Out(RequestSpecificValues.Current_Item.Web.ItemID, HttpContext.Current.Request.UserHostAddress))
                                {
                                    itemCheckedOutByOtherUser = true;
                                }
                            }

                            // Check to see if this is IP restricted
                            string restriction_message = String.Empty;
                            if (RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership > 0)
                            {
                                if (HttpContext.Current != null)
                                {
                                    int user_mask = (int)HttpContext.Current.Session["IP_Range_Membership"];
                                    int comparison = RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership & user_mask;
                                    if (comparison == 0)
                                    {
                                        int restriction = RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership;
                                        int restriction_counter = 1;
                                        while (restriction % 2 != 1)
                                        {
                                            restriction = restriction >> 1;
                                            restriction_counter++;
                                        }
                                        if (Engine_ApplicationCache_Gateway.IP_Restrictions[restriction_counter] != null )
                                            restriction_message = Engine_ApplicationCache_Gateway.IP_Restrictions[restriction_counter].Item_Restricted_Statement;
                                        else
                                            restriction_message = "Restricted Item";
                                    }
                                }
                            }

                            // Create the item viewer writer
                            subwriter = new Item_HtmlSubwriter( show_toc, (String.IsNullOrEmpty(UI_ApplicationCache_Gateway.Settings.Servers.JP2ServerUrl)), restriction_message, RequestSpecificValues );
                            ((Item_HtmlSubwriter)subwriter).Item_Checked_Out_By_Other_User = itemCheckedOutByOtherUser;
                        }
                        else
                        {
                            // Create the invalid item html subwrite and write the HTML
                            subwriter = new Error_HtmlSubwriter(true, RequestSpecificValues);
                        }
                        break;

                }
            }
            catch (Exception ee)
            {
                // Send to the dashboard
                if ((HttpContext.Current.Request.UserHostAddress == "127.0.0.1") || (HttpContext.Current.Request.UserHostAddress == HttpContext.Current.Request.ServerVariables["LOCAL_ADDR"]) || (HttpContext.Current.Request.Url.ToString().IndexOf("localhost") >= 0))
                {
                    RequestSpecificValues.Tracer.Add_Trace("Html_MainWriter.Constructor", "Exception caught!", Custom_Trace_Type_Enum.Error);
                    RequestSpecificValues.Tracer.Add_Trace("Html_MainWriter.Constructor", ee.Message, Custom_Trace_Type_Enum.Error);
                    RequestSpecificValues.Tracer.Add_Trace("Html_MainWriter.Constructor", ee.StackTrace, Custom_Trace_Type_Enum.Error);

                    // Wrap this into the SobekCM Exception
                    SobekCM_Traced_Exception newException = new SobekCM_Traced_Exception("Exception caught while building the mode-specific HTML Subwriter", ee, RequestSpecificValues.Tracer);

                    // Save this to the session state, and then forward to the dashboard
                    HttpContext.Current.Session["Last_Exception"] = newException;
                    HttpContext.Current.Response.Redirect("dashboard.aspx", false);
                    RequestSpecificValues.Current_Mode.Request_Completed = true;
                }
                else
                {
                    subwriter = new Error_HtmlSubwriter(false, RequestSpecificValues);
                }
            }
        }
        /// <summary> Perform all the work of adding to the response stream back to the web user </summary>
        /// <param name="Navigation_Place_Holder"> Place holder is used to add more complex server-side objects during execution</param>
        /// <param name="TOC_Place_Holder"> Place holder is used to add more complex server-side objects during execution</param>
        /// <param name="Main_Place_Holder"> Place holder is used to add more complex server-side objects during execution</param>
        /// <param name="myUfdcUploadPlaceHolder"> Place holder is used to add more complex server-side objects during execution </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <remarks> Since this class writes all the output directly to the response stream, this method simply returns, without doing anything</remarks>
        public override void Add_Controls(PlaceHolder Navigation_Place_Holder,
            PlaceHolder TOC_Place_Holder,
            PlaceHolder Main_Place_Holder,
            PlaceHolder myUfdcUploadPlaceHolder, Custom_Tracer Tracer)
        {
            Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Rendering the requested data in html format");

            // Render HTML and add controls depending on the current mode
            switch (currentMode.Mode)
            {
                #region Start adding HTML and controls for SIMPLE WEB CONTENT TEXT mode

                case Display_Mode_Enum.Simple_HTML_CMS:
                    subwriter = new Web_Content_HtmlSubwriter(hierarchyObject, currentMode, htmlSkin, htmlBasedContent, siteMap);

                    // Add any necessary controls
                    if (siteMap != null)
                    {
                        ((Web_Content_HtmlSubwriter)subwriter).Add_Controls(Main_Place_Holder, Tracer);
                    }

                    break;

                #endregion

                #region Start adding HTML and controls for MY SOBEK mode

                case Display_Mode_Enum.My_Sobek:

                    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Building the my sobek HTML subwriter");

                    // Build the my sobek subwriter
                    mySobekWriter = new MySobek_HtmlSubwriter( results_statistics, paged_results, codeManager, itemList, hierarchyObject, htmlSkin, translator, currentMode, currentItem, aggregationAliases, webSkins, currentUser, ipRestrictionInfo, iconList, urlPortals, statsDateRange, thematicHeadings, Tracer);
                    subwriter = mySobekWriter;
                    mySobekWriter.Hierarchy_Object = hierarchyObject;
                    mySobekWriter.Skin = htmlSkin;
                    mySobekWriter.Mode = currentMode;

                    // If the my sobek writer contains pop up forms, add the header here first
                    if ( mySobekWriter.Contains_Popup_Forms )
                    {
                        StringBuilder header_builder = new StringBuilder();
                        StringWriter header_writer = new StringWriter(header_builder);
                        Display_Header(header_writer, Tracer);
                        LiteralControl header_literal = new LiteralControl(header_builder.ToString());
                        Main_Place_Holder.Controls.Add(header_literal);
                    }

                    // Add any necessary controls
                    mySobekWriter.Add_Controls(Main_Place_Holder, myUfdcUploadPlaceHolder, Tracer);

                    // Finally, add the footer
                    if (mySobekWriter.Contains_Popup_Forms)
                    {
                        StringBuilder footer_builder = new StringBuilder();
                        StringWriter footer_writer = new StringWriter(footer_builder);
                        Display_Footer(footer_writer, Tracer);
                        LiteralControl footer_literal = new LiteralControl(footer_builder.ToString());
                        Main_Place_Holder.Controls.Add(footer_literal);
                    }

                    break;

                #endregion

                #region Start adding HTML and controls for ADMINISTRATIVE mode

                case Display_Mode_Enum.Administrative:

                    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Building the admin HTML subwriter");

                    // Build the my sobek subwriter
                    adminWriter = new Admin_HtmlSubwriter(results_statistics, paged_results, codeManager, itemList, hierarchyObject, htmlSkin, translator, currentMode, currentItem, aggregationAliases, webSkins, currentUser, ipRestrictionInfo, iconList, urlPortals, statsDateRange, thematicHeadings, Tracer);
                    subwriter = adminWriter;
                    adminWriter.Hierarchy_Object = hierarchyObject;
                    adminWriter.Skin = htmlSkin;
                    adminWriter.Mode = currentMode;

                    // If the my sobek writer contains pop up forms, add the header here first
                    if (adminWriter.Contains_Popup_Forms)
                    {
                        StringBuilder header_builder = new StringBuilder();
                        StringWriter header_writer = new StringWriter(header_builder);
                        Display_Header(header_writer, Tracer);
                        LiteralControl header_literal = new LiteralControl(header_builder.ToString());
                        Main_Place_Holder.Controls.Add(header_literal);
                    }

                    // Add any necessary controls
                    adminWriter.Add_Controls(Main_Place_Holder, myUfdcUploadPlaceHolder, Tracer);

                    // Finally, add the footer
                    if (adminWriter.Contains_Popup_Forms)
                    {
                        StringBuilder footer_builder = new StringBuilder();
                        StringWriter footer_writer = new StringWriter(footer_builder);
                        Display_Footer(footer_writer, Tracer);
                        LiteralControl footer_literal = new LiteralControl(footer_builder.ToString());
                        Main_Place_Holder.Controls.Add(footer_literal);
                    }

                    break;

                #endregion

                #region Start adding HTML and add controls for RESULTS mode

                case Display_Mode_Enum.Results:
                    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Building the Search Results HTML Subwriter");

                    // Build the results subwriter
                    resultsWriter = new Search_Results_HtmlSubwriter(results_statistics, paged_results, codeManager, translator, itemList, currentUser );
                    subwriter = resultsWriter;
                    resultsWriter.Hierarchy_Object = hierarchyObject;
                    resultsWriter.Skin = htmlSkin;
                    resultsWriter.Mode = currentMode;

                    // Make sure the corresponding 'search' is the latest
                    currentMode.Mode = Display_Mode_Enum.Search;
                    HttpContext.Current.Session["LastSearch"] = currentMode.Redirect_URL();
                    currentMode.Mode = Display_Mode_Enum.Results;

                    // Add the controls and save the tree info in the session state
                    //System.Web.HttpContext.Current.Session["tree_info"] = resultsWriter.Add_Controls(Main_Place_Holder, Tracer, null);
                    resultsWriter.Add_Controls(Main_Place_Holder, Tracer, null);

                    break;

                #endregion

                #region Add HTML and controls for PUBLIC FOLDER mode

                case Display_Mode_Enum.Public_Folder:
                    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Building the Public Folder HTML Subwriter");

                    // Build the subwriter for this case
                    subwriter = new Public_Folder_HtmlSubwriter(results_statistics, paged_results, codeManager, translator, itemList, currentUser, publicFolder)
                                    {Hierarchy_Object = hierarchyObject, Skin = htmlSkin, Mode = currentMode};

                    // Also try to add any controls
                    ((Public_Folder_HtmlSubwriter)subwriter).Add_Controls(Main_Place_Holder, Tracer, null );
                    break;

                #endregion

                #region Add HTML and controls for COLLECTION VIEWS

                case Display_Mode_Enum.Search:
                case Display_Mode_Enum.Aggregation_Home:
                case Display_Mode_Enum.Aggregation_Browse_Info:
                case Display_Mode_Enum.Aggregation_Browse_By:
                case Display_Mode_Enum.Aggregation_Browse_Map:
                case Display_Mode_Enum.Aggregation_Private_Items:
                case Display_Mode_Enum.Aggregation_Item_Count:
                case Display_Mode_Enum.Aggregation_Usage_Statistics:
                case Display_Mode_Enum.Aggregation_Admin_View:
                    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Building the Collection HTML Subwriter");

                    // Build the subwriter for this case
                    subwriter = new Aggregation_HtmlSubwriter(hierarchyObject, currentMode, htmlSkin, translator, thisBrowseObject,  results_statistics, paged_results, codeManager, itemList, thematicHeadings, currentUser, ipRestrictionInfo, htmlBasedContent, Tracer);

                    // Also try to add any controls
                    ((Aggregation_HtmlSubwriter) subwriter).Add_Controls(Main_Place_Holder, Tracer);

                    break;

                #endregion

                #region Start adding HTML and add controls for ITEM DISPLAY mode

                case Display_Mode_Enum.Item_Display:
                    if (!currentMode.Invalid_Item)
                    {
                        if (currentItem == null)
                            return;

                        //SobekCM.Library.ItemViewer.Viewers.abstractItemViewer page_viewer = null;

                        //// Set the code for bib level mets to show the volume list by dwe
                        //if ((currentItem.METS.RecordStatus == METS_Record_Status.BIB_LEVEL) && (currentMode.ViewerCode.Length == 0))
                        //{
                        //    currentMode.ViewerCode = "BI1";
                        //}

                        //// Get the valid viewer code
                        //Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Getting the appropriate item viewer");
                        //if (currentMode.ViewerCode != "TS")
                        //{
                        //    if ((currentMode.ViewerCode.Length == 0) && (currentMode.Coordinates.Length > 0))
                        //    {
                        //        currentMode.ViewerCode = "GM";
                        //    }
                        //    currentMode.ViewerCode = currentItem.Behaviors.Get_Valid_Viewer_Code(currentMode.ViewerCode, currentMode.Page);
                        //    SobekCM.Resource_Object.Behaviors.View_Object viewObject = currentItem.Behaviors.Get_Viewer(currentMode.ViewerCode);
                        //    page_viewer = SobekCM.Library.ItemViewer.Viewers.ItemViewer_Factory.Get_Viewer(viewObject, currentItem.Bib_Info.Type.Type.ToUpper());

                        //    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Created " + page_viewer.GetType().ToString().Replace("SobekCM.Library.ItemViewer.Viewers.", ""));

                        //    // Assign the rest of the information, if a page viewer was created
                        //    if (page_viewer != null)
                        //    {
                        //        page_viewer.CurrentItem = currentItem;
                        //        page_viewer.CurrentMode = currentMode;
                        //        page_viewer.Redirect += new SobekCM.Library.ItemViewer.Viewers.Redirect_Requested(itemWriter_Redirect);

                        //        // If this was the citation viewer, pass in the translation object
                        //        string type = page_viewer.GetType().ToString();
                        //        if (page_viewer.GetType().ToString() == "SobekCM.Library.ItemViewer.Viewers.Citation_ItemViewer")
                        //        {
                        //            ((SobekCM.Library.ItemViewer.Viewers.Citation_ItemViewer)page_viewer).Translator = translator;
                        //            if ( currentUser != null )
                        //            {
                        //                ((SobekCM.Library.ItemViewer.Viewers.Citation_ItemViewer)page_viewer).User_Can_Edit_Item = currentUser.Can_Edit_This_Item(currentItem);
                        //            }

                        //        }
                        //    }
                        //}

                        // Determine the browser
                        bool ie = (currentMode.Browser_Type.IndexOf("IE") >= 0 );
                        bool show_toc = false;
                        if (HttpContext.Current.Session["Show TOC"] != null)
                        {
                            Boolean.TryParse(HttpContext.Current.Session["Show TOC"].ToString(), out show_toc);
                        }

                        // Check that this item is not checked out by another user
                        bool itemCheckedOutByOtherUser = false;
                        if (currentItem.Behaviors.CheckOut_Required)
                        {
                            if (!checkedItems.Check_Out(currentItem.Web.ItemID, HttpContext.Current.Request.UserHostAddress))
                            {
                                itemCheckedOutByOtherUser = true;
                            }
                        }

                        // Check to see if this is IP restricted
                        string restriction_message = String.Empty;
                        if (currentItem.Behaviors.IP_Restriction_Membership > 0)
                        {
                            if (HttpContext.Current != null)
                            {
                                int user_mask = (int)HttpContext.Current.Session["IP_Range_Membership"];
                                int comparison = currentItem.Behaviors.IP_Restriction_Membership & user_mask;
                                if (comparison == 0)
                                {
                                    int restriction = currentItem.Behaviors.IP_Restriction_Membership;
                                    int restriction_counter = 0;
                                    while (restriction % 2 != 1)
                                    {
                                        restriction = restriction >> 1;
                                        restriction_counter++;
                                    }
                                    restriction_message = ipRestrictionInfo[restriction_counter].Item_Restricted_Statement;
                                }
                            }
                        }

                        // Create the item viewer writer
                        Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Building Item Writer");
                        itemWriter = new Item_HtmlSubwriter(currentItem, currentPage, currentUser,
                            codeManager, translator, show_toc, (SobekCM_Library_Settings.JP2_Server.Length > 0),
                            currentMode, hierarchyObject, restriction_message, itemsInTitle, Tracer);
                        subwriter = itemWriter;
                        itemWriter.Mode = currentMode;
                        itemWriter.Skin = htmlSkin;
                        itemWriter.Item_Checked_Out_By_Other_User = itemCheckedOutByOtherUser;

                        // Add the navigation part to this form
                        itemWriter.Add_Nav_Bar_Menu_Section(Navigation_Place_Holder, ie, Tracer);
                        //if (itemWriter.PageViewer != null)
                        //{
                        //    Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Allowing page viewer to add left navigation bar section to <i>navigationPlaceHolder</i>");
                        //    itemWriter.Nav_Bar_Menu_Section_Added = itemWriter.PageViewer.Add_Nav_Bar_Menu_Section(Navigation_Place_Holder, ie, Tracer);
                        //}

                        // Add the TOC section
                        Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Allowing item viewer to add table of contents to <i>tocPlaceHolder</i>");
                        itemWriter.Add_Standard_TOC(TOC_Place_Holder, Tracer);

                        // Add the main viewer section
                        itemWriter.Add_Main_Viewer_Section(Main_Place_Holder, Tracer);
                    }
                    break;

                #endregion

                default:
                    Tracer.Add_Trace("Html_MainWriter.Add_Html_And_Controls", "No controls or html added to page");
                    break;
            }
        }