Click here to Skip to main content
15,898,134 members
Articles / Web Development / ASP.NET

OneNote on iPhone and Palm Pré using Windows Azure

Rate me:
Please Sign up or sign in to vote.
4.96/5 (39 votes)
25 Dec 2009CPOL12 min read 80.8K   322   53  
Learn how to synchronize your OneNote notebooks on Windows Azure and access it from your iPhone or your Palm Pré.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using OneNote = Microsoft.Office.Interop.OneNote;
using System.Xml.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Runtime.Serialization;



namespace Rino
{
    /// <summary>
    /// Class for a page in a Notebook
    /// </summary>
    [DataContract]
    public class Page : PageHeader
    {
        /// <summary>
        /// Class to set HTML generation options
        /// </summary>
        public class Options
        {
            public bool FormatLine;
        }

        /// <summary>
        /// Current options for generation
        /// </summary>
        private Options CurrentOptions;


        /// <summary>
        /// Content of the page as a raw XML string.
        /// </summary>
        /// <returns>content as a raw XML string</returns>
        [DataMember]
        public string Content { get; set; }

        /// <summary>
        /// Get a page in Microsoft OneNote.
        /// </summary>
        /// <param name="header">header of the page to read</param>
        /// <returns>list of Notebook element found</returns>
        public static Page LoadPageFromOneNote(PageHeader header)
        {
            // Call OneNote API to get content
            string sPage;
            OneNote.ApplicationClass onApp = new OneNote.ApplicationClass();
            onApp.GetPageContent(header.ID, out sPage, OneNote.PageInfo.piAll);

            // Create a page from the header
            Page page = new Page();
            page.ID = header.ID;
            page.IsSubpage = header.IsSubpage;
            page.Name = header.Name;
            page.LastModifiedTime = header.LastModifiedTime;
            page.Content = sPage;

            return page;
        }

        /// <summary>
        /// Get content of the page as simplified HTML using default generation settings.
        /// </summary>
        /// <returns>content as simplified HTML</returns>
        public string ToHTML()
        {
            Options settings = new Options();
            settings.FormatLine = true;
            return ToHTML(settings);
        }

        /// <summary>
        /// Get content of the page as simplified HTML.
        /// </summary>
        /// <param name="settings">generation settings</param>
        /// <returns>content as simplified HTML</returns>
        public string ToHTML(Options settings)
        {
            // Set options
            if (settings == null)
                return ToHTML();
            CurrentOptions = settings;

            // Get XML
            XDocument page = XDocument.Parse(Content);

            // Init visitor
            output = new StringBuilder();
            XMLVisitor visitor = new XMLVisitor();
            InitVisitor(visitor);

            // Launch generation
            visitor.Visit(page);

            // Return result
            return output.ToString();
        }

        #region Generation visitor

        /// <summary>
        /// Max level for a paragraph
        /// </summary>
        private const int MaxTLevel = 16;

        /// <summary>
        /// Contextual variable
        /// </summary>
        private bool isInTitle;
        private int currentOutline;
        private bool[] levelIsList;
        private bool[] previousIsList;

        /// <summary>
        /// Current output when generating
        /// </summary>
        private StringBuilder output;

        /// <summary>
        /// Do contextual initialization for visitor
        /// </summary>
        /// <param name="visitor">visitor to initialize</param>
        private void InitVisitor(XMLVisitor visitor)
        {
            // Register templates
            visitor.Register("Page", VisitPage);
            visitor.Register("/Page", VisitSPage);
            visitor.Register("Title", VisitTitle);
            visitor.Register("Outline", VisitOutline);
            visitor.Register("/Outline", VisitSOutline);
            visitor.Register("T", VisitT);
            visitor.Register("Bullet", VisitBullet);
            visitor.Register("Number", VisitBullet);
            visitor.Register("Table", VisitTable);
            visitor.Register("/Table", VisitSTable);
            visitor.Register("Row", VisitRow);
            visitor.Register("/Row", VisitSRow);
            visitor.Register("Cell", VisitCell);
            visitor.Register("/Cell", VisitSCell);
            visitor.RegisterDefault(VisitButIgnore);
            
            // Init context
            currentOutline = 0;
            isInTitle = false;
            levelIsList = new bool[MaxTLevel];
            previousIsList = new bool[MaxTLevel];
            for (int i = 0; i < MaxTLevel; i++)
            {
                levelIsList[i] = false;
                previousIsList[i] = false;
            }
        }

        /// <summary>
        /// Visitor for Page tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitPage(XElement elem)
        {
            OutputLine("<html>");
        }

        /// <summary>
        /// Visitor for /Page tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitSPage(XElement elem)
        {
            // Close page
            OutputLine("</body>");
            OutputLine("</html>");
        }

        /// <summary>
        /// Visitor for Title tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitTitle(XElement elem)
        {
            isInTitle = true;
        }

        /// <summary>
        /// Visitor for Outline tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitOutline(XElement elem)
        {
            // Not in title
            isInTitle = false;
            currentOutline++;

            // Process begining tag
            if (currentOutline == 1)
                OutputLine("<body>");
            OutputLine(String.Format("<div title='{0}'>", HttpUtility.HtmlEncode(Name))); // HACK: use Title attribute to force iPhone page title
        }

        /// <summary>
        /// Visitor for /Outline tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitSOutline(XElement elem)
        {
            // Process ending tag
            ComputeListLevel(elem.Ancestors().Count());
            OutputLine("</div>");
        }

        /// <summary>
        /// Visitor for T tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitT(XElement elem)
        {
            // Get value
            string value = elem.Value;

            // If in title, just generate title
            if (isInTitle)
            {
                Output("<head><title>");
                Output(value);
                Output("</title></head>");
                return;
            }

            // Paragraph or line ?
            int level = elem.Ancestors().Count();
            string tag = "p";
            if (ComputeListLevel(level))
                tag = "li";

            // Indent
            Indent(level);

            // Empty line
            if (value.Length == 0)
            {
                OutputLine("<br>");
                return;
            }

            // Generate text
            Output('<'); Output(tag); Output('>');
            Output(value);
            Output("</"); Output(tag); Output('>');
            OutputLine();
        }

        /// <summary>
        /// Compute tag for list level.
        /// </summary>
        /// <param name="level">current level</param>
        /// <returns>true if the current level is in a list</returns>
        private bool ComputeListLevel(int level)
        {
            // Close all the pending tag
            for (int i = level+1; i < MaxTLevel; i++)
            {
                if (previousIsList[i])
                {
                    Indent(i);
                    OutputLine("</ul>");
                }
                previousIsList[i] = false;
            }

            // Need to process the current as a list
            bool currentIsList = levelIsList[level];
            if (currentIsList)
            {
                if (!previousIsList[level])
                {
                    Indent(level);
                    OutputLine("<ul>");
                }
                levelIsList[level] = false;
                previousIsList[level] = true;

                return true;
            }

            // Close the tag for previous level
            if (!currentIsList && previousIsList[level])
            {
                Indent(level);
                OutputLine("</ul>");
            }
            previousIsList[level] = false;

            return false;
        }

        /// <summary>
        /// Visitor for Bullet tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitBullet(XElement elem)
        {
            int level = elem.Ancestors().Count();
            levelIsList[level - 1] = true;
        }

        /// <summary>
        /// Visitor for Table tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitTable(XElement elem)
        {
            OutputLine("<table border='1'>");
        }

        /// <summary>
        /// Visitor for /Table tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitSTable(XElement elem)
        {
            OutputLine("</table>");
        }

        /// <summary>
        /// Visitor for Row tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitRow(XElement elem)
        {
            OutputLine("<tr>");
        }

        /// <summary>
        /// Visitor for /Row tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitSRow(XElement elem)
        {
            OutputLine("</tr>");
        }

        /// <summary>
        /// Visitor for Cell tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitCell(XElement elem)
        {
            OutputLine("<td>");
        }

        /// <summary>
        /// Visitor for /Cell tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitSCell(XElement elem)
        {
            OutputLine("</td>");
        }

        /// <summary>
        /// Visitor for all unknown tag.
        /// </summary>
        /// <param name="elem">element to process</param>
        private void VisitButIgnore(XElement elem)
        {
            // Do nothing
        }

        #region Formating function
        /// <summary>
        /// Append text to output buffer.
        /// </summary>
        /// <param name="text">value to append</param>
        private void Output(string text)
        {
            output.Append(text);
        }

        /// <summary>
        /// Append character to output buffer.
        /// </summary>
        /// <param name="text">value to append</param>
        private void Output(char character)
        {
            output.Append(character);
        }

        /// <summary>
        /// Append newline to output buffer.
        /// </summary>
        private void OutputLine()
        {
            if (CurrentOptions.FormatLine)
                output.AppendLine();
        }

        /// <summary>
        /// Append text and newline to output buffer.
        /// </summary>
        /// <param name="text">value to append</param>
        private void OutputLine(string text)
        {
            if (CurrentOptions.FormatLine)
                output.AppendLine(text);
            else
                output.Append(text);
        }

        /// <summary>
        /// Append an indent to output buffer.
        /// </summary>
        /// <param name="level">level to indent</param>
        private void Indent(int level)
        {
            if (CurrentOptions.FormatLine)
                output.Append(' ', level * 4);
        }
        #endregion
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect C2S
France France
Lionel is a software architect at C2S, a software company based in France and subsidiary of the Bouygues group.
Lionel is also the author of Liogo, an open-source Logo compiler for .NET.
Lionel is a contributor of DotNetGuru and Dr.Dobb's Journal.
Lionel is President and co-founder of OLPC France.

Comments and Discussions