{"id":370,"date":"2021-11-07T14:15:52","date_gmt":"2021-11-07T22:15:52","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/math-in-office\/?p=370"},"modified":"2021-11-07T14:15:52","modified_gmt":"2021-11-07T22:15:52","slug":"richedit-stories","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/math-in-office\/richedit-stories\/","title":{"rendered":"RichEdit Stories"},"content":{"rendered":"<p>Word and RichEdit have stories, but you won\u2019t find their story\u2019s definition in a dictionary. Their story is an object that <em>stores<\/em> rich text in computer memory. Rich text consists of Unicode plain text, associated character and paragraph formatting, and embedded objects such as images. Such a story can contain the narrative of a traditional story, but more generally it can contain any arbitrary set of Unicode characters. A RichEdit control is created with a built-in story called the \u201cmain story\u201d. Other stories may be created by the client or by RichEdit for special purposes. For example, when you select some text and hit Ctrl+c, the selected text range is noted, but for the sake of efficiency, no conversions take place until you paste a particular format or the RichEdit control is destroyed. If you start to modify the selected text, the text is first copied into a clipboard scratch story so that the text can continue to be pasted in any of the promised formats. This post describes how RichEdit stories are used and managed.<\/p>\n<h2>Client usage of multiple stories<\/h2>\n<p>Microsoft Word uses multiple stories in a document, such as a main story, a footnote story, a header story, a footer story, etc. A RichEdit client could do something similar in supporting a full-fledged document program. For example, OneNote instantiates a RichEdit control for editing and displaying a paragraph. Since a OneNote document can have many sections, each with many paragraphs, OneNote has a pool of RichEdit controls to be used as needed. A large OneNote document has many more paragraphs than RichEdit controls. An alternate approach would be to house each paragraph of a OneNote section in its own story all within a single control for the whole section. This approach might be more performant than using multiple relatively large controls since the stories package rich text efficiently, and paragraphs would only have to be loaded once.<\/p>\n<h2>Place-holder story<\/h2>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/math-in-office\/richedit-place-holder\/\">Place-holder controls<\/a> are used for user entry and need place-holder text to instruct the user what to do. As soon as the user types something, the place-holder text disappears, and what the user types is displayed instead. If the user deletes all the text, the place-holder text reappears. This behavior is accomplished by storing the place-holder text in its own story. The story that is currently active is displayed on screen.<\/p>\n<h2>Equation scratch story<\/h2>\n<p>The first use of stories in RichEdit was in RichEdit 6.0 (Office 2007) for converting UnicodeMath input into the internal <a href=\"https:\/\/docs.microsoft.com\/en-us\/archive\/blogs\/murrays\/officemath\">OfficeMath<\/a> format. In fact, the TOM2 <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/Hh768736(v=vs.85).aspx\">ITextStrings<\/a> interface handles a collection of rich-text strings useful for manipulating rich text, such as converting infix math expressions into the prefix OfficeMath form and vice versa. The ITextStrings strings collection is implemented by concatenating the strings together in a scratch story and maintaining an array of the string counts that delimit the strings. RichEdit also uses an ITextStrings scratch story in converting MathML and OMML into OfficeMath.<\/p>\n<h2>Programming stories<\/h2>\n<p>Stories can be programmed using the messages EM_SELECTSTORY, <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/controls\/em-getstorytype\">EM_GETSTORYTYPE<\/a>, and <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/controls\/em-setstorytype\">EM_SETSTORYTYPE<\/a> and by the methods in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/Hh768721(v=vs.85).aspx\">ITextStory<\/a>, which is part of TOM Version 2. Stories can be \u201cedited\u201d simultaneously using ITextRange2\u2019s and displayed independently of one another. A given ITextRange2 accesses one and only one story. In addition, only one story can be user active at a time, that is, only one story receives the keyboard and mouse input and is displayed. The EM_SELECTSTORY message isn\u2019t documented elsewhere on the web, so here\u2019s how it\u2019s used. The message is defined by<\/p>\n<p style=\"padding-left: 40px;\">#define EM_SELECTSTORY\u00a0\u00a0\u00a0\u00a0 (WM_USER + 263)<\/p>\n<p>The message selects the story with ID given by the wparam. It returns the active story ID. The lparam has the flag SSS_DONTDISPLAYSTORY defined by<\/p>\n<p style=\"padding-left: 40px;\">#define SSS_DONTDISPLAYSTORY\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1<\/p>\n<p>The <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/tom\/nn-tom-itextdocument2\">ITextDocument2<\/a> interface has methods to <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/tom\/nf-tom-itextdocument2-getactivestory\">get the \u200eactive story<\/a>, to <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/tom\/nf-tom-itextdocument2-getnewstory\">get a new story<\/a>, and to <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/tom\/nf-tom-itextdocument2-getstory\">get an existing story<\/a> by story ID. The story facility needs a stories collection, since among other things before the parent ITextServices instance is deleted, it needs to zombie any unreleased ITextStory pointers and delete the story data. The stories collection is accessed externally via methods in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/Hh768436(v=vs.85).aspx\">ITextDocument2<\/a>. RichEdit 6.0 (Office 2007) and later versions have a multistory facility (see <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/bb774062(v=vs.85).aspx\">ITextStoryRanges<\/a>), but it is not sufficiently lightweight and convenient for clients, so we added the ITextStory approach in RichEdit 8 (in 2012). The <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/bb774062(v=vs.85).aspx\">ITextStoryRanges<\/a> facility implements the original TOM version of stories as ranges and is oriented towards stories as used in Word. The current emphasis on a multitude of lightweight instances leads to a different model. A range adds extra instance size, so it saves space to instantiate ranges only when they are needed to manipulate stories.<\/p>\n<p>To minimize the size of the story, it only contains rich-text structures that are used. For example, if a control only has default formatting, it has no character or paragraph format run arrays. Some languages like Thai need cluster and word breaking, but if a story doesn\u2019t contain text of such languages, the cluster and word breaking structures are omitted. Similarly, if there are no embedded objects or images, there\u2019s no object array.<\/p>\n<p>The current RichEdit control has a single display that\u2019s used by the active story. A more advanced model would offer multiple displays and an enhanced ITextHost interface with methods that specify the ITextStory to be displayed.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Word and RichEdit have stories, but you won\u2019t find their story\u2019s definition in a dictionary. Their story is an object that stores rich text in computer memory. Rich text consists of Unicode plain text, associated character and paragraph formatting, and embedded objects such as images. Such a story can contain the narrative of a traditional [&hellip;]<\/p>\n","protected":false},"author":40611,"featured_media":55,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-370","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-math-in-office"],"acf":[],"blog_post_summary":"<p>Word and RichEdit have stories, but you won\u2019t find their story\u2019s definition in a dictionary. Their story is an object that stores rich text in computer memory. Rich text consists of Unicode plain text, associated character and paragraph formatting, and embedded objects such as images. Such a story can contain the narrative of a traditional [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/posts\/370","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/users\/40611"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/comments?post=370"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/posts\/370\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/media\/55"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/media?parent=370"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/categories?post=370"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/math-in-office\/wp-json\/wp\/v2\/tags?post=370"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}